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