ACPI: dock: unsuppress uevents
[safe/jmp/linux-2.6] / drivers / acpi / dock.c
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         /*
340          * Indicate that the status of the dock station has
341          * changed.
342          */
343         kobject_uevent(&dev->kobj, KOBJ_CHANGE);
344 }
345
346 /**
347  * eject_dock - respond to a dock eject request
348  * @ds: the dock station
349  *
350  * This is called after _DCK is called, to execute the dock station's
351  * _EJ0 method.
352  */
353 static void eject_dock(struct dock_station *ds)
354 {
355         struct acpi_object_list arg_list;
356         union acpi_object arg;
357         acpi_status status;
358         acpi_handle tmp;
359
360         /* all dock devices should have _EJ0, but check anyway */
361         status = acpi_get_handle(ds->handle, "_EJ0", &tmp);
362         if (ACPI_FAILURE(status)) {
363                 pr_debug("No _EJ0 support for dock device\n");
364                 return;
365         }
366
367         arg_list.count = 1;
368         arg_list.pointer = &arg;
369         arg.type = ACPI_TYPE_INTEGER;
370         arg.integer.value = 1;
371
372         if (ACPI_FAILURE(acpi_evaluate_object(ds->handle, "_EJ0",
373                                               &arg_list, NULL)))
374                 pr_debug("Failed to evaluate _EJ0!\n");
375 }
376
377 /**
378  * handle_dock - handle a dock event
379  * @ds: the dock station
380  * @dock: to dock, or undock - that is the question
381  *
382  * Execute the _DCK method in response to an acpi event
383  */
384 static void handle_dock(struct dock_station *ds, int dock)
385 {
386         acpi_status status;
387         struct acpi_object_list arg_list;
388         union acpi_object arg;
389         struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
390         struct acpi_buffer name_buffer = { ACPI_ALLOCATE_BUFFER, NULL };
391         union acpi_object *obj;
392
393         acpi_get_name(ds->handle, ACPI_FULL_PATHNAME, &name_buffer);
394         obj = name_buffer.pointer;
395
396         printk(KERN_INFO PREFIX "%s\n", dock ? "docking" : "undocking");
397
398         /* _DCK method has one argument */
399         arg_list.count = 1;
400         arg_list.pointer = &arg;
401         arg.type = ACPI_TYPE_INTEGER;
402         arg.integer.value = dock;
403         status = acpi_evaluate_object(ds->handle, "_DCK", &arg_list, &buffer);
404         if (ACPI_FAILURE(status))
405                 pr_debug("%s: failed to execute _DCK\n", obj->string.pointer);
406         kfree(buffer.pointer);
407         kfree(name_buffer.pointer);
408 }
409
410 static inline void dock(struct dock_station *ds)
411 {
412         handle_dock(ds, 1);
413 }
414
415 static inline void undock(struct dock_station *ds)
416 {
417         handle_dock(ds, 0);
418 }
419
420 static inline void begin_dock(struct dock_station *ds)
421 {
422         ds->flags |= DOCK_DOCKING;
423 }
424
425 static inline void complete_dock(struct dock_station *ds)
426 {
427         ds->flags &= ~(DOCK_DOCKING);
428         ds->last_dock_time = jiffies;
429 }
430
431 static inline void begin_undock(struct dock_station *ds)
432 {
433         ds->flags |= DOCK_UNDOCKING;
434 }
435
436 static inline void complete_undock(struct dock_station *ds)
437 {
438         ds->flags &= ~(DOCK_UNDOCKING);
439 }
440
441 /**
442  * dock_in_progress - see if we are in the middle of handling a dock event
443  * @ds: the dock station
444  *
445  * Sometimes while docking, false dock events can be sent to the driver
446  * because good connections aren't made or some other reason.  Ignore these
447  * if we are in the middle of doing something.
448  */
449 static int dock_in_progress(struct dock_station *ds)
450 {
451         if ((ds->flags & DOCK_DOCKING) ||
452             time_before(jiffies, (ds->last_dock_time + HZ)))
453                 return 1;
454         return 0;
455 }
456
457 /**
458  * register_dock_notifier - add yourself to the dock notifier list
459  * @nb: the callers notifier block
460  *
461  * If a driver wishes to be notified about dock events, they can
462  * use this function to put a notifier block on the dock notifier list.
463  * this notifier call chain will be called after a dock event, but
464  * before hotplugging any new devices.
465  */
466 int register_dock_notifier(struct notifier_block *nb)
467 {
468         if (!dock_station)
469                 return -ENODEV;
470
471         return atomic_notifier_chain_register(&dock_notifier_list, nb);
472 }
473
474 EXPORT_SYMBOL_GPL(register_dock_notifier);
475
476 /**
477  * unregister_dock_notifier - remove yourself from the dock notifier list
478  * @nb: the callers notifier block
479  */
480 void unregister_dock_notifier(struct notifier_block *nb)
481 {
482         if (!dock_station)
483                 return;
484
485         atomic_notifier_chain_unregister(&dock_notifier_list, nb);
486 }
487
488 EXPORT_SYMBOL_GPL(unregister_dock_notifier);
489
490 /**
491  * register_hotplug_dock_device - register a hotplug function
492  * @handle: the handle of the device
493  * @handler: the acpi_notifier_handler to call after docking
494  * @context: device specific data
495  *
496  * If a driver would like to perform a hotplug operation after a dock
497  * event, they can register an acpi_notifiy_handler to be called by
498  * the dock driver after _DCK is executed.
499  */
500 int
501 register_hotplug_dock_device(acpi_handle handle, acpi_notify_handler handler,
502                              void *context)
503 {
504         struct dock_dependent_device *dd;
505
506         if (!dock_station)
507                 return -ENODEV;
508
509         /*
510          * make sure this handle is for a device dependent on the dock,
511          * this would include the dock station itself
512          */
513         dd = find_dock_dependent_device(dock_station, handle);
514         if (dd) {
515                 dd->handler = handler;
516                 dd->context = context;
517                 dock_add_hotplug_device(dock_station, dd);
518                 return 0;
519         }
520
521         return -EINVAL;
522 }
523
524 EXPORT_SYMBOL_GPL(register_hotplug_dock_device);
525
526 /**
527  * unregister_hotplug_dock_device - remove yourself from the hotplug list
528  * @handle: the acpi handle of the device
529  */
530 void unregister_hotplug_dock_device(acpi_handle handle)
531 {
532         struct dock_dependent_device *dd;
533
534         if (!dock_station)
535                 return;
536
537         dd = find_dock_dependent_device(dock_station, handle);
538         if (dd)
539                 dock_del_hotplug_device(dock_station, dd);
540 }
541
542 EXPORT_SYMBOL_GPL(unregister_hotplug_dock_device);
543
544 /**
545  * handle_eject_request - handle an undock request checking for error conditions
546  *
547  * Check to make sure the dock device is still present, then undock and
548  * hotremove all the devices that may need removing.
549  */
550 static int handle_eject_request(struct dock_station *ds, u32 event)
551 {
552         if (!dock_present(ds))
553                 return -ENODEV;
554
555         if (dock_in_progress(ds))
556                 return -EBUSY;
557
558         /*
559          * here we need to generate the undock
560          * event prior to actually doing the undock
561          * so that the device struct still exists.
562          */
563         dock_event(ds, event, UNDOCK_EVENT);
564         hotplug_dock_devices(ds, ACPI_NOTIFY_EJECT_REQUEST);
565         undock(ds);
566         eject_dock(ds);
567         if (dock_present(ds)) {
568                 printk(KERN_ERR PREFIX "Unable to undock!\n");
569                 return -EBUSY;
570         }
571         complete_undock(ds);
572         return 0;
573 }
574
575 /**
576  * dock_notify - act upon an acpi dock notification
577  * @handle: the dock station handle
578  * @event: the acpi event
579  * @data: our driver data struct
580  *
581  * If we are notified to dock, then check to see if the dock is
582  * present and then dock.  Notify all drivers of the dock event,
583  * and then hotplug and devices that may need hotplugging.
584  */
585 static void dock_notify(acpi_handle handle, u32 event, void *data)
586 {
587         struct dock_station *ds = data;
588
589         switch (event) {
590         case ACPI_NOTIFY_BUS_CHECK:
591                 if (!dock_in_progress(ds) && dock_present(ds)) {
592                         begin_dock(ds);
593                         dock(ds);
594                         if (!dock_present(ds)) {
595                                 printk(KERN_ERR PREFIX "Unable to dock!\n");
596                                 break;
597                         }
598                         atomic_notifier_call_chain(&dock_notifier_list,
599                                                    event, NULL);
600                         hotplug_dock_devices(ds, event);
601                         complete_dock(ds);
602                         dock_event(ds, event, DOCK_EVENT);
603                 }
604                 break;
605         case ACPI_NOTIFY_DEVICE_CHECK:
606         /*
607          * According to acpi spec 3.0a, if a DEVICE_CHECK notification
608          * is sent and _DCK is present, it is assumed to mean an
609          * undock request.  This notify routine will only be called
610          * for objects defining _DCK, so we will fall through to eject
611          * request here.  However, we will pass an eject request through
612          * to the driver who wish to hotplug.
613          */
614         case ACPI_NOTIFY_EJECT_REQUEST:
615                 begin_undock(ds);
616                 if (immediate_undock)
617                         handle_eject_request(ds, event);
618                 else
619                         dock_event(ds, event, UNDOCK_EVENT);
620                 break;
621         default:
622                 printk(KERN_ERR PREFIX "Unknown dock event %d\n", event);
623         }
624 }
625
626 /**
627  * find_dock_devices - find devices on the dock station
628  * @handle: the handle of the device we are examining
629  * @lvl: unused
630  * @context: the dock station private data
631  * @rv: unused
632  *
633  * This function is called by acpi_walk_namespace.  It will
634  * check to see if an object has an _EJD method.  If it does, then it
635  * will see if it is dependent on the dock station.
636  */
637 static acpi_status
638 find_dock_devices(acpi_handle handle, u32 lvl, void *context, void **rv)
639 {
640         acpi_status status;
641         acpi_handle tmp, parent;
642         struct dock_station *ds = context;
643         struct dock_dependent_device *dd;
644
645         status = acpi_bus_get_ejd(handle, &tmp);
646         if (ACPI_FAILURE(status)) {
647                 /* try the parent device as well */
648                 status = acpi_get_parent(handle, &parent);
649                 if (ACPI_FAILURE(status))
650                         goto fdd_out;
651                 /* see if parent is dependent on dock */
652                 status = acpi_bus_get_ejd(parent, &tmp);
653                 if (ACPI_FAILURE(status))
654                         goto fdd_out;
655         }
656
657         if (tmp == ds->handle) {
658                 dd = alloc_dock_dependent_device(handle);
659                 if (dd)
660                         add_dock_dependent_device(ds, dd);
661         }
662 fdd_out:
663         return AE_OK;
664 }
665
666 /*
667  * show_docked - read method for "docked" file in sysfs
668  */
669 static ssize_t show_docked(struct device *dev,
670                            struct device_attribute *attr, char *buf)
671 {
672         return snprintf(buf, PAGE_SIZE, "%d\n", dock_present(dock_station));
673
674 }
675 DEVICE_ATTR(docked, S_IRUGO, show_docked, NULL);
676
677 /*
678  * show_flags - read method for flags file in sysfs
679  */
680 static ssize_t show_flags(struct device *dev,
681                           struct device_attribute *attr, char *buf)
682 {
683         return snprintf(buf, PAGE_SIZE, "%d\n", dock_station->flags);
684
685 }
686 DEVICE_ATTR(flags, S_IRUGO, show_flags, NULL);
687
688 /*
689  * write_undock - write method for "undock" file in sysfs
690  */
691 static ssize_t write_undock(struct device *dev, struct device_attribute *attr,
692                            const char *buf, size_t count)
693 {
694         int ret;
695
696         if (!count)
697                 return -EINVAL;
698
699         ret = handle_eject_request(dock_station, ACPI_NOTIFY_EJECT_REQUEST);
700         return ret ? ret: count;
701 }
702 DEVICE_ATTR(undock, S_IWUSR, NULL, write_undock);
703
704 /*
705  * show_dock_uid - read method for "uid" file in sysfs
706  */
707 static ssize_t show_dock_uid(struct device *dev,
708                              struct device_attribute *attr, char *buf)
709 {
710         unsigned long lbuf;
711         acpi_status status = acpi_evaluate_integer(dock_station->handle,
712                                         "_UID", NULL, &lbuf);
713         if (ACPI_FAILURE(status))
714             return 0;
715
716         return snprintf(buf, PAGE_SIZE, "%lx\n", lbuf);
717 }
718 DEVICE_ATTR(uid, S_IRUGO, show_dock_uid, NULL);
719
720 /**
721  * dock_add - add a new dock station
722  * @handle: the dock station handle
723  *
724  * allocated and initialize a new dock station device.  Find all devices
725  * that are on the dock station, and register for dock event notifications.
726  */
727 static int dock_add(acpi_handle handle)
728 {
729         int ret;
730         acpi_status status;
731         struct dock_dependent_device *dd;
732
733         /* allocate & initialize the dock_station private data */
734         dock_station = kzalloc(sizeof(*dock_station), GFP_KERNEL);
735         if (!dock_station)
736                 return -ENOMEM;
737         dock_station->handle = handle;
738         dock_station->last_dock_time = jiffies - HZ;
739         INIT_LIST_HEAD(&dock_station->dependent_devices);
740         INIT_LIST_HEAD(&dock_station->hotplug_devices);
741         spin_lock_init(&dock_station->dd_lock);
742         mutex_init(&dock_station->hp_lock);
743         ATOMIC_INIT_NOTIFIER_HEAD(&dock_notifier_list);
744
745         /* initialize platform device stuff */
746         dock_device =
747                 platform_device_register_simple(dock_device_name, 0, NULL, 0);
748         if (IS_ERR(dock_device)) {
749                 kfree(dock_station);
750                 dock_station = NULL;
751                 return PTR_ERR(dock_device);
752         }
753
754         /* we want the dock device to send uevents */
755         dock_device->dev.uevent_suppress = 0;
756
757         ret = device_create_file(&dock_device->dev, &dev_attr_docked);
758         if (ret) {
759                 printk("Error %d adding sysfs file\n", ret);
760                 platform_device_unregister(dock_device);
761                 kfree(dock_station);
762                 dock_station = NULL;
763                 return ret;
764         }
765         ret = device_create_file(&dock_device->dev, &dev_attr_undock);
766         if (ret) {
767                 printk("Error %d adding sysfs file\n", ret);
768                 device_remove_file(&dock_device->dev, &dev_attr_docked);
769                 platform_device_unregister(dock_device);
770                 kfree(dock_station);
771                 dock_station = NULL;
772                 return ret;
773         }
774         ret = device_create_file(&dock_device->dev, &dev_attr_uid);
775         if (ret) {
776                 printk("Error %d adding sysfs file\n", ret);
777                 device_remove_file(&dock_device->dev, &dev_attr_docked);
778                 device_remove_file(&dock_device->dev, &dev_attr_undock);
779                 platform_device_unregister(dock_device);
780                 kfree(dock_station);
781                 dock_station = NULL;
782                 return ret;
783         }
784         ret = device_create_file(&dock_device->dev, &dev_attr_flags);
785         if (ret) {
786                 printk("Error %d adding sysfs file\n", ret);
787                 device_remove_file(&dock_device->dev, &dev_attr_docked);
788                 device_remove_file(&dock_device->dev, &dev_attr_undock);
789                 device_remove_file(&dock_device->dev, &dev_attr_uid);
790                 platform_device_unregister(dock_device);
791                 kfree(dock_station);
792                 dock_station = NULL;
793                 return ret;
794         }
795
796         /* Find dependent devices */
797         acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
798                             ACPI_UINT32_MAX, find_dock_devices, dock_station,
799                             NULL);
800
801         /* add the dock station as a device dependent on itself */
802         dd = alloc_dock_dependent_device(handle);
803         if (!dd) {
804                 kfree(dock_station);
805                 dock_station = NULL;
806                 ret = -ENOMEM;
807                 goto dock_add_err_unregister;
808         }
809         add_dock_dependent_device(dock_station, dd);
810
811         /* register for dock events */
812         status = acpi_install_notify_handler(dock_station->handle,
813                                              ACPI_SYSTEM_NOTIFY,
814                                              dock_notify, dock_station);
815
816         if (ACPI_FAILURE(status)) {
817                 printk(KERN_ERR PREFIX "Error installing notify handler\n");
818                 ret = -ENODEV;
819                 goto dock_add_err;
820         }
821
822         printk(KERN_INFO PREFIX "%s \n", ACPI_DOCK_DRIVER_DESCRIPTION);
823
824         return 0;
825
826 dock_add_err:
827         kfree(dd);
828 dock_add_err_unregister:
829         device_remove_file(&dock_device->dev, &dev_attr_docked);
830         device_remove_file(&dock_device->dev, &dev_attr_undock);
831         device_remove_file(&dock_device->dev, &dev_attr_uid);
832         device_remove_file(&dock_device->dev, &dev_attr_flags);
833         platform_device_unregister(dock_device);
834         kfree(dock_station);
835         dock_station = NULL;
836         return ret;
837 }
838
839 /**
840  * dock_remove - free up resources related to the dock station
841  */
842 static int dock_remove(void)
843 {
844         struct dock_dependent_device *dd, *tmp;
845         acpi_status status;
846
847         if (!dock_station)
848                 return 0;
849
850         /* remove dependent devices */
851         list_for_each_entry_safe(dd, tmp, &dock_station->dependent_devices,
852                                  list)
853             kfree(dd);
854
855         /* remove dock notify handler */
856         status = acpi_remove_notify_handler(dock_station->handle,
857                                             ACPI_SYSTEM_NOTIFY,
858                                             dock_notify);
859         if (ACPI_FAILURE(status))
860                 printk(KERN_ERR "Error removing notify handler\n");
861
862         /* cleanup sysfs */
863         device_remove_file(&dock_device->dev, &dev_attr_docked);
864         device_remove_file(&dock_device->dev, &dev_attr_undock);
865         device_remove_file(&dock_device->dev, &dev_attr_uid);
866         device_remove_file(&dock_device->dev, &dev_attr_flags);
867         platform_device_unregister(dock_device);
868
869         /* free dock station memory */
870         kfree(dock_station);
871         dock_station = NULL;
872         return 0;
873 }
874
875 /**
876  * find_dock - look for a dock station
877  * @handle: acpi handle of a device
878  * @lvl: unused
879  * @context: counter of dock stations found
880  * @rv: unused
881  *
882  * This is called by acpi_walk_namespace to look for dock stations.
883  */
884 static acpi_status
885 find_dock(acpi_handle handle, u32 lvl, void *context, void **rv)
886 {
887         int *count = context;
888         acpi_status status = AE_OK;
889
890         if (is_dock(handle)) {
891                 if (dock_add(handle) >= 0) {
892                         (*count)++;
893                         status = AE_CTRL_TERMINATE;
894                 }
895         }
896         return status;
897 }
898
899 static int __init dock_init(void)
900 {
901         int num = 0;
902
903         dock_station = NULL;
904
905         /* look for a dock station */
906         acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
907                             ACPI_UINT32_MAX, find_dock, &num, NULL);
908
909         if (!num)
910                 printk(KERN_INFO "No dock devices found.\n");
911
912         return 0;
913 }
914
915 static void __exit dock_exit(void)
916 {
917         dock_remove();
918 }
919
920 postcore_initcall(dock_init);
921 module_exit(dock_exit);