0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/kernel.h>
0011 #include <linux/moduleparam.h>
0012 #include <linux/slab.h>
0013 #include <linux/init.h>
0014 #include <linux/types.h>
0015 #include <linux/notifier.h>
0016 #include <linux/platform_device.h>
0017 #include <linux/jiffies.h>
0018 #include <linux/stddef.h>
0019 #include <linux/acpi.h>
0020
0021 #include "internal.h"
0022
0023 static bool immediate_undock = 1;
0024 module_param(immediate_undock, bool, 0644);
0025 MODULE_PARM_DESC(immediate_undock, "1 (default) will cause the driver to "
0026 "undock immediately when the undock button is pressed, 0 will cause"
0027 " the driver to wait for userspace to write the undock sysfs file "
0028 " before undocking");
0029
0030 struct dock_station {
0031 acpi_handle handle;
0032 unsigned long last_dock_time;
0033 u32 flags;
0034 struct list_head dependent_devices;
0035
0036 struct list_head sibling;
0037 struct platform_device *dock_device;
0038 };
0039 static LIST_HEAD(dock_stations);
0040 static int dock_station_count;
0041
0042 struct dock_dependent_device {
0043 struct list_head list;
0044 struct acpi_device *adev;
0045 };
0046
0047 #define DOCK_DOCKING 0x00000001
0048 #define DOCK_UNDOCKING 0x00000002
0049 #define DOCK_IS_DOCK 0x00000010
0050 #define DOCK_IS_ATA 0x00000020
0051 #define DOCK_IS_BAT 0x00000040
0052 #define DOCK_EVENT 3
0053 #define UNDOCK_EVENT 2
0054
0055 enum dock_callback_type {
0056 DOCK_CALL_HANDLER,
0057 DOCK_CALL_FIXUP,
0058 DOCK_CALL_UEVENT,
0059 };
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071 static int add_dock_dependent_device(struct dock_station *ds,
0072 struct acpi_device *adev)
0073 {
0074 struct dock_dependent_device *dd;
0075
0076 dd = kzalloc(sizeof(*dd), GFP_KERNEL);
0077 if (!dd)
0078 return -ENOMEM;
0079
0080 dd->adev = adev;
0081 INIT_LIST_HEAD(&dd->list);
0082 list_add_tail(&dd->list, &ds->dependent_devices);
0083
0084 return 0;
0085 }
0086
0087 static void dock_hotplug_event(struct dock_dependent_device *dd, u32 event,
0088 enum dock_callback_type cb_type)
0089 {
0090 struct acpi_device *adev = dd->adev;
0091
0092 acpi_lock_hp_context();
0093
0094 if (!adev->hp)
0095 goto out;
0096
0097 if (cb_type == DOCK_CALL_FIXUP) {
0098 void (*fixup)(struct acpi_device *);
0099
0100 fixup = adev->hp->fixup;
0101 if (fixup) {
0102 acpi_unlock_hp_context();
0103 fixup(adev);
0104 return;
0105 }
0106 } else if (cb_type == DOCK_CALL_UEVENT) {
0107 void (*uevent)(struct acpi_device *, u32);
0108
0109 uevent = adev->hp->uevent;
0110 if (uevent) {
0111 acpi_unlock_hp_context();
0112 uevent(adev, event);
0113 return;
0114 }
0115 } else {
0116 int (*notify)(struct acpi_device *, u32);
0117
0118 notify = adev->hp->notify;
0119 if (notify) {
0120 acpi_unlock_hp_context();
0121 notify(adev, event);
0122 return;
0123 }
0124 }
0125
0126 out:
0127 acpi_unlock_hp_context();
0128 }
0129
0130 static struct dock_station *find_dock_station(acpi_handle handle)
0131 {
0132 struct dock_station *ds;
0133
0134 list_for_each_entry(ds, &dock_stations, sibling)
0135 if (ds->handle == handle)
0136 return ds;
0137
0138 return NULL;
0139 }
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149 static struct dock_dependent_device *
0150 find_dock_dependent_device(struct dock_station *ds, struct acpi_device *adev)
0151 {
0152 struct dock_dependent_device *dd;
0153
0154 list_for_each_entry(dd, &ds->dependent_devices, list)
0155 if (adev == dd->adev)
0156 return dd;
0157
0158 return NULL;
0159 }
0160
0161 void register_dock_dependent_device(struct acpi_device *adev,
0162 acpi_handle dshandle)
0163 {
0164 struct dock_station *ds = find_dock_station(dshandle);
0165
0166 if (ds && !find_dock_dependent_device(ds, adev))
0167 add_dock_dependent_device(ds, adev);
0168 }
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182 int is_dock_device(struct acpi_device *adev)
0183 {
0184 struct dock_station *dock_station;
0185
0186 if (!dock_station_count)
0187 return 0;
0188
0189 if (acpi_dock_match(adev->handle))
0190 return 1;
0191
0192 list_for_each_entry(dock_station, &dock_stations, sibling)
0193 if (find_dock_dependent_device(dock_station, adev))
0194 return 1;
0195
0196 return 0;
0197 }
0198 EXPORT_SYMBOL_GPL(is_dock_device);
0199
0200
0201
0202
0203
0204
0205
0206
0207 static int dock_present(struct dock_station *ds)
0208 {
0209 unsigned long long sta;
0210 acpi_status status;
0211
0212 if (ds) {
0213 status = acpi_evaluate_integer(ds->handle, "_STA", NULL, &sta);
0214 if (ACPI_SUCCESS(status) && sta)
0215 return 1;
0216 }
0217 return 0;
0218 }
0219
0220
0221
0222
0223
0224 static void hot_remove_dock_devices(struct dock_station *ds)
0225 {
0226 struct dock_dependent_device *dd;
0227
0228
0229
0230
0231
0232
0233 list_for_each_entry_reverse(dd, &ds->dependent_devices, list)
0234 dock_hotplug_event(dd, ACPI_NOTIFY_EJECT_REQUEST,
0235 DOCK_CALL_HANDLER);
0236
0237 list_for_each_entry_reverse(dd, &ds->dependent_devices, list)
0238 acpi_bus_trim(dd->adev);
0239 }
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251 static void hotplug_dock_devices(struct dock_station *ds, u32 event)
0252 {
0253 struct dock_dependent_device *dd;
0254
0255
0256 list_for_each_entry(dd, &ds->dependent_devices, list)
0257 dock_hotplug_event(dd, event, DOCK_CALL_FIXUP);
0258
0259
0260 list_for_each_entry(dd, &ds->dependent_devices, list)
0261 dock_hotplug_event(dd, event, DOCK_CALL_HANDLER);
0262
0263
0264
0265
0266
0267
0268
0269 list_for_each_entry(dd, &ds->dependent_devices, list) {
0270 struct acpi_device *adev = dd->adev;
0271
0272 if (!acpi_device_enumerated(adev)) {
0273 int ret = acpi_bus_scan(adev->handle);
0274
0275 if (ret)
0276 dev_dbg(&adev->dev, "scan error %d\n", -ret);
0277 }
0278 }
0279 }
0280
0281 static void dock_event(struct dock_station *ds, u32 event, int num)
0282 {
0283 struct device *dev = &ds->dock_device->dev;
0284 char event_string[13];
0285 char *envp[] = { event_string, NULL };
0286 struct dock_dependent_device *dd;
0287
0288 if (num == UNDOCK_EVENT)
0289 sprintf(event_string, "EVENT=undock");
0290 else
0291 sprintf(event_string, "EVENT=dock");
0292
0293
0294
0295
0296
0297 if (num == DOCK_EVENT)
0298 kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
0299
0300 list_for_each_entry(dd, &ds->dependent_devices, list)
0301 dock_hotplug_event(dd, event, DOCK_CALL_UEVENT);
0302
0303 if (num != DOCK_EVENT)
0304 kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
0305 }
0306
0307
0308
0309
0310
0311
0312
0313
0314 static void handle_dock(struct dock_station *ds, int dock)
0315 {
0316 acpi_status status;
0317 struct acpi_object_list arg_list;
0318 union acpi_object arg;
0319 unsigned long long value;
0320
0321 acpi_handle_info(ds->handle, "%s\n", dock ? "docking" : "undocking");
0322
0323
0324 arg_list.count = 1;
0325 arg_list.pointer = &arg;
0326 arg.type = ACPI_TYPE_INTEGER;
0327 arg.integer.value = dock;
0328 status = acpi_evaluate_integer(ds->handle, "_DCK", &arg_list, &value);
0329 if (ACPI_FAILURE(status) && status != AE_NOT_FOUND)
0330 acpi_handle_err(ds->handle, "Failed to execute _DCK (0x%x)\n",
0331 status);
0332 }
0333
0334 static inline void dock(struct dock_station *ds)
0335 {
0336 handle_dock(ds, 1);
0337 }
0338
0339 static inline void undock(struct dock_station *ds)
0340 {
0341 handle_dock(ds, 0);
0342 }
0343
0344 static inline void begin_dock(struct dock_station *ds)
0345 {
0346 ds->flags |= DOCK_DOCKING;
0347 }
0348
0349 static inline void complete_dock(struct dock_station *ds)
0350 {
0351 ds->flags &= ~(DOCK_DOCKING);
0352 ds->last_dock_time = jiffies;
0353 }
0354
0355 static inline void begin_undock(struct dock_station *ds)
0356 {
0357 ds->flags |= DOCK_UNDOCKING;
0358 }
0359
0360 static inline void complete_undock(struct dock_station *ds)
0361 {
0362 ds->flags &= ~(DOCK_UNDOCKING);
0363 }
0364
0365
0366
0367
0368
0369
0370
0371
0372
0373 static int dock_in_progress(struct dock_station *ds)
0374 {
0375 if ((ds->flags & DOCK_DOCKING) ||
0376 time_before(jiffies, (ds->last_dock_time + HZ)))
0377 return 1;
0378 return 0;
0379 }
0380
0381
0382
0383
0384
0385
0386
0387 static int handle_eject_request(struct dock_station *ds, u32 event)
0388 {
0389 if (dock_in_progress(ds))
0390 return -EBUSY;
0391
0392
0393
0394
0395
0396
0397
0398
0399 dock_event(ds, event, UNDOCK_EVENT);
0400
0401 hot_remove_dock_devices(ds);
0402 undock(ds);
0403 acpi_evaluate_lck(ds->handle, 0);
0404 acpi_evaluate_ej0(ds->handle);
0405 if (dock_present(ds)) {
0406 acpi_handle_err(ds->handle, "Unable to undock!\n");
0407 return -EBUSY;
0408 }
0409 complete_undock(ds);
0410 return 0;
0411 }
0412
0413
0414
0415
0416
0417
0418
0419
0420
0421
0422 int dock_notify(struct acpi_device *adev, u32 event)
0423 {
0424 acpi_handle handle = adev->handle;
0425 struct dock_station *ds = find_dock_station(handle);
0426 int surprise_removal = 0;
0427
0428 if (!ds)
0429 return -ENODEV;
0430
0431
0432
0433
0434
0435
0436 if ((ds->flags & DOCK_IS_DOCK) && event == ACPI_NOTIFY_DEVICE_CHECK)
0437 event = ACPI_NOTIFY_EJECT_REQUEST;
0438
0439
0440
0441
0442
0443
0444
0445
0446
0447
0448 switch (event) {
0449 case ACPI_NOTIFY_BUS_CHECK:
0450 case ACPI_NOTIFY_DEVICE_CHECK:
0451 if (!dock_in_progress(ds) && !acpi_device_enumerated(adev)) {
0452 begin_dock(ds);
0453 dock(ds);
0454 if (!dock_present(ds)) {
0455 acpi_handle_err(handle, "Unable to dock!\n");
0456 complete_dock(ds);
0457 break;
0458 }
0459 hotplug_dock_devices(ds, event);
0460 complete_dock(ds);
0461 dock_event(ds, event, DOCK_EVENT);
0462 acpi_evaluate_lck(ds->handle, 1);
0463 acpi_update_all_gpes();
0464 break;
0465 }
0466 if (dock_present(ds) || dock_in_progress(ds))
0467 break;
0468
0469 surprise_removal = 1;
0470 event = ACPI_NOTIFY_EJECT_REQUEST;
0471
0472 fallthrough;
0473 case ACPI_NOTIFY_EJECT_REQUEST:
0474 begin_undock(ds);
0475 if ((immediate_undock && !(ds->flags & DOCK_IS_ATA))
0476 || surprise_removal)
0477 handle_eject_request(ds, event);
0478 else
0479 dock_event(ds, event, UNDOCK_EVENT);
0480 break;
0481 }
0482 return 0;
0483 }
0484
0485
0486
0487
0488 static ssize_t docked_show(struct device *dev,
0489 struct device_attribute *attr, char *buf)
0490 {
0491 struct dock_station *dock_station = dev->platform_data;
0492 struct acpi_device *adev = acpi_fetch_acpi_dev(dock_station->handle);
0493
0494 return sysfs_emit(buf, "%u\n", acpi_device_enumerated(adev));
0495 }
0496 static DEVICE_ATTR_RO(docked);
0497
0498
0499
0500
0501 static ssize_t flags_show(struct device *dev,
0502 struct device_attribute *attr, char *buf)
0503 {
0504 struct dock_station *dock_station = dev->platform_data;
0505
0506 return sysfs_emit(buf, "%d\n", dock_station->flags);
0507
0508 }
0509 static DEVICE_ATTR_RO(flags);
0510
0511
0512
0513
0514 static ssize_t undock_store(struct device *dev, struct device_attribute *attr,
0515 const char *buf, size_t count)
0516 {
0517 int ret;
0518 struct dock_station *dock_station = dev->platform_data;
0519
0520 if (!count)
0521 return -EINVAL;
0522
0523 acpi_scan_lock_acquire();
0524 begin_undock(dock_station);
0525 ret = handle_eject_request(dock_station, ACPI_NOTIFY_EJECT_REQUEST);
0526 acpi_scan_lock_release();
0527 return ret ? ret : count;
0528 }
0529 static DEVICE_ATTR_WO(undock);
0530
0531
0532
0533
0534 static ssize_t uid_show(struct device *dev,
0535 struct device_attribute *attr, char *buf)
0536 {
0537 unsigned long long lbuf;
0538 struct dock_station *dock_station = dev->platform_data;
0539
0540 acpi_status status = acpi_evaluate_integer(dock_station->handle,
0541 "_UID", NULL, &lbuf);
0542 if (ACPI_FAILURE(status))
0543 return 0;
0544
0545 return sysfs_emit(buf, "%llx\n", lbuf);
0546 }
0547 static DEVICE_ATTR_RO(uid);
0548
0549 static ssize_t type_show(struct device *dev,
0550 struct device_attribute *attr, char *buf)
0551 {
0552 struct dock_station *dock_station = dev->platform_data;
0553 char *type;
0554
0555 if (dock_station->flags & DOCK_IS_DOCK)
0556 type = "dock_station";
0557 else if (dock_station->flags & DOCK_IS_ATA)
0558 type = "ata_bay";
0559 else if (dock_station->flags & DOCK_IS_BAT)
0560 type = "battery_bay";
0561 else
0562 type = "unknown";
0563
0564 return sysfs_emit(buf, "%s\n", type);
0565 }
0566 static DEVICE_ATTR_RO(type);
0567
0568 static struct attribute *dock_attributes[] = {
0569 &dev_attr_docked.attr,
0570 &dev_attr_flags.attr,
0571 &dev_attr_undock.attr,
0572 &dev_attr_uid.attr,
0573 &dev_attr_type.attr,
0574 NULL
0575 };
0576
0577 static const struct attribute_group dock_attribute_group = {
0578 .attrs = dock_attributes
0579 };
0580
0581
0582
0583
0584
0585
0586
0587 void acpi_dock_add(struct acpi_device *adev)
0588 {
0589 struct dock_station *dock_station, ds = { NULL, };
0590 struct platform_device_info pdevinfo;
0591 acpi_handle handle = adev->handle;
0592 struct platform_device *dd;
0593 int ret;
0594
0595 memset(&pdevinfo, 0, sizeof(pdevinfo));
0596 pdevinfo.name = "dock";
0597 pdevinfo.id = dock_station_count;
0598 pdevinfo.fwnode = acpi_fwnode_handle(adev);
0599 pdevinfo.data = &ds;
0600 pdevinfo.size_data = sizeof(ds);
0601 dd = platform_device_register_full(&pdevinfo);
0602 if (IS_ERR(dd))
0603 return;
0604
0605 dock_station = dd->dev.platform_data;
0606
0607 dock_station->handle = handle;
0608 dock_station->dock_device = dd;
0609 dock_station->last_dock_time = jiffies - HZ;
0610
0611 INIT_LIST_HEAD(&dock_station->sibling);
0612 INIT_LIST_HEAD(&dock_station->dependent_devices);
0613
0614
0615 dev_set_uevent_suppress(&dd->dev, 0);
0616
0617 if (acpi_dock_match(handle))
0618 dock_station->flags |= DOCK_IS_DOCK;
0619 if (acpi_ata_match(handle))
0620 dock_station->flags |= DOCK_IS_ATA;
0621 if (acpi_device_is_battery(adev))
0622 dock_station->flags |= DOCK_IS_BAT;
0623
0624 ret = sysfs_create_group(&dd->dev.kobj, &dock_attribute_group);
0625 if (ret)
0626 goto err_unregister;
0627
0628
0629 ret = add_dock_dependent_device(dock_station, adev);
0630 if (ret)
0631 goto err_rmgroup;
0632
0633 dock_station_count++;
0634 list_add(&dock_station->sibling, &dock_stations);
0635 adev->flags.is_dock_station = true;
0636 dev_info(&adev->dev, "ACPI dock station (docks/bays count: %d)\n",
0637 dock_station_count);
0638 return;
0639
0640 err_rmgroup:
0641 sysfs_remove_group(&dd->dev.kobj, &dock_attribute_group);
0642
0643 err_unregister:
0644 platform_device_unregister(dd);
0645 acpi_handle_err(handle, "%s encountered error %d\n", __func__, ret);
0646 }