diff options
-rw-r--r-- | drivers/acpi/dock.c | 167 | ||||
-rw-r--r-- | include/acpi/acpi_drivers.h | 22 |
2 files changed, 2 insertions, 187 deletions
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index a88fad9ff234..f6fd325078b3 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c | |||
@@ -68,15 +68,10 @@ struct dock_station { | |||
68 | }; | 68 | }; |
69 | static LIST_HEAD(dock_stations); | 69 | static LIST_HEAD(dock_stations); |
70 | static int dock_station_count; | 70 | static int dock_station_count; |
71 | static DEFINE_MUTEX(hotplug_lock); | ||
72 | 71 | ||
73 | struct dock_dependent_device { | 72 | struct dock_dependent_device { |
74 | struct list_head list; | 73 | struct list_head list; |
75 | struct acpi_device *adev; | 74 | 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 | }; | 75 | }; |
81 | 76 | ||
82 | #define DOCK_DOCKING 0x00000001 | 77 | #define DOCK_DOCKING 0x00000001 |
@@ -129,70 +124,15 @@ static void remove_dock_dependent_devices(struct dock_station *ds) | |||
129 | } | 124 | } |
130 | } | 125 | } |
131 | 126 | ||
132 | /** | ||
133 | * dock_init_hotplug - Initialize a hotplug device on a docking station. | ||
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 | */ | ||
140 | static 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 | |||
146 | mutex_lock(&hotplug_lock); | ||
147 | if (WARN_ON(dd->hp_context)) { | ||
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 | |||
161 | /** | ||
162 | * dock_release_hotplug - Decrement hotplug reference counter of dock device. | ||
163 | * @dd: Dock-dependent device. | ||
164 | * | ||
165 | * Decrement the reference counter of @dd and if 0, detach its hotplug | ||
166 | * operations from it, reset its context pointer and run the optional release | ||
167 | * routine if present. | ||
168 | */ | ||
169 | static void dock_release_hotplug(struct dock_dependent_device *dd) | ||
170 | { | ||
171 | mutex_lock(&hotplug_lock); | ||
172 | if (dd->hp_context && !--dd->hp_refcount) { | ||
173 | void (*release)(void *) = dd->hp_release; | ||
174 | void *context = dd->hp_context; | ||
175 | |||
176 | dd->hp_ops = NULL; | ||
177 | dd->hp_context = NULL; | ||
178 | dd->hp_release = NULL; | ||
179 | if (release) | ||
180 | release(context); | ||
181 | } | ||
182 | mutex_unlock(&hotplug_lock); | ||
183 | } | ||
184 | |||
185 | static void dock_hotplug_event(struct dock_dependent_device *dd, u32 event, | 127 | static void dock_hotplug_event(struct dock_dependent_device *dd, u32 event, |
186 | enum dock_callback_type cb_type) | 128 | enum dock_callback_type cb_type) |
187 | { | 129 | { |
188 | struct acpi_device *adev = dd->adev; | 130 | struct acpi_device *adev = dd->adev; |
189 | acpi_notify_handler cb = NULL; | ||
190 | bool run = false; | ||
191 | 131 | ||
192 | acpi_lock_hp_context(); | 132 | acpi_lock_hp_context(); |
193 | 133 | ||
194 | if (!adev->hp) | 134 | if (!adev->hp) |
195 | goto no_context; | 135 | goto out; |
196 | 136 | ||
197 | if (cb_type == DOCK_CALL_FIXUP) { | 137 | if (cb_type == DOCK_CALL_FIXUP) { |
198 | void (*fixup)(struct acpi_device *); | 138 | void (*fixup)(struct acpi_device *); |
@@ -223,37 +163,8 @@ static void dock_hotplug_event(struct dock_dependent_device *dd, u32 event, | |||
223 | } | 163 | } |
224 | } | 164 | } |
225 | 165 | ||
226 | no_context: | 166 | out: |
227 | acpi_unlock_hp_context(); | 167 | acpi_unlock_hp_context(); |
228 | |||
229 | mutex_lock(&hotplug_lock); | ||
230 | |||
231 | if (dd->hp_context) { | ||
232 | run = true; | ||
233 | dd->hp_refcount++; | ||
234 | if (dd->hp_ops) { | ||
235 | switch (cb_type) { | ||
236 | case DOCK_CALL_FIXUP: | ||
237 | cb = dd->hp_ops->fixup; | ||
238 | break; | ||
239 | case DOCK_CALL_UEVENT: | ||
240 | cb = dd->hp_ops->uevent; | ||
241 | break; | ||
242 | default: | ||
243 | cb = dd->hp_ops->handler; | ||
244 | } | ||
245 | } | ||
246 | } | ||
247 | |||
248 | mutex_unlock(&hotplug_lock); | ||
249 | |||
250 | if (!run) | ||
251 | return; | ||
252 | |||
253 | if (cb) | ||
254 | cb(dd->adev->handle, event, dd->hp_context); | ||
255 | |||
256 | dock_release_hotplug(dd); | ||
257 | } | 168 | } |
258 | 169 | ||
259 | static struct dock_station *find_dock_station(acpi_handle handle) | 170 | static struct dock_station *find_dock_station(acpi_handle handle) |
@@ -506,80 +417,6 @@ static int dock_in_progress(struct dock_station *ds) | |||
506 | } | 417 | } |
507 | 418 | ||
508 | /** | 419 | /** |
509 | * register_hotplug_dock_device - register a hotplug function | ||
510 | * @handle: the handle of the device | ||
511 | * @ops: handlers to call after docking | ||
512 | * @context: device specific data | ||
513 | * @init: Optional initialization routine to run after registration | ||
514 | * @release: Optional release routine to run on unregistration | ||
515 | * | ||
516 | * If a driver would like to perform a hotplug operation after a dock | ||
517 | * event, they can register an acpi_notifiy_handler to be called by | ||
518 | * the dock driver after _DCK is executed. | ||
519 | */ | ||
520 | int register_hotplug_dock_device(acpi_handle handle, | ||
521 | const struct acpi_dock_ops *ops, void *context, | ||
522 | void (*init)(void *), void (*release)(void *)) | ||
523 | { | ||
524 | struct dock_dependent_device *dd; | ||
525 | struct dock_station *dock_station; | ||
526 | struct acpi_device *adev; | ||
527 | int ret = -EINVAL; | ||
528 | |||
529 | if (WARN_ON(!context)) | ||
530 | return -EINVAL; | ||
531 | |||
532 | if (!dock_station_count) | ||
533 | return -ENODEV; | ||
534 | |||
535 | ret = acpi_bus_get_device(handle, &adev); | ||
536 | if (ret) | ||
537 | return ret; | ||
538 | |||
539 | /* | ||
540 | * make sure this handle is for a device dependent on the dock, | ||
541 | * this would include the dock station itself | ||
542 | */ | ||
543 | list_for_each_entry(dock_station, &dock_stations, sibling) { | ||
544 | /* | ||
545 | * An ATA bay can be in a dock and itself can be ejected | ||
546 | * separately, so there are two 'dock stations' which need the | ||
547 | * ops | ||
548 | */ | ||
549 | dd = find_dock_dependent_device(dock_station, adev); | ||
550 | if (dd && !dock_init_hotplug(dd, ops, context, init, release)) | ||
551 | ret = 0; | ||
552 | } | ||
553 | |||
554 | return ret; | ||
555 | } | ||
556 | EXPORT_SYMBOL_GPL(register_hotplug_dock_device); | ||
557 | |||
558 | /** | ||
559 | * unregister_hotplug_dock_device - remove yourself from the hotplug list | ||
560 | * @handle: the acpi handle of the device | ||
561 | */ | ||
562 | void unregister_hotplug_dock_device(acpi_handle handle) | ||
563 | { | ||
564 | struct dock_dependent_device *dd; | ||
565 | struct dock_station *dock_station; | ||
566 | struct acpi_device *adev; | ||
567 | |||
568 | if (!dock_station_count) | ||
569 | return; | ||
570 | |||
571 | if (acpi_bus_get_device(handle, &adev)) | ||
572 | return; | ||
573 | |||
574 | list_for_each_entry(dock_station, &dock_stations, sibling) { | ||
575 | dd = find_dock_dependent_device(dock_station, adev); | ||
576 | if (dd) | ||
577 | dock_release_hotplug(dd); | ||
578 | } | ||
579 | } | ||
580 | EXPORT_SYMBOL_GPL(unregister_hotplug_dock_device); | ||
581 | |||
582 | /** | ||
583 | * handle_eject_request - handle an undock request checking for error conditions | 420 | * handle_eject_request - handle an undock request checking for error conditions |
584 | * | 421 | * |
585 | * Check to make sure the dock device is still present, then undock and | 422 | * Check to make sure the dock device is still present, then undock and |
diff --git a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h index d6c98b9cbe38..d504613bbf80 100644 --- a/include/acpi/acpi_drivers.h +++ b/include/acpi/acpi_drivers.h | |||
@@ -109,36 +109,14 @@ void pci_acpi_crs_quirks(void); | |||
109 | /*-------------------------------------------------------------------------- | 109 | /*-------------------------------------------------------------------------- |
110 | Dock Station | 110 | Dock Station |
111 | -------------------------------------------------------------------------- */ | 111 | -------------------------------------------------------------------------- */ |
112 | struct acpi_dock_ops { | ||
113 | acpi_notify_handler fixup; | ||
114 | acpi_notify_handler handler; | ||
115 | acpi_notify_handler uevent; | ||
116 | }; | ||
117 | 112 | ||
118 | #ifdef CONFIG_ACPI_DOCK | 113 | #ifdef CONFIG_ACPI_DOCK |
119 | extern int is_dock_device(struct acpi_device *adev); | 114 | extern int is_dock_device(struct acpi_device *adev); |
120 | extern int register_hotplug_dock_device(acpi_handle handle, | ||
121 | const struct acpi_dock_ops *ops, | ||
122 | void *context, | ||
123 | void (*init)(void *), | ||
124 | void (*release)(void *)); | ||
125 | extern void unregister_hotplug_dock_device(acpi_handle handle); | ||
126 | #else | 115 | #else |
127 | static inline int is_dock_device(struct acpi_device *adev) | 116 | static inline int is_dock_device(struct acpi_device *adev) |
128 | { | 117 | { |
129 | return 0; | 118 | return 0; |
130 | } | 119 | } |
131 | static inline int register_hotplug_dock_device(acpi_handle handle, | ||
132 | const struct acpi_dock_ops *ops, | ||
133 | void *context, | ||
134 | void (*init)(void *), | ||
135 | void (*release)(void *)) | ||
136 | { | ||
137 | return -ENODEV; | ||
138 | } | ||
139 | static inline void unregister_hotplug_dock_device(acpi_handle handle) | ||
140 | { | ||
141 | } | ||
142 | #endif /* CONFIG_ACPI_DOCK */ | 120 | #endif /* CONFIG_ACPI_DOCK */ |
143 | 121 | ||
144 | #endif /*__ACPI_DRIVERS_H__*/ | 122 | #endif /*__ACPI_DRIVERS_H__*/ |