diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-06-26 12:37:52 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-06-26 12:37:52 -0400 |
| commit | cf2acfb2051fc67804162eebc5ebc8f55d3b7e2c (patch) | |
| tree | 06caac8e527f00b1a3284eb782278168f9a7cf8c | |
| parent | aada1bc92797434cdf31e76fc2c6ab29307a5f48 (diff) | |
| parent | 412af97838828bc6d035a1902c8974f944663da6 (diff) | |
Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6
* 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6:
ACPI: video: prevent NULL deref in acpi_get_pci_dev()
eeepc-laptop: add rfkill support for the 3G modem in Eee PC 901 Go
eeepc-laptop: get the right value for CMSG
eeepc-laptop: makes get_acpi() returns -ENODEV
eeepc-laptop: right parent device
eeepc-laptop: rfkill refactoring
eeepc-laptop.c: use pr_fmt and pr_<level>
eeepc-laptop: Register as a pci-hotplug device
| -rw-r--r-- | drivers/acpi/pci_root.c | 2 | ||||
| -rw-r--r-- | drivers/platform/x86/Kconfig | 2 | ||||
| -rw-r--r-- | drivers/platform/x86/eeepc-laptop.c | 346 |
3 files changed, 239 insertions, 111 deletions
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 8a5bf3b356fa..55b5b90c2a44 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c | |||
| @@ -395,7 +395,7 @@ struct pci_dev *acpi_get_pci_dev(acpi_handle handle) | |||
| 395 | fn = adr & 0xffff; | 395 | fn = adr & 0xffff; |
| 396 | 396 | ||
| 397 | pdev = pci_get_slot(pbus, PCI_DEVFN(dev, fn)); | 397 | pdev = pci_get_slot(pbus, PCI_DEVFN(dev, fn)); |
| 398 | if (hnd == handle) | 398 | if (!pdev || hnd == handle) |
| 399 | break; | 399 | break; |
| 400 | 400 | ||
| 401 | pbus = pdev->subordinate; | 401 | pbus = pdev->subordinate; |
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 7232fe7104aa..fee6a4022bc1 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig | |||
| @@ -357,6 +357,8 @@ config EEEPC_LAPTOP | |||
| 357 | depends on RFKILL || RFKILL = n | 357 | depends on RFKILL || RFKILL = n |
| 358 | select BACKLIGHT_CLASS_DEVICE | 358 | select BACKLIGHT_CLASS_DEVICE |
| 359 | select HWMON | 359 | select HWMON |
| 360 | select HOTPLUG | ||
| 361 | select HOTPLUG_PCI if PCI | ||
| 360 | ---help--- | 362 | ---help--- |
| 361 | This driver supports the Fn-Fx keys on Eee PC laptops. | 363 | This driver supports the Fn-Fx keys on Eee PC laptops. |
| 362 | 364 | ||
diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index 4207b26ff990..ec560f16d720 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c | |||
| @@ -16,6 +16,8 @@ | |||
| 16 | * GNU General Public License for more details. | 16 | * GNU General Public License for more details. |
| 17 | */ | 17 | */ |
| 18 | 18 | ||
| 19 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 20 | |||
| 19 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
| 20 | #include <linux/module.h> | 22 | #include <linux/module.h> |
| 21 | #include <linux/init.h> | 23 | #include <linux/init.h> |
| @@ -31,6 +33,7 @@ | |||
| 31 | #include <linux/input.h> | 33 | #include <linux/input.h> |
| 32 | #include <linux/rfkill.h> | 34 | #include <linux/rfkill.h> |
| 33 | #include <linux/pci.h> | 35 | #include <linux/pci.h> |
| 36 | #include <linux/pci_hotplug.h> | ||
| 34 | 37 | ||
| 35 | #define EEEPC_LAPTOP_VERSION "0.1" | 38 | #define EEEPC_LAPTOP_VERSION "0.1" |
| 36 | 39 | ||
| @@ -40,11 +43,6 @@ | |||
| 40 | #define EEEPC_HOTK_DEVICE_NAME "Hotkey" | 43 | #define EEEPC_HOTK_DEVICE_NAME "Hotkey" |
| 41 | #define EEEPC_HOTK_HID "ASUS010" | 44 | #define EEEPC_HOTK_HID "ASUS010" |
| 42 | 45 | ||
| 43 | #define EEEPC_LOG EEEPC_HOTK_FILE ": " | ||
| 44 | #define EEEPC_ERR KERN_ERR EEEPC_LOG | ||
| 45 | #define EEEPC_WARNING KERN_WARNING EEEPC_LOG | ||
| 46 | #define EEEPC_NOTICE KERN_NOTICE EEEPC_LOG | ||
| 47 | #define EEEPC_INFO KERN_INFO EEEPC_LOG | ||
| 48 | 46 | ||
| 49 | /* | 47 | /* |
| 50 | * Definitions for Asus EeePC | 48 | * Definitions for Asus EeePC |
| @@ -141,8 +139,10 @@ struct eeepc_hotk { | |||
| 141 | u16 event_count[128]; /* count for each event */ | 139 | u16 event_count[128]; /* count for each event */ |
| 142 | struct input_dev *inputdev; | 140 | struct input_dev *inputdev; |
| 143 | u16 *keycode_map; | 141 | u16 *keycode_map; |
| 144 | struct rfkill *eeepc_wlan_rfkill; | 142 | struct rfkill *wlan_rfkill; |
| 145 | struct rfkill *eeepc_bluetooth_rfkill; | 143 | struct rfkill *bluetooth_rfkill; |
| 144 | struct rfkill *wwan3g_rfkill; | ||
| 145 | struct hotplug_slot *hotplug_slot; | ||
| 146 | }; | 146 | }; |
| 147 | 147 | ||
| 148 | /* The actual device the driver binds to */ | 148 | /* The actual device the driver binds to */ |
| @@ -213,6 +213,15 @@ static struct acpi_driver eeepc_hotk_driver = { | |||
| 213 | }, | 213 | }, |
| 214 | }; | 214 | }; |
| 215 | 215 | ||
| 216 | /* PCI hotplug ops */ | ||
| 217 | static int eeepc_get_adapter_status(struct hotplug_slot *slot, u8 *value); | ||
| 218 | |||
| 219 | static struct hotplug_slot_ops eeepc_hotplug_slot_ops = { | ||
| 220 | .owner = THIS_MODULE, | ||
| 221 | .get_adapter_status = eeepc_get_adapter_status, | ||
| 222 | .get_power_status = eeepc_get_adapter_status, | ||
| 223 | }; | ||
| 224 | |||
| 216 | /* The backlight device /sys/class/backlight */ | 225 | /* The backlight device /sys/class/backlight */ |
| 217 | static struct backlight_device *eeepc_backlight_device; | 226 | static struct backlight_device *eeepc_backlight_device; |
| 218 | 227 | ||
| @@ -274,20 +283,20 @@ static int set_acpi(int cm, int value) | |||
| 274 | if (method == NULL) | 283 | if (method == NULL) |
| 275 | return -ENODEV; | 284 | return -ENODEV; |
| 276 | if (write_acpi_int(ehotk->handle, method, value, NULL)) | 285 | if (write_acpi_int(ehotk->handle, method, value, NULL)) |
| 277 | printk(EEEPC_WARNING "Error writing %s\n", method); | 286 | pr_warning("Error writing %s\n", method); |
| 278 | } | 287 | } |
| 279 | return 0; | 288 | return 0; |
| 280 | } | 289 | } |
| 281 | 290 | ||
| 282 | static int get_acpi(int cm) | 291 | static int get_acpi(int cm) |
| 283 | { | 292 | { |
| 284 | int value = -1; | 293 | int value = -ENODEV; |
| 285 | if ((ehotk->cm_supported & (0x1 << cm))) { | 294 | if ((ehotk->cm_supported & (0x1 << cm))) { |
| 286 | const char *method = cm_getv[cm]; | 295 | const char *method = cm_getv[cm]; |
| 287 | if (method == NULL) | 296 | if (method == NULL) |
| 288 | return -ENODEV; | 297 | return -ENODEV; |
| 289 | if (read_acpi_int(ehotk->handle, method, &value)) | 298 | if (read_acpi_int(ehotk->handle, method, &value)) |
| 290 | printk(EEEPC_WARNING "Error reading %s\n", method); | 299 | pr_warning("Error reading %s\n", method); |
| 291 | } | 300 | } |
| 292 | return value; | 301 | return value; |
| 293 | } | 302 | } |
| @@ -359,13 +368,19 @@ static ssize_t store_sys_acpi(int cm, const char *buf, size_t count) | |||
| 359 | 368 | ||
| 360 | rv = parse_arg(buf, count, &value); | 369 | rv = parse_arg(buf, count, &value); |
| 361 | if (rv > 0) | 370 | if (rv > 0) |
| 362 | set_acpi(cm, value); | 371 | value = set_acpi(cm, value); |
| 372 | if (value < 0) | ||
| 373 | return value; | ||
| 363 | return rv; | 374 | return rv; |
| 364 | } | 375 | } |
| 365 | 376 | ||
| 366 | static ssize_t show_sys_acpi(int cm, char *buf) | 377 | static ssize_t show_sys_acpi(int cm, char *buf) |
| 367 | { | 378 | { |
| 368 | return sprintf(buf, "%d\n", get_acpi(cm)); | 379 | int value = get_acpi(cm); |
| 380 | |||
| 381 | if (value < 0) | ||
| 382 | return value; | ||
| 383 | return sprintf(buf, "%d\n", value); | ||
| 369 | } | 384 | } |
| 370 | 385 | ||
| 371 | #define EEEPC_CREATE_DEVICE_ATTR(_name, _cm) \ | 386 | #define EEEPC_CREATE_DEVICE_ATTR(_name, _cm) \ |
| @@ -539,6 +554,28 @@ static int eeepc_setkeycode(struct input_dev *dev, int scancode, int keycode) | |||
| 539 | return -EINVAL; | 554 | return -EINVAL; |
| 540 | } | 555 | } |
| 541 | 556 | ||
| 557 | static void cmsg_quirk(int cm, const char *name) | ||
| 558 | { | ||
| 559 | int dummy; | ||
| 560 | |||
| 561 | /* Some BIOSes do not report cm although it is avaliable. | ||
| 562 | Check if cm_getv[cm] works and, if yes, assume cm should be set. */ | ||
| 563 | if (!(ehotk->cm_supported & (1 << cm)) | ||
| 564 | && !read_acpi_int(ehotk->handle, cm_getv[cm], &dummy)) { | ||
| 565 | pr_info("%s (%x) not reported by BIOS," | ||
| 566 | " enabling anyway\n", name, 1 << cm); | ||
| 567 | ehotk->cm_supported |= 1 << cm; | ||
| 568 | } | ||
| 569 | } | ||
| 570 | |||
| 571 | static void cmsg_quirks(void) | ||
| 572 | { | ||
| 573 | cmsg_quirk(CM_ASL_LID, "LID"); | ||
| 574 | cmsg_quirk(CM_ASL_TYPE, "TYPE"); | ||
| 575 | cmsg_quirk(CM_ASL_PANELPOWER, "PANELPOWER"); | ||
| 576 | cmsg_quirk(CM_ASL_TPD, "TPD"); | ||
| 577 | } | ||
| 578 | |||
| 542 | static int eeepc_hotk_check(void) | 579 | static int eeepc_hotk_check(void) |
| 543 | { | 580 | { |
| 544 | const struct key_entry *key; | 581 | const struct key_entry *key; |
| @@ -551,26 +588,24 @@ static int eeepc_hotk_check(void) | |||
| 551 | if (ehotk->device->status.present) { | 588 | if (ehotk->device->status.present) { |
| 552 | if (write_acpi_int(ehotk->handle, "INIT", ehotk->init_flag, | 589 | if (write_acpi_int(ehotk->handle, "INIT", ehotk->init_flag, |
| 553 | &buffer)) { | 590 | &buffer)) { |
| 554 | printk(EEEPC_ERR "Hotkey initialization failed\n"); | 591 | pr_err("Hotkey initialization failed\n"); |
| 555 | return -ENODEV; | 592 | return -ENODEV; |
| 556 | } else { | 593 | } else { |
| 557 | printk(EEEPC_NOTICE "Hotkey init flags 0x%x\n", | 594 | pr_notice("Hotkey init flags 0x%x\n", ehotk->init_flag); |
| 558 | ehotk->init_flag); | ||
| 559 | } | 595 | } |
| 560 | /* get control methods supported */ | 596 | /* get control methods supported */ |
| 561 | if (read_acpi_int(ehotk->handle, "CMSG" | 597 | if (read_acpi_int(ehotk->handle, "CMSG" |
| 562 | , &ehotk->cm_supported)) { | 598 | , &ehotk->cm_supported)) { |
| 563 | printk(EEEPC_ERR | 599 | pr_err("Get control methods supported failed\n"); |
| 564 | "Get control methods supported failed\n"); | ||
| 565 | return -ENODEV; | 600 | return -ENODEV; |
| 566 | } else { | 601 | } else { |
| 567 | printk(EEEPC_INFO | 602 | cmsg_quirks(); |
| 568 | "Get control methods supported: 0x%x\n", | 603 | pr_info("Get control methods supported: 0x%x\n", |
| 569 | ehotk->cm_supported); | 604 | ehotk->cm_supported); |
| 570 | } | 605 | } |
| 571 | ehotk->inputdev = input_allocate_device(); | 606 | ehotk->inputdev = input_allocate_device(); |
| 572 | if (!ehotk->inputdev) { | 607 | if (!ehotk->inputdev) { |
| 573 | printk(EEEPC_INFO "Unable to allocate input device\n"); | 608 | pr_info("Unable to allocate input device\n"); |
| 574 | return 0; | 609 | return 0; |
| 575 | } | 610 | } |
| 576 | ehotk->inputdev->name = "Asus EeePC extra buttons"; | 611 | ehotk->inputdev->name = "Asus EeePC extra buttons"; |
| @@ -589,12 +624,12 @@ static int eeepc_hotk_check(void) | |||
| 589 | } | 624 | } |
| 590 | result = input_register_device(ehotk->inputdev); | 625 | result = input_register_device(ehotk->inputdev); |
| 591 | if (result) { | 626 | if (result) { |
| 592 | printk(EEEPC_INFO "Unable to register input device\n"); | 627 | pr_info("Unable to register input device\n"); |
| 593 | input_free_device(ehotk->inputdev); | 628 | input_free_device(ehotk->inputdev); |
| 594 | return 0; | 629 | return 0; |
| 595 | } | 630 | } |
| 596 | } else { | 631 | } else { |
| 597 | printk(EEEPC_ERR "Hotkey device not present, aborting\n"); | 632 | pr_err("Hotkey device not present, aborting\n"); |
| 598 | return -EINVAL; | 633 | return -EINVAL; |
| 599 | } | 634 | } |
| 600 | return 0; | 635 | return 0; |
| @@ -612,6 +647,19 @@ static int notify_brn(void) | |||
| 612 | return -1; | 647 | return -1; |
| 613 | } | 648 | } |
| 614 | 649 | ||
| 650 | static int eeepc_get_adapter_status(struct hotplug_slot *hotplug_slot, | ||
| 651 | u8 *value) | ||
| 652 | { | ||
| 653 | int val = get_acpi(CM_ASL_WLAN); | ||
| 654 | |||
| 655 | if (val == 1 || val == 0) | ||
| 656 | *value = val; | ||
| 657 | else | ||
| 658 | return -EINVAL; | ||
| 659 | |||
| 660 | return 0; | ||
| 661 | } | ||
| 662 | |||
| 615 | static void eeepc_rfkill_hotplug(void) | 663 | static void eeepc_rfkill_hotplug(void) |
| 616 | { | 664 | { |
| 617 | struct pci_dev *dev; | 665 | struct pci_dev *dev; |
| @@ -619,7 +667,7 @@ static void eeepc_rfkill_hotplug(void) | |||
| 619 | bool blocked; | 667 | bool blocked; |
| 620 | 668 | ||
| 621 | if (!bus) { | 669 | if (!bus) { |
| 622 | printk(EEEPC_WARNING "Unable to find PCI bus 1?\n"); | 670 | pr_warning("Unable to find PCI bus 1?\n"); |
| 623 | return; | 671 | return; |
| 624 | } | 672 | } |
| 625 | 673 | ||
| @@ -635,7 +683,7 @@ static void eeepc_rfkill_hotplug(void) | |||
| 635 | if (dev) { | 683 | if (dev) { |
| 636 | pci_bus_assign_resources(bus); | 684 | pci_bus_assign_resources(bus); |
| 637 | if (pci_bus_add_device(dev)) | 685 | if (pci_bus_add_device(dev)) |
| 638 | printk(EEEPC_ERR "Unable to hotplug wifi\n"); | 686 | pr_err("Unable to hotplug wifi\n"); |
| 639 | } | 687 | } |
| 640 | } else { | 688 | } else { |
| 641 | dev = pci_get_slot(bus, 0); | 689 | dev = pci_get_slot(bus, 0); |
| @@ -645,7 +693,7 @@ static void eeepc_rfkill_hotplug(void) | |||
| 645 | } | 693 | } |
| 646 | } | 694 | } |
| 647 | 695 | ||
| 648 | rfkill_set_sw_state(ehotk->eeepc_wlan_rfkill, blocked); | 696 | rfkill_set_sw_state(ehotk->wlan_rfkill, blocked); |
| 649 | } | 697 | } |
| 650 | 698 | ||
| 651 | static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data) | 699 | static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data) |
| @@ -718,8 +766,7 @@ static int eeepc_register_rfkill_notifier(char *node) | |||
| 718 | eeepc_rfkill_notify, | 766 | eeepc_rfkill_notify, |
| 719 | NULL); | 767 | NULL); |
| 720 | if (ACPI_FAILURE(status)) | 768 | if (ACPI_FAILURE(status)) |
| 721 | printk(EEEPC_WARNING | 769 | pr_warning("Failed to register notify on %s\n", node); |
| 722 | "Failed to register notify on %s\n", node); | ||
| 723 | } else | 770 | } else |
| 724 | return -ENODEV; | 771 | return -ENODEV; |
| 725 | 772 | ||
| @@ -738,19 +785,66 @@ static void eeepc_unregister_rfkill_notifier(char *node) | |||
| 738 | ACPI_SYSTEM_NOTIFY, | 785 | ACPI_SYSTEM_NOTIFY, |
| 739 | eeepc_rfkill_notify); | 786 | eeepc_rfkill_notify); |
| 740 | if (ACPI_FAILURE(status)) | 787 | if (ACPI_FAILURE(status)) |
| 741 | printk(EEEPC_ERR | 788 | pr_err("Error removing rfkill notify handler %s\n", |
| 742 | "Error removing rfkill notify handler %s\n", | ||
| 743 | node); | 789 | node); |
| 744 | } | 790 | } |
| 745 | } | 791 | } |
| 746 | 792 | ||
| 793 | static void eeepc_cleanup_pci_hotplug(struct hotplug_slot *hotplug_slot) | ||
| 794 | { | ||
| 795 | kfree(hotplug_slot->info); | ||
| 796 | kfree(hotplug_slot); | ||
| 797 | } | ||
| 798 | |||
| 799 | static int eeepc_setup_pci_hotplug(void) | ||
| 800 | { | ||
| 801 | int ret = -ENOMEM; | ||
| 802 | struct pci_bus *bus = pci_find_bus(0, 1); | ||
| 803 | |||
| 804 | if (!bus) { | ||
| 805 | pr_err("Unable to find wifi PCI bus\n"); | ||
| 806 | return -ENODEV; | ||
| 807 | } | ||
| 808 | |||
| 809 | ehotk->hotplug_slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL); | ||
| 810 | if (!ehotk->hotplug_slot) | ||
| 811 | goto error_slot; | ||
| 812 | |||
| 813 | ehotk->hotplug_slot->info = kzalloc(sizeof(struct hotplug_slot_info), | ||
| 814 | GFP_KERNEL); | ||
| 815 | if (!ehotk->hotplug_slot->info) | ||
| 816 | goto error_info; | ||
| 817 | |||
| 818 | ehotk->hotplug_slot->private = ehotk; | ||
| 819 | ehotk->hotplug_slot->release = &eeepc_cleanup_pci_hotplug; | ||
| 820 | ehotk->hotplug_slot->ops = &eeepc_hotplug_slot_ops; | ||
| 821 | eeepc_get_adapter_status(ehotk->hotplug_slot, | ||
| 822 | &ehotk->hotplug_slot->info->adapter_status); | ||
| 823 | |||
| 824 | ret = pci_hp_register(ehotk->hotplug_slot, bus, 0, "eeepc-wifi"); | ||
| 825 | if (ret) { | ||
| 826 | pr_err("Unable to register hotplug slot - %d\n", ret); | ||
| 827 | goto error_register; | ||
| 828 | } | ||
| 829 | |||
| 830 | return 0; | ||
| 831 | |||
| 832 | error_register: | ||
| 833 | kfree(ehotk->hotplug_slot->info); | ||
| 834 | error_info: | ||
| 835 | kfree(ehotk->hotplug_slot); | ||
| 836 | ehotk->hotplug_slot = NULL; | ||
| 837 | error_slot: | ||
| 838 | return ret; | ||
| 839 | } | ||
| 840 | |||
| 747 | static int eeepc_hotk_add(struct acpi_device *device) | 841 | static int eeepc_hotk_add(struct acpi_device *device) |
| 748 | { | 842 | { |
| 749 | int result; | 843 | int result; |
| 750 | 844 | ||
| 751 | if (!device) | 845 | if (!device) |
| 752 | return -EINVAL; | 846 | return -EINVAL; |
| 753 | printk(EEEPC_NOTICE EEEPC_HOTK_NAME "\n"); | 847 | pr_notice(EEEPC_HOTK_NAME "\n"); |
| 754 | ehotk = kzalloc(sizeof(struct eeepc_hotk), GFP_KERNEL); | 848 | ehotk = kzalloc(sizeof(struct eeepc_hotk), GFP_KERNEL); |
| 755 | if (!ehotk) | 849 | if (!ehotk) |
| 756 | return -ENOMEM; | 850 | return -ENOMEM; |
| @@ -764,53 +858,8 @@ static int eeepc_hotk_add(struct acpi_device *device) | |||
| 764 | if (result) | 858 | if (result) |
| 765 | goto ehotk_fail; | 859 | goto ehotk_fail; |
| 766 | 860 | ||
| 767 | eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6"); | ||
| 768 | eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7"); | ||
| 769 | |||
| 770 | if (get_acpi(CM_ASL_WLAN) != -1) { | ||
| 771 | ehotk->eeepc_wlan_rfkill = rfkill_alloc("eeepc-wlan", | ||
| 772 | &device->dev, | ||
| 773 | RFKILL_TYPE_WLAN, | ||
| 774 | &eeepc_rfkill_ops, | ||
| 775 | (void *)CM_ASL_WLAN); | ||
| 776 | |||
| 777 | if (!ehotk->eeepc_wlan_rfkill) | ||
| 778 | goto wlan_fail; | ||
| 779 | |||
| 780 | rfkill_init_sw_state(ehotk->eeepc_wlan_rfkill, | ||
| 781 | get_acpi(CM_ASL_WLAN) != 1); | ||
| 782 | result = rfkill_register(ehotk->eeepc_wlan_rfkill); | ||
| 783 | if (result) | ||
| 784 | goto wlan_fail; | ||
| 785 | } | ||
| 786 | |||
| 787 | if (get_acpi(CM_ASL_BLUETOOTH) != -1) { | ||
| 788 | ehotk->eeepc_bluetooth_rfkill = | ||
| 789 | rfkill_alloc("eeepc-bluetooth", | ||
| 790 | &device->dev, | ||
| 791 | RFKILL_TYPE_BLUETOOTH, | ||
| 792 | &eeepc_rfkill_ops, | ||
| 793 | (void *)CM_ASL_BLUETOOTH); | ||
| 794 | |||
| 795 | if (!ehotk->eeepc_bluetooth_rfkill) | ||
| 796 | goto bluetooth_fail; | ||
| 797 | |||
| 798 | rfkill_init_sw_state(ehotk->eeepc_bluetooth_rfkill, | ||
| 799 | get_acpi(CM_ASL_BLUETOOTH) != 1); | ||
| 800 | result = rfkill_register(ehotk->eeepc_bluetooth_rfkill); | ||
| 801 | if (result) | ||
| 802 | goto bluetooth_fail; | ||
| 803 | } | ||
| 804 | |||
| 805 | return 0; | 861 | return 0; |
| 806 | 862 | ||
| 807 | bluetooth_fail: | ||
| 808 | rfkill_destroy(ehotk->eeepc_bluetooth_rfkill); | ||
| 809 | rfkill_unregister(ehotk->eeepc_wlan_rfkill); | ||
| 810 | wlan_fail: | ||
| 811 | rfkill_destroy(ehotk->eeepc_wlan_rfkill); | ||
| 812 | eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6"); | ||
| 813 | eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7"); | ||
| 814 | ehotk_fail: | 863 | ehotk_fail: |
| 815 | kfree(ehotk); | 864 | kfree(ehotk); |
| 816 | ehotk = NULL; | 865 | ehotk = NULL; |
| @@ -823,16 +872,13 @@ static int eeepc_hotk_remove(struct acpi_device *device, int type) | |||
| 823 | if (!device || !acpi_driver_data(device)) | 872 | if (!device || !acpi_driver_data(device)) |
| 824 | return -EINVAL; | 873 | return -EINVAL; |
| 825 | 874 | ||
| 826 | eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6"); | ||
| 827 | eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7"); | ||
| 828 | |||
| 829 | kfree(ehotk); | 875 | kfree(ehotk); |
| 830 | return 0; | 876 | return 0; |
| 831 | } | 877 | } |
| 832 | 878 | ||
| 833 | static int eeepc_hotk_resume(struct acpi_device *device) | 879 | static int eeepc_hotk_resume(struct acpi_device *device) |
| 834 | { | 880 | { |
| 835 | if (ehotk->eeepc_wlan_rfkill) { | 881 | if (ehotk->wlan_rfkill) { |
| 836 | bool wlan; | 882 | bool wlan; |
| 837 | 883 | ||
| 838 | /* Workaround - it seems that _PTS disables the wireless | 884 | /* Workaround - it seems that _PTS disables the wireless |
| @@ -844,14 +890,13 @@ static int eeepc_hotk_resume(struct acpi_device *device) | |||
| 844 | wlan = get_acpi(CM_ASL_WLAN); | 890 | wlan = get_acpi(CM_ASL_WLAN); |
| 845 | set_acpi(CM_ASL_WLAN, wlan); | 891 | set_acpi(CM_ASL_WLAN, wlan); |
| 846 | 892 | ||
| 847 | rfkill_set_sw_state(ehotk->eeepc_wlan_rfkill, | 893 | rfkill_set_sw_state(ehotk->wlan_rfkill, wlan != 1); |
| 848 | wlan != 1); | ||
| 849 | 894 | ||
| 850 | eeepc_rfkill_hotplug(); | 895 | eeepc_rfkill_hotplug(); |
| 851 | } | 896 | } |
| 852 | 897 | ||
| 853 | if (ehotk->eeepc_bluetooth_rfkill) | 898 | if (ehotk->bluetooth_rfkill) |
| 854 | rfkill_set_sw_state(ehotk->eeepc_bluetooth_rfkill, | 899 | rfkill_set_sw_state(ehotk->bluetooth_rfkill, |
| 855 | get_acpi(CM_ASL_BLUETOOTH) != 1); | 900 | get_acpi(CM_ASL_BLUETOOTH) != 1); |
| 856 | 901 | ||
| 857 | return 0; | 902 | return 0; |
| @@ -973,10 +1018,16 @@ static void eeepc_backlight_exit(void) | |||
| 973 | 1018 | ||
| 974 | static void eeepc_rfkill_exit(void) | 1019 | static void eeepc_rfkill_exit(void) |
| 975 | { | 1020 | { |
| 976 | if (ehotk->eeepc_wlan_rfkill) | 1021 | eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6"); |
| 977 | rfkill_unregister(ehotk->eeepc_wlan_rfkill); | 1022 | eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7"); |
| 978 | if (ehotk->eeepc_bluetooth_rfkill) | 1023 | if (ehotk->wlan_rfkill) |
| 979 | rfkill_unregister(ehotk->eeepc_bluetooth_rfkill); | 1024 | rfkill_unregister(ehotk->wlan_rfkill); |
| 1025 | if (ehotk->bluetooth_rfkill) | ||
| 1026 | rfkill_unregister(ehotk->bluetooth_rfkill); | ||
| 1027 | if (ehotk->wwan3g_rfkill) | ||
| 1028 | rfkill_unregister(ehotk->wwan3g_rfkill); | ||
| 1029 | if (ehotk->hotplug_slot) | ||
| 1030 | pci_hp_deregister(ehotk->hotplug_slot); | ||
| 980 | } | 1031 | } |
| 981 | 1032 | ||
| 982 | static void eeepc_input_exit(void) | 1033 | static void eeepc_input_exit(void) |
| @@ -1011,6 +1062,75 @@ static void __exit eeepc_laptop_exit(void) | |||
| 1011 | platform_driver_unregister(&platform_driver); | 1062 | platform_driver_unregister(&platform_driver); |
| 1012 | } | 1063 | } |
| 1013 | 1064 | ||
| 1065 | static int eeepc_new_rfkill(struct rfkill **rfkill, | ||
| 1066 | const char *name, struct device *dev, | ||
| 1067 | enum rfkill_type type, int cm) | ||
| 1068 | { | ||
| 1069 | int result; | ||
| 1070 | |||
| 1071 | result = get_acpi(cm); | ||
| 1072 | if (result < 0) | ||
| 1073 | return result; | ||
| 1074 | |||
| 1075 | *rfkill = rfkill_alloc(name, dev, type, | ||
| 1076 | &eeepc_rfkill_ops, (void *)(unsigned long)cm); | ||
| 1077 | |||
| 1078 | if (!*rfkill) | ||
| 1079 | return -EINVAL; | ||
| 1080 | |||
| 1081 | rfkill_init_sw_state(*rfkill, get_acpi(cm) != 1); | ||
| 1082 | result = rfkill_register(*rfkill); | ||
| 1083 | if (result) { | ||
| 1084 | rfkill_destroy(*rfkill); | ||
| 1085 | *rfkill = NULL; | ||
| 1086 | return result; | ||
| 1087 | } | ||
| 1088 | return 0; | ||
| 1089 | } | ||
| 1090 | |||
| 1091 | |||
| 1092 | static int eeepc_rfkill_init(struct device *dev) | ||
| 1093 | { | ||
| 1094 | int result = 0; | ||
| 1095 | |||
| 1096 | eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6"); | ||
| 1097 | eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7"); | ||
| 1098 | |||
| 1099 | result = eeepc_new_rfkill(&ehotk->wlan_rfkill, | ||
| 1100 | "eeepc-wlan", dev, | ||
| 1101 | RFKILL_TYPE_WLAN, CM_ASL_WLAN); | ||
| 1102 | |||
| 1103 | if (result && result != -ENODEV) | ||
| 1104 | goto exit; | ||
| 1105 | |||
| 1106 | result = eeepc_new_rfkill(&ehotk->bluetooth_rfkill, | ||
| 1107 | "eeepc-bluetooth", dev, | ||
| 1108 | RFKILL_TYPE_BLUETOOTH, CM_ASL_BLUETOOTH); | ||
| 1109 | |||
| 1110 | if (result && result != -ENODEV) | ||
| 1111 | goto exit; | ||
| 1112 | |||
| 1113 | result = eeepc_new_rfkill(&ehotk->wwan3g_rfkill, | ||
| 1114 | "eeepc-wwan3g", dev, | ||
| 1115 | RFKILL_TYPE_WWAN, CM_ASL_3G); | ||
| 1116 | |||
| 1117 | if (result && result != -ENODEV) | ||
| 1118 | goto exit; | ||
| 1119 | |||
| 1120 | result = eeepc_setup_pci_hotplug(); | ||
| 1121 | /* | ||
| 1122 | * If we get -EBUSY then something else is handling the PCI hotplug - | ||
| 1123 | * don't fail in this case | ||
| 1124 | */ | ||
| 1125 | if (result == -EBUSY) | ||
| 1126 | result = 0; | ||
| 1127 | |||
| 1128 | exit: | ||
| 1129 | if (result && result != -ENODEV) | ||
| 1130 | eeepc_rfkill_exit(); | ||
| 1131 | return result; | ||
| 1132 | } | ||
| 1133 | |||
| 1014 | static int eeepc_backlight_init(struct device *dev) | 1134 | static int eeepc_backlight_init(struct device *dev) |
| 1015 | { | 1135 | { |
| 1016 | struct backlight_device *bd; | 1136 | struct backlight_device *bd; |
| @@ -1018,8 +1138,7 @@ static int eeepc_backlight_init(struct device *dev) | |||
| 1018 | bd = backlight_device_register(EEEPC_HOTK_FILE, dev, | 1138 | bd = backlight_device_register(EEEPC_HOTK_FILE, dev, |
| 1019 | NULL, &eeepcbl_ops); | 1139 | NULL, &eeepcbl_ops); |
| 1020 | if (IS_ERR(bd)) { | 1140 | if (IS_ERR(bd)) { |
| 1021 | printk(EEEPC_ERR | 1141 | pr_err("Could not register eeepc backlight device\n"); |
| 1022 | "Could not register eeepc backlight device\n"); | ||
| 1023 | eeepc_backlight_device = NULL; | 1142 | eeepc_backlight_device = NULL; |
| 1024 | return PTR_ERR(bd); | 1143 | return PTR_ERR(bd); |
| 1025 | } | 1144 | } |
| @@ -1038,8 +1157,7 @@ static int eeepc_hwmon_init(struct device *dev) | |||
| 1038 | 1157 | ||
| 1039 | hwmon = hwmon_device_register(dev); | 1158 | hwmon = hwmon_device_register(dev); |
| 1040 | if (IS_ERR(hwmon)) { | 1159 | if (IS_ERR(hwmon)) { |
| 1041 | printk(EEEPC_ERR | 1160 | pr_err("Could not register eeepc hwmon device\n"); |
| 1042 | "Could not register eeepc hwmon device\n"); | ||
| 1043 | eeepc_hwmon_device = NULL; | 1161 | eeepc_hwmon_device = NULL; |
| 1044 | return PTR_ERR(hwmon); | 1162 | return PTR_ERR(hwmon); |
| 1045 | } | 1163 | } |
| @@ -1065,19 +1183,6 @@ static int __init eeepc_laptop_init(void) | |||
| 1065 | acpi_bus_unregister_driver(&eeepc_hotk_driver); | 1183 | acpi_bus_unregister_driver(&eeepc_hotk_driver); |
| 1066 | return -ENODEV; | 1184 | return -ENODEV; |
| 1067 | } | 1185 | } |
| 1068 | dev = acpi_get_physical_device(ehotk->device->handle); | ||
| 1069 | |||
| 1070 | if (!acpi_video_backlight_support()) { | ||
| 1071 | result = eeepc_backlight_init(dev); | ||
| 1072 | if (result) | ||
| 1073 | goto fail_backlight; | ||
| 1074 | } else | ||
| 1075 | printk(EEEPC_INFO "Backlight controlled by ACPI video " | ||
| 1076 | "driver\n"); | ||
| 1077 | |||
| 1078 | result = eeepc_hwmon_init(dev); | ||
| 1079 | if (result) | ||
| 1080 | goto fail_hwmon; | ||
| 1081 | 1186 | ||
| 1082 | eeepc_enable_camera(); | 1187 | eeepc_enable_camera(); |
| 1083 | 1188 | ||
| @@ -1097,7 +1202,33 @@ static int __init eeepc_laptop_init(void) | |||
| 1097 | &platform_attribute_group); | 1202 | &platform_attribute_group); |
| 1098 | if (result) | 1203 | if (result) |
| 1099 | goto fail_sysfs; | 1204 | goto fail_sysfs; |
| 1205 | |||
| 1206 | dev = &platform_device->dev; | ||
| 1207 | |||
| 1208 | if (!acpi_video_backlight_support()) { | ||
| 1209 | result = eeepc_backlight_init(dev); | ||
| 1210 | if (result) | ||
| 1211 | goto fail_backlight; | ||
| 1212 | } else | ||
| 1213 | pr_info("Backlight controlled by ACPI video " | ||
| 1214 | "driver\n"); | ||
| 1215 | |||
| 1216 | result = eeepc_hwmon_init(dev); | ||
| 1217 | if (result) | ||
| 1218 | goto fail_hwmon; | ||
| 1219 | |||
| 1220 | result = eeepc_rfkill_init(dev); | ||
| 1221 | if (result) | ||
| 1222 | goto fail_rfkill; | ||
| 1223 | |||
| 1100 | return 0; | 1224 | return 0; |
| 1225 | fail_rfkill: | ||
| 1226 | eeepc_hwmon_exit(); | ||
| 1227 | fail_hwmon: | ||
| 1228 | eeepc_backlight_exit(); | ||
| 1229 | fail_backlight: | ||
| 1230 | sysfs_remove_group(&platform_device->dev.kobj, | ||
| 1231 | &platform_attribute_group); | ||
| 1101 | fail_sysfs: | 1232 | fail_sysfs: |
| 1102 | platform_device_del(platform_device); | 1233 | platform_device_del(platform_device); |
| 1103 | fail_platform_device2: | 1234 | fail_platform_device2: |
| @@ -1105,12 +1236,7 @@ fail_platform_device2: | |||
| 1105 | fail_platform_device1: | 1236 | fail_platform_device1: |
| 1106 | platform_driver_unregister(&platform_driver); | 1237 | platform_driver_unregister(&platform_driver); |
| 1107 | fail_platform_driver: | 1238 | fail_platform_driver: |
| 1108 | eeepc_hwmon_exit(); | ||
| 1109 | fail_hwmon: | ||
| 1110 | eeepc_backlight_exit(); | ||
| 1111 | fail_backlight: | ||
| 1112 | eeepc_input_exit(); | 1239 | eeepc_input_exit(); |
| 1113 | eeepc_rfkill_exit(); | ||
| 1114 | return result; | 1240 | return result; |
| 1115 | } | 1241 | } |
| 1116 | 1242 | ||
