ACPI / dock: Add .uevent() callback to struct acpi_hotplug_context
[firefly-linux-kernel-4.4.55.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/slab.h>
28 #include <linux/init.h>
29 #include <linux/types.h>
30 #include <linux/notifier.h>
31 #include <linux/platform_device.h>
32 #include <linux/jiffies.h>
33 #include <linux/stddef.h>
34 #include <linux/acpi.h>
35
36 #include "internal.h"
37
38 #define PREFIX "ACPI: "
39
40 #define ACPI_DOCK_DRIVER_DESCRIPTION "ACPI Dock Station Driver"
41
42 ACPI_MODULE_NAME("dock");
43 MODULE_AUTHOR("Kristen Carlson Accardi");
44 MODULE_DESCRIPTION(ACPI_DOCK_DRIVER_DESCRIPTION);
45 MODULE_LICENSE("GPL");
46
47 static bool immediate_undock = 1;
48 module_param(immediate_undock, bool, 0644);
49 MODULE_PARM_DESC(immediate_undock, "1 (default) will cause the driver to "
50         "undock immediately when the undock button is pressed, 0 will cause"
51         " the driver to wait for userspace to write the undock sysfs file "
52         " before undocking");
53
54 static const struct acpi_device_id dock_device_ids[] = {
55         {"LNXDOCK", 0},
56         {"", 0},
57 };
58 MODULE_DEVICE_TABLE(acpi, dock_device_ids);
59
60 struct dock_station {
61         acpi_handle handle;
62         unsigned long last_dock_time;
63         u32 flags;
64         struct list_head dependent_devices;
65
66         struct list_head sibling;
67         struct platform_device *dock_device;
68 };
69 static LIST_HEAD(dock_stations);
70 static int dock_station_count;
71 static DEFINE_MUTEX(hotplug_lock);
72
73 struct dock_dependent_device {
74         struct list_head list;
75         struct acpi_device *adev;
76         const struct acpi_dock_ops *hp_ops;
77         void *hp_context;
78         unsigned int hp_refcount;
79         void (*hp_release)(void *);
80 };
81
82 #define DOCK_DOCKING    0x00000001
83 #define DOCK_UNDOCKING  0x00000002
84 #define DOCK_IS_DOCK    0x00000010
85 #define DOCK_IS_ATA     0x00000020
86 #define DOCK_IS_BAT     0x00000040
87 #define DOCK_EVENT      3
88 #define UNDOCK_EVENT    2
89
90 enum dock_callback_type {
91         DOCK_CALL_HANDLER,
92         DOCK_CALL_FIXUP,
93         DOCK_CALL_UEVENT,
94 };
95
96 /*****************************************************************************
97  *                         Dock Dependent device functions                   *
98  *****************************************************************************/
99 /**
100  * add_dock_dependent_device - associate a device with the dock station
101  * @ds: Dock station.
102  * @adev: Dependent ACPI device object.
103  *
104  * Add the dependent device to the dock's dependent device list.
105  */
106 static int add_dock_dependent_device(struct dock_station *ds,
107                                      struct acpi_device *adev)
108 {
109         struct dock_dependent_device *dd;
110
111         dd = kzalloc(sizeof(*dd), GFP_KERNEL);
112         if (!dd)
113                 return -ENOMEM;
114
115         dd->adev = adev;
116         INIT_LIST_HEAD(&dd->list);
117         list_add_tail(&dd->list, &ds->dependent_devices);
118
119         return 0;
120 }
121
122 static void remove_dock_dependent_devices(struct dock_station *ds)
123 {
124         struct dock_dependent_device *dd, *aux;
125
126         list_for_each_entry_safe(dd, aux, &ds->dependent_devices, list) {
127                 list_del(&dd->list);
128                 kfree(dd);
129         }
130 }
131
132 /**
133  * dock_init_hotplug - Initialize a hotplug device on a docking station.
134  * @dd: Dock-dependent device.
135  * @ops: Dock operations to attach to the dependent device.
136  * @context: Data to pass to the @ops callbacks and @release.
137  * @init: Optional initialization routine to run after setting up context.
138  * @release: Optional release routine to run on removal.
139  */
140 static int dock_init_hotplug(struct dock_dependent_device *dd,
141                              const struct acpi_dock_ops *ops, void *context,
142                              void (*init)(void *), void (*release)(void *))
143 {
144         int ret = 0;
145
146         mutex_lock(&hotplug_lock);
147         if (WARN_ON(dd->hp_context)) {
148                 ret = -EEXIST;
149         } else {
150                 dd->hp_refcount = 1;
151                 dd->hp_ops = ops;
152                 dd->hp_context = context;
153                 dd->hp_release = release;
154                 if (init)
155                         init(context);
156         }
157         mutex_unlock(&hotplug_lock);
158         return ret;
159 }
160
161 /**
162  * dock_release_hotplug - Decrement hotplug reference counter of dock device.
163  * @dd: Dock-dependent device.
164  *
165  * Decrement the reference counter of @dd and if 0, detach its hotplug
166  * operations from it, reset its context pointer and run the optional release
167  * routine if present.
168  */
169 static void dock_release_hotplug(struct dock_dependent_device *dd)
170 {
171         mutex_lock(&hotplug_lock);
172         if (dd->hp_context && !--dd->hp_refcount) {
173                 void (*release)(void *) = dd->hp_release;
174                 void *context = dd->hp_context;
175
176                 dd->hp_ops = NULL;
177                 dd->hp_context = NULL;
178                 dd->hp_release = NULL;
179                 if (release)
180                         release(context);
181         }
182         mutex_unlock(&hotplug_lock);
183 }
184
185 static void dock_hotplug_event(struct dock_dependent_device *dd, u32 event,
186                                enum dock_callback_type cb_type)
187 {
188         struct acpi_device *adev = dd->adev;
189         acpi_notify_handler cb = NULL;
190         bool run = false;
191
192         acpi_lock_hp_context();
193
194         if (!adev->hp)
195                 goto no_context;
196
197         if (cb_type == DOCK_CALL_FIXUP) {
198                 void (*fixup)(struct acpi_device *);
199
200                 fixup = adev->hp->fixup;
201                 if (fixup) {
202                         acpi_unlock_hp_context();
203                         fixup(adev);
204                         return;
205                 }
206         } else if (cb_type == DOCK_CALL_UEVENT) {
207                 void (*uevent)(struct acpi_device *, u32);
208
209                 uevent = adev->hp->uevent;
210                 if (uevent) {
211                         acpi_unlock_hp_context();
212                         uevent(adev, event);
213                         return;
214                 }
215         } else {
216                 int (*notify)(struct acpi_device *, u32);
217
218                 notify = adev->hp->notify;
219                 if (notify) {
220                         acpi_unlock_hp_context();
221                         notify(adev, event);
222                         return;
223                 }
224         }
225
226  no_context:
227         acpi_unlock_hp_context();
228
229         mutex_lock(&hotplug_lock);
230
231         if (dd->hp_context) {
232                 run = true;
233                 dd->hp_refcount++;
234                 if (dd->hp_ops) {
235                         switch (cb_type) {
236                         case DOCK_CALL_FIXUP:
237                                 cb = dd->hp_ops->fixup;
238                                 break;
239                         case DOCK_CALL_UEVENT:
240                                 cb = dd->hp_ops->uevent;
241                                 break;
242                         default:
243                                 cb = dd->hp_ops->handler;
244                         }
245                 }
246         }
247
248         mutex_unlock(&hotplug_lock);
249
250         if (!run)
251                 return;
252
253         if (cb)
254                 cb(dd->adev->handle, event, dd->hp_context);
255
256         dock_release_hotplug(dd);
257 }
258
259 static struct dock_station *find_dock_station(acpi_handle handle)
260 {
261         struct dock_station *ds;
262
263         list_for_each_entry(ds, &dock_stations, sibling)
264                 if (ds->handle == handle)
265                         return ds;
266
267         return NULL;
268 }
269
270 /**
271  * find_dock_dependent_device - get a device dependent on this dock
272  * @ds: the dock station
273  * @adev: ACPI device object to find.
274  *
275  * iterate over the dependent device list for this dock.  If the
276  * dependent device matches the handle, return.
277  */
278 static struct dock_dependent_device *
279 find_dock_dependent_device(struct dock_station *ds, struct acpi_device *adev)
280 {
281         struct dock_dependent_device *dd;
282
283         list_for_each_entry(dd, &ds->dependent_devices, list)
284                 if (adev == dd->adev)
285                         return dd;
286
287         return NULL;
288 }
289
290 void register_dock_dependent_device(struct acpi_device *adev,
291                                     acpi_handle dshandle)
292 {
293         struct dock_station *ds = find_dock_station(dshandle);
294
295         if (ds && !find_dock_dependent_device(ds, adev))
296                 add_dock_dependent_device(ds, adev);
297 }
298
299 /*****************************************************************************
300  *                         Dock functions                                    *
301  *****************************************************************************/
302
303 /**
304  * is_dock_device - see if a device is on a dock station
305  * @adev: ACPI device object to check.
306  *
307  * If this device is either the dock station itself,
308  * or is a device dependent on the dock station, then it
309  * is a dock device
310  */
311 int is_dock_device(struct acpi_device *adev)
312 {
313         struct dock_station *dock_station;
314
315         if (!dock_station_count)
316                 return 0;
317
318         if (acpi_dock_match(adev->handle))
319                 return 1;
320
321         list_for_each_entry(dock_station, &dock_stations, sibling)
322                 if (find_dock_dependent_device(dock_station, adev))
323                         return 1;
324
325         return 0;
326 }
327 EXPORT_SYMBOL_GPL(is_dock_device);
328
329 /**
330  * dock_present - see if the dock station is present.
331  * @ds: the dock station
332  *
333  * execute the _STA method.  note that present does not
334  * imply that we are docked.
335  */
336 static int dock_present(struct dock_station *ds)
337 {
338         unsigned long long sta;
339         acpi_status status;
340
341         if (ds) {
342                 status = acpi_evaluate_integer(ds->handle, "_STA", NULL, &sta);
343                 if (ACPI_SUCCESS(status) && sta)
344                         return 1;
345         }
346         return 0;
347 }
348
349 /**
350  * hot_remove_dock_devices - Remove dock station devices.
351  * @ds: Dock station.
352  */
353 static void hot_remove_dock_devices(struct dock_station *ds)
354 {
355         struct dock_dependent_device *dd;
356
357         /*
358          * Walk the list in reverse order so that devices that have been added
359          * last are removed first (in case there are some indirect dependencies
360          * between them).
361          */
362         list_for_each_entry_reverse(dd, &ds->dependent_devices, list)
363                 dock_hotplug_event(dd, ACPI_NOTIFY_EJECT_REQUEST, false);
364
365         list_for_each_entry_reverse(dd, &ds->dependent_devices, list)
366                 acpi_bus_trim(dd->adev);
367 }
368
369 /**
370  * hotplug_dock_devices - Insert devices on a dock station.
371  * @ds: the dock station
372  * @event: either bus check or device check request
373  *
374  * Some devices on the dock station need to have drivers called
375  * to perform hotplug operations after a dock event has occurred.
376  * Traverse the list of dock devices that have registered a
377  * hotplug handler, and call the handler.
378  */
379 static void hotplug_dock_devices(struct dock_station *ds, u32 event)
380 {
381         struct dock_dependent_device *dd;
382
383         /* Call driver specific post-dock fixups. */
384         list_for_each_entry(dd, &ds->dependent_devices, list)
385                 dock_hotplug_event(dd, event, DOCK_CALL_FIXUP);
386
387         /* Call driver specific hotplug functions. */
388         list_for_each_entry(dd, &ds->dependent_devices, list)
389                 dock_hotplug_event(dd, event, DOCK_CALL_HANDLER);
390
391         /*
392          * Check if all devices have been enumerated already.  If not, run
393          * acpi_bus_scan() for them and that will cause scan handlers to be
394          * attached to device objects or acpi_drivers to be stopped/started if
395          * they are present.
396          */
397         list_for_each_entry(dd, &ds->dependent_devices, list) {
398                 struct acpi_device *adev = dd->adev;
399
400                 if (!acpi_device_enumerated(adev)) {
401                         int ret = acpi_bus_scan(adev->handle);
402                         if (ret)
403                                 dev_dbg(&adev->dev, "scan error %d\n", -ret);
404                 }
405         }
406 }
407
408 static void dock_event(struct dock_station *ds, u32 event, int num)
409 {
410         struct device *dev = &ds->dock_device->dev;
411         char event_string[13];
412         char *envp[] = { event_string, NULL };
413         struct dock_dependent_device *dd;
414
415         if (num == UNDOCK_EVENT)
416                 sprintf(event_string, "EVENT=undock");
417         else
418                 sprintf(event_string, "EVENT=dock");
419
420         /*
421          * Indicate that the status of the dock station has
422          * changed.
423          */
424         if (num == DOCK_EVENT)
425                 kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
426
427         list_for_each_entry(dd, &ds->dependent_devices, list)
428                 dock_hotplug_event(dd, event, DOCK_CALL_UEVENT);
429
430         if (num != DOCK_EVENT)
431                 kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
432 }
433
434 /**
435  * handle_dock - handle a dock event
436  * @ds: the dock station
437  * @dock: to dock, or undock - that is the question
438  *
439  * Execute the _DCK method in response to an acpi event
440  */
441 static void handle_dock(struct dock_station *ds, int dock)
442 {
443         acpi_status status;
444         struct acpi_object_list arg_list;
445         union acpi_object arg;
446         unsigned long long value;
447
448         acpi_handle_info(ds->handle, "%s\n", dock ? "docking" : "undocking");
449
450         /* _DCK method has one argument */
451         arg_list.count = 1;
452         arg_list.pointer = &arg;
453         arg.type = ACPI_TYPE_INTEGER;
454         arg.integer.value = dock;
455         status = acpi_evaluate_integer(ds->handle, "_DCK", &arg_list, &value);
456         if (ACPI_FAILURE(status) && status != AE_NOT_FOUND)
457                 acpi_handle_err(ds->handle, "Failed to execute _DCK (0x%x)\n",
458                                 status);
459 }
460
461 static inline void dock(struct dock_station *ds)
462 {
463         handle_dock(ds, 1);
464 }
465
466 static inline void undock(struct dock_station *ds)
467 {
468         handle_dock(ds, 0);
469 }
470
471 static inline void begin_dock(struct dock_station *ds)
472 {
473         ds->flags |= DOCK_DOCKING;
474 }
475
476 static inline void complete_dock(struct dock_station *ds)
477 {
478         ds->flags &= ~(DOCK_DOCKING);
479         ds->last_dock_time = jiffies;
480 }
481
482 static inline void begin_undock(struct dock_station *ds)
483 {
484         ds->flags |= DOCK_UNDOCKING;
485 }
486
487 static inline void complete_undock(struct dock_station *ds)
488 {
489         ds->flags &= ~(DOCK_UNDOCKING);
490 }
491
492 /**
493  * dock_in_progress - see if we are in the middle of handling a dock event
494  * @ds: the dock station
495  *
496  * Sometimes while docking, false dock events can be sent to the driver
497  * because good connections aren't made or some other reason.  Ignore these
498  * if we are in the middle of doing something.
499  */
500 static int dock_in_progress(struct dock_station *ds)
501 {
502         if ((ds->flags & DOCK_DOCKING) ||
503             time_before(jiffies, (ds->last_dock_time + HZ)))
504                 return 1;
505         return 0;
506 }
507
508 /**
509  * register_hotplug_dock_device - register a hotplug function
510  * @handle: the handle of the device
511  * @ops: handlers to call after docking
512  * @context: device specific data
513  * @init: Optional initialization routine to run after registration
514  * @release: Optional release routine to run on unregistration
515  *
516  * If a driver would like to perform a hotplug operation after a dock
517  * event, they can register an acpi_notifiy_handler to be called by
518  * the dock driver after _DCK is executed.
519  */
520 int register_hotplug_dock_device(acpi_handle handle,
521                                  const struct acpi_dock_ops *ops, void *context,
522                                  void (*init)(void *), void (*release)(void *))
523 {
524         struct dock_dependent_device *dd;
525         struct dock_station *dock_station;
526         struct acpi_device *adev;
527         int ret = -EINVAL;
528
529         if (WARN_ON(!context))
530                 return -EINVAL;
531
532         if (!dock_station_count)
533                 return -ENODEV;
534
535         ret = acpi_bus_get_device(handle, &adev);
536         if (ret)
537                 return ret;
538
539         /*
540          * make sure this handle is for a device dependent on the dock,
541          * this would include the dock station itself
542          */
543         list_for_each_entry(dock_station, &dock_stations, sibling) {
544                 /*
545                  * An ATA bay can be in a dock and itself can be ejected
546                  * separately, so there are two 'dock stations' which need the
547                  * ops
548                  */
549                 dd = find_dock_dependent_device(dock_station, adev);
550                 if (dd && !dock_init_hotplug(dd, ops, context, init, release))
551                         ret = 0;
552         }
553
554         return ret;
555 }
556 EXPORT_SYMBOL_GPL(register_hotplug_dock_device);
557
558 /**
559  * unregister_hotplug_dock_device - remove yourself from the hotplug list
560  * @handle: the acpi handle of the device
561  */
562 void unregister_hotplug_dock_device(acpi_handle handle)
563 {
564         struct dock_dependent_device *dd;
565         struct dock_station *dock_station;
566         struct acpi_device *adev;
567
568         if (!dock_station_count)
569                 return;
570
571         if (acpi_bus_get_device(handle, &adev))
572                 return;
573
574         list_for_each_entry(dock_station, &dock_stations, sibling) {
575                 dd = find_dock_dependent_device(dock_station, adev);
576                 if (dd)
577                         dock_release_hotplug(dd);
578         }
579 }
580 EXPORT_SYMBOL_GPL(unregister_hotplug_dock_device);
581
582 /**
583  * handle_eject_request - handle an undock request checking for error conditions
584  *
585  * Check to make sure the dock device is still present, then undock and
586  * hotremove all the devices that may need removing.
587  */
588 static int handle_eject_request(struct dock_station *ds, u32 event)
589 {
590         if (dock_in_progress(ds))
591                 return -EBUSY;
592
593         /*
594          * here we need to generate the undock
595          * event prior to actually doing the undock
596          * so that the device struct still exists.
597          * Also, even send the dock event if the
598          * device is not present anymore
599          */
600         dock_event(ds, event, UNDOCK_EVENT);
601
602         hot_remove_dock_devices(ds);
603         undock(ds);
604         acpi_evaluate_lck(ds->handle, 0);
605         acpi_evaluate_ej0(ds->handle);
606         if (dock_present(ds)) {
607                 acpi_handle_err(ds->handle, "Unable to undock!\n");
608                 return -EBUSY;
609         }
610         complete_undock(ds);
611         return 0;
612 }
613
614 /**
615  * dock_notify - Handle ACPI dock notification.
616  * @adev: Dock station's ACPI device object.
617  * @event: Event code.
618  *
619  * If we are notified to dock, then check to see if the dock is
620  * present and then dock.  Notify all drivers of the dock event,
621  * and then hotplug and devices that may need hotplugging.
622  */
623 int dock_notify(struct acpi_device *adev, u32 event)
624 {
625         acpi_handle handle = adev->handle;
626         struct dock_station *ds = find_dock_station(handle);
627         int surprise_removal = 0;
628
629         if (!ds)
630                 return -ENODEV;
631
632         /*
633          * According to acpi spec 3.0a, if a DEVICE_CHECK notification
634          * is sent and _DCK is present, it is assumed to mean an undock
635          * request.
636          */
637         if ((ds->flags & DOCK_IS_DOCK) && event == ACPI_NOTIFY_DEVICE_CHECK)
638                 event = ACPI_NOTIFY_EJECT_REQUEST;
639
640         /*
641          * dock station: BUS_CHECK - docked or surprise removal
642          *               DEVICE_CHECK - undocked
643          * other device: BUS_CHECK/DEVICE_CHECK - added or surprise removal
644          *
645          * To simplify event handling, dock dependent device handler always
646          * get ACPI_NOTIFY_BUS_CHECK/ACPI_NOTIFY_DEVICE_CHECK for add and
647          * ACPI_NOTIFY_EJECT_REQUEST for removal
648          */
649         switch (event) {
650         case ACPI_NOTIFY_BUS_CHECK:
651         case ACPI_NOTIFY_DEVICE_CHECK:
652                 if (!dock_in_progress(ds) && !acpi_device_enumerated(adev)) {
653                         begin_dock(ds);
654                         dock(ds);
655                         if (!dock_present(ds)) {
656                                 acpi_handle_err(handle, "Unable to dock!\n");
657                                 complete_dock(ds);
658                                 break;
659                         }
660                         hotplug_dock_devices(ds, event);
661                         complete_dock(ds);
662                         dock_event(ds, event, DOCK_EVENT);
663                         acpi_evaluate_lck(ds->handle, 1);
664                         acpi_update_all_gpes();
665                         break;
666                 }
667                 if (dock_present(ds) || dock_in_progress(ds))
668                         break;
669                 /* This is a surprise removal */
670                 surprise_removal = 1;
671                 event = ACPI_NOTIFY_EJECT_REQUEST;
672                 /* Fall back */
673         case ACPI_NOTIFY_EJECT_REQUEST:
674                 begin_undock(ds);
675                 if ((immediate_undock && !(ds->flags & DOCK_IS_ATA))
676                    || surprise_removal)
677                         handle_eject_request(ds, event);
678                 else
679                         dock_event(ds, event, UNDOCK_EVENT);
680                 break;
681         }
682         return 0;
683 }
684
685 /*
686  * show_docked - read method for "docked" file in sysfs
687  */
688 static ssize_t show_docked(struct device *dev,
689                            struct device_attribute *attr, char *buf)
690 {
691         struct dock_station *dock_station = dev->platform_data;
692         struct acpi_device *adev = NULL;
693
694         acpi_bus_get_device(dock_station->handle, &adev);
695         return snprintf(buf, PAGE_SIZE, "%u\n", acpi_device_enumerated(adev));
696 }
697 static DEVICE_ATTR(docked, S_IRUGO, show_docked, NULL);
698
699 /*
700  * show_flags - read method for flags file in sysfs
701  */
702 static ssize_t show_flags(struct device *dev,
703                           struct device_attribute *attr, char *buf)
704 {
705         struct dock_station *dock_station = dev->platform_data;
706         return snprintf(buf, PAGE_SIZE, "%d\n", dock_station->flags);
707
708 }
709 static DEVICE_ATTR(flags, S_IRUGO, show_flags, NULL);
710
711 /*
712  * write_undock - write method for "undock" file in sysfs
713  */
714 static ssize_t write_undock(struct device *dev, struct device_attribute *attr,
715                            const char *buf, size_t count)
716 {
717         int ret;
718         struct dock_station *dock_station = dev->platform_data;
719
720         if (!count)
721                 return -EINVAL;
722
723         acpi_scan_lock_acquire();
724         begin_undock(dock_station);
725         ret = handle_eject_request(dock_station, ACPI_NOTIFY_EJECT_REQUEST);
726         acpi_scan_lock_release();
727         return ret ? ret: count;
728 }
729 static DEVICE_ATTR(undock, S_IWUSR, NULL, write_undock);
730
731 /*
732  * show_dock_uid - read method for "uid" file in sysfs
733  */
734 static ssize_t show_dock_uid(struct device *dev,
735                              struct device_attribute *attr, char *buf)
736 {
737         unsigned long long lbuf;
738         struct dock_station *dock_station = dev->platform_data;
739         acpi_status status = acpi_evaluate_integer(dock_station->handle,
740                                         "_UID", NULL, &lbuf);
741         if (ACPI_FAILURE(status))
742             return 0;
743
744         return snprintf(buf, PAGE_SIZE, "%llx\n", lbuf);
745 }
746 static DEVICE_ATTR(uid, S_IRUGO, show_dock_uid, NULL);
747
748 static ssize_t show_dock_type(struct device *dev,
749                 struct device_attribute *attr, char *buf)
750 {
751         struct dock_station *dock_station = dev->platform_data;
752         char *type;
753
754         if (dock_station->flags & DOCK_IS_DOCK)
755                 type = "dock_station";
756         else if (dock_station->flags & DOCK_IS_ATA)
757                 type = "ata_bay";
758         else if (dock_station->flags & DOCK_IS_BAT)
759                 type = "battery_bay";
760         else
761                 type = "unknown";
762
763         return snprintf(buf, PAGE_SIZE, "%s\n", type);
764 }
765 static DEVICE_ATTR(type, S_IRUGO, show_dock_type, NULL);
766
767 static struct attribute *dock_attributes[] = {
768         &dev_attr_docked.attr,
769         &dev_attr_flags.attr,
770         &dev_attr_undock.attr,
771         &dev_attr_uid.attr,
772         &dev_attr_type.attr,
773         NULL
774 };
775
776 static struct attribute_group dock_attribute_group = {
777         .attrs = dock_attributes
778 };
779
780 /**
781  * acpi_dock_add - Add a new dock station
782  * @adev: Dock station ACPI device object.
783  *
784  * allocated and initialize a new dock station device.
785  */
786 void acpi_dock_add(struct acpi_device *adev)
787 {
788         struct dock_station *dock_station, ds = { NULL, };
789         struct platform_device_info pdevinfo;
790         acpi_handle handle = adev->handle;
791         struct platform_device *dd;
792         int ret;
793
794         memset(&pdevinfo, 0, sizeof(pdevinfo));
795         pdevinfo.name = "dock";
796         pdevinfo.id = dock_station_count;
797         pdevinfo.acpi_node.companion = adev;
798         pdevinfo.data = &ds;
799         pdevinfo.size_data = sizeof(ds);
800         dd = platform_device_register_full(&pdevinfo);
801         if (IS_ERR(dd))
802                 return;
803
804         dock_station = dd->dev.platform_data;
805
806         dock_station->handle = handle;
807         dock_station->dock_device = dd;
808         dock_station->last_dock_time = jiffies - HZ;
809
810         INIT_LIST_HEAD(&dock_station->sibling);
811         INIT_LIST_HEAD(&dock_station->dependent_devices);
812
813         /* we want the dock device to send uevents */
814         dev_set_uevent_suppress(&dd->dev, 0);
815
816         if (acpi_dock_match(handle))
817                 dock_station->flags |= DOCK_IS_DOCK;
818         if (acpi_ata_match(handle))
819                 dock_station->flags |= DOCK_IS_ATA;
820         if (acpi_device_is_battery(adev))
821                 dock_station->flags |= DOCK_IS_BAT;
822
823         ret = sysfs_create_group(&dd->dev.kobj, &dock_attribute_group);
824         if (ret)
825                 goto err_unregister;
826
827         /* add the dock station as a device dependent on itself */
828         ret = add_dock_dependent_device(dock_station, adev);
829         if (ret)
830                 goto err_rmgroup;
831
832         dock_station_count++;
833         list_add(&dock_station->sibling, &dock_stations);
834         adev->flags.is_dock_station = true;
835         dev_info(&adev->dev, "ACPI dock station (docks/bays count: %d)\n",
836                  dock_station_count);
837         return;
838
839 err_rmgroup:
840         remove_dock_dependent_devices(dock_station);
841         sysfs_remove_group(&dd->dev.kobj, &dock_attribute_group);
842 err_unregister:
843         platform_device_unregister(dd);
844         acpi_handle_err(handle, "%s encountered error %d\n", __func__, ret);
845 }