diff options
author | Seth Forshee <seth.forshee@canonical.com> | 2011-09-20 17:55:53 -0400 |
---|---|---|
committer | Matthew Garrett <mjg@redhat.com> | 2011-10-24 10:52:36 -0400 |
commit | 36d03f93558c66527e5dbf602cb2eb4ccbd899a6 (patch) | |
tree | 058ea19223d9962fbb92b2409cb1c16b478ee9ae /drivers/platform | |
parent | a540d6b5b577f5a320d873a9cc8778ff20bf5ddf (diff) |
toshiba_acpi: Don't add devices for unsupported features
Test for features up-front to determine whether or not they are
supported, and avoid creating devices and proc files for
unsupported features.
Signed-off-by: Seth Forshee <seth.forshee@canonical.com>
Signed-off-by: Matthew Garrett <mjg@redhat.com>
Diffstat (limited to 'drivers/platform')
-rw-r--r-- | drivers/platform/x86/toshiba_acpi.c | 102 |
1 files changed, 67 insertions, 35 deletions
diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index cc629e621e46..c51a64c49559 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c | |||
@@ -113,11 +113,15 @@ struct toshiba_acpi_dev { | |||
113 | struct input_dev *hotkey_dev; | 113 | struct input_dev *hotkey_dev; |
114 | struct backlight_device *backlight_dev; | 114 | struct backlight_device *backlight_dev; |
115 | struct led_classdev led_dev; | 115 | struct led_classdev led_dev; |
116 | int illumination_installed; | 116 | |
117 | int force_fan; | 117 | int force_fan; |
118 | int last_key_event; | 118 | int last_key_event; |
119 | int key_event_valid; | 119 | int key_event_valid; |
120 | 120 | ||
121 | int illumination_supported:1; | ||
122 | int video_supported:1; | ||
123 | int fan_supported:1; | ||
124 | |||
121 | struct mutex mutex; | 125 | struct mutex mutex; |
122 | }; | 126 | }; |
123 | 127 | ||
@@ -545,24 +549,31 @@ static const struct file_operations lcd_proc_fops = { | |||
545 | .write = lcd_proc_write, | 549 | .write = lcd_proc_write, |
546 | }; | 550 | }; |
547 | 551 | ||
552 | static int get_video_status(struct toshiba_acpi_dev *dev, u32 *status) | ||
553 | { | ||
554 | u32 hci_result; | ||
555 | |||
556 | hci_read1(dev, HCI_VIDEO_OUT, status, &hci_result); | ||
557 | return hci_result == HCI_SUCCESS ? 0 : -EIO; | ||
558 | } | ||
559 | |||
548 | static int video_proc_show(struct seq_file *m, void *v) | 560 | static int video_proc_show(struct seq_file *m, void *v) |
549 | { | 561 | { |
550 | struct toshiba_acpi_dev *dev = m->private; | 562 | struct toshiba_acpi_dev *dev = m->private; |
551 | u32 hci_result; | ||
552 | u32 value; | 563 | u32 value; |
564 | int ret; | ||
553 | 565 | ||
554 | hci_read1(dev, HCI_VIDEO_OUT, &value, &hci_result); | 566 | ret = get_video_status(dev, &value); |
555 | if (hci_result == HCI_SUCCESS) { | 567 | if (!ret) { |
556 | int is_lcd = (value & HCI_VIDEO_OUT_LCD) ? 1 : 0; | 568 | int is_lcd = (value & HCI_VIDEO_OUT_LCD) ? 1 : 0; |
557 | int is_crt = (value & HCI_VIDEO_OUT_CRT) ? 1 : 0; | 569 | int is_crt = (value & HCI_VIDEO_OUT_CRT) ? 1 : 0; |
558 | int is_tv = (value & HCI_VIDEO_OUT_TV) ? 1 : 0; | 570 | int is_tv = (value & HCI_VIDEO_OUT_TV) ? 1 : 0; |
559 | seq_printf(m, "lcd_out: %d\n", is_lcd); | 571 | seq_printf(m, "lcd_out: %d\n", is_lcd); |
560 | seq_printf(m, "crt_out: %d\n", is_crt); | 572 | seq_printf(m, "crt_out: %d\n", is_crt); |
561 | seq_printf(m, "tv_out: %d\n", is_tv); | 573 | seq_printf(m, "tv_out: %d\n", is_tv); |
562 | return 0; | ||
563 | } | 574 | } |
564 | 575 | ||
565 | return -EIO; | 576 | return ret; |
566 | } | 577 | } |
567 | 578 | ||
568 | static int video_proc_open(struct inode *inode, struct file *file) | 579 | static int video_proc_open(struct inode *inode, struct file *file) |
@@ -575,13 +586,12 @@ static ssize_t video_proc_write(struct file *file, const char __user *buf, | |||
575 | { | 586 | { |
576 | struct toshiba_acpi_dev *dev = PDE(file->f_path.dentry->d_inode)->data; | 587 | struct toshiba_acpi_dev *dev = PDE(file->f_path.dentry->d_inode)->data; |
577 | char *cmd, *buffer; | 588 | char *cmd, *buffer; |
578 | int ret = 0; | 589 | int ret; |
579 | int value; | 590 | int value; |
580 | int remain = count; | 591 | int remain = count; |
581 | int lcd_out = -1; | 592 | int lcd_out = -1; |
582 | int crt_out = -1; | 593 | int crt_out = -1; |
583 | int tv_out = -1; | 594 | int tv_out = -1; |
584 | u32 hci_result; | ||
585 | u32 video_out; | 595 | u32 video_out; |
586 | 596 | ||
587 | cmd = kmalloc(count + 1, GFP_KERNEL); | 597 | cmd = kmalloc(count + 1, GFP_KERNEL); |
@@ -616,8 +626,8 @@ static ssize_t video_proc_write(struct file *file, const char __user *buf, | |||
616 | 626 | ||
617 | kfree(cmd); | 627 | kfree(cmd); |
618 | 628 | ||
619 | hci_read1(dev, HCI_VIDEO_OUT, &video_out, &hci_result); | 629 | ret = get_video_status(dev, &video_out); |
620 | if (hci_result == HCI_SUCCESS) { | 630 | if (!ret) { |
621 | unsigned int new_video_out = video_out; | 631 | unsigned int new_video_out = video_out; |
622 | if (lcd_out != -1) | 632 | if (lcd_out != -1) |
623 | _set_bit(&new_video_out, HCI_VIDEO_OUT_LCD, lcd_out); | 633 | _set_bit(&new_video_out, HCI_VIDEO_OUT_LCD, lcd_out); |
@@ -629,8 +639,6 @@ static ssize_t video_proc_write(struct file *file, const char __user *buf, | |||
629 | * video setting if something changed. */ | 639 | * video setting if something changed. */ |
630 | if (new_video_out != video_out) | 640 | if (new_video_out != video_out) |
631 | ret = write_acpi_int(METHOD_VIDEO_OUT, new_video_out); | 641 | ret = write_acpi_int(METHOD_VIDEO_OUT, new_video_out); |
632 | } else { | ||
633 | ret = -EIO; | ||
634 | } | 642 | } |
635 | 643 | ||
636 | return ret ? ret : count; | 644 | return ret ? ret : count; |
@@ -645,20 +653,27 @@ static const struct file_operations video_proc_fops = { | |||
645 | .write = video_proc_write, | 653 | .write = video_proc_write, |
646 | }; | 654 | }; |
647 | 655 | ||
656 | static int get_fan_status(struct toshiba_acpi_dev *dev, u32 *status) | ||
657 | { | ||
658 | u32 hci_result; | ||
659 | |||
660 | hci_read1(dev, HCI_FAN, status, &hci_result); | ||
661 | return hci_result == HCI_SUCCESS ? 0 : -EIO; | ||
662 | } | ||
663 | |||
648 | static int fan_proc_show(struct seq_file *m, void *v) | 664 | static int fan_proc_show(struct seq_file *m, void *v) |
649 | { | 665 | { |
650 | struct toshiba_acpi_dev *dev = m->private; | 666 | struct toshiba_acpi_dev *dev = m->private; |
651 | u32 hci_result; | 667 | int ret; |
652 | u32 value; | 668 | u32 value; |
653 | 669 | ||
654 | hci_read1(dev, HCI_FAN, &value, &hci_result); | 670 | ret = get_fan_status(dev, &value); |
655 | if (hci_result == HCI_SUCCESS) { | 671 | if (!ret) { |
656 | seq_printf(m, "running: %d\n", (value > 0)); | 672 | seq_printf(m, "running: %d\n", (value > 0)); |
657 | seq_printf(m, "force_on: %d\n", dev->force_fan); | 673 | seq_printf(m, "force_on: %d\n", dev->force_fan); |
658 | return 0; | ||
659 | } | 674 | } |
660 | 675 | ||
661 | return -EIO; | 676 | return ret; |
662 | } | 677 | } |
663 | 678 | ||
664 | static int fan_proc_open(struct inode *inode, struct file *file) | 679 | static int fan_proc_open(struct inode *inode, struct file *file) |
@@ -797,24 +812,32 @@ static const struct file_operations version_proc_fops = { | |||
797 | static void __devinit | 812 | static void __devinit |
798 | create_toshiba_proc_entries(struct toshiba_acpi_dev *dev) | 813 | create_toshiba_proc_entries(struct toshiba_acpi_dev *dev) |
799 | { | 814 | { |
800 | proc_create_data("lcd", S_IRUGO | S_IWUSR, toshiba_proc_dir, | 815 | if (dev->backlight_dev) |
801 | &lcd_proc_fops, dev); | 816 | proc_create_data("lcd", S_IRUGO | S_IWUSR, toshiba_proc_dir, |
802 | proc_create_data("video", S_IRUGO | S_IWUSR, toshiba_proc_dir, | 817 | &lcd_proc_fops, dev); |
803 | &video_proc_fops, dev); | 818 | if (dev->video_supported) |
804 | proc_create_data("fan", S_IRUGO | S_IWUSR, toshiba_proc_dir, | 819 | proc_create_data("video", S_IRUGO | S_IWUSR, toshiba_proc_dir, |
805 | &fan_proc_fops, dev); | 820 | &video_proc_fops, dev); |
806 | proc_create_data("keys", S_IRUGO | S_IWUSR, toshiba_proc_dir, | 821 | if (dev->fan_supported) |
807 | &keys_proc_fops, dev); | 822 | proc_create_data("fan", S_IRUGO | S_IWUSR, toshiba_proc_dir, |
823 | &fan_proc_fops, dev); | ||
824 | if (dev->hotkey_dev) | ||
825 | proc_create_data("keys", S_IRUGO | S_IWUSR, toshiba_proc_dir, | ||
826 | &keys_proc_fops, dev); | ||
808 | proc_create_data("version", S_IRUGO, toshiba_proc_dir, | 827 | proc_create_data("version", S_IRUGO, toshiba_proc_dir, |
809 | &version_proc_fops, dev); | 828 | &version_proc_fops, dev); |
810 | } | 829 | } |
811 | 830 | ||
812 | static void remove_toshiba_proc_entries(void) | 831 | static void remove_toshiba_proc_entries(struct toshiba_acpi_dev *dev) |
813 | { | 832 | { |
814 | remove_proc_entry("lcd", toshiba_proc_dir); | 833 | if (dev->backlight_dev) |
815 | remove_proc_entry("video", toshiba_proc_dir); | 834 | remove_proc_entry("lcd", toshiba_proc_dir); |
816 | remove_proc_entry("fan", toshiba_proc_dir); | 835 | if (dev->video_supported) |
817 | remove_proc_entry("keys", toshiba_proc_dir); | 836 | remove_proc_entry("video", toshiba_proc_dir); |
837 | if (dev->fan_supported) | ||
838 | remove_proc_entry("fan", toshiba_proc_dir); | ||
839 | if (dev->hotkey_dev) | ||
840 | remove_proc_entry("keys", toshiba_proc_dir); | ||
818 | remove_proc_entry("version", toshiba_proc_dir); | 841 | remove_proc_entry("version", toshiba_proc_dir); |
819 | } | 842 | } |
820 | 843 | ||
@@ -869,7 +892,7 @@ static int toshiba_acpi_remove(struct acpi_device *acpi_dev, int type) | |||
869 | { | 892 | { |
870 | struct toshiba_acpi_dev *dev = acpi_driver_data(acpi_dev); | 893 | struct toshiba_acpi_dev *dev = acpi_driver_data(acpi_dev); |
871 | 894 | ||
872 | remove_toshiba_proc_entries(); | 895 | remove_toshiba_proc_entries(dev); |
873 | 896 | ||
874 | if (dev->hotkey_dev) { | 897 | if (dev->hotkey_dev) { |
875 | input_unregister_device(dev->hotkey_dev); | 898 | input_unregister_device(dev->hotkey_dev); |
@@ -884,7 +907,7 @@ static int toshiba_acpi_remove(struct acpi_device *acpi_dev, int type) | |||
884 | if (dev->backlight_dev) | 907 | if (dev->backlight_dev) |
885 | backlight_device_unregister(dev->backlight_dev); | 908 | backlight_device_unregister(dev->backlight_dev); |
886 | 909 | ||
887 | if (dev->illumination_installed) | 910 | if (dev->illumination_supported) |
888 | led_classdev_unregister(&dev->led_dev); | 911 | led_classdev_unregister(&dev->led_dev); |
889 | 912 | ||
890 | kfree(dev); | 913 | kfree(dev); |
@@ -913,6 +936,7 @@ static int __devinit toshiba_acpi_add(struct acpi_device *acpi_dev) | |||
913 | struct toshiba_acpi_dev *dev; | 936 | struct toshiba_acpi_dev *dev; |
914 | const char *hci_method; | 937 | const char *hci_method; |
915 | u32 hci_result; | 938 | u32 hci_result; |
939 | u32 dummy; | ||
916 | bool bt_present; | 940 | bool bt_present; |
917 | int ret = 0; | 941 | int ret = 0; |
918 | struct backlight_properties props; | 942 | struct backlight_properties props; |
@@ -941,8 +965,6 @@ static int __devinit toshiba_acpi_add(struct acpi_device *acpi_dev) | |||
941 | /* enable event fifo */ | 965 | /* enable event fifo */ |
942 | hci_write1(dev, HCI_SYSTEM_EVENT, 1, &hci_result); | 966 | hci_write1(dev, HCI_SYSTEM_EVENT, 1, &hci_result); |
943 | 967 | ||
944 | create_toshiba_proc_entries(dev); | ||
945 | |||
946 | props.type = BACKLIGHT_PLATFORM; | 968 | props.type = BACKLIGHT_PLATFORM; |
947 | props.max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1; | 969 | props.max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1; |
948 | dev->backlight_dev = backlight_device_register("toshiba", | 970 | dev->backlight_dev = backlight_device_register("toshiba", |
@@ -985,9 +1007,19 @@ static int __devinit toshiba_acpi_add(struct acpi_device *acpi_dev) | |||
985 | dev->led_dev.brightness_set = toshiba_illumination_set; | 1007 | dev->led_dev.brightness_set = toshiba_illumination_set; |
986 | dev->led_dev.brightness_get = toshiba_illumination_get; | 1008 | dev->led_dev.brightness_get = toshiba_illumination_get; |
987 | if (!led_classdev_register(&acpi_dev->dev, &dev->led_dev)) | 1009 | if (!led_classdev_register(&acpi_dev->dev, &dev->led_dev)) |
988 | dev->illumination_installed = 1; | 1010 | dev->illumination_supported = 1; |
989 | } | 1011 | } |
990 | 1012 | ||
1013 | /* Determine whether or not BIOS supports fan and video interfaces */ | ||
1014 | |||
1015 | ret = get_video_status(dev, &dummy); | ||
1016 | dev->video_supported = !ret; | ||
1017 | |||
1018 | ret = get_fan_status(dev, &dummy); | ||
1019 | dev->fan_supported = !ret; | ||
1020 | |||
1021 | create_toshiba_proc_entries(dev); | ||
1022 | |||
991 | return 0; | 1023 | return 0; |
992 | 1024 | ||
993 | error: | 1025 | error: |