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 /drivers | |
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
Diffstat (limited to 'drivers')
-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 | ||