Merge branch 'drm-patches' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied...
[sfrench/cifs-2.6.git] / 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         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);