ACPI: asus_acpi: Add support for Asus Z81SP
[safe/jmp/linux-2.6] / drivers / acpi / dock.c
index e4c1a4f..688e83a 100644 (file)
@@ -48,7 +48,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 +118,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 +134,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 +299,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 +321,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 +446,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 +460,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 +565,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 +615,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;
 }
 
@@ -673,7 +689,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 */
@@ -784,7 +800,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 +823,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;
 }