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