Add common orderly_poweroff()
[safe/jmp/linux-2.6] / drivers / acpi / dock.c
index e4c1a4f..4546bf8 100644 (file)
 #include <linux/notifier.h>
 #include <linux/platform_device.h>
 #include <linux/jiffies.h>
+#include <linux/stddef.h>
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
 
-#define ACPI_DOCK_DRIVER_NAME "ACPI Dock Station Driver"
+#define ACPI_DOCK_DRIVER_DESCRIPTION "ACPI Dock Station Driver"
 
-ACPI_MODULE_NAME("dock")
+ACPI_MODULE_NAME("dock");
 MODULE_AUTHOR("Kristen Carlson Accardi");
-MODULE_DESCRIPTION(ACPI_DOCK_DRIVER_NAME);
+MODULE_DESCRIPTION(ACPI_DOCK_DRIVER_DESCRIPTION);
 MODULE_LICENSE("GPL");
 
 static struct atomic_notifier_head dock_notifier_list;
@@ -48,7 +49,7 @@ struct dock_station {
        unsigned long last_dock_time;
        u32 flags;
        spinlock_t dd_lock;
-       spinlock_t hp_lock;
+       struct mutex hp_lock;
        struct list_head dependent_devices;
        struct list_head hotplug_devices;
 };
@@ -118,9 +119,9 @@ static void
 dock_add_hotplug_device(struct dock_station *ds,
                        struct dock_dependent_device *dd)
 {
-       spin_lock(&ds->hp_lock);
+       mutex_lock(&ds->hp_lock);
        list_add_tail(&dd->hotplug_list, &ds->hotplug_devices);
-       spin_unlock(&ds->hp_lock);
+       mutex_unlock(&ds->hp_lock);
 }
 
 /**
@@ -134,9 +135,9 @@ static void
 dock_del_hotplug_device(struct dock_station *ds,
                        struct dock_dependent_device *dd)
 {
-       spin_lock(&ds->hp_lock);
+       mutex_lock(&ds->hp_lock);
        list_del(&dd->hotplug_list);
-       spin_unlock(&ds->hp_lock);
+       mutex_unlock(&ds->hp_lock);
 }
 
 /**
@@ -299,7 +300,7 @@ static void hotplug_dock_devices(struct dock_station *ds, u32 event)
 {
        struct dock_dependent_device *dd;
 
-       spin_lock(&ds->hp_lock);
+       mutex_lock(&ds->hp_lock);
 
        /*
         * First call driver specific hotplug functions
@@ -321,15 +322,17 @@ static void hotplug_dock_devices(struct dock_station *ds, u32 event)
                else
                        dock_create_acpi_device(dd->handle);
        }
-       spin_unlock(&ds->hp_lock);
+       mutex_unlock(&ds->hp_lock);
 }
 
 static void dock_event(struct dock_station *ds, u32 event, int num)
 {
+       struct device *dev = &dock_device.dev;
        /*
-        * we don't do events until someone tells me that
-        * they would like to have them.
+        * Indicate that the status of the dock station has
+        * changed.
         */
+       kobject_uevent(&dev->kobj, KOBJ_CHANGE);
 }
 
 /**
@@ -444,6 +447,9 @@ static int dock_in_progress(struct dock_station *ds)
  */
 int register_dock_notifier(struct notifier_block *nb)
 {
+       if (!dock_station)
+               return -ENODEV;
+
        return atomic_notifier_chain_register(&dock_notifier_list, nb);
 }
 
@@ -455,6 +461,9 @@ EXPORT_SYMBOL_GPL(register_dock_notifier);
  */
 void unregister_dock_notifier(struct notifier_block *nb)
 {
+       if (!dock_station)
+               return;
+
        atomic_notifier_chain_unregister(&dock_notifier_list, nb);
 }
 
@@ -557,7 +566,7 @@ static int handle_eject_request(struct dock_station *ds, u32 event)
  */
 static void dock_notify(acpi_handle handle, u32 event, void *data)
 {
-       struct dock_station *ds = (struct dock_station *)data;
+       struct dock_station *ds = data;
 
        switch (event) {
        case ACPI_NOTIFY_BUS_CHECK:
@@ -607,20 +616,28 @@ static acpi_status
 find_dock_devices(acpi_handle handle, u32 lvl, void *context, void **rv)
 {
        acpi_status status;
-       acpi_handle tmp;
-       struct dock_station *ds = (struct dock_station *)context;
+       acpi_handle tmp, parent;
+       struct dock_station *ds = context;
        struct dock_dependent_device *dd;
 
        status = acpi_bus_get_ejd(handle, &tmp);
-       if (ACPI_FAILURE(status))
-               return AE_OK;
+       if (ACPI_FAILURE(status)) {
+               /* try the parent device as well */
+               status = acpi_get_parent(handle, &parent);
+               if (ACPI_FAILURE(status))
+                       goto fdd_out;
+               /* see if parent is dependent on dock */
+               status = acpi_bus_get_ejd(parent, &tmp);
+               if (ACPI_FAILURE(status))
+                       goto fdd_out;
+       }
 
        if (tmp == ds->handle) {
                dd = alloc_dock_dependent_device(handle);
                if (dd)
                        add_dock_dependent_device(ds, dd);
        }
-
+fdd_out:
        return AE_OK;
 }
 
@@ -651,6 +668,23 @@ static ssize_t write_undock(struct device *dev, struct device_attribute *attr,
 }
 DEVICE_ATTR(undock, S_IWUSR, NULL, write_undock);
 
+/*
+ * show_dock_uid - read method for "uid" file in sysfs
+ */
+static ssize_t show_dock_uid(struct device *dev,
+                            struct device_attribute *attr, char *buf)
+{
+       unsigned long lbuf;
+       acpi_status status = acpi_evaluate_integer(dock_station->handle, "_UID", NULL, &lbuf);
+       if(ACPI_FAILURE(status)) {
+           return 0;
+       }
+       return snprintf(buf, PAGE_SIZE, "%lx\n", lbuf);
+}
+DEVICE_ATTR(uid, S_IRUGO, show_dock_uid, NULL);
+
+
+
 /**
  * dock_add - add a new dock station
  * @handle: the dock station handle
@@ -673,7 +707,7 @@ static int dock_add(acpi_handle handle)
        INIT_LIST_HEAD(&dock_station->dependent_devices);
        INIT_LIST_HEAD(&dock_station->hotplug_devices);
        spin_lock_init(&dock_station->dd_lock);
-       spin_lock_init(&dock_station->hp_lock);
+       mutex_init(&dock_station->hp_lock);
        ATOMIC_INIT_NOTIFIER_HEAD(&dock_notifier_list);
 
        /* initialize platform device stuff */
@@ -699,6 +733,13 @@ static int dock_add(acpi_handle handle)
                kfree(dock_station);
                return ret;
        }
+       ret = device_create_file(&dock_device.dev, &dev_attr_uid);
+       if (ret) {
+               printk("Error %d adding sysfs file\n", ret);
+               platform_device_unregister(&dock_device);
+               kfree(dock_station);
+               return ret;
+       }
 
        /* Find dependent devices */
        acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
@@ -725,7 +766,7 @@ static int dock_add(acpi_handle handle)
                goto dock_add_err;
        }
 
-       printk(KERN_INFO PREFIX "%s \n", ACPI_DOCK_DRIVER_NAME);
+       printk(KERN_INFO PREFIX "%s \n", ACPI_DOCK_DRIVER_DESCRIPTION);
 
        return 0;
 
@@ -784,7 +825,7 @@ static int dock_remove(void)
 static acpi_status
 find_dock(acpi_handle handle, u32 lvl, void *context, void **rv)
 {
-       int *count = (int *)context;
+       int *count = context;
        acpi_status status = AE_OK;
 
        if (is_dock(handle)) {
@@ -807,7 +848,7 @@ static int __init dock_init(void)
                            ACPI_UINT32_MAX, find_dock, &num, NULL);
 
        if (!num)
-               return -ENODEV;
+               printk(KERN_INFO "No dock devices found.\n");
 
        return 0;
 }