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