2 * dock.c - ACPI dock station driver
4 * Copyright (C) 2006, 2014, Intel Corp.
5 * Author: Kristen Carlson Accardi <kristen.c.accardi@intel.com>
6 * Rafael J. Wysocki <rafael.j.wysocki@intel.com>
8 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or (at
13 * your option) any later version.
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
20 * You should have received a copy of the GNU General Public License along
21 * with this program; if not, write to the Free Software Foundation, Inc.,
22 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
24 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
27 #include <linux/kernel.h>
28 #include <linux/module.h>
29 #include <linux/slab.h>
30 #include <linux/init.h>
31 #include <linux/types.h>
32 #include <linux/notifier.h>
33 #include <linux/platform_device.h>
34 #include <linux/jiffies.h>
35 #include <linux/stddef.h>
36 #include <linux/acpi.h>
40 #define ACPI_DOCK_DRIVER_DESCRIPTION "ACPI Dock Station Driver"
42 ACPI_MODULE_NAME("dock");
43 MODULE_AUTHOR("Kristen Carlson Accardi");
44 MODULE_DESCRIPTION(ACPI_DOCK_DRIVER_DESCRIPTION
);
45 MODULE_LICENSE("GPL");
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 "
56 unsigned long last_dock_time
;
58 struct list_head dependent_devices
;
60 struct list_head sibling
;
61 struct platform_device
*dock_device
;
63 static LIST_HEAD(dock_stations
);
64 static int dock_station_count
;
66 struct dock_dependent_device
{
67 struct list_head list
;
68 struct acpi_device
*adev
;
71 #define DOCK_DOCKING 0x00000001
72 #define DOCK_UNDOCKING 0x00000002
73 #define DOCK_IS_DOCK 0x00000010
74 #define DOCK_IS_ATA 0x00000020
75 #define DOCK_IS_BAT 0x00000040
77 #define UNDOCK_EVENT 2
79 enum dock_callback_type
{
85 /*****************************************************************************
86 * Dock Dependent device functions *
87 *****************************************************************************/
89 * add_dock_dependent_device - associate a device with the dock station
91 * @adev: Dependent ACPI device object.
93 * Add the dependent device to the dock's dependent device list.
95 static int add_dock_dependent_device(struct dock_station
*ds
,
96 struct acpi_device
*adev
)
98 struct dock_dependent_device
*dd
;
100 dd
= kzalloc(sizeof(*dd
), GFP_KERNEL
);
105 INIT_LIST_HEAD(&dd
->list
);
106 list_add_tail(&dd
->list
, &ds
->dependent_devices
);
111 static void dock_hotplug_event(struct dock_dependent_device
*dd
, u32 event
,
112 enum dock_callback_type cb_type
)
114 struct acpi_device
*adev
= dd
->adev
;
116 acpi_lock_hp_context();
121 if (cb_type
== DOCK_CALL_FIXUP
) {
122 void (*fixup
)(struct acpi_device
*);
124 fixup
= adev
->hp
->fixup
;
126 acpi_unlock_hp_context();
130 } else if (cb_type
== DOCK_CALL_UEVENT
) {
131 void (*uevent
)(struct acpi_device
*, u32
);
133 uevent
= adev
->hp
->uevent
;
135 acpi_unlock_hp_context();
140 int (*notify
)(struct acpi_device
*, u32
);
142 notify
= adev
->hp
->notify
;
144 acpi_unlock_hp_context();
151 acpi_unlock_hp_context();
154 static struct dock_station
*find_dock_station(acpi_handle handle
)
156 struct dock_station
*ds
;
158 list_for_each_entry(ds
, &dock_stations
, sibling
)
159 if (ds
->handle
== handle
)
166 * find_dock_dependent_device - get a device dependent on this dock
167 * @ds: the dock station
168 * @adev: ACPI device object to find.
170 * iterate over the dependent device list for this dock. If the
171 * dependent device matches the handle, return.
173 static struct dock_dependent_device
*
174 find_dock_dependent_device(struct dock_station
*ds
, struct acpi_device
*adev
)
176 struct dock_dependent_device
*dd
;
178 list_for_each_entry(dd
, &ds
->dependent_devices
, list
)
179 if (adev
== dd
->adev
)
185 void register_dock_dependent_device(struct acpi_device
*adev
,
186 acpi_handle dshandle
)
188 struct dock_station
*ds
= find_dock_station(dshandle
);
190 if (ds
&& !find_dock_dependent_device(ds
, adev
))
191 add_dock_dependent_device(ds
, adev
);
194 /*****************************************************************************
196 *****************************************************************************/
199 * is_dock_device - see if a device is on a dock station
200 * @adev: ACPI device object to check.
202 * If this device is either the dock station itself,
203 * or is a device dependent on the dock station, then it
206 int is_dock_device(struct acpi_device
*adev
)
208 struct dock_station
*dock_station
;
210 if (!dock_station_count
)
213 if (acpi_dock_match(adev
->handle
))
216 list_for_each_entry(dock_station
, &dock_stations
, sibling
)
217 if (find_dock_dependent_device(dock_station
, adev
))
222 EXPORT_SYMBOL_GPL(is_dock_device
);
225 * dock_present - see if the dock station is present.
226 * @ds: the dock station
228 * execute the _STA method. note that present does not
229 * imply that we are docked.
231 static int dock_present(struct dock_station
*ds
)
233 unsigned long long sta
;
237 status
= acpi_evaluate_integer(ds
->handle
, "_STA", NULL
, &sta
);
238 if (ACPI_SUCCESS(status
) && sta
)
245 * hot_remove_dock_devices - Remove dock station devices.
248 static void hot_remove_dock_devices(struct dock_station
*ds
)
250 struct dock_dependent_device
*dd
;
253 * Walk the list in reverse order so that devices that have been added
254 * last are removed first (in case there are some indirect dependencies
257 list_for_each_entry_reverse(dd
, &ds
->dependent_devices
, list
)
258 dock_hotplug_event(dd
, ACPI_NOTIFY_EJECT_REQUEST
, false);
260 list_for_each_entry_reverse(dd
, &ds
->dependent_devices
, list
)
261 acpi_bus_trim(dd
->adev
);
265 * hotplug_dock_devices - Insert devices on a dock station.
266 * @ds: the dock station
267 * @event: either bus check or device check request
269 * Some devices on the dock station need to have drivers called
270 * to perform hotplug operations after a dock event has occurred.
271 * Traverse the list of dock devices that have registered a
272 * hotplug handler, and call the handler.
274 static void hotplug_dock_devices(struct dock_station
*ds
, u32 event
)
276 struct dock_dependent_device
*dd
;
278 /* Call driver specific post-dock fixups. */
279 list_for_each_entry(dd
, &ds
->dependent_devices
, list
)
280 dock_hotplug_event(dd
, event
, DOCK_CALL_FIXUP
);
282 /* Call driver specific hotplug functions. */
283 list_for_each_entry(dd
, &ds
->dependent_devices
, list
)
284 dock_hotplug_event(dd
, event
, DOCK_CALL_HANDLER
);
287 * Check if all devices have been enumerated already. If not, run
288 * acpi_bus_scan() for them and that will cause scan handlers to be
289 * attached to device objects or acpi_drivers to be stopped/started if
292 list_for_each_entry(dd
, &ds
->dependent_devices
, list
) {
293 struct acpi_device
*adev
= dd
->adev
;
295 if (!acpi_device_enumerated(adev
)) {
296 int ret
= acpi_bus_scan(adev
->handle
);
298 dev_dbg(&adev
->dev
, "scan error %d\n", -ret
);
303 static void dock_event(struct dock_station
*ds
, u32 event
, int num
)
305 struct device
*dev
= &ds
->dock_device
->dev
;
306 char event_string
[13];
307 char *envp
[] = { event_string
, NULL
};
308 struct dock_dependent_device
*dd
;
310 if (num
== UNDOCK_EVENT
)
311 sprintf(event_string
, "EVENT=undock");
313 sprintf(event_string
, "EVENT=dock");
316 * Indicate that the status of the dock station has
319 if (num
== DOCK_EVENT
)
320 kobject_uevent_env(&dev
->kobj
, KOBJ_CHANGE
, envp
);
322 list_for_each_entry(dd
, &ds
->dependent_devices
, list
)
323 dock_hotplug_event(dd
, event
, DOCK_CALL_UEVENT
);
325 if (num
!= DOCK_EVENT
)
326 kobject_uevent_env(&dev
->kobj
, KOBJ_CHANGE
, envp
);
330 * handle_dock - handle a dock event
331 * @ds: the dock station
332 * @dock: to dock, or undock - that is the question
334 * Execute the _DCK method in response to an acpi event
336 static void handle_dock(struct dock_station
*ds
, int dock
)
339 struct acpi_object_list arg_list
;
340 union acpi_object arg
;
341 unsigned long long value
;
343 acpi_handle_info(ds
->handle
, "%s\n", dock
? "docking" : "undocking");
345 /* _DCK method has one argument */
347 arg_list
.pointer
= &arg
;
348 arg
.type
= ACPI_TYPE_INTEGER
;
349 arg
.integer
.value
= dock
;
350 status
= acpi_evaluate_integer(ds
->handle
, "_DCK", &arg_list
, &value
);
351 if (ACPI_FAILURE(status
) && status
!= AE_NOT_FOUND
)
352 acpi_handle_err(ds
->handle
, "Failed to execute _DCK (0x%x)\n",
356 static inline void dock(struct dock_station
*ds
)
361 static inline void undock(struct dock_station
*ds
)
366 static inline void begin_dock(struct dock_station
*ds
)
368 ds
->flags
|= DOCK_DOCKING
;
371 static inline void complete_dock(struct dock_station
*ds
)
373 ds
->flags
&= ~(DOCK_DOCKING
);
374 ds
->last_dock_time
= jiffies
;
377 static inline void begin_undock(struct dock_station
*ds
)
379 ds
->flags
|= DOCK_UNDOCKING
;
382 static inline void complete_undock(struct dock_station
*ds
)
384 ds
->flags
&= ~(DOCK_UNDOCKING
);
388 * dock_in_progress - see if we are in the middle of handling a dock event
389 * @ds: the dock station
391 * Sometimes while docking, false dock events can be sent to the driver
392 * because good connections aren't made or some other reason. Ignore these
393 * if we are in the middle of doing something.
395 static int dock_in_progress(struct dock_station
*ds
)
397 if ((ds
->flags
& DOCK_DOCKING
) ||
398 time_before(jiffies
, (ds
->last_dock_time
+ HZ
)))
404 * handle_eject_request - handle an undock request checking for error conditions
406 * Check to make sure the dock device is still present, then undock and
407 * hotremove all the devices that may need removing.
409 static int handle_eject_request(struct dock_station
*ds
, u32 event
)
411 if (dock_in_progress(ds
))
415 * here we need to generate the undock
416 * event prior to actually doing the undock
417 * so that the device struct still exists.
418 * Also, even send the dock event if the
419 * device is not present anymore
421 dock_event(ds
, event
, UNDOCK_EVENT
);
423 hot_remove_dock_devices(ds
);
425 acpi_evaluate_lck(ds
->handle
, 0);
426 acpi_evaluate_ej0(ds
->handle
);
427 if (dock_present(ds
)) {
428 acpi_handle_err(ds
->handle
, "Unable to undock!\n");
436 * dock_notify - Handle ACPI dock notification.
437 * @adev: Dock station's ACPI device object.
438 * @event: Event code.
440 * If we are notified to dock, then check to see if the dock is
441 * present and then dock. Notify all drivers of the dock event,
442 * and then hotplug and devices that may need hotplugging.
444 int dock_notify(struct acpi_device
*adev
, u32 event
)
446 acpi_handle handle
= adev
->handle
;
447 struct dock_station
*ds
= find_dock_station(handle
);
448 int surprise_removal
= 0;
454 * According to acpi spec 3.0a, if a DEVICE_CHECK notification
455 * is sent and _DCK is present, it is assumed to mean an undock
458 if ((ds
->flags
& DOCK_IS_DOCK
) && event
== ACPI_NOTIFY_DEVICE_CHECK
)
459 event
= ACPI_NOTIFY_EJECT_REQUEST
;
462 * dock station: BUS_CHECK - docked or surprise removal
463 * DEVICE_CHECK - undocked
464 * other device: BUS_CHECK/DEVICE_CHECK - added or surprise removal
466 * To simplify event handling, dock dependent device handler always
467 * get ACPI_NOTIFY_BUS_CHECK/ACPI_NOTIFY_DEVICE_CHECK for add and
468 * ACPI_NOTIFY_EJECT_REQUEST for removal
471 case ACPI_NOTIFY_BUS_CHECK
:
472 case ACPI_NOTIFY_DEVICE_CHECK
:
473 if (!dock_in_progress(ds
) && !acpi_device_enumerated(adev
)) {
476 if (!dock_present(ds
)) {
477 acpi_handle_err(handle
, "Unable to dock!\n");
481 hotplug_dock_devices(ds
, event
);
483 dock_event(ds
, event
, DOCK_EVENT
);
484 acpi_evaluate_lck(ds
->handle
, 1);
485 acpi_update_all_gpes();
488 if (dock_present(ds
) || dock_in_progress(ds
))
490 /* This is a surprise removal */
491 surprise_removal
= 1;
492 event
= ACPI_NOTIFY_EJECT_REQUEST
;
494 case ACPI_NOTIFY_EJECT_REQUEST
:
496 if ((immediate_undock
&& !(ds
->flags
& DOCK_IS_ATA
))
498 handle_eject_request(ds
, event
);
500 dock_event(ds
, event
, UNDOCK_EVENT
);
507 * show_docked - read method for "docked" file in sysfs
509 static ssize_t
show_docked(struct device
*dev
,
510 struct device_attribute
*attr
, char *buf
)
512 struct dock_station
*dock_station
= dev
->platform_data
;
513 struct acpi_device
*adev
= NULL
;
515 acpi_bus_get_device(dock_station
->handle
, &adev
);
516 return snprintf(buf
, PAGE_SIZE
, "%u\n", acpi_device_enumerated(adev
));
518 static DEVICE_ATTR(docked
, S_IRUGO
, show_docked
, NULL
);
521 * show_flags - read method for flags file in sysfs
523 static ssize_t
show_flags(struct device
*dev
,
524 struct device_attribute
*attr
, char *buf
)
526 struct dock_station
*dock_station
= dev
->platform_data
;
527 return snprintf(buf
, PAGE_SIZE
, "%d\n", dock_station
->flags
);
530 static DEVICE_ATTR(flags
, S_IRUGO
, show_flags
, NULL
);
533 * write_undock - write method for "undock" file in sysfs
535 static ssize_t
write_undock(struct device
*dev
, struct device_attribute
*attr
,
536 const char *buf
, size_t count
)
539 struct dock_station
*dock_station
= dev
->platform_data
;
544 acpi_scan_lock_acquire();
545 begin_undock(dock_station
);
546 ret
= handle_eject_request(dock_station
, ACPI_NOTIFY_EJECT_REQUEST
);
547 acpi_scan_lock_release();
548 return ret
? ret
: count
;
550 static DEVICE_ATTR(undock
, S_IWUSR
, NULL
, write_undock
);
553 * show_dock_uid - read method for "uid" file in sysfs
555 static ssize_t
show_dock_uid(struct device
*dev
,
556 struct device_attribute
*attr
, char *buf
)
558 unsigned long long lbuf
;
559 struct dock_station
*dock_station
= dev
->platform_data
;
560 acpi_status status
= acpi_evaluate_integer(dock_station
->handle
,
561 "_UID", NULL
, &lbuf
);
562 if (ACPI_FAILURE(status
))
565 return snprintf(buf
, PAGE_SIZE
, "%llx\n", lbuf
);
567 static DEVICE_ATTR(uid
, S_IRUGO
, show_dock_uid
, NULL
);
569 static ssize_t
show_dock_type(struct device
*dev
,
570 struct device_attribute
*attr
, char *buf
)
572 struct dock_station
*dock_station
= dev
->platform_data
;
575 if (dock_station
->flags
& DOCK_IS_DOCK
)
576 type
= "dock_station";
577 else if (dock_station
->flags
& DOCK_IS_ATA
)
579 else if (dock_station
->flags
& DOCK_IS_BAT
)
580 type
= "battery_bay";
584 return snprintf(buf
, PAGE_SIZE
, "%s\n", type
);
586 static DEVICE_ATTR(type
, S_IRUGO
, show_dock_type
, NULL
);
588 static struct attribute
*dock_attributes
[] = {
589 &dev_attr_docked
.attr
,
590 &dev_attr_flags
.attr
,
591 &dev_attr_undock
.attr
,
597 static struct attribute_group dock_attribute_group
= {
598 .attrs
= dock_attributes
602 * acpi_dock_add - Add a new dock station
603 * @adev: Dock station ACPI device object.
605 * allocated and initialize a new dock station device.
607 void acpi_dock_add(struct acpi_device
*adev
)
609 struct dock_station
*dock_station
, ds
= { NULL
, };
610 struct platform_device_info pdevinfo
;
611 acpi_handle handle
= adev
->handle
;
612 struct platform_device
*dd
;
615 memset(&pdevinfo
, 0, sizeof(pdevinfo
));
616 pdevinfo
.name
= "dock";
617 pdevinfo
.id
= dock_station_count
;
618 pdevinfo
.acpi_node
.companion
= adev
;
620 pdevinfo
.size_data
= sizeof(ds
);
621 dd
= platform_device_register_full(&pdevinfo
);
625 dock_station
= dd
->dev
.platform_data
;
627 dock_station
->handle
= handle
;
628 dock_station
->dock_device
= dd
;
629 dock_station
->last_dock_time
= jiffies
- HZ
;
631 INIT_LIST_HEAD(&dock_station
->sibling
);
632 INIT_LIST_HEAD(&dock_station
->dependent_devices
);
634 /* we want the dock device to send uevents */
635 dev_set_uevent_suppress(&dd
->dev
, 0);
637 if (acpi_dock_match(handle
))
638 dock_station
->flags
|= DOCK_IS_DOCK
;
639 if (acpi_ata_match(handle
))
640 dock_station
->flags
|= DOCK_IS_ATA
;
641 if (acpi_device_is_battery(adev
))
642 dock_station
->flags
|= DOCK_IS_BAT
;
644 ret
= sysfs_create_group(&dd
->dev
.kobj
, &dock_attribute_group
);
648 /* add the dock station as a device dependent on itself */
649 ret
= add_dock_dependent_device(dock_station
, adev
);
653 dock_station_count
++;
654 list_add(&dock_station
->sibling
, &dock_stations
);
655 adev
->flags
.is_dock_station
= true;
656 dev_info(&adev
->dev
, "ACPI dock station (docks/bays count: %d)\n",
661 sysfs_remove_group(&dd
->dev
.kobj
, &dock_attribute_group
);
664 platform_device_unregister(dd
);
665 acpi_handle_err(handle
, "%s encountered error %d\n", __func__
, ret
);