]> rtime.felk.cvut.cz Git - linux-imx.git/blobdiff - drivers/pci/hotplug/acpiphp_glue.c
ACPI / dock / PCI: Synchronous handling of dock events for PCI devices
[linux-imx.git] / drivers / pci / hotplug / acpiphp_glue.c
index 050b6f9abfd1d16a662cdbfa57dc5b9f70e870f5..59df8575a48ce834fb48ea002689ed97ed9ca51a 100644 (file)
@@ -61,6 +61,7 @@ static DEFINE_MUTEX(bridge_mutex);
 static void handle_hotplug_event_bridge (acpi_handle, u32, void *);
 static void acpiphp_sanitize_bus(struct pci_bus *bus);
 static void acpiphp_set_hpp_values(struct pci_bus *bus);
+static void hotplug_event_func(acpi_handle handle, u32 type, void *context);
 static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *context);
 static void free_bridge(struct kref *kref);
 
@@ -147,7 +148,7 @@ static int post_dock_fixups(struct notifier_block *nb, unsigned long val,
 
 
 static const struct acpi_dock_ops acpiphp_dock_ops = {
-       .handler = handle_hotplug_event_func,
+       .handler = hotplug_event_func,
 };
 
 /* Check whether the PCI device is managed by native PCIe hotplug driver */
@@ -179,6 +180,20 @@ static bool device_is_managed_by_native_pciehp(struct pci_dev *pdev)
        return true;
 }
 
+static void acpiphp_dock_init(void *data)
+{
+       struct acpiphp_func *func = data;
+
+       get_bridge(func->slot->bridge);
+}
+
+static void acpiphp_dock_release(void *data)
+{
+       struct acpiphp_func *func = data;
+
+       put_bridge(func->slot->bridge);
+}
+
 /* callback routine to register each ACPI PCI slot object */
 static acpi_status
 register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
@@ -298,7 +313,8 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
                 */
                newfunc->flags &= ~FUNC_HAS_EJ0;
                if (register_hotplug_dock_device(handle,
-                       &acpiphp_dock_ops, newfunc))
+                       &acpiphp_dock_ops, newfunc,
+                       acpiphp_dock_init, acpiphp_dock_release))
                        dbg("failed to register dock device\n");
 
                /* we need to be notified when dock events happen
@@ -1068,22 +1084,12 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type,
        alloc_acpi_hp_work(handle, type, context, _handle_hotplug_event_bridge);
 }
 
-static void _handle_hotplug_event_func(struct work_struct *work)
+static void hotplug_event_func(acpi_handle handle, u32 type, void *context)
 {
-       struct acpiphp_func *func;
+       struct acpiphp_func *func = context;
        char objname[64];
        struct acpi_buffer buffer = { .length = sizeof(objname),
                                      .pointer = objname };
-       struct acpi_hp_work *hp_work;
-       acpi_handle handle;
-       u32 type;
-
-       hp_work = container_of(work, struct acpi_hp_work, work);
-       handle = hp_work->handle;
-       type = hp_work->type;
-       func = (struct acpiphp_func *)hp_work->context;
-
-       acpi_scan_lock_acquire();
 
        acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
 
@@ -1116,6 +1122,18 @@ static void _handle_hotplug_event_func(struct work_struct *work)
                warn("notify_handler: unknown event type 0x%x for %s\n", type, objname);
                break;
        }
+}
+
+static void _handle_hotplug_event_func(struct work_struct *work)
+{
+       struct acpi_hp_work *hp_work;
+       struct acpiphp_func *func;
+
+       hp_work = container_of(work, struct acpi_hp_work, work);
+       func = hp_work->context;
+       acpi_scan_lock_acquire();
+
+       hotplug_event_func(hp_work->handle, hp_work->type, func);
 
        acpi_scan_lock_release();
        kfree(hp_work); /* allocated in handle_hotplug_event_func */