summaryrefslogtreecommitdiffstats
path: root/drivers/acpi/dock.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/dock.c')
-rw-r--r--drivers/acpi/dock.c104
1 files changed, 42 insertions, 62 deletions
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c
index 3199ce9..8c3967c 100644
--- a/drivers/acpi/dock.c
+++ b/drivers/acpi/dock.c
@@ -72,7 +72,7 @@ static DEFINE_MUTEX(hotplug_lock);
struct dock_dependent_device {
struct list_head list;
- acpi_handle handle;
+ struct acpi_device *adev;
const struct acpi_dock_ops *hp_ops;
void *hp_context;
unsigned int hp_refcount;
@@ -98,12 +98,13 @@ enum dock_callback_type {
*****************************************************************************/
/**
* add_dock_dependent_device - associate a device with the dock station
- * @ds: The dock station
- * @handle: handle of the dependent device
+ * @ds: Dock station.
+ * @adev: Dependent ACPI device object.
*
* Add the dependent device to the dock's dependent device list.
*/
-static int add_dock_dependent_device(struct dock_station *ds, acpi_handle handle)
+static int add_dock_dependent_device(struct dock_station *ds,
+ struct acpi_device *adev)
{
struct dock_dependent_device *dd;
@@ -111,7 +112,7 @@ static int add_dock_dependent_device(struct dock_station *ds, acpi_handle handle
if (!dd)
return -ENOMEM;
- dd->handle = handle;
+ dd->adev = adev;
INIT_LIST_HEAD(&dd->list);
list_add_tail(&dd->list, &ds->dependent_devices);
@@ -212,7 +213,7 @@ static void dock_hotplug_event(struct dock_dependent_device *dd, u32 event,
return;
if (cb)
- cb(dd->handle, event, dd->hp_context);
+ cb(dd->adev->handle, event, dd->hp_context);
dock_release_hotplug(dd);
}
@@ -231,18 +232,18 @@ static struct dock_station *find_dock_station(acpi_handle handle)
/**
* find_dock_dependent_device - get a device dependent on this dock
* @ds: the dock station
- * @handle: the acpi_handle of the device we want
+ * @adev: ACPI device object to find.
*
* iterate over the dependent device list for this dock. If the
* dependent device matches the handle, return.
*/
static struct dock_dependent_device *
-find_dock_dependent_device(struct dock_station *ds, acpi_handle handle)
+find_dock_dependent_device(struct dock_station *ds, struct acpi_device *adev)
{
struct dock_dependent_device *dd;
list_for_each_entry(dd, &ds->dependent_devices, list)
- if (handle == dd->handle)
+ if (adev == dd->adev)
return dd;
return NULL;
@@ -252,10 +253,9 @@ void register_dock_dependent_device(struct acpi_device *adev,
acpi_handle dshandle)
{
struct dock_station *ds = find_dock_station(dshandle);
- acpi_handle handle = adev->handle;
- if (ds && !find_dock_dependent_device(ds, handle))
- add_dock_dependent_device(ds, handle);
+ if (ds && !find_dock_dependent_device(ds, adev))
+ add_dock_dependent_device(ds, adev);
}
/*****************************************************************************
@@ -264,24 +264,24 @@ void register_dock_dependent_device(struct acpi_device *adev,
/**
* is_dock_device - see if a device is on a dock station
- * @handle: acpi handle of the device
+ * @adev: ACPI device object to check.
*
* If this device is either the dock station itself,
* or is a device dependent on the dock station, then it
* is a dock device
*/
-int is_dock_device(acpi_handle handle)
+int is_dock_device(struct acpi_device *adev)
{
struct dock_station *dock_station;
if (!dock_station_count)
return 0;
- if (acpi_dock_match(handle))
+ if (acpi_dock_match(adev->handle))
return 1;
list_for_each_entry(dock_station, &dock_stations, sibling)
- if (find_dock_dependent_device(dock_station, handle))
+ if (find_dock_dependent_device(dock_station, adev))
return 1;
return 0;
@@ -309,43 +309,6 @@ static int dock_present(struct dock_station *ds)
}
/**
- * dock_create_acpi_device - add new devices to acpi
- * @handle - handle of the device to add
- *
- * This function will create a new acpi_device for the given
- * handle if one does not exist already. This should cause
- * acpi to scan for drivers for the given devices, and call
- * matching driver's add routine.
- */
-static void dock_create_acpi_device(acpi_handle handle)
-{
- struct acpi_device *device = NULL;
- int ret;
-
- acpi_bus_get_device(handle, &device);
- if (!acpi_device_enumerated(device)) {
- ret = acpi_bus_scan(handle);
- if (ret)
- pr_debug("error adding bus, %x\n", -ret);
- }
-}
-
-/**
- * dock_remove_acpi_device - remove the acpi_device struct from acpi
- * @handle - the handle of the device to remove
- *
- * Tell acpi to remove the acpi_device. This should cause any loaded
- * driver to have it's remove routine called.
- */
-static void dock_remove_acpi_device(acpi_handle handle)
-{
- struct acpi_device *device;
-
- if (!acpi_bus_get_device(handle, &device))
- acpi_bus_trim(device);
-}
-
-/**
* hot_remove_dock_devices - Remove dock station devices.
* @ds: Dock station.
*/
@@ -362,7 +325,7 @@ static void hot_remove_dock_devices(struct dock_station *ds)
dock_hotplug_event(dd, ACPI_NOTIFY_EJECT_REQUEST, false);
list_for_each_entry_reverse(dd, &ds->dependent_devices, list)
- dock_remove_acpi_device(dd->handle);
+ acpi_bus_trim(dd->adev);
}
/**
@@ -388,12 +351,20 @@ static void hotplug_dock_devices(struct dock_station *ds, u32 event)
dock_hotplug_event(dd, event, DOCK_CALL_HANDLER);
/*
- * Now make sure that an acpi_device is created for each dependent
- * device. That will cause scan handlers to be attached to device
- * objects or acpi_drivers to be stopped/started if they are present.
+ * Check if all devices have been enumerated already. If not, run
+ * acpi_bus_scan() for them and that will cause scan handlers to be
+ * attached to device objects or acpi_drivers to be stopped/started if
+ * they are present.
*/
- list_for_each_entry(dd, &ds->dependent_devices, list)
- dock_create_acpi_device(dd->handle);
+ list_for_each_entry(dd, &ds->dependent_devices, list) {
+ struct acpi_device *adev = dd->adev;
+
+ if (!acpi_device_enumerated(adev)) {
+ int ret = acpi_bus_scan(adev->handle);
+ if (ret)
+ dev_dbg(&adev->dev, "scan error %d\n", -ret);
+ }
+ }
}
static void dock_event(struct dock_station *ds, u32 event, int num)
@@ -514,6 +485,7 @@ int register_hotplug_dock_device(acpi_handle handle,
{
struct dock_dependent_device *dd;
struct dock_station *dock_station;
+ struct acpi_device *adev;
int ret = -EINVAL;
if (WARN_ON(!context))
@@ -522,6 +494,10 @@ int register_hotplug_dock_device(acpi_handle handle,
if (!dock_station_count)
return -ENODEV;
+ ret = acpi_bus_get_device(handle, &adev);
+ if (ret)
+ return ret;
+
/*
* make sure this handle is for a device dependent on the dock,
* this would include the dock station itself
@@ -532,7 +508,7 @@ int register_hotplug_dock_device(acpi_handle handle,
* separately, so there are two 'dock stations' which need the
* ops
*/
- dd = find_dock_dependent_device(dock_station, handle);
+ dd = find_dock_dependent_device(dock_station, adev);
if (dd && !dock_init_hotplug(dd, ops, context, init, release))
ret = 0;
}
@@ -549,12 +525,16 @@ void unregister_hotplug_dock_device(acpi_handle handle)
{
struct dock_dependent_device *dd;
struct dock_station *dock_station;
+ struct acpi_device *adev;
if (!dock_station_count)
return;
+ if (acpi_bus_get_device(handle, &adev))
+ return;
+
list_for_each_entry(dock_station, &dock_stations, sibling) {
- dd = find_dock_dependent_device(dock_station, handle);
+ dd = find_dock_dependent_device(dock_station, adev);
if (dd)
dock_release_hotplug(dd);
}
@@ -807,7 +787,7 @@ void acpi_dock_add(struct acpi_device *adev)
goto err_unregister;
/* add the dock station as a device dependent on itself */
- ret = add_dock_dependent_device(dock_station, handle);
+ ret = add_dock_dependent_device(dock_station, adev);
if (ret)
goto err_rmgroup;
OpenPOWER on IntegriCloud