Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/acpi/dock.c
15109 views
1
/*
2
* dock.c - ACPI dock station driver
3
*
4
* Copyright (C) 2006 Kristen Carlson Accardi <[email protected]>
5
*
6
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
7
*
8
* This program is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License as published by
10
* the Free Software Foundation; either version 2 of the License, or (at
11
* your option) any later version.
12
*
13
* This program is distributed in the hope that it will be useful, but
14
* WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
* General Public License for more details.
17
*
18
* You should have received a copy of the GNU General Public License along
19
* with this program; if not, write to the Free Software Foundation, Inc.,
20
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
21
*
22
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
23
*/
24
25
#include <linux/kernel.h>
26
#include <linux/module.h>
27
#include <linux/slab.h>
28
#include <linux/init.h>
29
#include <linux/types.h>
30
#include <linux/notifier.h>
31
#include <linux/platform_device.h>
32
#include <linux/jiffies.h>
33
#include <linux/stddef.h>
34
#include <acpi/acpi_bus.h>
35
#include <acpi/acpi_drivers.h>
36
37
#define PREFIX "ACPI: "
38
39
#define ACPI_DOCK_DRIVER_DESCRIPTION "ACPI Dock Station Driver"
40
41
ACPI_MODULE_NAME("dock");
42
MODULE_AUTHOR("Kristen Carlson Accardi");
43
MODULE_DESCRIPTION(ACPI_DOCK_DRIVER_DESCRIPTION);
44
MODULE_LICENSE("GPL");
45
46
static int immediate_undock = 1;
47
module_param(immediate_undock, bool, 0644);
48
MODULE_PARM_DESC(immediate_undock, "1 (default) will cause the driver to "
49
"undock immediately when the undock button is pressed, 0 will cause"
50
" the driver to wait for userspace to write the undock sysfs file "
51
" before undocking");
52
53
static struct atomic_notifier_head dock_notifier_list;
54
55
static const struct acpi_device_id dock_device_ids[] = {
56
{"LNXDOCK", 0},
57
{"", 0},
58
};
59
MODULE_DEVICE_TABLE(acpi, dock_device_ids);
60
61
struct dock_station {
62
acpi_handle handle;
63
unsigned long last_dock_time;
64
u32 flags;
65
spinlock_t dd_lock;
66
struct mutex hp_lock;
67
struct list_head dependent_devices;
68
struct list_head hotplug_devices;
69
70
struct list_head sibling;
71
struct platform_device *dock_device;
72
};
73
static LIST_HEAD(dock_stations);
74
static int dock_station_count;
75
76
struct dock_dependent_device {
77
struct list_head list;
78
struct list_head hotplug_list;
79
acpi_handle handle;
80
struct acpi_dock_ops *ops;
81
void *context;
82
};
83
84
#define DOCK_DOCKING 0x00000001
85
#define DOCK_UNDOCKING 0x00000002
86
#define DOCK_IS_DOCK 0x00000010
87
#define DOCK_IS_ATA 0x00000020
88
#define DOCK_IS_BAT 0x00000040
89
#define DOCK_EVENT 3
90
#define UNDOCK_EVENT 2
91
92
/*****************************************************************************
93
* Dock Dependent device functions *
94
*****************************************************************************/
95
/**
96
* add_dock_dependent_device - associate a device with the dock station
97
* @ds: The dock station
98
* @handle: handle of the dependent device
99
*
100
* Add the dependent device to the dock's dependent device list.
101
*/
102
static int
103
add_dock_dependent_device(struct dock_station *ds, acpi_handle handle)
104
{
105
struct dock_dependent_device *dd;
106
107
dd = kzalloc(sizeof(*dd), GFP_KERNEL);
108
if (!dd)
109
return -ENOMEM;
110
111
dd->handle = handle;
112
INIT_LIST_HEAD(&dd->list);
113
INIT_LIST_HEAD(&dd->hotplug_list);
114
115
spin_lock(&ds->dd_lock);
116
list_add_tail(&dd->list, &ds->dependent_devices);
117
spin_unlock(&ds->dd_lock);
118
119
return 0;
120
}
121
122
/**
123
* dock_add_hotplug_device - associate a hotplug handler with the dock station
124
* @ds: The dock station
125
* @dd: The dependent device struct
126
*
127
* Add the dependent device to the dock's hotplug device list
128
*/
129
static void
130
dock_add_hotplug_device(struct dock_station *ds,
131
struct dock_dependent_device *dd)
132
{
133
mutex_lock(&ds->hp_lock);
134
list_add_tail(&dd->hotplug_list, &ds->hotplug_devices);
135
mutex_unlock(&ds->hp_lock);
136
}
137
138
/**
139
* dock_del_hotplug_device - remove a hotplug handler from the dock station
140
* @ds: The dock station
141
* @dd: the dependent device struct
142
*
143
* Delete the dependent device from the dock's hotplug device list
144
*/
145
static void
146
dock_del_hotplug_device(struct dock_station *ds,
147
struct dock_dependent_device *dd)
148
{
149
mutex_lock(&ds->hp_lock);
150
list_del(&dd->hotplug_list);
151
mutex_unlock(&ds->hp_lock);
152
}
153
154
/**
155
* find_dock_dependent_device - get a device dependent on this dock
156
* @ds: the dock station
157
* @handle: the acpi_handle of the device we want
158
*
159
* iterate over the dependent device list for this dock. If the
160
* dependent device matches the handle, return.
161
*/
162
static struct dock_dependent_device *
163
find_dock_dependent_device(struct dock_station *ds, acpi_handle handle)
164
{
165
struct dock_dependent_device *dd;
166
167
spin_lock(&ds->dd_lock);
168
list_for_each_entry(dd, &ds->dependent_devices, list) {
169
if (handle == dd->handle) {
170
spin_unlock(&ds->dd_lock);
171
return dd;
172
}
173
}
174
spin_unlock(&ds->dd_lock);
175
return NULL;
176
}
177
178
/*****************************************************************************
179
* Dock functions *
180
*****************************************************************************/
181
/**
182
* is_dock - see if a device is a dock station
183
* @handle: acpi handle of the device
184
*
185
* If an acpi object has a _DCK method, then it is by definition a dock
186
* station, so return true.
187
*/
188
static int is_dock(acpi_handle handle)
189
{
190
acpi_status status;
191
acpi_handle tmp;
192
193
status = acpi_get_handle(handle, "_DCK", &tmp);
194
if (ACPI_FAILURE(status))
195
return 0;
196
return 1;
197
}
198
199
static int is_ejectable(acpi_handle handle)
200
{
201
acpi_status status;
202
acpi_handle tmp;
203
204
status = acpi_get_handle(handle, "_EJ0", &tmp);
205
if (ACPI_FAILURE(status))
206
return 0;
207
return 1;
208
}
209
210
static int is_ata(acpi_handle handle)
211
{
212
acpi_handle tmp;
213
214
if ((ACPI_SUCCESS(acpi_get_handle(handle, "_GTF", &tmp))) ||
215
(ACPI_SUCCESS(acpi_get_handle(handle, "_GTM", &tmp))) ||
216
(ACPI_SUCCESS(acpi_get_handle(handle, "_STM", &tmp))) ||
217
(ACPI_SUCCESS(acpi_get_handle(handle, "_SDD", &tmp))))
218
return 1;
219
220
return 0;
221
}
222
223
static int is_battery(acpi_handle handle)
224
{
225
struct acpi_device_info *info;
226
int ret = 1;
227
228
if (!ACPI_SUCCESS(acpi_get_object_info(handle, &info)))
229
return 0;
230
if (!(info->valid & ACPI_VALID_HID))
231
ret = 0;
232
else
233
ret = !strcmp("PNP0C0A", info->hardware_id.string);
234
235
kfree(info);
236
return ret;
237
}
238
239
static int is_ejectable_bay(acpi_handle handle)
240
{
241
acpi_handle phandle;
242
243
if (!is_ejectable(handle))
244
return 0;
245
if (is_battery(handle) || is_ata(handle))
246
return 1;
247
if (!acpi_get_parent(handle, &phandle) && is_ata(phandle))
248
return 1;
249
return 0;
250
}
251
252
/**
253
* is_dock_device - see if a device is on a dock station
254
* @handle: acpi handle of the device
255
*
256
* If this device is either the dock station itself,
257
* or is a device dependent on the dock station, then it
258
* is a dock device
259
*/
260
int is_dock_device(acpi_handle handle)
261
{
262
struct dock_station *dock_station;
263
264
if (!dock_station_count)
265
return 0;
266
267
if (is_dock(handle))
268
return 1;
269
270
list_for_each_entry(dock_station, &dock_stations, sibling)
271
if (find_dock_dependent_device(dock_station, handle))
272
return 1;
273
274
return 0;
275
}
276
EXPORT_SYMBOL_GPL(is_dock_device);
277
278
/**
279
* dock_present - see if the dock station is present.
280
* @ds: the dock station
281
*
282
* execute the _STA method. note that present does not
283
* imply that we are docked.
284
*/
285
static int dock_present(struct dock_station *ds)
286
{
287
unsigned long long sta;
288
acpi_status status;
289
290
if (ds) {
291
status = acpi_evaluate_integer(ds->handle, "_STA", NULL, &sta);
292
if (ACPI_SUCCESS(status) && sta)
293
return 1;
294
}
295
return 0;
296
}
297
298
/**
299
* dock_create_acpi_device - add new devices to acpi
300
* @handle - handle of the device to add
301
*
302
* This function will create a new acpi_device for the given
303
* handle if one does not exist already. This should cause
304
* acpi to scan for drivers for the given devices, and call
305
* matching driver's add routine.
306
*
307
* Returns a pointer to the acpi_device corresponding to the handle.
308
*/
309
static struct acpi_device * dock_create_acpi_device(acpi_handle handle)
310
{
311
struct acpi_device *device;
312
struct acpi_device *parent_device;
313
acpi_handle parent;
314
int ret;
315
316
if (acpi_bus_get_device(handle, &device)) {
317
/*
318
* no device created for this object,
319
* so we should create one.
320
*/
321
acpi_get_parent(handle, &parent);
322
if (acpi_bus_get_device(parent, &parent_device))
323
parent_device = NULL;
324
325
ret = acpi_bus_add(&device, parent_device, handle,
326
ACPI_BUS_TYPE_DEVICE);
327
if (ret) {
328
pr_debug("error adding bus, %x\n", -ret);
329
return NULL;
330
}
331
}
332
return device;
333
}
334
335
/**
336
* dock_remove_acpi_device - remove the acpi_device struct from acpi
337
* @handle - the handle of the device to remove
338
*
339
* Tell acpi to remove the acpi_device. This should cause any loaded
340
* driver to have it's remove routine called.
341
*/
342
static void dock_remove_acpi_device(acpi_handle handle)
343
{
344
struct acpi_device *device;
345
int ret;
346
347
if (!acpi_bus_get_device(handle, &device)) {
348
ret = acpi_bus_trim(device, 1);
349
if (ret)
350
pr_debug("error removing bus, %x\n", -ret);
351
}
352
}
353
354
/**
355
* hotplug_dock_devices - insert or remove devices on the dock station
356
* @ds: the dock station
357
* @event: either bus check or eject request
358
*
359
* Some devices on the dock station need to have drivers called
360
* to perform hotplug operations after a dock event has occurred.
361
* Traverse the list of dock devices that have registered a
362
* hotplug handler, and call the handler.
363
*/
364
static void hotplug_dock_devices(struct dock_station *ds, u32 event)
365
{
366
struct dock_dependent_device *dd;
367
368
mutex_lock(&ds->hp_lock);
369
370
/*
371
* First call driver specific hotplug functions
372
*/
373
list_for_each_entry(dd, &ds->hotplug_devices, hotplug_list)
374
if (dd->ops && dd->ops->handler)
375
dd->ops->handler(dd->handle, event, dd->context);
376
377
/*
378
* Now make sure that an acpi_device is created for each
379
* dependent device, or removed if this is an eject request.
380
* This will cause acpi_drivers to be stopped/started if they
381
* exist
382
*/
383
list_for_each_entry(dd, &ds->dependent_devices, list) {
384
if (event == ACPI_NOTIFY_EJECT_REQUEST)
385
dock_remove_acpi_device(dd->handle);
386
else
387
dock_create_acpi_device(dd->handle);
388
}
389
mutex_unlock(&ds->hp_lock);
390
}
391
392
static void dock_event(struct dock_station *ds, u32 event, int num)
393
{
394
struct device *dev = &ds->dock_device->dev;
395
char event_string[13];
396
char *envp[] = { event_string, NULL };
397
struct dock_dependent_device *dd;
398
399
if (num == UNDOCK_EVENT)
400
sprintf(event_string, "EVENT=undock");
401
else
402
sprintf(event_string, "EVENT=dock");
403
404
/*
405
* Indicate that the status of the dock station has
406
* changed.
407
*/
408
if (num == DOCK_EVENT)
409
kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
410
411
list_for_each_entry(dd, &ds->hotplug_devices, hotplug_list)
412
if (dd->ops && dd->ops->uevent)
413
dd->ops->uevent(dd->handle, event, dd->context);
414
415
if (num != DOCK_EVENT)
416
kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
417
}
418
419
/**
420
* eject_dock - respond to a dock eject request
421
* @ds: the dock station
422
*
423
* This is called after _DCK is called, to execute the dock station's
424
* _EJ0 method.
425
*/
426
static void eject_dock(struct dock_station *ds)
427
{
428
struct acpi_object_list arg_list;
429
union acpi_object arg;
430
acpi_status status;
431
acpi_handle tmp;
432
433
/* all dock devices should have _EJ0, but check anyway */
434
status = acpi_get_handle(ds->handle, "_EJ0", &tmp);
435
if (ACPI_FAILURE(status)) {
436
pr_debug("No _EJ0 support for dock device\n");
437
return;
438
}
439
440
arg_list.count = 1;
441
arg_list.pointer = &arg;
442
arg.type = ACPI_TYPE_INTEGER;
443
arg.integer.value = 1;
444
445
status = acpi_evaluate_object(ds->handle, "_EJ0", &arg_list, NULL);
446
if (ACPI_FAILURE(status))
447
pr_debug("Failed to evaluate _EJ0!\n");
448
}
449
450
/**
451
* handle_dock - handle a dock event
452
* @ds: the dock station
453
* @dock: to dock, or undock - that is the question
454
*
455
* Execute the _DCK method in response to an acpi event
456
*/
457
static void handle_dock(struct dock_station *ds, int dock)
458
{
459
acpi_status status;
460
struct acpi_object_list arg_list;
461
union acpi_object arg;
462
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
463
struct acpi_buffer name_buffer = { ACPI_ALLOCATE_BUFFER, NULL };
464
465
acpi_get_name(ds->handle, ACPI_FULL_PATHNAME, &name_buffer);
466
467
printk(KERN_INFO PREFIX "%s - %s\n",
468
(char *)name_buffer.pointer, dock ? "docking" : "undocking");
469
470
/* _DCK method has one argument */
471
arg_list.count = 1;
472
arg_list.pointer = &arg;
473
arg.type = ACPI_TYPE_INTEGER;
474
arg.integer.value = dock;
475
status = acpi_evaluate_object(ds->handle, "_DCK", &arg_list, &buffer);
476
if (ACPI_FAILURE(status) && status != AE_NOT_FOUND)
477
ACPI_EXCEPTION((AE_INFO, status, "%s - failed to execute"
478
" _DCK\n", (char *)name_buffer.pointer));
479
480
kfree(buffer.pointer);
481
kfree(name_buffer.pointer);
482
}
483
484
static inline void dock(struct dock_station *ds)
485
{
486
handle_dock(ds, 1);
487
}
488
489
static inline void undock(struct dock_station *ds)
490
{
491
handle_dock(ds, 0);
492
}
493
494
static inline void begin_dock(struct dock_station *ds)
495
{
496
ds->flags |= DOCK_DOCKING;
497
}
498
499
static inline void complete_dock(struct dock_station *ds)
500
{
501
ds->flags &= ~(DOCK_DOCKING);
502
ds->last_dock_time = jiffies;
503
}
504
505
static inline void begin_undock(struct dock_station *ds)
506
{
507
ds->flags |= DOCK_UNDOCKING;
508
}
509
510
static inline void complete_undock(struct dock_station *ds)
511
{
512
ds->flags &= ~(DOCK_UNDOCKING);
513
}
514
515
static void dock_lock(struct dock_station *ds, int lock)
516
{
517
struct acpi_object_list arg_list;
518
union acpi_object arg;
519
acpi_status status;
520
521
arg_list.count = 1;
522
arg_list.pointer = &arg;
523
arg.type = ACPI_TYPE_INTEGER;
524
arg.integer.value = !!lock;
525
status = acpi_evaluate_object(ds->handle, "_LCK", &arg_list, NULL);
526
if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
527
if (lock)
528
printk(KERN_WARNING PREFIX "Locking device failed\n");
529
else
530
printk(KERN_WARNING PREFIX "Unlocking device failed\n");
531
}
532
}
533
534
/**
535
* dock_in_progress - see if we are in the middle of handling a dock event
536
* @ds: the dock station
537
*
538
* Sometimes while docking, false dock events can be sent to the driver
539
* because good connections aren't made or some other reason. Ignore these
540
* if we are in the middle of doing something.
541
*/
542
static int dock_in_progress(struct dock_station *ds)
543
{
544
if ((ds->flags & DOCK_DOCKING) ||
545
time_before(jiffies, (ds->last_dock_time + HZ)))
546
return 1;
547
return 0;
548
}
549
550
/**
551
* register_dock_notifier - add yourself to the dock notifier list
552
* @nb: the callers notifier block
553
*
554
* If a driver wishes to be notified about dock events, they can
555
* use this function to put a notifier block on the dock notifier list.
556
* this notifier call chain will be called after a dock event, but
557
* before hotplugging any new devices.
558
*/
559
int register_dock_notifier(struct notifier_block *nb)
560
{
561
if (!dock_station_count)
562
return -ENODEV;
563
564
return atomic_notifier_chain_register(&dock_notifier_list, nb);
565
}
566
EXPORT_SYMBOL_GPL(register_dock_notifier);
567
568
/**
569
* unregister_dock_notifier - remove yourself from the dock notifier list
570
* @nb: the callers notifier block
571
*/
572
void unregister_dock_notifier(struct notifier_block *nb)
573
{
574
if (!dock_station_count)
575
return;
576
577
atomic_notifier_chain_unregister(&dock_notifier_list, nb);
578
}
579
EXPORT_SYMBOL_GPL(unregister_dock_notifier);
580
581
/**
582
* register_hotplug_dock_device - register a hotplug function
583
* @handle: the handle of the device
584
* @ops: handlers to call after docking
585
* @context: device specific data
586
*
587
* If a driver would like to perform a hotplug operation after a dock
588
* event, they can register an acpi_notifiy_handler to be called by
589
* the dock driver after _DCK is executed.
590
*/
591
int
592
register_hotplug_dock_device(acpi_handle handle, struct acpi_dock_ops *ops,
593
void *context)
594
{
595
struct dock_dependent_device *dd;
596
struct dock_station *dock_station;
597
int ret = -EINVAL;
598
599
if (!dock_station_count)
600
return -ENODEV;
601
602
/*
603
* make sure this handle is for a device dependent on the dock,
604
* this would include the dock station itself
605
*/
606
list_for_each_entry(dock_station, &dock_stations, sibling) {
607
/*
608
* An ATA bay can be in a dock and itself can be ejected
609
* separately, so there are two 'dock stations' which need the
610
* ops
611
*/
612
dd = find_dock_dependent_device(dock_station, handle);
613
if (dd) {
614
dd->ops = ops;
615
dd->context = context;
616
dock_add_hotplug_device(dock_station, dd);
617
ret = 0;
618
}
619
}
620
621
return ret;
622
}
623
EXPORT_SYMBOL_GPL(register_hotplug_dock_device);
624
625
/**
626
* unregister_hotplug_dock_device - remove yourself from the hotplug list
627
* @handle: the acpi handle of the device
628
*/
629
void unregister_hotplug_dock_device(acpi_handle handle)
630
{
631
struct dock_dependent_device *dd;
632
struct dock_station *dock_station;
633
634
if (!dock_station_count)
635
return;
636
637
list_for_each_entry(dock_station, &dock_stations, sibling) {
638
dd = find_dock_dependent_device(dock_station, handle);
639
if (dd)
640
dock_del_hotplug_device(dock_station, dd);
641
}
642
}
643
EXPORT_SYMBOL_GPL(unregister_hotplug_dock_device);
644
645
/**
646
* handle_eject_request - handle an undock request checking for error conditions
647
*
648
* Check to make sure the dock device is still present, then undock and
649
* hotremove all the devices that may need removing.
650
*/
651
static int handle_eject_request(struct dock_station *ds, u32 event)
652
{
653
if (dock_in_progress(ds))
654
return -EBUSY;
655
656
/*
657
* here we need to generate the undock
658
* event prior to actually doing the undock
659
* so that the device struct still exists.
660
* Also, even send the dock event if the
661
* device is not present anymore
662
*/
663
dock_event(ds, event, UNDOCK_EVENT);
664
665
hotplug_dock_devices(ds, ACPI_NOTIFY_EJECT_REQUEST);
666
undock(ds);
667
dock_lock(ds, 0);
668
eject_dock(ds);
669
if (dock_present(ds)) {
670
printk(KERN_ERR PREFIX "Unable to undock!\n");
671
return -EBUSY;
672
}
673
complete_undock(ds);
674
return 0;
675
}
676
677
/**
678
* dock_notify - act upon an acpi dock notification
679
* @handle: the dock station handle
680
* @event: the acpi event
681
* @data: our driver data struct
682
*
683
* If we are notified to dock, then check to see if the dock is
684
* present and then dock. Notify all drivers of the dock event,
685
* and then hotplug and devices that may need hotplugging.
686
*/
687
static void dock_notify(acpi_handle handle, u32 event, void *data)
688
{
689
struct dock_station *ds = data;
690
struct acpi_device *tmp;
691
int surprise_removal = 0;
692
693
/*
694
* According to acpi spec 3.0a, if a DEVICE_CHECK notification
695
* is sent and _DCK is present, it is assumed to mean an undock
696
* request.
697
*/
698
if ((ds->flags & DOCK_IS_DOCK) && event == ACPI_NOTIFY_DEVICE_CHECK)
699
event = ACPI_NOTIFY_EJECT_REQUEST;
700
701
/*
702
* dock station: BUS_CHECK - docked or surprise removal
703
* DEVICE_CHECK - undocked
704
* other device: BUS_CHECK/DEVICE_CHECK - added or surprise removal
705
*
706
* To simplify event handling, dock dependent device handler always
707
* get ACPI_NOTIFY_BUS_CHECK/ACPI_NOTIFY_DEVICE_CHECK for add and
708
* ACPI_NOTIFY_EJECT_REQUEST for removal
709
*/
710
switch (event) {
711
case ACPI_NOTIFY_BUS_CHECK:
712
case ACPI_NOTIFY_DEVICE_CHECK:
713
if (!dock_in_progress(ds) && acpi_bus_get_device(ds->handle,
714
&tmp)) {
715
begin_dock(ds);
716
dock(ds);
717
if (!dock_present(ds)) {
718
printk(KERN_ERR PREFIX "Unable to dock!\n");
719
complete_dock(ds);
720
break;
721
}
722
atomic_notifier_call_chain(&dock_notifier_list,
723
event, NULL);
724
hotplug_dock_devices(ds, event);
725
complete_dock(ds);
726
dock_event(ds, event, DOCK_EVENT);
727
dock_lock(ds, 1);
728
acpi_update_all_gpes();
729
break;
730
}
731
if (dock_present(ds) || dock_in_progress(ds))
732
break;
733
/* This is a surprise removal */
734
surprise_removal = 1;
735
event = ACPI_NOTIFY_EJECT_REQUEST;
736
/* Fall back */
737
case ACPI_NOTIFY_EJECT_REQUEST:
738
begin_undock(ds);
739
if ((immediate_undock && !(ds->flags & DOCK_IS_ATA))
740
|| surprise_removal)
741
handle_eject_request(ds, event);
742
else
743
dock_event(ds, event, UNDOCK_EVENT);
744
break;
745
default:
746
printk(KERN_ERR PREFIX "Unknown dock event %d\n", event);
747
}
748
}
749
750
struct dock_data {
751
acpi_handle handle;
752
unsigned long event;
753
struct dock_station *ds;
754
};
755
756
static void acpi_dock_deferred_cb(void *context)
757
{
758
struct dock_data *data = context;
759
760
dock_notify(data->handle, data->event, data->ds);
761
kfree(data);
762
}
763
764
static int acpi_dock_notifier_call(struct notifier_block *this,
765
unsigned long event, void *data)
766
{
767
struct dock_station *dock_station;
768
acpi_handle handle = data;
769
770
if (event != ACPI_NOTIFY_BUS_CHECK && event != ACPI_NOTIFY_DEVICE_CHECK
771
&& event != ACPI_NOTIFY_EJECT_REQUEST)
772
return 0;
773
list_for_each_entry(dock_station, &dock_stations, sibling) {
774
if (dock_station->handle == handle) {
775
struct dock_data *dd;
776
777
dd = kmalloc(sizeof(*dd), GFP_KERNEL);
778
if (!dd)
779
return 0;
780
dd->handle = handle;
781
dd->event = event;
782
dd->ds = dock_station;
783
acpi_os_hotplug_execute(acpi_dock_deferred_cb, dd);
784
return 0 ;
785
}
786
}
787
return 0;
788
}
789
790
static struct notifier_block dock_acpi_notifier = {
791
.notifier_call = acpi_dock_notifier_call,
792
};
793
794
/**
795
* find_dock_devices - find devices on the dock station
796
* @handle: the handle of the device we are examining
797
* @lvl: unused
798
* @context: the dock station private data
799
* @rv: unused
800
*
801
* This function is called by acpi_walk_namespace. It will
802
* check to see if an object has an _EJD method. If it does, then it
803
* will see if it is dependent on the dock station.
804
*/
805
static acpi_status
806
find_dock_devices(acpi_handle handle, u32 lvl, void *context, void **rv)
807
{
808
acpi_status status;
809
acpi_handle tmp, parent;
810
struct dock_station *ds = context;
811
812
status = acpi_bus_get_ejd(handle, &tmp);
813
if (ACPI_FAILURE(status)) {
814
/* try the parent device as well */
815
status = acpi_get_parent(handle, &parent);
816
if (ACPI_FAILURE(status))
817
goto fdd_out;
818
/* see if parent is dependent on dock */
819
status = acpi_bus_get_ejd(parent, &tmp);
820
if (ACPI_FAILURE(status))
821
goto fdd_out;
822
}
823
824
if (tmp == ds->handle)
825
add_dock_dependent_device(ds, handle);
826
827
fdd_out:
828
return AE_OK;
829
}
830
831
/*
832
* show_docked - read method for "docked" file in sysfs
833
*/
834
static ssize_t show_docked(struct device *dev,
835
struct device_attribute *attr, char *buf)
836
{
837
struct acpi_device *tmp;
838
839
struct dock_station *dock_station = dev->platform_data;
840
841
if (ACPI_SUCCESS(acpi_bus_get_device(dock_station->handle, &tmp)))
842
return snprintf(buf, PAGE_SIZE, "1\n");
843
return snprintf(buf, PAGE_SIZE, "0\n");
844
}
845
static DEVICE_ATTR(docked, S_IRUGO, show_docked, NULL);
846
847
/*
848
* show_flags - read method for flags file in sysfs
849
*/
850
static ssize_t show_flags(struct device *dev,
851
struct device_attribute *attr, char *buf)
852
{
853
struct dock_station *dock_station = dev->platform_data;
854
return snprintf(buf, PAGE_SIZE, "%d\n", dock_station->flags);
855
856
}
857
static DEVICE_ATTR(flags, S_IRUGO, show_flags, NULL);
858
859
/*
860
* write_undock - write method for "undock" file in sysfs
861
*/
862
static ssize_t write_undock(struct device *dev, struct device_attribute *attr,
863
const char *buf, size_t count)
864
{
865
int ret;
866
struct dock_station *dock_station = dev->platform_data;
867
868
if (!count)
869
return -EINVAL;
870
871
begin_undock(dock_station);
872
ret = handle_eject_request(dock_station, ACPI_NOTIFY_EJECT_REQUEST);
873
return ret ? ret: count;
874
}
875
static DEVICE_ATTR(undock, S_IWUSR, NULL, write_undock);
876
877
/*
878
* show_dock_uid - read method for "uid" file in sysfs
879
*/
880
static ssize_t show_dock_uid(struct device *dev,
881
struct device_attribute *attr, char *buf)
882
{
883
unsigned long long lbuf;
884
struct dock_station *dock_station = dev->platform_data;
885
acpi_status status = acpi_evaluate_integer(dock_station->handle,
886
"_UID", NULL, &lbuf);
887
if (ACPI_FAILURE(status))
888
return 0;
889
890
return snprintf(buf, PAGE_SIZE, "%llx\n", lbuf);
891
}
892
static DEVICE_ATTR(uid, S_IRUGO, show_dock_uid, NULL);
893
894
static ssize_t show_dock_type(struct device *dev,
895
struct device_attribute *attr, char *buf)
896
{
897
struct dock_station *dock_station = dev->platform_data;
898
char *type;
899
900
if (dock_station->flags & DOCK_IS_DOCK)
901
type = "dock_station";
902
else if (dock_station->flags & DOCK_IS_ATA)
903
type = "ata_bay";
904
else if (dock_station->flags & DOCK_IS_BAT)
905
type = "battery_bay";
906
else
907
type = "unknown";
908
909
return snprintf(buf, PAGE_SIZE, "%s\n", type);
910
}
911
static DEVICE_ATTR(type, S_IRUGO, show_dock_type, NULL);
912
913
static struct attribute *dock_attributes[] = {
914
&dev_attr_docked.attr,
915
&dev_attr_flags.attr,
916
&dev_attr_undock.attr,
917
&dev_attr_uid.attr,
918
&dev_attr_type.attr,
919
NULL
920
};
921
922
static struct attribute_group dock_attribute_group = {
923
.attrs = dock_attributes
924
};
925
926
/**
927
* dock_add - add a new dock station
928
* @handle: the dock station handle
929
*
930
* allocated and initialize a new dock station device. Find all devices
931
* that are on the dock station, and register for dock event notifications.
932
*/
933
static int __init dock_add(acpi_handle handle)
934
{
935
int ret, id;
936
struct dock_station ds, *dock_station;
937
struct platform_device *dd;
938
939
id = dock_station_count;
940
memset(&ds, 0, sizeof(ds));
941
dd = platform_device_register_data(NULL, "dock", id, &ds, sizeof(ds));
942
if (IS_ERR(dd))
943
return PTR_ERR(dd);
944
945
dock_station = dd->dev.platform_data;
946
947
dock_station->handle = handle;
948
dock_station->dock_device = dd;
949
dock_station->last_dock_time = jiffies - HZ;
950
951
mutex_init(&dock_station->hp_lock);
952
spin_lock_init(&dock_station->dd_lock);
953
INIT_LIST_HEAD(&dock_station->sibling);
954
INIT_LIST_HEAD(&dock_station->hotplug_devices);
955
ATOMIC_INIT_NOTIFIER_HEAD(&dock_notifier_list);
956
INIT_LIST_HEAD(&dock_station->dependent_devices);
957
958
/* we want the dock device to send uevents */
959
dev_set_uevent_suppress(&dd->dev, 0);
960
961
if (is_dock(handle))
962
dock_station->flags |= DOCK_IS_DOCK;
963
if (is_ata(handle))
964
dock_station->flags |= DOCK_IS_ATA;
965
if (is_battery(handle))
966
dock_station->flags |= DOCK_IS_BAT;
967
968
ret = sysfs_create_group(&dd->dev.kobj, &dock_attribute_group);
969
if (ret)
970
goto err_unregister;
971
972
/* Find dependent devices */
973
acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
974
ACPI_UINT32_MAX, find_dock_devices, NULL,
975
dock_station, NULL);
976
977
/* add the dock station as a device dependent on itself */
978
ret = add_dock_dependent_device(dock_station, handle);
979
if (ret)
980
goto err_rmgroup;
981
982
dock_station_count++;
983
list_add(&dock_station->sibling, &dock_stations);
984
return 0;
985
986
err_rmgroup:
987
sysfs_remove_group(&dd->dev.kobj, &dock_attribute_group);
988
err_unregister:
989
platform_device_unregister(dd);
990
printk(KERN_ERR "%s encountered error %d\n", __func__, ret);
991
return ret;
992
}
993
994
/**
995
* dock_remove - free up resources related to the dock station
996
*/
997
static int dock_remove(struct dock_station *ds)
998
{
999
struct dock_dependent_device *dd, *tmp;
1000
struct platform_device *dock_device = ds->dock_device;
1001
1002
if (!dock_station_count)
1003
return 0;
1004
1005
/* remove dependent devices */
1006
list_for_each_entry_safe(dd, tmp, &ds->dependent_devices, list)
1007
kfree(dd);
1008
1009
list_del(&ds->sibling);
1010
1011
/* cleanup sysfs */
1012
sysfs_remove_group(&dock_device->dev.kobj, &dock_attribute_group);
1013
platform_device_unregister(dock_device);
1014
1015
return 0;
1016
}
1017
1018
/**
1019
* find_dock - look for a dock station
1020
* @handle: acpi handle of a device
1021
* @lvl: unused
1022
* @context: counter of dock stations found
1023
* @rv: unused
1024
*
1025
* This is called by acpi_walk_namespace to look for dock stations.
1026
*/
1027
static __init acpi_status
1028
find_dock(acpi_handle handle, u32 lvl, void *context, void **rv)
1029
{
1030
if (is_dock(handle))
1031
dock_add(handle);
1032
1033
return AE_OK;
1034
}
1035
1036
static __init acpi_status
1037
find_bay(acpi_handle handle, u32 lvl, void *context, void **rv)
1038
{
1039
/* If bay is a dock, it's already handled */
1040
if (is_ejectable_bay(handle) && !is_dock(handle))
1041
dock_add(handle);
1042
return AE_OK;
1043
}
1044
1045
static int __init dock_init(void)
1046
{
1047
if (acpi_disabled)
1048
return 0;
1049
1050
/* look for a dock station */
1051
acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
1052
ACPI_UINT32_MAX, find_dock, NULL, NULL, NULL);
1053
1054
/* look for bay */
1055
acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
1056
ACPI_UINT32_MAX, find_bay, NULL, NULL, NULL);
1057
if (!dock_station_count) {
1058
printk(KERN_INFO PREFIX "No dock devices found.\n");
1059
return 0;
1060
}
1061
1062
register_acpi_bus_notifier(&dock_acpi_notifier);
1063
printk(KERN_INFO PREFIX "%s: %d docks/bays found\n",
1064
ACPI_DOCK_DRIVER_DESCRIPTION, dock_station_count);
1065
return 0;
1066
}
1067
1068
static void __exit dock_exit(void)
1069
{
1070
struct dock_station *tmp, *dock_station;
1071
1072
unregister_acpi_bus_notifier(&dock_acpi_notifier);
1073
list_for_each_entry_safe(dock_station, tmp, &dock_stations, sibling)
1074
dock_remove(dock_station);
1075
}
1076
1077
/*
1078
* Must be called before drivers of devices in dock, otherwise we can't know
1079
* which devices are in a dock
1080
*/
1081
subsys_initcall(dock_init);
1082
module_exit(dock_exit);
1083
1084