xref: /openbmc/linux/drivers/acpi/dock.c (revision 643d1f7f)
1 /*
2  *  dock.c - ACPI dock station driver
3  *
4  *  Copyright (C) 2006 Kristen Carlson Accardi <kristen.c.accardi@intel.com>
5  *
6  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or (at
11  *  your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful, but
14  *  WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  *  General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License along
19  *  with this program; if not, write to the Free Software Foundation, Inc.,
20  *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
21  *
22  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
23  */
24 
25 #include <linux/kernel.h>
26 #include <linux/module.h>
27 #include <linux/init.h>
28 #include <linux/types.h>
29 #include <linux/notifier.h>
30 #include <linux/platform_device.h>
31 #include <linux/jiffies.h>
32 #include <linux/stddef.h>
33 #include <acpi/acpi_bus.h>
34 #include <acpi/acpi_drivers.h>
35 
36 #define ACPI_DOCK_DRIVER_DESCRIPTION "ACPI Dock Station Driver"
37 
38 ACPI_MODULE_NAME("dock");
39 MODULE_AUTHOR("Kristen Carlson Accardi");
40 MODULE_DESCRIPTION(ACPI_DOCK_DRIVER_DESCRIPTION);
41 MODULE_LICENSE("GPL");
42 
43 static int immediate_undock = 1;
44 module_param(immediate_undock, bool, 0644);
45 MODULE_PARM_DESC(immediate_undock, "1 (default) will cause the driver to "
46 	"undock immediately when the undock button is pressed, 0 will cause"
47 	" the driver to wait for userspace to write the undock sysfs file "
48 	" before undocking");
49 
50 static struct atomic_notifier_head dock_notifier_list;
51 static struct platform_device *dock_device;
52 static char dock_device_name[] = "dock";
53 
54 struct dock_station {
55 	acpi_handle handle;
56 	unsigned long last_dock_time;
57 	u32 flags;
58 	spinlock_t dd_lock;
59 	struct mutex hp_lock;
60 	struct list_head dependent_devices;
61 	struct list_head hotplug_devices;
62 };
63 
64 struct dock_dependent_device {
65 	struct list_head list;
66 	struct list_head hotplug_list;
67 	acpi_handle handle;
68 	acpi_notify_handler handler;
69 	void *context;
70 };
71 
72 #define DOCK_DOCKING	0x00000001
73 #define DOCK_UNDOCKING  0x00000002
74 #define DOCK_EVENT	3
75 #define UNDOCK_EVENT	2
76 
77 static struct dock_station *dock_station;
78 
79 /*****************************************************************************
80  *                         Dock Dependent device functions                   *
81  *****************************************************************************/
82 /**
83  *  alloc_dock_dependent_device - allocate and init a dependent device
84  *  @handle: the acpi_handle of the dependent device
85  *
86  *  Allocate memory for a dependent device structure for a device referenced
87  *  by the acpi handle
88  */
89 static struct dock_dependent_device *
90 alloc_dock_dependent_device(acpi_handle handle)
91 {
92 	struct dock_dependent_device *dd;
93 
94 	dd = kzalloc(sizeof(*dd), GFP_KERNEL);
95 	if (dd) {
96 		dd->handle = handle;
97 		INIT_LIST_HEAD(&dd->list);
98 		INIT_LIST_HEAD(&dd->hotplug_list);
99 	}
100 	return dd;
101 }
102 
103 /**
104  * add_dock_dependent_device - associate a device with the dock station
105  * @ds: The dock station
106  * @dd: The dependent device
107  *
108  * Add the dependent device to the dock's dependent device list.
109  */
110 static void
111 add_dock_dependent_device(struct dock_station *ds,
112 			  struct dock_dependent_device *dd)
113 {
114 	spin_lock(&ds->dd_lock);
115 	list_add_tail(&dd->list, &ds->dependent_devices);
116 	spin_unlock(&ds->dd_lock);
117 }
118 
119 /**
120  * dock_add_hotplug_device - associate a hotplug handler with the dock station
121  * @ds: The dock station
122  * @dd: The dependent device struct
123  *
124  * Add the dependent device to the dock's hotplug device list
125  */
126 static void
127 dock_add_hotplug_device(struct dock_station *ds,
128 			struct dock_dependent_device *dd)
129 {
130 	mutex_lock(&ds->hp_lock);
131 	list_add_tail(&dd->hotplug_list, &ds->hotplug_devices);
132 	mutex_unlock(&ds->hp_lock);
133 }
134 
135 /**
136  * dock_del_hotplug_device - remove a hotplug handler from the dock station
137  * @ds: The dock station
138  * @dd: the dependent device struct
139  *
140  * Delete the dependent device from the dock's hotplug device list
141  */
142 static void
143 dock_del_hotplug_device(struct dock_station *ds,
144 			struct dock_dependent_device *dd)
145 {
146 	mutex_lock(&ds->hp_lock);
147 	list_del(&dd->hotplug_list);
148 	mutex_unlock(&ds->hp_lock);
149 }
150 
151 /**
152  * find_dock_dependent_device - get a device dependent on this dock
153  * @ds: the dock station
154  * @handle: the acpi_handle of the device we want
155  *
156  * iterate over the dependent device list for this dock.  If the
157  * dependent device matches the handle, return.
158  */
159 static struct dock_dependent_device *
160 find_dock_dependent_device(struct dock_station *ds, acpi_handle handle)
161 {
162 	struct dock_dependent_device *dd;
163 
164 	spin_lock(&ds->dd_lock);
165 	list_for_each_entry(dd, &ds->dependent_devices, list) {
166 		if (handle == dd->handle) {
167 			spin_unlock(&ds->dd_lock);
168 			return dd;
169 		}
170 	}
171 	spin_unlock(&ds->dd_lock);
172 	return NULL;
173 }
174 
175 /*****************************************************************************
176  *                         Dock functions                                    *
177  *****************************************************************************/
178 /**
179  * is_dock - see if a device is a dock station
180  * @handle: acpi handle of the device
181  *
182  * If an acpi object has a _DCK method, then it is by definition a dock
183  * station, so return true.
184  */
185 static int is_dock(acpi_handle handle)
186 {
187 	acpi_status status;
188 	acpi_handle tmp;
189 
190 	status = acpi_get_handle(handle, "_DCK", &tmp);
191 	if (ACPI_FAILURE(status))
192 		return 0;
193 	return 1;
194 }
195 
196 /**
197  * is_dock_device - see if a device is on a dock station
198  * @handle: acpi handle of the device
199  *
200  * If this device is either the dock station itself,
201  * or is a device dependent on the dock station, then it
202  * is a dock device
203  */
204 int is_dock_device(acpi_handle handle)
205 {
206 	if (!dock_station)
207 		return 0;
208 
209 	if (is_dock(handle) || find_dock_dependent_device(dock_station, handle))
210 		return 1;
211 
212 	return 0;
213 }
214 
215 EXPORT_SYMBOL_GPL(is_dock_device);
216 
217 /**
218  * dock_present - see if the dock station is present.
219  * @ds: the dock station
220  *
221  * execute the _STA method.  note that present does not
222  * imply that we are docked.
223  */
224 static int dock_present(struct dock_station *ds)
225 {
226 	unsigned long sta;
227 	acpi_status status;
228 
229 	if (ds) {
230 		status = acpi_evaluate_integer(ds->handle, "_STA", NULL, &sta);
231 		if (ACPI_SUCCESS(status) && sta)
232 			return 1;
233 	}
234 	return 0;
235 }
236 
237 
238 
239 /**
240  * dock_create_acpi_device - add new devices to acpi
241  * @handle - handle of the device to add
242  *
243  *  This function will create a new acpi_device for the given
244  *  handle if one does not exist already.  This should cause
245  *  acpi to scan for drivers for the given devices, and call
246  *  matching driver's add routine.
247  *
248  *  Returns a pointer to the acpi_device corresponding to the handle.
249  */
250 static struct acpi_device * dock_create_acpi_device(acpi_handle handle)
251 {
252 	struct acpi_device *device = NULL;
253 	struct acpi_device *parent_device;
254 	acpi_handle parent;
255 	int ret;
256 
257 	if (acpi_bus_get_device(handle, &device)) {
258 		/*
259 		 * no device created for this object,
260 		 * so we should create one.
261 		 */
262 		acpi_get_parent(handle, &parent);
263 		if (acpi_bus_get_device(parent, &parent_device))
264 			parent_device = NULL;
265 
266 		ret = acpi_bus_add(&device, parent_device, handle,
267 			ACPI_BUS_TYPE_DEVICE);
268 		if (ret) {
269 			pr_debug("error adding bus, %x\n",
270 				-ret);
271 			return NULL;
272 		}
273 	}
274 	return device;
275 }
276 
277 /**
278  * dock_remove_acpi_device - remove the acpi_device struct from acpi
279  * @handle - the handle of the device to remove
280  *
281  *  Tell acpi to remove the acpi_device.  This should cause any loaded
282  *  driver to have it's remove routine called.
283  */
284 static void dock_remove_acpi_device(acpi_handle handle)
285 {
286 	struct acpi_device *device;
287 	int ret;
288 
289 	if (!acpi_bus_get_device(handle, &device)) {
290 		ret = acpi_bus_trim(device, 1);
291 		if (ret)
292 			pr_debug("error removing bus, %x\n", -ret);
293 	}
294 }
295 
296 
297 /**
298  * hotplug_dock_devices - insert or remove devices on the dock station
299  * @ds: the dock station
300  * @event: either bus check or eject request
301  *
302  * Some devices on the dock station need to have drivers called
303  * to perform hotplug operations after a dock event has occurred.
304  * Traverse the list of dock devices that have registered a
305  * hotplug handler, and call the handler.
306  */
307 static void hotplug_dock_devices(struct dock_station *ds, u32 event)
308 {
309 	struct dock_dependent_device *dd;
310 
311 	mutex_lock(&ds->hp_lock);
312 
313 	/*
314 	 * First call driver specific hotplug functions
315 	 */
316 	list_for_each_entry(dd, &ds->hotplug_devices, hotplug_list) {
317 		if (dd->handler)
318 			dd->handler(dd->handle, event, dd->context);
319 	}
320 
321 	/*
322 	 * Now make sure that an acpi_device is created for each
323 	 * dependent device, or removed if this is an eject request.
324 	 * This will cause acpi_drivers to be stopped/started if they
325 	 * exist
326 	 */
327 	list_for_each_entry(dd, &ds->dependent_devices, list) {
328 		if (event == ACPI_NOTIFY_EJECT_REQUEST)
329 			dock_remove_acpi_device(dd->handle);
330 		else
331 			dock_create_acpi_device(dd->handle);
332 	}
333 	mutex_unlock(&ds->hp_lock);
334 }
335 
336 static void dock_event(struct dock_station *ds, u32 event, int num)
337 {
338 	struct device *dev = &dock_device->dev;
339 	char event_string[13];
340 	char *envp[] = { event_string, NULL };
341 
342 	if (num == UNDOCK_EVENT)
343 		sprintf(event_string, "EVENT=undock");
344 	else
345 		sprintf(event_string, "EVENT=dock");
346 
347 	/*
348 	 * Indicate that the status of the dock station has
349 	 * changed.
350 	 */
351 	kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
352 }
353 
354 /**
355  * eject_dock - respond to a dock eject request
356  * @ds: the dock station
357  *
358  * This is called after _DCK is called, to execute the dock station's
359  * _EJ0 method.
360  */
361 static void eject_dock(struct dock_station *ds)
362 {
363 	struct acpi_object_list arg_list;
364 	union acpi_object arg;
365 	acpi_status status;
366 	acpi_handle tmp;
367 
368 	/* all dock devices should have _EJ0, but check anyway */
369 	status = acpi_get_handle(ds->handle, "_EJ0", &tmp);
370 	if (ACPI_FAILURE(status)) {
371 		pr_debug("No _EJ0 support for dock device\n");
372 		return;
373 	}
374 
375 	arg_list.count = 1;
376 	arg_list.pointer = &arg;
377 	arg.type = ACPI_TYPE_INTEGER;
378 	arg.integer.value = 1;
379 
380 	if (ACPI_FAILURE(acpi_evaluate_object(ds->handle, "_EJ0",
381 					      &arg_list, NULL)))
382 		pr_debug("Failed to evaluate _EJ0!\n");
383 }
384 
385 /**
386  * handle_dock - handle a dock event
387  * @ds: the dock station
388  * @dock: to dock, or undock - that is the question
389  *
390  * Execute the _DCK method in response to an acpi event
391  */
392 static void handle_dock(struct dock_station *ds, int dock)
393 {
394 	acpi_status status;
395 	struct acpi_object_list arg_list;
396 	union acpi_object arg;
397 	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
398 	struct acpi_buffer name_buffer = { ACPI_ALLOCATE_BUFFER, NULL };
399 
400 	acpi_get_name(ds->handle, ACPI_FULL_PATHNAME, &name_buffer);
401 
402 	printk(KERN_INFO PREFIX "%s - %s\n",
403 		(char *)name_buffer.pointer, dock ? "docking" : "undocking");
404 
405 	/* _DCK method has one argument */
406 	arg_list.count = 1;
407 	arg_list.pointer = &arg;
408 	arg.type = ACPI_TYPE_INTEGER;
409 	arg.integer.value = dock;
410 	status = acpi_evaluate_object(ds->handle, "_DCK", &arg_list, &buffer);
411 	if (ACPI_FAILURE(status))
412 		printk(KERN_ERR PREFIX "%s - failed to execute _DCK\n",
413 			 (char *)name_buffer.pointer);
414 	kfree(buffer.pointer);
415 	kfree(name_buffer.pointer);
416 }
417 
418 static inline void dock(struct dock_station *ds)
419 {
420 	handle_dock(ds, 1);
421 }
422 
423 static inline void undock(struct dock_station *ds)
424 {
425 	handle_dock(ds, 0);
426 }
427 
428 static inline void begin_dock(struct dock_station *ds)
429 {
430 	ds->flags |= DOCK_DOCKING;
431 }
432 
433 static inline void complete_dock(struct dock_station *ds)
434 {
435 	ds->flags &= ~(DOCK_DOCKING);
436 	ds->last_dock_time = jiffies;
437 }
438 
439 static inline void begin_undock(struct dock_station *ds)
440 {
441 	ds->flags |= DOCK_UNDOCKING;
442 }
443 
444 static inline void complete_undock(struct dock_station *ds)
445 {
446 	ds->flags &= ~(DOCK_UNDOCKING);
447 }
448 
449 /**
450  * dock_in_progress - see if we are in the middle of handling a dock event
451  * @ds: the dock station
452  *
453  * Sometimes while docking, false dock events can be sent to the driver
454  * because good connections aren't made or some other reason.  Ignore these
455  * if we are in the middle of doing something.
456  */
457 static int dock_in_progress(struct dock_station *ds)
458 {
459 	if ((ds->flags & DOCK_DOCKING) ||
460 	    time_before(jiffies, (ds->last_dock_time + HZ)))
461 		return 1;
462 	return 0;
463 }
464 
465 /**
466  * register_dock_notifier - add yourself to the dock notifier list
467  * @nb: the callers notifier block
468  *
469  * If a driver wishes to be notified about dock events, they can
470  * use this function to put a notifier block on the dock notifier list.
471  * this notifier call chain will be called after a dock event, but
472  * before hotplugging any new devices.
473  */
474 int register_dock_notifier(struct notifier_block *nb)
475 {
476 	if (!dock_station)
477 		return -ENODEV;
478 
479 	return atomic_notifier_chain_register(&dock_notifier_list, nb);
480 }
481 
482 EXPORT_SYMBOL_GPL(register_dock_notifier);
483 
484 /**
485  * unregister_dock_notifier - remove yourself from the dock notifier list
486  * @nb: the callers notifier block
487  */
488 void unregister_dock_notifier(struct notifier_block *nb)
489 {
490 	if (!dock_station)
491 		return;
492 
493 	atomic_notifier_chain_unregister(&dock_notifier_list, nb);
494 }
495 
496 EXPORT_SYMBOL_GPL(unregister_dock_notifier);
497 
498 /**
499  * register_hotplug_dock_device - register a hotplug function
500  * @handle: the handle of the device
501  * @handler: the acpi_notifier_handler to call after docking
502  * @context: device specific data
503  *
504  * If a driver would like to perform a hotplug operation after a dock
505  * event, they can register an acpi_notifiy_handler to be called by
506  * the dock driver after _DCK is executed.
507  */
508 int
509 register_hotplug_dock_device(acpi_handle handle, acpi_notify_handler handler,
510 			     void *context)
511 {
512 	struct dock_dependent_device *dd;
513 
514 	if (!dock_station)
515 		return -ENODEV;
516 
517 	/*
518 	 * make sure this handle is for a device dependent on the dock,
519 	 * this would include the dock station itself
520 	 */
521 	dd = find_dock_dependent_device(dock_station, handle);
522 	if (dd) {
523 		dd->handler = handler;
524 		dd->context = context;
525 		dock_add_hotplug_device(dock_station, dd);
526 		return 0;
527 	}
528 
529 	return -EINVAL;
530 }
531 
532 EXPORT_SYMBOL_GPL(register_hotplug_dock_device);
533 
534 /**
535  * unregister_hotplug_dock_device - remove yourself from the hotplug list
536  * @handle: the acpi handle of the device
537  */
538 void unregister_hotplug_dock_device(acpi_handle handle)
539 {
540 	struct dock_dependent_device *dd;
541 
542 	if (!dock_station)
543 		return;
544 
545 	dd = find_dock_dependent_device(dock_station, handle);
546 	if (dd)
547 		dock_del_hotplug_device(dock_station, dd);
548 }
549 
550 EXPORT_SYMBOL_GPL(unregister_hotplug_dock_device);
551 
552 /**
553  * handle_eject_request - handle an undock request checking for error conditions
554  *
555  * Check to make sure the dock device is still present, then undock and
556  * hotremove all the devices that may need removing.
557  */
558 static int handle_eject_request(struct dock_station *ds, u32 event)
559 {
560 	if (!dock_present(ds))
561 		return -ENODEV;
562 
563 	if (dock_in_progress(ds))
564 		return -EBUSY;
565 
566 	/*
567 	 * here we need to generate the undock
568 	 * event prior to actually doing the undock
569 	 * so that the device struct still exists.
570 	 */
571 	dock_event(ds, event, UNDOCK_EVENT);
572 	hotplug_dock_devices(ds, ACPI_NOTIFY_EJECT_REQUEST);
573 	undock(ds);
574 	eject_dock(ds);
575 	if (dock_present(ds)) {
576 		printk(KERN_ERR PREFIX "Unable to undock!\n");
577 		return -EBUSY;
578 	}
579 	complete_undock(ds);
580 	return 0;
581 }
582 
583 /**
584  * dock_notify - act upon an acpi dock notification
585  * @handle: the dock station handle
586  * @event: the acpi event
587  * @data: our driver data struct
588  *
589  * If we are notified to dock, then check to see if the dock is
590  * present and then dock.  Notify all drivers of the dock event,
591  * and then hotplug and devices that may need hotplugging.
592  */
593 static void dock_notify(acpi_handle handle, u32 event, void *data)
594 {
595 	struct dock_station *ds = data;
596 
597 	switch (event) {
598 	case ACPI_NOTIFY_BUS_CHECK:
599 		if (!dock_in_progress(ds) && dock_present(ds)) {
600 			begin_dock(ds);
601 			dock(ds);
602 			if (!dock_present(ds)) {
603 				printk(KERN_ERR PREFIX "Unable to dock!\n");
604 				break;
605 			}
606 			atomic_notifier_call_chain(&dock_notifier_list,
607 						   event, NULL);
608 			hotplug_dock_devices(ds, event);
609 			complete_dock(ds);
610 			dock_event(ds, event, DOCK_EVENT);
611 		}
612 		break;
613 	case ACPI_NOTIFY_DEVICE_CHECK:
614 	/*
615          * According to acpi spec 3.0a, if a DEVICE_CHECK notification
616          * is sent and _DCK is present, it is assumed to mean an
617          * undock request.  This notify routine will only be called
618          * for objects defining _DCK, so we will fall through to eject
619          * request here.  However, we will pass an eject request through
620 	 * to the driver who wish to hotplug.
621          */
622 	case ACPI_NOTIFY_EJECT_REQUEST:
623 		begin_undock(ds);
624 		if (immediate_undock)
625 			handle_eject_request(ds, event);
626 		else
627 			dock_event(ds, event, UNDOCK_EVENT);
628 		break;
629 	default:
630 		printk(KERN_ERR PREFIX "Unknown dock event %d\n", event);
631 	}
632 }
633 
634 /**
635  * find_dock_devices - find devices on the dock station
636  * @handle: the handle of the device we are examining
637  * @lvl: unused
638  * @context: the dock station private data
639  * @rv: unused
640  *
641  * This function is called by acpi_walk_namespace.  It will
642  * check to see if an object has an _EJD method.  If it does, then it
643  * will see if it is dependent on the dock station.
644  */
645 static acpi_status
646 find_dock_devices(acpi_handle handle, u32 lvl, void *context, void **rv)
647 {
648 	acpi_status status;
649 	acpi_handle tmp, parent;
650 	struct dock_station *ds = context;
651 	struct dock_dependent_device *dd;
652 
653 	status = acpi_bus_get_ejd(handle, &tmp);
654 	if (ACPI_FAILURE(status)) {
655 		/* try the parent device as well */
656 		status = acpi_get_parent(handle, &parent);
657 		if (ACPI_FAILURE(status))
658 			goto fdd_out;
659 		/* see if parent is dependent on dock */
660 		status = acpi_bus_get_ejd(parent, &tmp);
661 		if (ACPI_FAILURE(status))
662 			goto fdd_out;
663 	}
664 
665 	if (tmp == ds->handle) {
666 		dd = alloc_dock_dependent_device(handle);
667 		if (dd)
668 			add_dock_dependent_device(ds, dd);
669 	}
670 fdd_out:
671 	return AE_OK;
672 }
673 
674 /*
675  * show_docked - read method for "docked" file in sysfs
676  */
677 static ssize_t show_docked(struct device *dev,
678 			   struct device_attribute *attr, char *buf)
679 {
680 	return snprintf(buf, PAGE_SIZE, "%d\n", dock_present(dock_station));
681 
682 }
683 DEVICE_ATTR(docked, S_IRUGO, show_docked, NULL);
684 
685 /*
686  * show_flags - read method for flags file in sysfs
687  */
688 static ssize_t show_flags(struct device *dev,
689 			  struct device_attribute *attr, char *buf)
690 {
691 	return snprintf(buf, PAGE_SIZE, "%d\n", dock_station->flags);
692 
693 }
694 DEVICE_ATTR(flags, S_IRUGO, show_flags, NULL);
695 
696 /*
697  * write_undock - write method for "undock" file in sysfs
698  */
699 static ssize_t write_undock(struct device *dev, struct device_attribute *attr,
700 			   const char *buf, size_t count)
701 {
702 	int ret;
703 
704 	if (!count)
705 		return -EINVAL;
706 
707 	ret = handle_eject_request(dock_station, ACPI_NOTIFY_EJECT_REQUEST);
708 	return ret ? ret: count;
709 }
710 DEVICE_ATTR(undock, S_IWUSR, NULL, write_undock);
711 
712 /*
713  * show_dock_uid - read method for "uid" file in sysfs
714  */
715 static ssize_t show_dock_uid(struct device *dev,
716 			     struct device_attribute *attr, char *buf)
717 {
718 	unsigned long lbuf;
719 	acpi_status status = acpi_evaluate_integer(dock_station->handle,
720 					"_UID", NULL, &lbuf);
721 	if (ACPI_FAILURE(status))
722 	    return 0;
723 
724 	return snprintf(buf, PAGE_SIZE, "%lx\n", lbuf);
725 }
726 DEVICE_ATTR(uid, S_IRUGO, show_dock_uid, NULL);
727 
728 /**
729  * dock_add - add a new dock station
730  * @handle: the dock station handle
731  *
732  * allocated and initialize a new dock station device.  Find all devices
733  * that are on the dock station, and register for dock event notifications.
734  */
735 static int dock_add(acpi_handle handle)
736 {
737 	int ret;
738 	acpi_status status;
739 	struct dock_dependent_device *dd;
740 
741 	/* allocate & initialize the dock_station private data */
742 	dock_station = kzalloc(sizeof(*dock_station), GFP_KERNEL);
743 	if (!dock_station)
744 		return -ENOMEM;
745 	dock_station->handle = handle;
746 	dock_station->last_dock_time = jiffies - HZ;
747 	INIT_LIST_HEAD(&dock_station->dependent_devices);
748 	INIT_LIST_HEAD(&dock_station->hotplug_devices);
749 	spin_lock_init(&dock_station->dd_lock);
750 	mutex_init(&dock_station->hp_lock);
751 	ATOMIC_INIT_NOTIFIER_HEAD(&dock_notifier_list);
752 
753 	/* initialize platform device stuff */
754 	dock_device =
755 		platform_device_register_simple(dock_device_name, 0, NULL, 0);
756 	if (IS_ERR(dock_device)) {
757 		kfree(dock_station);
758 		dock_station = NULL;
759 		return PTR_ERR(dock_device);
760 	}
761 
762 	/* we want the dock device to send uevents */
763 	dock_device->dev.uevent_suppress = 0;
764 
765 	ret = device_create_file(&dock_device->dev, &dev_attr_docked);
766 	if (ret) {
767 		printk("Error %d adding sysfs file\n", ret);
768 		platform_device_unregister(dock_device);
769 		kfree(dock_station);
770 		dock_station = NULL;
771 		return ret;
772 	}
773 	ret = device_create_file(&dock_device->dev, &dev_attr_undock);
774 	if (ret) {
775 		printk("Error %d adding sysfs file\n", ret);
776 		device_remove_file(&dock_device->dev, &dev_attr_docked);
777 		platform_device_unregister(dock_device);
778 		kfree(dock_station);
779 		dock_station = NULL;
780 		return ret;
781 	}
782 	ret = device_create_file(&dock_device->dev, &dev_attr_uid);
783 	if (ret) {
784 		printk("Error %d adding sysfs file\n", ret);
785 		device_remove_file(&dock_device->dev, &dev_attr_docked);
786 		device_remove_file(&dock_device->dev, &dev_attr_undock);
787 		platform_device_unregister(dock_device);
788 		kfree(dock_station);
789 		dock_station = NULL;
790 		return ret;
791 	}
792 	ret = device_create_file(&dock_device->dev, &dev_attr_flags);
793 	if (ret) {
794 		printk("Error %d adding sysfs file\n", ret);
795 		device_remove_file(&dock_device->dev, &dev_attr_docked);
796 		device_remove_file(&dock_device->dev, &dev_attr_undock);
797 		device_remove_file(&dock_device->dev, &dev_attr_uid);
798 		platform_device_unregister(dock_device);
799 		kfree(dock_station);
800 		dock_station = NULL;
801 		return ret;
802 	}
803 
804 	/* Find dependent devices */
805 	acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
806 			    ACPI_UINT32_MAX, find_dock_devices, dock_station,
807 			    NULL);
808 
809 	/* add the dock station as a device dependent on itself */
810 	dd = alloc_dock_dependent_device(handle);
811 	if (!dd) {
812 		kfree(dock_station);
813 		dock_station = NULL;
814 		ret = -ENOMEM;
815 		goto dock_add_err_unregister;
816 	}
817 	add_dock_dependent_device(dock_station, dd);
818 
819 	/* register for dock events */
820 	status = acpi_install_notify_handler(dock_station->handle,
821 					     ACPI_SYSTEM_NOTIFY,
822 					     dock_notify, dock_station);
823 
824 	if (ACPI_FAILURE(status)) {
825 		printk(KERN_ERR PREFIX "Error installing notify handler\n");
826 		ret = -ENODEV;
827 		goto dock_add_err;
828 	}
829 
830 	printk(KERN_INFO PREFIX "%s \n", ACPI_DOCK_DRIVER_DESCRIPTION);
831 
832 	return 0;
833 
834 dock_add_err:
835 	kfree(dd);
836 dock_add_err_unregister:
837 	device_remove_file(&dock_device->dev, &dev_attr_docked);
838 	device_remove_file(&dock_device->dev, &dev_attr_undock);
839 	device_remove_file(&dock_device->dev, &dev_attr_uid);
840 	device_remove_file(&dock_device->dev, &dev_attr_flags);
841 	platform_device_unregister(dock_device);
842 	kfree(dock_station);
843 	dock_station = NULL;
844 	return ret;
845 }
846 
847 /**
848  * dock_remove - free up resources related to the dock station
849  */
850 static int dock_remove(void)
851 {
852 	struct dock_dependent_device *dd, *tmp;
853 	acpi_status status;
854 
855 	if (!dock_station)
856 		return 0;
857 
858 	/* remove dependent devices */
859 	list_for_each_entry_safe(dd, tmp, &dock_station->dependent_devices,
860 				 list)
861 	    kfree(dd);
862 
863 	/* remove dock notify handler */
864 	status = acpi_remove_notify_handler(dock_station->handle,
865 					    ACPI_SYSTEM_NOTIFY,
866 					    dock_notify);
867 	if (ACPI_FAILURE(status))
868 		printk(KERN_ERR "Error removing notify handler\n");
869 
870 	/* cleanup sysfs */
871 	device_remove_file(&dock_device->dev, &dev_attr_docked);
872 	device_remove_file(&dock_device->dev, &dev_attr_undock);
873 	device_remove_file(&dock_device->dev, &dev_attr_uid);
874 	device_remove_file(&dock_device->dev, &dev_attr_flags);
875 	platform_device_unregister(dock_device);
876 
877 	/* free dock station memory */
878 	kfree(dock_station);
879 	dock_station = NULL;
880 	return 0;
881 }
882 
883 /**
884  * find_dock - look for a dock station
885  * @handle: acpi handle of a device
886  * @lvl: unused
887  * @context: counter of dock stations found
888  * @rv: unused
889  *
890  * This is called by acpi_walk_namespace to look for dock stations.
891  */
892 static acpi_status
893 find_dock(acpi_handle handle, u32 lvl, void *context, void **rv)
894 {
895 	int *count = context;
896 	acpi_status status = AE_OK;
897 
898 	if (is_dock(handle)) {
899 		if (dock_add(handle) >= 0) {
900 			(*count)++;
901 			status = AE_CTRL_TERMINATE;
902 		}
903 	}
904 	return status;
905 }
906 
907 static int __init dock_init(void)
908 {
909 	int num = 0;
910 
911 	dock_station = NULL;
912 
913 	/* look for a dock station */
914 	acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
915 			    ACPI_UINT32_MAX, find_dock, &num, NULL);
916 
917 	if (!num)
918 		printk(KERN_INFO "No dock devices found.\n");
919 
920 	return 0;
921 }
922 
923 static void __exit dock_exit(void)
924 {
925 	dock_remove();
926 }
927 
928 postcore_initcall(dock_init);
929 module_exit(dock_exit);
930