Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0-or-later
2 : : /*
3 : : * dock.c - ACPI dock station driver
4 : : *
5 : : * Copyright (C) 2006, 2014, Intel Corp.
6 : : * Author: Kristen Carlson Accardi <kristen.c.accardi@intel.com>
7 : : * Rafael J. Wysocki <rafael.j.wysocki@intel.com>
8 : : */
9 : :
10 : : #include <linux/kernel.h>
11 : : #include <linux/moduleparam.h>
12 : : #include <linux/slab.h>
13 : : #include <linux/init.h>
14 : : #include <linux/types.h>
15 : : #include <linux/notifier.h>
16 : : #include <linux/platform_device.h>
17 : : #include <linux/jiffies.h>
18 : : #include <linux/stddef.h>
19 : : #include <linux/acpi.h>
20 : :
21 : : #include "internal.h"
22 : :
23 : : ACPI_MODULE_NAME("dock");
24 : :
25 : : static bool immediate_undock = 1;
26 : : module_param(immediate_undock, bool, 0644);
27 : : MODULE_PARM_DESC(immediate_undock, "1 (default) will cause the driver to "
28 : : "undock immediately when the undock button is pressed, 0 will cause"
29 : : " the driver to wait for userspace to write the undock sysfs file "
30 : : " before undocking");
31 : :
32 : : struct dock_station {
33 : : acpi_handle handle;
34 : : unsigned long last_dock_time;
35 : : u32 flags;
36 : : struct list_head dependent_devices;
37 : :
38 : : struct list_head sibling;
39 : : struct platform_device *dock_device;
40 : : };
41 : : static LIST_HEAD(dock_stations);
42 : : static int dock_station_count;
43 : :
44 : : struct dock_dependent_device {
45 : : struct list_head list;
46 : : struct acpi_device *adev;
47 : : };
48 : :
49 : : #define DOCK_DOCKING 0x00000001
50 : : #define DOCK_UNDOCKING 0x00000002
51 : : #define DOCK_IS_DOCK 0x00000010
52 : : #define DOCK_IS_ATA 0x00000020
53 : : #define DOCK_IS_BAT 0x00000040
54 : : #define DOCK_EVENT 3
55 : : #define UNDOCK_EVENT 2
56 : :
57 : : enum dock_callback_type {
58 : : DOCK_CALL_HANDLER,
59 : : DOCK_CALL_FIXUP,
60 : : DOCK_CALL_UEVENT,
61 : : };
62 : :
63 : : /*****************************************************************************
64 : : * Dock Dependent device functions *
65 : : *****************************************************************************/
66 : : /**
67 : : * add_dock_dependent_device - associate a device with the dock station
68 : : * @ds: Dock station.
69 : : * @adev: Dependent ACPI device object.
70 : : *
71 : : * Add the dependent device to the dock's dependent device list.
72 : : */
73 : 0 : static int add_dock_dependent_device(struct dock_station *ds,
74 : : struct acpi_device *adev)
75 : : {
76 : 0 : struct dock_dependent_device *dd;
77 : :
78 : 0 : dd = kzalloc(sizeof(*dd), GFP_KERNEL);
79 [ # # ]: 0 : if (!dd)
80 : : return -ENOMEM;
81 : :
82 : 0 : dd->adev = adev;
83 : 0 : INIT_LIST_HEAD(&dd->list);
84 : 0 : list_add_tail(&dd->list, &ds->dependent_devices);
85 : :
86 : 0 : return 0;
87 : : }
88 : :
89 : : static void dock_hotplug_event(struct dock_dependent_device *dd, u32 event,
90 : : enum dock_callback_type cb_type)
91 : : {
92 : : struct acpi_device *adev = dd->adev;
93 : :
94 : : acpi_lock_hp_context();
95 : :
96 : : if (!adev->hp)
97 : : goto out;
98 : :
99 : : if (cb_type == DOCK_CALL_FIXUP) {
100 : : void (*fixup)(struct acpi_device *);
101 : :
102 : : fixup = adev->hp->fixup;
103 : : if (fixup) {
104 : : acpi_unlock_hp_context();
105 : : fixup(adev);
106 : : return;
107 : : }
108 : : } else if (cb_type == DOCK_CALL_UEVENT) {
109 : : void (*uevent)(struct acpi_device *, u32);
110 : :
111 : : uevent = adev->hp->uevent;
112 : : if (uevent) {
113 : : acpi_unlock_hp_context();
114 : : uevent(adev, event);
115 : : return;
116 : : }
117 : : } else {
118 : : int (*notify)(struct acpi_device *, u32);
119 : :
120 : : notify = adev->hp->notify;
121 : : if (notify) {
122 : : acpi_unlock_hp_context();
123 : : notify(adev, event);
124 : : return;
125 : : }
126 : : }
127 : :
128 : : out:
129 : : acpi_unlock_hp_context();
130 : : }
131 : :
132 : 0 : static struct dock_station *find_dock_station(acpi_handle handle)
133 : : {
134 : 0 : struct dock_station *ds;
135 : :
136 [ # # # # ]: 0 : list_for_each_entry(ds, &dock_stations, sibling)
137 [ # # # # ]: 0 : if (ds->handle == handle)
138 : : return ds;
139 : :
140 : : return NULL;
141 : : }
142 : :
143 : : /**
144 : : * find_dock_dependent_device - get a device dependent on this dock
145 : : * @ds: the dock station
146 : : * @adev: ACPI device object to find.
147 : : *
148 : : * iterate over the dependent device list for this dock. If the
149 : : * dependent device matches the handle, return.
150 : : */
151 : : static struct dock_dependent_device *
152 : 0 : find_dock_dependent_device(struct dock_station *ds, struct acpi_device *adev)
153 : : {
154 : 0 : struct dock_dependent_device *dd;
155 : :
156 [ # # # # ]: 0 : list_for_each_entry(dd, &ds->dependent_devices, list)
157 [ # # # # ]: 0 : if (adev == dd->adev)
158 : : return dd;
159 : :
160 : : return NULL;
161 : : }
162 : :
163 : 0 : void register_dock_dependent_device(struct acpi_device *adev,
164 : : acpi_handle dshandle)
165 : : {
166 : 0 : struct dock_station *ds = find_dock_station(dshandle);
167 : :
168 [ # # # # ]: 0 : if (ds && !find_dock_dependent_device(ds, adev))
169 : 0 : add_dock_dependent_device(ds, adev);
170 : 0 : }
171 : :
172 : : /*****************************************************************************
173 : : * Dock functions *
174 : : *****************************************************************************/
175 : :
176 : : /**
177 : : * is_dock_device - see if a device is on a dock station
178 : : * @adev: ACPI device object to check.
179 : : *
180 : : * If this device is either the dock station itself,
181 : : * or is a device dependent on the dock station, then it
182 : : * is a dock device
183 : : */
184 : 2808 : int is_dock_device(struct acpi_device *adev)
185 : : {
186 : 2808 : struct dock_station *dock_station;
187 : :
188 [ - + ]: 2808 : if (!dock_station_count)
189 : : return 0;
190 : :
191 [ # # ]: 0 : if (acpi_dock_match(adev->handle))
192 : : return 1;
193 : :
194 [ # # ]: 0 : list_for_each_entry(dock_station, &dock_stations, sibling)
195 [ # # ]: 0 : if (find_dock_dependent_device(dock_station, adev))
196 : : return 1;
197 : :
198 : : return 0;
199 : : }
200 : : EXPORT_SYMBOL_GPL(is_dock_device);
201 : :
202 : : /**
203 : : * dock_present - see if the dock station is present.
204 : : * @ds: the dock station
205 : : *
206 : : * execute the _STA method. note that present does not
207 : : * imply that we are docked.
208 : : */
209 : 0 : static int dock_present(struct dock_station *ds)
210 : : {
211 : 0 : unsigned long long sta;
212 : 0 : acpi_status status;
213 : :
214 [ # # ]: 0 : if (ds) {
215 : 0 : status = acpi_evaluate_integer(ds->handle, "_STA", NULL, &sta);
216 [ # # # # ]: 0 : if (ACPI_SUCCESS(status) && sta)
217 : 0 : return 1;
218 : : }
219 : : return 0;
220 : : }
221 : :
222 : : /**
223 : : * hot_remove_dock_devices - Remove dock station devices.
224 : : * @ds: Dock station.
225 : : */
226 : 0 : static void hot_remove_dock_devices(struct dock_station *ds)
227 : : {
228 : 0 : struct dock_dependent_device *dd;
229 : :
230 : : /*
231 : : * Walk the list in reverse order so that devices that have been added
232 : : * last are removed first (in case there are some indirect dependencies
233 : : * between them).
234 : : */
235 [ # # ]: 0 : list_for_each_entry_reverse(dd, &ds->dependent_devices, list)
236 : 0 : dock_hotplug_event(dd, ACPI_NOTIFY_EJECT_REQUEST, false);
237 : :
238 [ # # ]: 0 : list_for_each_entry_reverse(dd, &ds->dependent_devices, list)
239 : 0 : acpi_bus_trim(dd->adev);
240 : 0 : }
241 : :
242 : : /**
243 : : * hotplug_dock_devices - Insert devices on a dock station.
244 : : * @ds: the dock station
245 : : * @event: either bus check or device check request
246 : : *
247 : : * Some devices on the dock station need to have drivers called
248 : : * to perform hotplug operations after a dock event has occurred.
249 : : * Traverse the list of dock devices that have registered a
250 : : * hotplug handler, and call the handler.
251 : : */
252 : 0 : static void hotplug_dock_devices(struct dock_station *ds, u32 event)
253 : : {
254 : 0 : struct dock_dependent_device *dd;
255 : :
256 : : /* Call driver specific post-dock fixups. */
257 [ # # ]: 0 : list_for_each_entry(dd, &ds->dependent_devices, list)
258 : 0 : dock_hotplug_event(dd, event, DOCK_CALL_FIXUP);
259 : :
260 : : /* Call driver specific hotplug functions. */
261 [ # # ]: 0 : list_for_each_entry(dd, &ds->dependent_devices, list)
262 : 0 : dock_hotplug_event(dd, event, DOCK_CALL_HANDLER);
263 : :
264 : : /*
265 : : * Check if all devices have been enumerated already. If not, run
266 : : * acpi_bus_scan() for them and that will cause scan handlers to be
267 : : * attached to device objects or acpi_drivers to be stopped/started if
268 : : * they are present.
269 : : */
270 [ # # ]: 0 : list_for_each_entry(dd, &ds->dependent_devices, list) {
271 : 0 : struct acpi_device *adev = dd->adev;
272 : :
273 [ # # # # ]: 0 : if (!acpi_device_enumerated(adev)) {
274 : 0 : int ret = acpi_bus_scan(adev->handle);
275 : 0 : if (ret)
276 : : dev_dbg(&adev->dev, "scan error %d\n", -ret);
277 : : }
278 : : }
279 : 0 : }
280 : :
281 : 0 : static void dock_event(struct dock_station *ds, u32 event, int num)
282 : : {
283 : 0 : struct device *dev = &ds->dock_device->dev;
284 : 0 : char event_string[13];
285 : 0 : char *envp[] = { event_string, NULL };
286 : 0 : struct dock_dependent_device *dd;
287 : :
288 [ # # ]: 0 : if (num == UNDOCK_EVENT)
289 : 0 : sprintf(event_string, "EVENT=undock");
290 : : else
291 : 0 : sprintf(event_string, "EVENT=dock");
292 : :
293 : : /*
294 : : * Indicate that the status of the dock station has
295 : : * changed.
296 : : */
297 [ # # ]: 0 : if (num == DOCK_EVENT)
298 : 0 : kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
299 : :
300 [ # # ]: 0 : list_for_each_entry(dd, &ds->dependent_devices, list)
301 : 0 : dock_hotplug_event(dd, event, DOCK_CALL_UEVENT);
302 : :
303 [ # # ]: 0 : if (num != DOCK_EVENT)
304 : 0 : kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
305 : 0 : }
306 : :
307 : : /**
308 : : * handle_dock - handle a dock event
309 : : * @ds: the dock station
310 : : * @dock: to dock, or undock - that is the question
311 : : *
312 : : * Execute the _DCK method in response to an acpi event
313 : : */
314 : : static void handle_dock(struct dock_station *ds, int dock)
315 : : {
316 : : acpi_status status;
317 : : struct acpi_object_list arg_list;
318 : : union acpi_object arg;
319 : : unsigned long long value;
320 : :
321 : : acpi_handle_info(ds->handle, "%s\n", dock ? "docking" : "undocking");
322 : :
323 : : /* _DCK method has one argument */
324 : : arg_list.count = 1;
325 : : arg_list.pointer = &arg;
326 : : arg.type = ACPI_TYPE_INTEGER;
327 : : arg.integer.value = dock;
328 : : status = acpi_evaluate_integer(ds->handle, "_DCK", &arg_list, &value);
329 : : if (ACPI_FAILURE(status) && status != AE_NOT_FOUND)
330 : : acpi_handle_err(ds->handle, "Failed to execute _DCK (0x%x)\n",
331 : : status);
332 : : }
333 : :
334 : 0 : static inline void dock(struct dock_station *ds)
335 : : {
336 : 0 : handle_dock(ds, 1);
337 : : }
338 : :
339 : 0 : static inline void undock(struct dock_station *ds)
340 : : {
341 : 0 : handle_dock(ds, 0);
342 : : }
343 : :
344 : 0 : static inline void begin_dock(struct dock_station *ds)
345 : : {
346 : 0 : ds->flags |= DOCK_DOCKING;
347 : : }
348 : :
349 : 0 : static inline void complete_dock(struct dock_station *ds)
350 : : {
351 : 0 : ds->flags &= ~(DOCK_DOCKING);
352 : 0 : ds->last_dock_time = jiffies;
353 : 0 : }
354 : :
355 : 0 : static inline void begin_undock(struct dock_station *ds)
356 : : {
357 : 0 : ds->flags |= DOCK_UNDOCKING;
358 : : }
359 : :
360 : 0 : static inline void complete_undock(struct dock_station *ds)
361 : : {
362 : 0 : ds->flags &= ~(DOCK_UNDOCKING);
363 : : }
364 : :
365 : : /**
366 : : * dock_in_progress - see if we are in the middle of handling a dock event
367 : : * @ds: the dock station
368 : : *
369 : : * Sometimes while docking, false dock events can be sent to the driver
370 : : * because good connections aren't made or some other reason. Ignore these
371 : : * if we are in the middle of doing something.
372 : : */
373 : 0 : static int dock_in_progress(struct dock_station *ds)
374 : : {
375 : 0 : if ((ds->flags & DOCK_DOCKING) ||
376 [ # # # # : 0 : time_before(jiffies, (ds->last_dock_time + HZ)))
# # ]
377 : : return 1;
378 : : return 0;
379 : : }
380 : :
381 : : /**
382 : : * handle_eject_request - handle an undock request checking for error conditions
383 : : *
384 : : * Check to make sure the dock device is still present, then undock and
385 : : * hotremove all the devices that may need removing.
386 : : */
387 : 0 : static int handle_eject_request(struct dock_station *ds, u32 event)
388 : : {
389 [ # # ]: 0 : if (dock_in_progress(ds))
390 : : return -EBUSY;
391 : :
392 : : /*
393 : : * here we need to generate the undock
394 : : * event prior to actually doing the undock
395 : : * so that the device struct still exists.
396 : : * Also, even send the dock event if the
397 : : * device is not present anymore
398 : : */
399 : 0 : dock_event(ds, event, UNDOCK_EVENT);
400 : :
401 : 0 : hot_remove_dock_devices(ds);
402 : 0 : undock(ds);
403 : 0 : acpi_evaluate_lck(ds->handle, 0);
404 : 0 : acpi_evaluate_ej0(ds->handle);
405 [ # # ]: 0 : if (dock_present(ds)) {
406 : 0 : acpi_handle_err(ds->handle, "Unable to undock!\n");
407 : 0 : return -EBUSY;
408 : : }
409 : 0 : complete_undock(ds);
410 : 0 : return 0;
411 : : }
412 : :
413 : : /**
414 : : * dock_notify - Handle ACPI dock notification.
415 : : * @adev: Dock station's ACPI device object.
416 : : * @event: Event code.
417 : : *
418 : : * If we are notified to dock, then check to see if the dock is
419 : : * present and then dock. Notify all drivers of the dock event,
420 : : * and then hotplug and devices that may need hotplugging.
421 : : */
422 : 0 : int dock_notify(struct acpi_device *adev, u32 event)
423 : : {
424 : 0 : acpi_handle handle = adev->handle;
425 : 0 : struct dock_station *ds = find_dock_station(handle);
426 : 0 : int surprise_removal = 0;
427 : :
428 [ # # ]: 0 : if (!ds)
429 : : return -ENODEV;
430 : :
431 : : /*
432 : : * According to acpi spec 3.0a, if a DEVICE_CHECK notification
433 : : * is sent and _DCK is present, it is assumed to mean an undock
434 : : * request.
435 : : */
436 [ # # # # ]: 0 : if ((ds->flags & DOCK_IS_DOCK) && event == ACPI_NOTIFY_DEVICE_CHECK)
437 : : event = ACPI_NOTIFY_EJECT_REQUEST;
438 : :
439 : : /*
440 : : * dock station: BUS_CHECK - docked or surprise removal
441 : : * DEVICE_CHECK - undocked
442 : : * other device: BUS_CHECK/DEVICE_CHECK - added or surprise removal
443 : : *
444 : : * To simplify event handling, dock dependent device handler always
445 : : * get ACPI_NOTIFY_BUS_CHECK/ACPI_NOTIFY_DEVICE_CHECK for add and
446 : : * ACPI_NOTIFY_EJECT_REQUEST for removal
447 : : */
448 [ # # # ]: 0 : switch (event) {
449 : 0 : case ACPI_NOTIFY_BUS_CHECK:
450 : : case ACPI_NOTIFY_DEVICE_CHECK:
451 [ # # # # ]: 0 : if (!dock_in_progress(ds) && !acpi_device_enumerated(adev)) {
452 : 0 : begin_dock(ds);
453 : 0 : dock(ds);
454 [ # # ]: 0 : if (!dock_present(ds)) {
455 : 0 : acpi_handle_err(handle, "Unable to dock!\n");
456 : 0 : complete_dock(ds);
457 : : break;
458 : : }
459 : 0 : hotplug_dock_devices(ds, event);
460 : 0 : complete_dock(ds);
461 : 0 : dock_event(ds, event, DOCK_EVENT);
462 : 0 : acpi_evaluate_lck(ds->handle, 1);
463 : 0 : acpi_update_all_gpes();
464 : 0 : break;
465 : : }
466 [ # # # # ]: 0 : if (dock_present(ds) || dock_in_progress(ds))
467 : : break;
468 : : /* This is a surprise removal */
469 : : surprise_removal = 1;
470 : : event = ACPI_NOTIFY_EJECT_REQUEST;
471 : : /* Fall back */
472 : : /* fall through */
473 : 0 : case ACPI_NOTIFY_EJECT_REQUEST:
474 : 0 : begin_undock(ds);
475 [ # # # # ]: 0 : if ((immediate_undock && !(ds->flags & DOCK_IS_ATA))
476 [ # # ]: 0 : || surprise_removal)
477 : 0 : handle_eject_request(ds, event);
478 : : else
479 : 0 : dock_event(ds, event, UNDOCK_EVENT);
480 : : break;
481 : : }
482 : 0 : return 0;
483 : : }
484 : :
485 : : /*
486 : : * show_docked - read method for "docked" file in sysfs
487 : : */
488 : 0 : static ssize_t show_docked(struct device *dev,
489 : : struct device_attribute *attr, char *buf)
490 : : {
491 : 0 : struct dock_station *dock_station = dev->platform_data;
492 : 0 : struct acpi_device *adev = NULL;
493 : :
494 : 0 : acpi_bus_get_device(dock_station->handle, &adev);
495 [ # # ]: 0 : return snprintf(buf, PAGE_SIZE, "%u\n", acpi_device_enumerated(adev));
496 : : }
497 : : static DEVICE_ATTR(docked, S_IRUGO, show_docked, NULL);
498 : :
499 : : /*
500 : : * show_flags - read method for flags file in sysfs
501 : : */
502 : 0 : static ssize_t show_flags(struct device *dev,
503 : : struct device_attribute *attr, char *buf)
504 : : {
505 : 0 : struct dock_station *dock_station = dev->platform_data;
506 : 0 : return snprintf(buf, PAGE_SIZE, "%d\n", dock_station->flags);
507 : :
508 : : }
509 : : static DEVICE_ATTR(flags, S_IRUGO, show_flags, NULL);
510 : :
511 : : /*
512 : : * write_undock - write method for "undock" file in sysfs
513 : : */
514 : 0 : static ssize_t write_undock(struct device *dev, struct device_attribute *attr,
515 : : const char *buf, size_t count)
516 : : {
517 : 0 : int ret;
518 : 0 : struct dock_station *dock_station = dev->platform_data;
519 : :
520 [ # # ]: 0 : if (!count)
521 : : return -EINVAL;
522 : :
523 : 0 : acpi_scan_lock_acquire();
524 : 0 : begin_undock(dock_station);
525 : 0 : ret = handle_eject_request(dock_station, ACPI_NOTIFY_EJECT_REQUEST);
526 : 0 : acpi_scan_lock_release();
527 [ # # ]: 0 : return ret ? ret: count;
528 : : }
529 : : static DEVICE_ATTR(undock, S_IWUSR, NULL, write_undock);
530 : :
531 : : /*
532 : : * show_dock_uid - read method for "uid" file in sysfs
533 : : */
534 : 0 : static ssize_t show_dock_uid(struct device *dev,
535 : : struct device_attribute *attr, char *buf)
536 : : {
537 : 0 : unsigned long long lbuf;
538 : 0 : struct dock_station *dock_station = dev->platform_data;
539 : 0 : acpi_status status = acpi_evaluate_integer(dock_station->handle,
540 : : "_UID", NULL, &lbuf);
541 [ # # ]: 0 : if (ACPI_FAILURE(status))
542 : : return 0;
543 : :
544 : 0 : return snprintf(buf, PAGE_SIZE, "%llx\n", lbuf);
545 : : }
546 : : static DEVICE_ATTR(uid, S_IRUGO, show_dock_uid, NULL);
547 : :
548 : 0 : static ssize_t show_dock_type(struct device *dev,
549 : : struct device_attribute *attr, char *buf)
550 : : {
551 : 0 : struct dock_station *dock_station = dev->platform_data;
552 : 0 : char *type;
553 : :
554 [ # # ]: 0 : if (dock_station->flags & DOCK_IS_DOCK)
555 : : type = "dock_station";
556 [ # # ]: 0 : else if (dock_station->flags & DOCK_IS_ATA)
557 : : type = "ata_bay";
558 [ # # ]: 0 : else if (dock_station->flags & DOCK_IS_BAT)
559 : : type = "battery_bay";
560 : : else
561 : 0 : type = "unknown";
562 : :
563 : 0 : return snprintf(buf, PAGE_SIZE, "%s\n", type);
564 : : }
565 : : static DEVICE_ATTR(type, S_IRUGO, show_dock_type, NULL);
566 : :
567 : : static struct attribute *dock_attributes[] = {
568 : : &dev_attr_docked.attr,
569 : : &dev_attr_flags.attr,
570 : : &dev_attr_undock.attr,
571 : : &dev_attr_uid.attr,
572 : : &dev_attr_type.attr,
573 : : NULL
574 : : };
575 : :
576 : : static const struct attribute_group dock_attribute_group = {
577 : : .attrs = dock_attributes
578 : : };
579 : :
580 : : /**
581 : : * acpi_dock_add - Add a new dock station
582 : : * @adev: Dock station ACPI device object.
583 : : *
584 : : * allocated and initialize a new dock station device.
585 : : */
586 : 0 : void acpi_dock_add(struct acpi_device *adev)
587 : : {
588 : 0 : struct dock_station *dock_station, ds = { NULL, };
589 : 0 : struct platform_device_info pdevinfo;
590 : 0 : acpi_handle handle = adev->handle;
591 : 0 : struct platform_device *dd;
592 : 0 : int ret;
593 : :
594 : 0 : memset(&pdevinfo, 0, sizeof(pdevinfo));
595 : 0 : pdevinfo.name = "dock";
596 : 0 : pdevinfo.id = dock_station_count;
597 : 0 : pdevinfo.fwnode = acpi_fwnode_handle(adev);
598 : 0 : pdevinfo.data = &ds;
599 : 0 : pdevinfo.size_data = sizeof(ds);
600 : 0 : dd = platform_device_register_full(&pdevinfo);
601 [ # # ]: 0 : if (IS_ERR(dd))
602 : 0 : return;
603 : :
604 : 0 : dock_station = dd->dev.platform_data;
605 : :
606 : 0 : dock_station->handle = handle;
607 : 0 : dock_station->dock_device = dd;
608 : 0 : dock_station->last_dock_time = jiffies - HZ;
609 : :
610 : 0 : INIT_LIST_HEAD(&dock_station->sibling);
611 : 0 : INIT_LIST_HEAD(&dock_station->dependent_devices);
612 : :
613 : : /* we want the dock device to send uevents */
614 : 0 : dev_set_uevent_suppress(&dd->dev, 0);
615 : :
616 [ # # ]: 0 : if (acpi_dock_match(handle))
617 : 0 : dock_station->flags |= DOCK_IS_DOCK;
618 [ # # ]: 0 : if (acpi_ata_match(handle))
619 : 0 : dock_station->flags |= DOCK_IS_ATA;
620 [ # # ]: 0 : if (acpi_device_is_battery(adev))
621 : 0 : dock_station->flags |= DOCK_IS_BAT;
622 : :
623 : 0 : ret = sysfs_create_group(&dd->dev.kobj, &dock_attribute_group);
624 [ # # ]: 0 : if (ret)
625 : 0 : goto err_unregister;
626 : :
627 : : /* add the dock station as a device dependent on itself */
628 : 0 : ret = add_dock_dependent_device(dock_station, adev);
629 [ # # ]: 0 : if (ret)
630 : 0 : goto err_rmgroup;
631 : :
632 : 0 : dock_station_count++;
633 : 0 : list_add(&dock_station->sibling, &dock_stations);
634 : 0 : adev->flags.is_dock_station = true;
635 : 0 : dev_info(&adev->dev, "ACPI dock station (docks/bays count: %d)\n",
636 : : dock_station_count);
637 : 0 : return;
638 : :
639 : : err_rmgroup:
640 : 0 : sysfs_remove_group(&dd->dev.kobj, &dock_attribute_group);
641 : :
642 : 0 : err_unregister:
643 : 0 : platform_device_unregister(dd);
644 : 0 : acpi_handle_err(handle, "%s encountered error %d\n", __func__, ret);
645 : : }
|