aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/acpi/bus.c2
-rw-r--r--drivers/acpi/container.c3
-rw-r--r--drivers/acpi/dock.c452
-rw-r--r--drivers/acpi/internal.h14
-rw-r--r--drivers/acpi/osl.c14
-rw-r--r--drivers/acpi/scan.c59
-rw-r--r--drivers/ata/libata-acpi.c72
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c134
-rw-r--r--include/acpi/acpi_bus.h24
-rw-r--r--include/acpi/acpi_drivers.h26
10 files changed, 295 insertions, 505 deletions
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index e61e7b8a2eaf..afe6f9a919c1 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -400,7 +400,7 @@ static void acpi_bus_notify(acpi_handle handle, u32 type, void *data)
400 case ACPI_NOTIFY_BUS_CHECK: 400 case ACPI_NOTIFY_BUS_CHECK:
401 case ACPI_NOTIFY_DEVICE_CHECK: 401 case ACPI_NOTIFY_DEVICE_CHECK:
402 case ACPI_NOTIFY_EJECT_REQUEST: 402 case ACPI_NOTIFY_EJECT_REQUEST:
403 status = acpi_hotplug_execute(acpi_device_hotplug, adev, type); 403 status = acpi_hotplug_schedule(adev, type);
404 if (ACPI_SUCCESS(status)) 404 if (ACPI_SUCCESS(status))
405 return; 405 return;
406 default: 406 default:
diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c
index 368f9ddb8480..a55cccbc7356 100644
--- a/drivers/acpi/container.c
+++ b/drivers/acpi/container.c
@@ -68,6 +68,9 @@ static int container_device_attach(struct acpi_device *adev,
68 struct device *dev; 68 struct device *dev;
69 int ret; 69 int ret;
70 70
71 if (adev->flags.is_dock_station)
72 return 0;
73
71 cdev = kzalloc(sizeof(*cdev), GFP_KERNEL); 74 cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);
72 if (!cdev) 75 if (!cdev)
73 return -ENOMEM; 76 return -ENOMEM;
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c
index 5bfd769fc91f..a7bd3002dbbc 100644
--- a/drivers/acpi/dock.c
+++ b/drivers/acpi/dock.c
@@ -1,7 +1,9 @@
1/* 1/*
2 * dock.c - ACPI dock station driver 2 * dock.c - ACPI dock station driver
3 * 3 *
4 * Copyright (C) 2006 Kristen Carlson Accardi <kristen.c.accardi@intel.com> 4 * Copyright (C) 2006, 2014, Intel Corp.
5 * Author: Kristen Carlson Accardi <kristen.c.accardi@intel.com>
6 * Rafael J. Wysocki <rafael.j.wysocki@intel.com>
5 * 7 *
6 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 8 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
7 * 9 *
@@ -68,15 +70,10 @@ struct dock_station {
68}; 70};
69static LIST_HEAD(dock_stations); 71static LIST_HEAD(dock_stations);
70static int dock_station_count; 72static int dock_station_count;
71static DEFINE_MUTEX(hotplug_lock);
72 73
73struct dock_dependent_device { 74struct dock_dependent_device {
74 struct list_head list; 75 struct list_head list;
75 acpi_handle handle; 76 struct acpi_device *adev;
76 const struct acpi_dock_ops *hp_ops;
77 void *hp_context;
78 unsigned int hp_refcount;
79 void (*hp_release)(void *);
80}; 77};
81 78
82#define DOCK_DOCKING 0x00000001 79#define DOCK_DOCKING 0x00000001
@@ -98,13 +95,13 @@ enum dock_callback_type {
98 *****************************************************************************/ 95 *****************************************************************************/
99/** 96/**
100 * add_dock_dependent_device - associate a device with the dock station 97 * add_dock_dependent_device - associate a device with the dock station
101 * @ds: The dock station 98 * @ds: Dock station.
102 * @handle: handle of the dependent device 99 * @adev: Dependent ACPI device object.
103 * 100 *
104 * Add the dependent device to the dock's dependent device list. 101 * Add the dependent device to the dock's dependent device list.
105 */ 102 */
106static int __init 103static int add_dock_dependent_device(struct dock_station *ds,
107add_dock_dependent_device(struct dock_station *ds, acpi_handle handle) 104 struct acpi_device *adev)
108{ 105{
109 struct dock_dependent_device *dd; 106 struct dock_dependent_device *dd;
110 107
@@ -112,180 +109,120 @@ add_dock_dependent_device(struct dock_station *ds, acpi_handle handle)
112 if (!dd) 109 if (!dd)
113 return -ENOMEM; 110 return -ENOMEM;
114 111
115 dd->handle = handle; 112 dd->adev = adev;
116 INIT_LIST_HEAD(&dd->list); 113 INIT_LIST_HEAD(&dd->list);
117 list_add_tail(&dd->list, &ds->dependent_devices); 114 list_add_tail(&dd->list, &ds->dependent_devices);
118 115
119 return 0; 116 return 0;
120} 117}
121 118
122static void remove_dock_dependent_devices(struct dock_station *ds) 119static void dock_hotplug_event(struct dock_dependent_device *dd, u32 event,
120 enum dock_callback_type cb_type)
123{ 121{
124 struct dock_dependent_device *dd, *aux; 122 struct acpi_device *adev = dd->adev;
125 123
126 list_for_each_entry_safe(dd, aux, &ds->dependent_devices, list) { 124 acpi_lock_hp_context();
127 list_del(&dd->list);
128 kfree(dd);
129 }
130}
131 125
132/** 126 if (!adev->hp)
133 * dock_init_hotplug - Initialize a hotplug device on a docking station. 127 goto out;
134 * @dd: Dock-dependent device.
135 * @ops: Dock operations to attach to the dependent device.
136 * @context: Data to pass to the @ops callbacks and @release.
137 * @init: Optional initialization routine to run after setting up context.
138 * @release: Optional release routine to run on removal.
139 */
140static int dock_init_hotplug(struct dock_dependent_device *dd,
141 const struct acpi_dock_ops *ops, void *context,
142 void (*init)(void *), void (*release)(void *))
143{
144 int ret = 0;
145 128
146 mutex_lock(&hotplug_lock); 129 if (cb_type == DOCK_CALL_FIXUP) {
147 if (WARN_ON(dd->hp_context)) { 130 void (*fixup)(struct acpi_device *);
148 ret = -EEXIST;
149 } else {
150 dd->hp_refcount = 1;
151 dd->hp_ops = ops;
152 dd->hp_context = context;
153 dd->hp_release = release;
154 if (init)
155 init(context);
156 }
157 mutex_unlock(&hotplug_lock);
158 return ret;
159}
160 131
161/** 132 fixup = adev->hp->fixup;
162 * dock_release_hotplug - Decrement hotplug reference counter of dock device. 133 if (fixup) {
163 * @dd: Dock-dependent device. 134 acpi_unlock_hp_context();
164 * 135 fixup(adev);
165 * Decrement the reference counter of @dd and if 0, detach its hotplug 136 return;
166 * operations from it, reset its context pointer and run the optional release 137 }
167 * routine if present. 138 } else if (cb_type == DOCK_CALL_UEVENT) {
168 */ 139 void (*uevent)(struct acpi_device *, u32);
169static void dock_release_hotplug(struct dock_dependent_device *dd) 140
170{ 141 uevent = adev->hp->uevent;
171 mutex_lock(&hotplug_lock); 142 if (uevent) {
172 if (dd->hp_context && !--dd->hp_refcount) { 143 acpi_unlock_hp_context();
173 void (*release)(void *) = dd->hp_release; 144 uevent(adev, event);
174 void *context = dd->hp_context; 145 return;
175 146 }
176 dd->hp_ops = NULL; 147 } else {
177 dd->hp_context = NULL; 148 int (*notify)(struct acpi_device *, u32);
178 dd->hp_release = NULL;
179 if (release)
180 release(context);
181 }
182 mutex_unlock(&hotplug_lock);
183}
184 149
185static void dock_hotplug_event(struct dock_dependent_device *dd, u32 event, 150 notify = adev->hp->notify;
186 enum dock_callback_type cb_type) 151 if (notify) {
187{ 152 acpi_unlock_hp_context();
188 acpi_notify_handler cb = NULL; 153 notify(adev, event);
189 bool run = false;