aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/acpi/dock.c167
-rw-r--r--include/acpi/acpi_drivers.h22
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};
69static LIST_HEAD(dock_stations); 69static LIST_HEAD(dock_stations);
70static int dock_station_count; 70static int dock_station_count;
71static DEFINE_MUTEX(hotplug_lock);
72 71
73struct dock_dependent_device { 72struct 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 */
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
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 */
169static 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
185static void dock_hotplug_event(struct dock_dependent_device *dd, u32 event, 127static 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
259static struct dock_station *find_dock_station(acpi_handle handle) 170static 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 */
520int 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}
556EXPORT_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 */
562void 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}
580EXPORT_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 -------------------------------------------------------------------------- */
112struct 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
119extern int is_dock_device(struct acpi_device *adev); 114extern int is_dock_device(struct acpi_device *adev);
120extern 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 *));
125extern void unregister_hotplug_dock_device(acpi_handle handle);
126#else 115#else
127static inline int is_dock_device(struct acpi_device *adev) 116static inline int is_dock_device(struct acpi_device *adev)
128{ 117{
129 return 0; 118 return 0;
130} 119}
131static 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}
139static 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__*/