Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

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