Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Revert "Revert "ACPI: dock driver""

This reverts 953969ddf5b049361ed1e8471cc43dc4134d2a6f commit.

Len Brown c8f7a62c 953969dd

+788 -1
+7
drivers/acpi/Kconfig
··· 133 133 This driver adds support for ACPI fan devices, allowing user-mode 134 134 applications to perform basic fan control (on, off, status). 135 135 136 + config ACPI_DOCK 137 + tristate "Dock" 138 + depends on !ACPI_IBM_DOCK 139 + default y 140 + help 141 + This driver adds support for ACPI controlled docking stations 142 + 136 143 config ACPI_PROCESSOR 137 144 tristate "Processor" 138 145 default y
+1
drivers/acpi/Makefile
··· 42 42 obj-$(CONFIG_ACPI_BUTTON) += button.o 43 43 obj-$(CONFIG_ACPI_EC) += ec.o 44 44 obj-$(CONFIG_ACPI_FAN) += fan.o 45 + obj-$(CONFIG_ACPI_DOCK) += dock.o 45 46 obj-$(CONFIG_ACPI_VIDEO) += video.o 46 47 obj-$(CONFIG_ACPI_HOTKEY) += hotkey.o 47 48 obj-y += pci_root.o pci_link.o pci_irq.o pci_bind.o
+739
drivers/acpi/dock.c
··· 1 + /* 2 + * dock.c - ACPI dock station driver 3 + * 4 + * Copyright (C) 2006 Kristen Carlson Accardi <kristen.c.accardi@intel.com> 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/init.h> 28 + #include <linux/types.h> 29 + #include <linux/notifier.h> 30 + #include <acpi/acpi_bus.h> 31 + #include <acpi/acpi_drivers.h> 32 + 33 + #define ACPI_DOCK_DRIVER_NAME "ACPI Dock Station Driver" 34 + 35 + ACPI_MODULE_NAME("dock") 36 + MODULE_AUTHOR("Kristen Carlson Accardi"); 37 + MODULE_DESCRIPTION(ACPI_DOCK_DRIVER_NAME); 38 + MODULE_LICENSE("GPL"); 39 + 40 + static struct atomic_notifier_head dock_notifier_list; 41 + 42 + struct dock_station { 43 + acpi_handle handle; 44 + unsigned long last_dock_time; 45 + u32 flags; 46 + spinlock_t dd_lock; 47 + spinlock_t hp_lock; 48 + struct list_head dependent_devices; 49 + struct list_head hotplug_devices; 50 + }; 51 + 52 + struct dock_dependent_device { 53 + struct list_head list; 54 + struct list_head hotplug_list; 55 + acpi_handle handle; 56 + acpi_notify_handler handler; 57 + void *context; 58 + }; 59 + 60 + #define DOCK_DOCKING 0x00000001 61 + #define DOCK_EVENT KOBJ_DOCK 62 + #define UNDOCK_EVENT KOBJ_UNDOCK 63 + 64 + static struct dock_station *dock_station; 65 + 66 + /***************************************************************************** 67 + * Dock Dependent device functions * 68 + *****************************************************************************/ 69 + /** 70 + * alloc_dock_dependent_device - allocate and init a dependent device 71 + * @handle: the acpi_handle of the dependent device 72 + * 73 + * Allocate memory for a dependent device structure for a device referenced 74 + * by the acpi handle 75 + */ 76 + static struct dock_dependent_device * 77 + alloc_dock_dependent_device(acpi_handle handle) 78 + { 79 + struct dock_dependent_device *dd; 80 + 81 + dd = kzalloc(sizeof(*dd), GFP_KERNEL); 82 + if (dd) { 83 + dd->handle = handle; 84 + INIT_LIST_HEAD(&dd->list); 85 + INIT_LIST_HEAD(&dd->hotplug_list); 86 + } 87 + return dd; 88 + } 89 + 90 + /** 91 + * add_dock_dependent_device - associate a device with the dock station 92 + * @ds: The dock station 93 + * @dd: The dependent device 94 + * 95 + * Add the dependent device to the dock's dependent device list. 96 + */ 97 + static void 98 + add_dock_dependent_device(struct dock_station *ds, 99 + struct dock_dependent_device *dd) 100 + { 101 + spin_lock(&ds->dd_lock); 102 + list_add_tail(&dd->list, &ds->dependent_devices); 103 + spin_unlock(&ds->dd_lock); 104 + } 105 + 106 + /** 107 + * dock_add_hotplug_device - associate a hotplug handler with the dock station 108 + * @ds: The dock station 109 + * @dd: The dependent device struct 110 + * 111 + * Add the dependent device to the dock's hotplug device list 112 + */ 113 + static void 114 + dock_add_hotplug_device(struct dock_station *ds, 115 + struct dock_dependent_device *dd) 116 + { 117 + spin_lock(&ds->hp_lock); 118 + list_add_tail(&dd->hotplug_list, &ds->hotplug_devices); 119 + spin_unlock(&ds->hp_lock); 120 + } 121 + 122 + /** 123 + * dock_del_hotplug_device - remove a hotplug handler from the dock station 124 + * @ds: The dock station 125 + * @dd: the dependent device struct 126 + * 127 + * Delete the dependent device from the dock's hotplug device list 128 + */ 129 + static void 130 + dock_del_hotplug_device(struct dock_station *ds, 131 + struct dock_dependent_device *dd) 132 + { 133 + spin_lock(&ds->hp_lock); 134 + list_del(&dd->hotplug_list); 135 + spin_unlock(&ds->hp_lock); 136 + } 137 + 138 + /** 139 + * find_dock_dependent_device - get a device dependent on this dock 140 + * @ds: the dock station 141 + * @handle: the acpi_handle of the device we want 142 + * 143 + * iterate over the dependent device list for this dock. If the 144 + * dependent device matches the handle, return. 145 + */ 146 + static struct dock_dependent_device * 147 + find_dock_dependent_device(struct dock_station *ds, acpi_handle handle) 148 + { 149 + struct dock_dependent_device *dd; 150 + 151 + spin_lock(&ds->dd_lock); 152 + list_for_each_entry(dd, &ds->dependent_devices, list) { 153 + if (handle == dd->handle) { 154 + spin_unlock(&ds->dd_lock); 155 + return dd; 156 + } 157 + } 158 + spin_unlock(&ds->dd_lock); 159 + return NULL; 160 + } 161 + 162 + /***************************************************************************** 163 + * Dock functions * 164 + *****************************************************************************/ 165 + /** 166 + * is_dock - see if a device is a dock station 167 + * @handle: acpi handle of the device 168 + * 169 + * If an acpi object has a _DCK method, then it is by definition a dock 170 + * station, so return true. 171 + */ 172 + static int is_dock(acpi_handle handle) 173 + { 174 + acpi_status status; 175 + acpi_handle tmp; 176 + 177 + status = acpi_get_handle(handle, "_DCK", &tmp); 178 + if (ACPI_FAILURE(status)) 179 + return 0; 180 + return 1; 181 + } 182 + 183 + /** 184 + * is_dock_device - see if a device is on a dock station 185 + * @handle: acpi handle of the device 186 + * 187 + * If this device is either the dock station itself, 188 + * or is a device dependent on the dock station, then it 189 + * is a dock device 190 + */ 191 + int is_dock_device(acpi_handle handle) 192 + { 193 + if (!dock_station) 194 + return 0; 195 + 196 + if (is_dock(handle) || find_dock_dependent_device(dock_station, handle)) 197 + return 1; 198 + 199 + return 0; 200 + } 201 + 202 + EXPORT_SYMBOL_GPL(is_dock_device); 203 + 204 + /** 205 + * dock_present - see if the dock station is present. 206 + * @ds: the dock station 207 + * 208 + * execute the _STA method. note that present does not 209 + * imply that we are docked. 210 + */ 211 + static int dock_present(struct dock_station *ds) 212 + { 213 + unsigned long sta; 214 + acpi_status status; 215 + 216 + if (ds) { 217 + status = acpi_evaluate_integer(ds->handle, "_STA", NULL, &sta); 218 + if (ACPI_SUCCESS(status) && sta) 219 + return 1; 220 + } 221 + return 0; 222 + } 223 + 224 + 225 + 226 + /** 227 + * dock_create_acpi_device - add new devices to acpi 228 + * @handle - handle of the device to add 229 + * 230 + * This function will create a new acpi_device for the given 231 + * handle if one does not exist already. This should cause 232 + * acpi to scan for drivers for the given devices, and call 233 + * matching driver's add routine. 234 + * 235 + * Returns a pointer to the acpi_device corresponding to the handle. 236 + */ 237 + static struct acpi_device * dock_create_acpi_device(acpi_handle handle) 238 + { 239 + struct acpi_device *device = NULL; 240 + struct acpi_device *parent_device; 241 + acpi_handle parent; 242 + int ret; 243 + 244 + if (acpi_bus_get_device(handle, &device)) { 245 + /* 246 + * no device created for this object, 247 + * so we should create one. 248 + */ 249 + acpi_get_parent(handle, &parent); 250 + if (acpi_bus_get_device(parent, &parent_device)) 251 + parent_device = NULL; 252 + 253 + ret = acpi_bus_add(&device, parent_device, handle, 254 + ACPI_BUS_TYPE_DEVICE); 255 + if (ret) { 256 + pr_debug("error adding bus, %x\n", 257 + -ret); 258 + return NULL; 259 + } 260 + } 261 + return device; 262 + } 263 + 264 + /** 265 + * dock_remove_acpi_device - remove the acpi_device struct from acpi 266 + * @handle - the handle of the device to remove 267 + * 268 + * Tell acpi to remove the acpi_device. This should cause any loaded 269 + * driver to have it's remove routine called. 270 + */ 271 + static void dock_remove_acpi_device(acpi_handle handle) 272 + { 273 + struct acpi_device *device; 274 + int ret; 275 + 276 + if (!acpi_bus_get_device(handle, &device)) { 277 + ret = acpi_bus_trim(device, 1); 278 + if (ret) 279 + pr_debug("error removing bus, %x\n", -ret); 280 + } 281 + } 282 + 283 + 284 + /** 285 + * hotplug_dock_devices - insert or remove devices on the dock station 286 + * @ds: the dock station 287 + * @event: either bus check or eject request 288 + * 289 + * Some devices on the dock station need to have drivers called 290 + * to perform hotplug operations after a dock event has occurred. 291 + * Traverse the list of dock devices that have registered a 292 + * hotplug handler, and call the handler. 293 + */ 294 + static void hotplug_dock_devices(struct dock_station *ds, u32 event) 295 + { 296 + struct dock_dependent_device *dd; 297 + 298 + spin_lock(&ds->hp_lock); 299 + 300 + /* 301 + * First call driver specific hotplug functions 302 + */ 303 + list_for_each_entry(dd, &ds->hotplug_devices, hotplug_list) { 304 + if (dd->handler) 305 + dd->handler(dd->handle, event, dd->context); 306 + } 307 + 308 + /* 309 + * Now make sure that an acpi_device is created for each 310 + * dependent device, or removed if this is an eject request. 311 + * This will cause acpi_drivers to be stopped/started if they 312 + * exist 313 + */ 314 + list_for_each_entry(dd, &ds->dependent_devices, list) { 315 + if (event == ACPI_NOTIFY_EJECT_REQUEST) 316 + dock_remove_acpi_device(dd->handle); 317 + else 318 + dock_create_acpi_device(dd->handle); 319 + } 320 + spin_unlock(&ds->hp_lock); 321 + } 322 + 323 + static void dock_event(struct dock_station *ds, u32 event, int num) 324 + { 325 + struct acpi_device *device; 326 + 327 + device = dock_create_acpi_device(ds->handle); 328 + if (device) 329 + kobject_uevent(&device->kobj, num); 330 + } 331 + 332 + /** 333 + * eject_dock - respond to a dock eject request 334 + * @ds: the dock station 335 + * 336 + * This is called after _DCK is called, to execute the dock station's 337 + * _EJ0 method. 338 + */ 339 + static void eject_dock(struct dock_station *ds) 340 + { 341 + struct acpi_object_list arg_list; 342 + union acpi_object arg; 343 + acpi_status status; 344 + acpi_handle tmp; 345 + 346 + /* all dock devices should have _EJ0, but check anyway */ 347 + status = acpi_get_handle(ds->handle, "_EJ0", &tmp); 348 + if (ACPI_FAILURE(status)) { 349 + pr_debug("No _EJ0 support for dock device\n"); 350 + return; 351 + } 352 + 353 + arg_list.count = 1; 354 + arg_list.pointer = &arg; 355 + arg.type = ACPI_TYPE_INTEGER; 356 + arg.integer.value = 1; 357 + 358 + if (ACPI_FAILURE(acpi_evaluate_object(ds->handle, "_EJ0", 359 + &arg_list, NULL))) 360 + pr_debug("Failed to evaluate _EJ0!\n"); 361 + } 362 + 363 + /** 364 + * handle_dock - handle a dock event 365 + * @ds: the dock station 366 + * @dock: to dock, or undock - that is the question 367 + * 368 + * Execute the _DCK method in response to an acpi event 369 + */ 370 + static void handle_dock(struct dock_station *ds, int dock) 371 + { 372 + acpi_status status; 373 + struct acpi_object_list arg_list; 374 + union acpi_object arg; 375 + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 376 + struct acpi_buffer name_buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 377 + union acpi_object *obj; 378 + 379 + acpi_get_name(ds->handle, ACPI_FULL_PATHNAME, &name_buffer); 380 + obj = name_buffer.pointer; 381 + 382 + printk(KERN_INFO PREFIX "%s\n", dock ? "docking" : "undocking"); 383 + 384 + /* _DCK method has one argument */ 385 + arg_list.count = 1; 386 + arg_list.pointer = &arg; 387 + arg.type = ACPI_TYPE_INTEGER; 388 + arg.integer.value = dock; 389 + status = acpi_evaluate_object(ds->handle, "_DCK", &arg_list, &buffer); 390 + if (ACPI_FAILURE(status)) 391 + pr_debug("%s: failed to execute _DCK\n", obj->string.pointer); 392 + kfree(buffer.pointer); 393 + kfree(name_buffer.pointer); 394 + } 395 + 396 + static inline void dock(struct dock_station *ds) 397 + { 398 + handle_dock(ds, 1); 399 + } 400 + 401 + static inline void undock(struct dock_station *ds) 402 + { 403 + handle_dock(ds, 0); 404 + } 405 + 406 + static inline void begin_dock(struct dock_station *ds) 407 + { 408 + ds->flags |= DOCK_DOCKING; 409 + } 410 + 411 + static inline void complete_dock(struct dock_station *ds) 412 + { 413 + ds->flags &= ~(DOCK_DOCKING); 414 + ds->last_dock_time = jiffies; 415 + } 416 + 417 + /** 418 + * dock_in_progress - see if we are in the middle of handling a dock event 419 + * @ds: the dock station 420 + * 421 + * Sometimes while docking, false dock events can be sent to the driver 422 + * because good connections aren't made or some other reason. Ignore these 423 + * if we are in the middle of doing something. 424 + */ 425 + static int dock_in_progress(struct dock_station *ds) 426 + { 427 + if ((ds->flags & DOCK_DOCKING) || 428 + time_before(jiffies, (ds->last_dock_time + HZ))) 429 + return 1; 430 + return 0; 431 + } 432 + 433 + /** 434 + * register_dock_notifier - add yourself to the dock notifier list 435 + * @nb: the callers notifier block 436 + * 437 + * If a driver wishes to be notified about dock events, they can 438 + * use this function to put a notifier block on the dock notifier list. 439 + * this notifier call chain will be called after a dock event, but 440 + * before hotplugging any new devices. 441 + */ 442 + int register_dock_notifier(struct notifier_block *nb) 443 + { 444 + return atomic_notifier_chain_register(&dock_notifier_list, nb); 445 + } 446 + 447 + EXPORT_SYMBOL_GPL(register_dock_notifier); 448 + 449 + /** 450 + * unregister_dock_notifier - remove yourself from the dock notifier list 451 + * @nb: the callers notifier block 452 + */ 453 + void unregister_dock_notifier(struct notifier_block *nb) 454 + { 455 + atomic_notifier_chain_unregister(&dock_notifier_list, nb); 456 + } 457 + 458 + EXPORT_SYMBOL_GPL(unregister_dock_notifier); 459 + 460 + /** 461 + * register_hotplug_dock_device - register a hotplug function 462 + * @handle: the handle of the device 463 + * @handler: the acpi_notifier_handler to call after docking 464 + * @context: device specific data 465 + * 466 + * If a driver would like to perform a hotplug operation after a dock 467 + * event, they can register an acpi_notifiy_handler to be called by 468 + * the dock driver after _DCK is executed. 469 + */ 470 + int 471 + register_hotplug_dock_device(acpi_handle handle, acpi_notify_handler handler, 472 + void *context) 473 + { 474 + struct dock_dependent_device *dd; 475 + 476 + if (!dock_station) 477 + return -ENODEV; 478 + 479 + /* 480 + * make sure this handle is for a device dependent on the dock, 481 + * this would include the dock station itself 482 + */ 483 + dd = find_dock_dependent_device(dock_station, handle); 484 + if (dd) { 485 + dd->handler = handler; 486 + dd->context = context; 487 + dock_add_hotplug_device(dock_station, dd); 488 + return 0; 489 + } 490 + 491 + return -EINVAL; 492 + } 493 + 494 + EXPORT_SYMBOL_GPL(register_hotplug_dock_device); 495 + 496 + /** 497 + * unregister_hotplug_dock_device - remove yourself from the hotplug list 498 + * @handle: the acpi handle of the device 499 + */ 500 + void unregister_hotplug_dock_device(acpi_handle handle) 501 + { 502 + struct dock_dependent_device *dd; 503 + 504 + if (!dock_station) 505 + return; 506 + 507 + dd = find_dock_dependent_device(dock_station, handle); 508 + if (dd) 509 + dock_del_hotplug_device(dock_station, dd); 510 + } 511 + 512 + EXPORT_SYMBOL_GPL(unregister_hotplug_dock_device); 513 + 514 + /** 515 + * dock_notify - act upon an acpi dock notification 516 + * @handle: the dock station handle 517 + * @event: the acpi event 518 + * @data: our driver data struct 519 + * 520 + * If we are notified to dock, then check to see if the dock is 521 + * present and then dock. Notify all drivers of the dock event, 522 + * and then hotplug and devices that may need hotplugging. For undock 523 + * check to make sure the dock device is still present, then undock 524 + * and hotremove all the devices that may need removing. 525 + */ 526 + static void dock_notify(acpi_handle handle, u32 event, void *data) 527 + { 528 + struct dock_station *ds = (struct dock_station *)data; 529 + 530 + switch (event) { 531 + case ACPI_NOTIFY_BUS_CHECK: 532 + if (!dock_in_progress(ds) && dock_present(ds)) { 533 + begin_dock(ds); 534 + dock(ds); 535 + if (!dock_present(ds)) { 536 + printk(KERN_ERR PREFIX "Unable to dock!\n"); 537 + break; 538 + } 539 + atomic_notifier_call_chain(&dock_notifier_list, 540 + event, NULL); 541 + hotplug_dock_devices(ds, event); 542 + complete_dock(ds); 543 + dock_event(ds, event, DOCK_EVENT); 544 + } 545 + break; 546 + case ACPI_NOTIFY_DEVICE_CHECK: 547 + /* 548 + * According to acpi spec 3.0a, if a DEVICE_CHECK notification 549 + * is sent and _DCK is present, it is assumed to mean an 550 + * undock request. This notify routine will only be called 551 + * for objects defining _DCK, so we will fall through to eject 552 + * request here. However, we will pass an eject request through 553 + * to the driver who wish to hotplug. 554 + */ 555 + case ACPI_NOTIFY_EJECT_REQUEST: 556 + if (!dock_in_progress(ds) && dock_present(ds)) { 557 + /* 558 + * here we need to generate the undock 559 + * event prior to actually doing the undock 560 + * so that the device struct still exists. 561 + */ 562 + dock_event(ds, event, UNDOCK_EVENT); 563 + hotplug_dock_devices(ds, ACPI_NOTIFY_EJECT_REQUEST); 564 + undock(ds); 565 + eject_dock(ds); 566 + if (dock_present(ds)) 567 + printk(KERN_ERR PREFIX "Unable to undock!\n"); 568 + } 569 + break; 570 + default: 571 + printk(KERN_ERR PREFIX "Unknown dock event %d\n", event); 572 + } 573 + } 574 + 575 + /** 576 + * find_dock_devices - find devices on the dock station 577 + * @handle: the handle of the device we are examining 578 + * @lvl: unused 579 + * @context: the dock station private data 580 + * @rv: unused 581 + * 582 + * This function is called by acpi_walk_namespace. It will 583 + * check to see if an object has an _EJD method. If it does, then it 584 + * will see if it is dependent on the dock station. 585 + */ 586 + static acpi_status 587 + find_dock_devices(acpi_handle handle, u32 lvl, void *context, void **rv) 588 + { 589 + acpi_status status; 590 + acpi_handle tmp; 591 + struct dock_station *ds = (struct dock_station *)context; 592 + struct dock_dependent_device *dd; 593 + 594 + status = acpi_bus_get_ejd(handle, &tmp); 595 + if (ACPI_FAILURE(status)) 596 + return AE_OK; 597 + 598 + if (tmp == ds->handle) { 599 + dd = alloc_dock_dependent_device(handle); 600 + if (dd) 601 + add_dock_dependent_device(ds, dd); 602 + } 603 + 604 + return AE_OK; 605 + } 606 + 607 + /** 608 + * dock_add - add a new dock station 609 + * @handle: the dock station handle 610 + * 611 + * allocated and initialize a new dock station device. Find all devices 612 + * that are on the dock station, and register for dock event notifications. 613 + */ 614 + static int dock_add(acpi_handle handle) 615 + { 616 + int ret; 617 + acpi_status status; 618 + struct dock_dependent_device *dd; 619 + 620 + /* allocate & initialize the dock_station private data */ 621 + dock_station = kzalloc(sizeof(*dock_station), GFP_KERNEL); 622 + if (!dock_station) 623 + return -ENOMEM; 624 + dock_station->handle = handle; 625 + dock_station->last_dock_time = jiffies - HZ; 626 + INIT_LIST_HEAD(&dock_station->dependent_devices); 627 + INIT_LIST_HEAD(&dock_station->hotplug_devices); 628 + spin_lock_init(&dock_station->dd_lock); 629 + spin_lock_init(&dock_station->hp_lock); 630 + 631 + /* Find dependent devices */ 632 + acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, 633 + ACPI_UINT32_MAX, find_dock_devices, dock_station, 634 + NULL); 635 + 636 + /* add the dock station as a device dependent on itself */ 637 + dd = alloc_dock_dependent_device(handle); 638 + if (!dd) { 639 + kfree(dock_station); 640 + return -ENOMEM; 641 + } 642 + add_dock_dependent_device(dock_station, dd); 643 + 644 + /* register for dock events */ 645 + status = acpi_install_notify_handler(dock_station->handle, 646 + ACPI_SYSTEM_NOTIFY, 647 + dock_notify, dock_station); 648 + 649 + if (ACPI_FAILURE(status)) { 650 + printk(KERN_ERR PREFIX "Error installing notify handler\n"); 651 + ret = -ENODEV; 652 + goto dock_add_err; 653 + } 654 + 655 + printk(KERN_INFO PREFIX "%s \n", ACPI_DOCK_DRIVER_NAME); 656 + 657 + return 0; 658 + 659 + dock_add_err: 660 + kfree(dock_station); 661 + kfree(dd); 662 + return ret; 663 + } 664 + 665 + /** 666 + * dock_remove - free up resources related to the dock station 667 + */ 668 + static int dock_remove(void) 669 + { 670 + struct dock_dependent_device *dd, *tmp; 671 + acpi_status status; 672 + 673 + if (!dock_station) 674 + return 0; 675 + 676 + /* remove dependent devices */ 677 + list_for_each_entry_safe(dd, tmp, &dock_station->dependent_devices, 678 + list) 679 + kfree(dd); 680 + 681 + /* remove dock notify handler */ 682 + status = acpi_remove_notify_handler(dock_station->handle, 683 + ACPI_SYSTEM_NOTIFY, 684 + dock_notify); 685 + if (ACPI_FAILURE(status)) 686 + printk(KERN_ERR "Error removing notify handler\n"); 687 + 688 + /* free dock station memory */ 689 + kfree(dock_station); 690 + return 0; 691 + } 692 + 693 + /** 694 + * find_dock - look for a dock station 695 + * @handle: acpi handle of a device 696 + * @lvl: unused 697 + * @context: counter of dock stations found 698 + * @rv: unused 699 + * 700 + * This is called by acpi_walk_namespace to look for dock stations. 701 + */ 702 + static acpi_status 703 + find_dock(acpi_handle handle, u32 lvl, void *context, void **rv) 704 + { 705 + int *count = (int *)context; 706 + acpi_status status = AE_OK; 707 + 708 + if (is_dock(handle)) { 709 + if (dock_add(handle) >= 0) { 710 + (*count)++; 711 + status = AE_CTRL_TERMINATE; 712 + } 713 + } 714 + return status; 715 + } 716 + 717 + static int __init dock_init(void) 718 + { 719 + int num = 0; 720 + 721 + dock_station = NULL; 722 + 723 + /* look for a dock station */ 724 + acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, 725 + ACPI_UINT32_MAX, find_dock, &num, NULL); 726 + 727 + if (!num) 728 + return -ENODEV; 729 + 730 + return 0; 731 + } 732 + 733 + static void __exit dock_exit(void) 734 + { 735 + dock_remove(); 736 + } 737 + 738 + postcore_initcall(dock_init); 739 + module_exit(dock_exit);
+23
drivers/acpi/scan.c
··· 663 663 Device Enumeration 664 664 -------------------------------------------------------------------------- */ 665 665 666 + acpi_status 667 + acpi_bus_get_ejd(acpi_handle handle, acpi_handle *ejd) 668 + { 669 + acpi_status status; 670 + acpi_handle tmp; 671 + struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; 672 + union acpi_object *obj; 673 + 674 + status = acpi_get_handle(handle, "_EJD", &tmp); 675 + if (ACPI_FAILURE(status)) 676 + return status; 677 + 678 + status = acpi_evaluate_object(handle, "_EJD", NULL, &buffer); 679 + if (ACPI_SUCCESS(status)) { 680 + obj = buffer.pointer; 681 + status = acpi_get_handle(NULL, obj->string.pointer, ejd); 682 + kfree(buffer.pointer); 683 + } 684 + return status; 685 + } 686 + EXPORT_SYMBOL_GPL(acpi_bus_get_ejd); 687 + 688 + 666 689 static int acpi_bus_get_flags(struct acpi_device *device) 667 690 { 668 691 acpi_status status = AE_OK;
+1 -1
include/acpi/acpi_bus.h
··· 334 334 acpi_handle handle, int type); 335 335 int acpi_bus_trim(struct acpi_device *start, int rmdevice); 336 336 int acpi_bus_start(struct acpi_device *device); 337 - 337 + acpi_status acpi_bus_get_ejd(acpi_handle handle, acpi_handle *ejd); 338 338 int acpi_match_ids(struct acpi_device *device, char *ids); 339 339 int acpi_create_dir(struct acpi_device *); 340 340 void acpi_remove_dir(struct acpi_device *);
+17
include/acpi/acpi_drivers.h
··· 110 110 111 111 extern int acpi_specific_hotkey_enabled; 112 112 113 + /*-------------------------------------------------------------------------- 114 + Dock Station 115 + -------------------------------------------------------------------------- */ 116 + #if defined(CONFIG_ACPI_DOCK) || defined(CONFIG_ACPI_DOCK_MODULE) 117 + extern int is_dock_device(acpi_handle handle); 118 + extern int register_dock_notifier(struct notifier_block *nb); 119 + extern void unregister_dock_notifier(struct notifier_block *nb); 120 + extern int register_hotplug_dock_device(acpi_handle handle, 121 + acpi_notify_handler handler, void *context); 122 + extern void unregister_hotplug_dock_device(acpi_handle handle); 123 + #else 124 + #define is_dock_device(h) (0) 125 + #define register_dock_notifier(nb) (-ENODEV) 126 + #define unregister_dock_notifier(nb) do { } while(0) 127 + #define register_hotplug_dock_device(h1, h2, c) (-ENODEV) 128 + #define unregister_hotplug_dock_device(h) do { } while(0) 129 + #endif 113 130 #endif /*__ACPI_DRIVERS_H__*/