Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'for_linus' of git://cavan.codon.org.uk/platform-drivers-x86

Pull x86 platform driver updates from Matthew Garrett:
"A moderate number of changes, but nothing awfully significant.

A lot of const cleanups, some reworking and additions to the rfkill
quirks in the asus driver, a new driver for generating falling laptop
events on Toshibas and some misc fixes.

Maybe vendors have stopped inventing things"

* 'for_linus' of git://cavan.codon.org.uk/platform-drivers-x86: (41 commits)
platform/x86: Enable build support for toshiba_haps
Documentation: Add file about toshiba_haps module
platform/x86: Toshiba HDD Active Protection Sensor
asus-nb-wmi: Add wapf4 quirk for the U32U
alienware-wmi: make hdmi_mux enabled on case-by-case basis
ideapad-laptop: Constify DMI table and other r/o variables
asus-nb-wmi.c: Rename x401u quirk to wapf4
compal-laptop: correct invalid hwmon name
toshiba_acpi: Add Qosmio X75-A to the alt keymap dmi list
toshiba_acpi: Add extra check to backlight code
Fix log message about future removal of interface
ideapad-laptop: Disable touchpad interface on Yoga models
asus-nb-wmi: Add wapf4 quirk for the X550CC
intel_ips: Make ips_mcp_limits variables static
thinkpad_acpi: Mark volume_alsa_control_{vol,mute} as __initdata
fujitsu-laptop: Mark fujitsu_dmi_table[] DMI table as __initconst
hp-wmi: Add missing __init annotations to initialization code
hp_accel: Constify ACPI and DMI tables
fujitsu-tablet: Mark DMI callbacks as __init code
dell-laptop: Mark dell_quirks[] DMI table as __initconst
...

+608 -108
+2
Documentation/laptops/00-INDEX
··· 18 18 - info on Linux Sony Programmable I/O Device support. 19 19 thinkpad-acpi.txt 20 20 - information on the (IBM and Lenovo) ThinkPad ACPI Extras driver. 21 + toshiba_haps.txt 22 + - information on the Toshiba HDD Active Protection Sensor driver.
+76
Documentation/laptops/toshiba_haps.txt
··· 1 + Kernel driver toshiba_haps 2 + Toshiba HDD Active Protection Sensor 3 + ==================================== 4 + 5 + Author: Azael Avalos <coproscefalo@gmail.com> 6 + 7 + 8 + 0. Contents 9 + ----------- 10 + 11 + 1. Description 12 + 2. Interface 13 + 3. Accelerometer axes 14 + 4. Supported devices 15 + 5. Usage 16 + 17 + 18 + 1. Description 19 + -------------- 20 + 21 + This driver provides support for the accelerometer found in various Toshiba 22 + laptops, being called "Toshiba HDD Protection - Shock Sensor" officialy, 23 + and detects laptops automatically with this device. 24 + On Windows, Toshiba provided software monitors this device and provides 25 + automatic HDD protection (head unload) on sudden moves or harsh vibrations, 26 + however, this driver only provides a notification via a sysfs file to let 27 + userspace tools or daemons act accordingly, as well as providing a sysfs 28 + file to set the desired protection level or sensor sensibility. 29 + 30 + 31 + 2. Interface 32 + ------------ 33 + 34 + This device comes with 3 methods: 35 + _STA - Checks existence of the device, returning Zero if the device does not 36 + exists or is not supported. 37 + PTLV - Sets the desired protection level. 38 + RSSS - Shuts down the HDD protection interface for a few seconds, 39 + then restores normal operation. 40 + 41 + Note: 42 + The presence of Solid State Drives (SSD) can make this driver to fail loading, 43 + given the fact that such drives have no movable parts, and thus, not requiring 44 + any "protection" as well as failing during the evaluation of the _STA method 45 + found under this device. 46 + 47 + 48 + 3. Accelerometer axes 49 + --------------------- 50 + 51 + This device does not report any axes, however, to query the sensor position 52 + a couple HCI (Hardware Configuration Interface) calls (0x6D and 0xA6) are 53 + provided to query such information, handled by the kernel module toshiba_acpi 54 + since kernel version 3.15. 55 + 56 + 57 + 4. Supported devices 58 + -------------------- 59 + 60 + This driver binds itself to the ACPI device TOS620A, and any Toshiba laptop 61 + with this device is supported, given the fact that they have the presence of 62 + conventional HDD and not only SSD, or a combination of both HDD and SSD. 63 + 64 + 65 + 5. Usage 66 + -------- 67 + 68 + The sysfs files under /sys/devices/LNXSYSTM:00/LNXSYBUS:00/TOS620A:00/ are: 69 + protection_level - The protection_level is readable and writeable, and 70 + provides a way to let userspace query the current protection 71 + level, as well as set the desired protection level, the 72 + available protection levels are: 73 + 0 - Disabled | 1 - Low | 2 - Medium | 3 - High 74 + reset_protection - The reset_protection entry is writeable only, being "1" 75 + the only parameter it accepts, it is used to trigger 76 + a reset of the protection interface.
+1 -1
MAINTAINERS
··· 10017 10017 X86 PLATFORM DRIVERS 10018 10018 M: Matthew Garrett <matthew.garrett@nebula.com> 10019 10019 L: platform-driver-x86@vger.kernel.org 10020 - T: git git://git.kernel.org/pub/scm/linux/kernel/git/mjg59/platform-drivers-x86.git 10020 + T: git git://cavan.codon.org.uk/platform-drivers-x86.git 10021 10021 S: Maintained 10022 10022 F: drivers/platform/x86/ 10023 10023
+19
drivers/platform/x86/Kconfig
··· 652 652 If you have a modern Toshiba laptop with a Bluetooth and an 653 653 RFKill switch (such as the Portege R500), say Y. 654 654 655 + config TOSHIBA_HAPS 656 + tristate "Toshiba HDD Active Protection Sensor" 657 + depends on ACPI 658 + ---help--- 659 + This driver adds support for the built-in accelerometer 660 + found on recent Toshiba laptops equiped with HID TOS620A 661 + device. 662 + 663 + This driver receives ACPI notify events 0x80 when the sensor 664 + detects a sudden move or a harsh vibration, as well as an 665 + ACPI notify event 0x81 whenever the movement or vibration has 666 + been stabilized. 667 + 668 + Also provides sysfs entries to get/set the desired protection 669 + level and reseting the HDD protection interface. 670 + 671 + If you have a recent Toshiba laptop with a built-in accelerometer 672 + device, say Y. 673 + 655 674 config ACPI_CMPC 656 675 tristate "CMPC Laptop Extras" 657 676 depends on X86 && ACPI
+1
drivers/platform/x86/Makefile
··· 38 38 obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o 39 39 40 40 obj-$(CONFIG_TOSHIBA_BT_RFKILL) += toshiba_bluetooth.o 41 + obj-$(CONFIG_TOSHIBA_HAPS) += toshiba_haps.o 41 42 obj-$(CONFIG_INTEL_SCU_IPC) += intel_scu_ipc.o 42 43 obj-$(CONFIG_INTEL_SCU_IPC_UTIL) += intel_scu_ipcutil.o 43 44 obj-$(CONFIG_INTEL_MFLD_THERMAL) += intel_mid_thermal.o
+30 -24
drivers/platform/x86/acer-wmi.c
··· 96 96 WMID_ACCEL_EVENT = 0x5, 97 97 }; 98 98 99 - static const struct key_entry acer_wmi_keymap[] = { 99 + static const struct key_entry acer_wmi_keymap[] __initconst = { 100 100 {KE_KEY, 0x01, {KEY_WLAN} }, /* WiFi */ 101 101 {KE_KEY, 0x03, {KEY_WLAN} }, /* WiFi */ 102 102 {KE_KEY, 0x04, {KEY_WLAN} }, /* WiFi */ ··· 294 294 295 295 static struct quirk_entry *quirks; 296 296 297 - static void set_quirks(void) 297 + static void __init set_quirks(void) 298 298 { 299 299 if (!interface) 300 300 return; ··· 306 306 interface->capability |= ACER_CAP_BRIGHTNESS; 307 307 } 308 308 309 - static int dmi_matched(const struct dmi_system_id *dmi) 309 + static int __init dmi_matched(const struct dmi_system_id *dmi) 310 310 { 311 311 quirks = dmi->driver_data; 312 312 return 1; ··· 337 337 }; 338 338 339 339 /* The Aspire One has a dummy ACPI-WMI interface - disable it */ 340 - static struct dmi_system_id acer_blacklist[] = { 340 + static const struct dmi_system_id acer_blacklist[] __initconst = { 341 341 { 342 342 .ident = "Acer Aspire One (SSD)", 343 343 .matches = { ··· 355 355 {} 356 356 }; 357 357 358 - static struct dmi_system_id acer_quirks[] = { 358 + static const struct dmi_system_id acer_quirks[] __initconst = { 359 359 { 360 360 .callback = dmi_matched, 361 361 .ident = "Acer Aspire 1360", ··· 530 530 {} 531 531 }; 532 532 533 - static int video_set_backlight_video_vendor(const struct dmi_system_id *d) 533 + static int __init 534 + video_set_backlight_video_vendor(const struct dmi_system_id *d) 534 535 { 535 536 interface->capability &= ~ACER_CAP_BRIGHTNESS; 536 537 pr_info("Brightness must be controlled by generic video driver\n"); 537 538 return 0; 538 539 } 539 540 540 - static const struct dmi_system_id video_vendor_dmi_table[] = { 541 + static const struct dmi_system_id video_vendor_dmi_table[] __initconst = { 541 542 { 542 543 .callback = video_set_backlight_video_vendor, 543 544 .ident = "Acer TravelMate 4750", ··· 583 582 }; 584 583 585 584 /* Find which quirks are needed for a particular vendor/ model pair */ 586 - static void find_quirks(void) 585 + static void __init find_quirks(void) 587 586 { 588 587 if (!force_series) { 589 588 dmi_check_system(acer_quirks); ··· 750 749 return wmab_execute(&args, NULL); 751 750 } 752 751 753 - static acpi_status AMW0_find_mailled(void) 752 + static acpi_status __init AMW0_find_mailled(void) 754 753 { 755 754 struct wmab_args args; 756 755 struct wmab_ret ret; ··· 782 781 return AE_OK; 783 782 } 784 783 785 - static int AMW0_set_cap_acpi_check_device_found; 784 + static int AMW0_set_cap_acpi_check_device_found __initdata; 786 785 787 - static acpi_status AMW0_set_cap_acpi_check_device_cb(acpi_handle handle, 786 + static acpi_status __init AMW0_set_cap_acpi_check_device_cb(acpi_handle handle, 788 787 u32 level, void *context, void **retval) 789 788 { 790 789 AMW0_set_cap_acpi_check_device_found = 1; 791 790 return AE_OK; 792 791 } 793 792 794 - static const struct acpi_device_id norfkill_ids[] = { 793 + static const struct acpi_device_id norfkill_ids[] __initconst = { 795 794 { "VPC2004", 0}, 796 795 { "IBM0068", 0}, 797 796 { "LEN0068", 0}, ··· 799 798 { "", 0}, 800 799 }; 801 800 802 - static int AMW0_set_cap_acpi_check_device(void) 801 + static int __init AMW0_set_cap_acpi_check_device(void) 803 802 { 804 803 const struct acpi_device_id *id; 805 804 ··· 809 808 return AMW0_set_cap_acpi_check_device_found; 810 809 } 811 810 812 - static acpi_status AMW0_set_capabilities(void) 811 + static acpi_status __init AMW0_set_capabilities(void) 813 812 { 814 813 struct wmab_args args; 815 814 struct wmab_ret ret; ··· 1185 1184 return wmid3_set_device_status(value, device); 1186 1185 } 1187 1186 1188 - static void type_aa_dmi_decode(const struct dmi_header *header, void *dummy) 1187 + static void __init type_aa_dmi_decode(const struct dmi_header *header, void *d) 1189 1188 { 1190 1189 struct hotkey_function_type_aa *type_aa; 1191 1190 ··· 1210 1209 commun_fn_key_number = type_aa->commun_fn_key_number; 1211 1210 } 1212 1211 1213 - static acpi_status WMID_set_capabilities(void) 1212 + static acpi_status __init WMID_set_capabilities(void) 1214 1213 { 1215 1214 struct acpi_buffer out = {ACPI_ALLOCATE_BUFFER, NULL}; 1216 1215 union acpi_object *obj; ··· 1659 1658 u32 result; \ 1660 1659 acpi_status status; 1661 1660 1662 - pr_info("This threeg sysfs will be removed in 2012 - used by: %s\n", 1661 + pr_info("This threeg sysfs will be removed in 2014 - used by: %s\n", 1663 1662 current->comm); 1664 1663 status = get_u32(&result, ACER_CAP_THREEG); 1665 1664 if (ACPI_SUCCESS(status)) ··· 1672 1671 { 1673 1672 u32 tmp = simple_strtoul(buf, NULL, 10); 1674 1673 acpi_status status = set_u32(tmp, ACER_CAP_THREEG); 1675 - pr_info("This threeg sysfs will be removed in 2012 - used by: %s\n", 1674 + pr_info("This threeg sysfs will be removed in 2014 - used by: %s\n", 1676 1675 current->comm); 1677 1676 if (ACPI_FAILURE(status)) 1678 1677 return -EINVAL; ··· 1684 1683 static ssize_t show_interface(struct device *dev, struct device_attribute *attr, 1685 1684 char *buf) 1686 1685 { 1687 - pr_info("This interface sysfs will be removed in 2012 - used by: %s\n", 1686 + pr_info("This interface sysfs will be removed in 2014 - used by: %s\n", 1688 1687 current->comm); 1689 1688 switch (interface->type) { 1690 1689 case ACER_AMW0: ··· 1778 1777 } 1779 1778 } 1780 1779 1781 - static acpi_status 1780 + static acpi_status __init 1782 1781 wmid3_set_lm_mode(struct lm_input_params *params, 1783 1782 struct lm_return_value *return_value) 1784 1783 { ··· 1812 1811 return status; 1813 1812 } 1814 1813 1815 - static int acer_wmi_enable_ec_raw(void) 1814 + static int __init acer_wmi_enable_ec_raw(void) 1816 1815 { 1817 1816 struct lm_return_value return_value; 1818 1817 acpi_status status; ··· 1835 1834 return status; 1836 1835 } 1837 1836 1838 - static int acer_wmi_enable_lm(void) 1837 + static int __init acer_wmi_enable_lm(void) 1839 1838 { 1840 1839 struct lm_return_value return_value; 1841 1840 acpi_status status; ··· 2044 2043 return 0; 2045 2044 } 2046 2045 2046 + #ifdef CONFIG_PM_SLEEP 2047 2047 static int acer_suspend(struct device *dev) 2048 2048 { 2049 2049 u32 value; ··· 2085 2083 2086 2084 return 0; 2087 2085 } 2086 + #else 2087 + #define acer_suspend NULL 2088 + #define acer_resume NULL 2089 + #endif 2088 2090 2089 2091 static SIMPLE_DEV_PM_OPS(acer_pm, acer_suspend, acer_resume); 2090 2092 ··· 2126 2120 return 0; 2127 2121 } 2128 2122 2129 - static int create_sysfs(void) 2123 + static int __init create_sysfs(void) 2130 2124 { 2131 2125 int retval = -ENOMEM; 2132 2126 ··· 2155 2149 debugfs_remove(interface->debug.root); 2156 2150 } 2157 2151 2158 - static int create_debugfs(void) 2152 + static int __init create_debugfs(void) 2159 2153 { 2160 2154 interface->debug.root = debugfs_create_dir("acer-wmi", NULL); 2161 2155 if (!interface->debug.root) {
+22 -4
drivers/platform/x86/alienware-wmi.c
··· 59 59 60 60 struct quirk_entry { 61 61 u8 num_zones; 62 + u8 hdmi_mux; 62 63 }; 63 64 64 65 static struct quirk_entry *quirks; 65 66 66 67 static struct quirk_entry quirk_unknown = { 67 68 .num_zones = 2, 69 + .hdmi_mux = 0, 68 70 }; 69 71 70 72 static struct quirk_entry quirk_x51_family = { 71 73 .num_zones = 3, 74 + .hdmi_mux = 0. 72 75 }; 73 76 74 - static int dmi_matched(const struct dmi_system_id *dmi) 77 + static struct quirk_entry quirk_asm100 = { 78 + .num_zones = 2, 79 + .hdmi_mux = 1, 80 + }; 81 + 82 + static int __init dmi_matched(const struct dmi_system_id *dmi) 75 83 { 76 84 quirks = dmi->driver_data; 77 85 return 1; 78 86 } 79 87 80 - static struct dmi_system_id alienware_quirks[] = { 88 + static const struct dmi_system_id alienware_quirks[] __initconst = { 81 89 { 82 90 .callback = dmi_matched, 83 91 .ident = "Alienware X51 R1", ··· 104 96 }, 105 97 .driver_data = &quirk_x51_family, 106 98 }, 99 + { 100 + .callback = dmi_matched, 101 + .ident = "Alienware ASM100", 102 + .matches = { 103 + DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), 104 + DMI_MATCH(DMI_PRODUCT_NAME, "ASM100"), 105 + }, 106 + .driver_data = &quirk_asm100, 107 + }, 107 108 {} 108 109 }; 109 110 ··· 554 537 555 538 static void remove_hdmi(struct platform_device *dev) 556 539 { 557 - sysfs_remove_group(&dev->dev.kobj, &hdmi_attribute_group); 540 + if (quirks->hdmi_mux > 0) 541 + sysfs_remove_group(&dev->dev.kobj, &hdmi_attribute_group); 558 542 } 559 543 560 544 static int create_hdmi(struct platform_device *dev) ··· 601 583 if (ret) 602 584 goto fail_platform_device2; 603 585 604 - if (interface == WMAX) { 586 + if (quirks->hdmi_mux > 0) { 605 587 ret = create_hdmi(platform_device); 606 588 if (ret) 607 589 goto fail_prep_hdmi;
+67 -13
drivers/platform/x86/asus-nb-wmi.c
··· 70 70 .no_display_toggle = true, 71 71 }; 72 72 73 - static struct quirk_entry quirk_asus_x401u = { 73 + static struct quirk_entry quirk_asus_wapf4 = { 74 74 .wapf = 4, 75 + }; 76 + 77 + static struct quirk_entry quirk_asus_x200ca = { 78 + .wapf = 2, 75 79 }; 76 80 77 81 static int dmi_matched(const struct dmi_system_id *dmi) ··· 84 80 return 1; 85 81 } 86 82 87 - static struct dmi_system_id asus_quirks[] = { 83 + static const struct dmi_system_id asus_quirks[] = { 84 + { 85 + .callback = dmi_matched, 86 + .ident = "ASUSTeK COMPUTER INC. U32U", 87 + .matches = { 88 + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), 89 + DMI_MATCH(DMI_PRODUCT_NAME, "U32U"), 90 + }, 91 + /* 92 + * Note this machine has a Brazos APU, and most Brazos Asus 93 + * machines need quirk_asus_x55u / wmi_backlight_power but 94 + * here acpi-video seems to work fine for backlight control. 95 + */ 96 + .driver_data = &quirk_asus_wapf4, 97 + }, 88 98 { 89 99 .callback = dmi_matched, 90 100 .ident = "ASUSTeK COMPUTER INC. X401U", ··· 115 97 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 116 98 DMI_MATCH(DMI_PRODUCT_NAME, "X401A"), 117 99 }, 118 - .driver_data = &quirk_asus_x401u, 100 + .driver_data = &quirk_asus_wapf4, 119 101 }, 120 102 { 121 103 .callback = dmi_matched, ··· 124 106 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 125 107 DMI_MATCH(DMI_PRODUCT_NAME, "X401A1"), 126 108 }, 127 - .driver_data = &quirk_asus_x401u, 109 + .driver_data = &quirk_asus_wapf4, 128 110 }, 129 111 { 130 112 .callback = dmi_matched, ··· 142 124 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 143 125 DMI_MATCH(DMI_PRODUCT_NAME, "X501A"), 144 126 }, 145 - .driver_data = &quirk_asus_x401u, 127 + .driver_data = &quirk_asus_wapf4, 146 128 }, 147 129 { 148 130 .callback = dmi_matched, ··· 151 133 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 152 134 DMI_MATCH(DMI_PRODUCT_NAME, "X501A1"), 153 135 }, 154 - .driver_data = &quirk_asus_x401u, 136 + .driver_data = &quirk_asus_wapf4, 155 137 }, 156 138 { 157 139 .callback = dmi_matched, ··· 160 142 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 161 143 DMI_MATCH(DMI_PRODUCT_NAME, "X550CA"), 162 144 }, 163 - .driver_data = &quirk_asus_x401u, 145 + .driver_data = &quirk_asus_wapf4, 146 + }, 147 + { 148 + .callback = dmi_matched, 149 + .ident = "ASUSTeK COMPUTER INC. X550CC", 150 + .matches = { 151 + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 152 + DMI_MATCH(DMI_PRODUCT_NAME, "X550CC"), 153 + }, 154 + .driver_data = &quirk_asus_wapf4, 155 + }, 156 + { 157 + .callback = dmi_matched, 158 + .ident = "ASUSTeK COMPUTER INC. X550CL", 159 + .matches = { 160 + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 161 + DMI_MATCH(DMI_PRODUCT_NAME, "X550CL"), 162 + }, 163 + .driver_data = &quirk_asus_wapf4, 164 164 }, 165 165 { 166 166 .callback = dmi_matched, ··· 187 151 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 188 152 DMI_MATCH(DMI_PRODUCT_NAME, "X55A"), 189 153 }, 190 - .driver_data = &quirk_asus_x401u, 154 + .driver_data = &quirk_asus_wapf4, 191 155 }, 192 156 { 193 157 .callback = dmi_matched, ··· 196 160 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 197 161 DMI_MATCH(DMI_PRODUCT_NAME, "X55C"), 198 162 }, 199 - .driver_data = &quirk_asus_x401u, 163 + .driver_data = &quirk_asus_wapf4, 200 164 }, 201 165 { 202 166 .callback = dmi_matched, ··· 214 178 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 215 179 DMI_MATCH(DMI_PRODUCT_NAME, "X55VD"), 216 180 }, 217 - .driver_data = &quirk_asus_x401u, 181 + .driver_data = &quirk_asus_wapf4, 218 182 }, 219 183 { 220 184 .callback = dmi_matched, ··· 223 187 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 224 188 DMI_MATCH(DMI_PRODUCT_NAME, "X75A"), 225 189 }, 226 - .driver_data = &quirk_asus_x401u, 190 + .driver_data = &quirk_asus_wapf4, 191 + }, 192 + { 193 + .callback = dmi_matched, 194 + .ident = "ASUSTeK COMPUTER INC. X75VBP", 195 + .matches = { 196 + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 197 + DMI_MATCH(DMI_PRODUCT_NAME, "X75VBP"), 198 + }, 199 + .driver_data = &quirk_asus_wapf4, 227 200 }, 228 201 { 229 202 .callback = dmi_matched, ··· 241 196 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 242 197 DMI_MATCH(DMI_PRODUCT_NAME, "1015E"), 243 198 }, 244 - .driver_data = &quirk_asus_x401u, 199 + .driver_data = &quirk_asus_wapf4, 245 200 }, 246 201 { 247 202 .callback = dmi_matched, ··· 250 205 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 251 206 DMI_MATCH(DMI_PRODUCT_NAME, "1015U"), 252 207 }, 253 - .driver_data = &quirk_asus_x401u, 208 + .driver_data = &quirk_asus_wapf4, 209 + }, 210 + { 211 + .callback = dmi_matched, 212 + .ident = "ASUSTeK COMPUTER INC. X200CA", 213 + .matches = { 214 + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 215 + DMI_MATCH(DMI_PRODUCT_NAME, "X200CA"), 216 + }, 217 + .driver_data = &quirk_asus_x200ca, 254 218 }, 255 219 {}, 256 220 };
+10 -6
drivers/platform/x86/asus-wmi.c
··· 46 46 #include <linux/platform_device.h> 47 47 #include <linux/thermal.h> 48 48 #include <linux/acpi.h> 49 + #include <linux/dmi.h> 49 50 #include <acpi/video.h> 50 51 51 52 #include "asus-wmi.h" ··· 555 554 goto error; 556 555 } 557 556 558 - if (wlan_led_presence(asus) && (asus->driver->quirks->wapf == 4)) { 557 + if (wlan_led_presence(asus) && (asus->driver->quirks->wapf > 0)) { 559 558 INIT_WORK(&asus->wlan_led_work, wlan_led_update); 560 559 561 560 asus->wlan_led.name = "asus::wlan"; ··· 885 884 return -EINVAL; 886 885 887 886 if ((dev_id == ASUS_WMI_DEVID_WLAN) && 888 - (asus->driver->quirks->wapf == 4)) 887 + (asus->driver->quirks->wapf > 0)) 889 888 rfkill_set_led_trigger_name(*rfkill, "asus-wlan"); 890 889 891 890 rfkill_init_sw_state(*rfkill, !result); ··· 1271 1270 int power; 1272 1271 1273 1272 max = read_brightness_max(asus); 1274 - 1275 - if (max == -ENODEV) 1276 - max = 0; 1277 - else if (max < 0) 1273 + if (max < 0) 1278 1274 return max; 1279 1275 1280 1276 power = read_backlight_power(asus); ··· 1732 1734 struct platform_driver *pdrv = to_platform_driver(pdev->dev.driver); 1733 1735 struct asus_wmi_driver *wdrv = to_asus_wmi_driver(pdrv); 1734 1736 struct asus_wmi *asus; 1737 + const char *chassis_type; 1735 1738 acpi_status status; 1736 1739 int err; 1737 1740 u32 result; ··· 1769 1770 if (err) 1770 1771 goto fail_rfkill; 1771 1772 1773 + /* Some Asus desktop boards export an acpi-video backlight interface, 1774 + stop this from showing up */ 1775 + chassis_type = dmi_get_system_info(DMI_CHASSIS_TYPE); 1776 + if (chassis_type && !strcmp(chassis_type, "3")) 1777 + acpi_video_dmi_promote_vendor(); 1772 1778 if (asus->driver->quirks->wmi_backlight_power) 1773 1779 acpi_video_dmi_promote_vendor(); 1774 1780 if (!acpi_video_backlight_support()) {
+1 -1
drivers/platform/x86/compal-laptop.c
··· 1028 1028 return err; 1029 1029 1030 1030 hwmon_dev = hwmon_device_register_with_groups(&pdev->dev, 1031 - DRIVER_NAME, data, 1031 + "compal", data, 1032 1032 compal_hwmon_groups); 1033 1033 if (IS_ERR(hwmon_dev)) { 1034 1034 err = PTR_ERR(hwmon_dev);
+3 -3
drivers/platform/x86/dell-laptop.c
··· 70 70 .touchpad_led = 1, 71 71 }; 72 72 73 - static int dmi_matched(const struct dmi_system_id *dmi) 73 + static int __init dmi_matched(const struct dmi_system_id *dmi) 74 74 { 75 75 quirks = dmi->driver_data; 76 76 return 1; ··· 123 123 }; 124 124 MODULE_DEVICE_TABLE(dmi, dell_device_table); 125 125 126 - static struct dmi_system_id dell_quirks[] = { 126 + static const struct dmi_system_id dell_quirks[] __initconst = { 127 127 { 128 128 .callback = dmi_matched, 129 129 .ident = "Dell Vostro V130", ··· 780 780 .flags = LED_CORE_SUSPENDRESUME, 781 781 }; 782 782 783 - static int touchpad_led_init(struct device *dev) 783 + static int __init touchpad_led_init(struct device *dev) 784 784 { 785 785 return led_classdev_register(dev, &touchpad_led); 786 786 }
+4 -4
drivers/platform/x86/eeepc-laptop.c
··· 1053 1053 return sprintf(buf, "%d\n", get()); 1054 1054 } 1055 1055 1056 - #define EEEPC_CREATE_SENSOR_ATTR(_name, _mode, _set, _get) \ 1056 + #define EEEPC_CREATE_SENSOR_ATTR(_name, _mode, _get, _set) \ 1057 1057 static ssize_t show_##_name(struct device *dev, \ 1058 1058 struct device_attribute *attr, \ 1059 1059 char *buf) \ 1060 1060 { \ 1061 - return show_sys_hwmon(_set, buf); \ 1061 + return show_sys_hwmon(_get, buf); \ 1062 1062 } \ 1063 1063 static ssize_t store_##_name(struct device *dev, \ 1064 1064 struct device_attribute *attr, \ 1065 1065 const char *buf, size_t count) \ 1066 1066 { \ 1067 - return store_sys_hwmon(_get, buf, count); \ 1067 + return store_sys_hwmon(_set, buf, count); \ 1068 1068 } \ 1069 - static DEVICE_ATTR(_name, _mode, show_##_name, store_##_name); 1069 + static DEVICE_ATTR(_name, _mode, show_##_name, store_##_name) 1070 1070 1071 1071 EEEPC_CREATE_SENSOR_ATTR(fan1_input, S_IRUGO, eeepc_get_fan_rpm, NULL); 1072 1072 EEEPC_CREATE_SENSOR_ATTR(pwm1, S_IRUGO | S_IWUSR,
+1 -1
drivers/platform/x86/eeepc-wmi.c
··· 145 145 return 1; 146 146 } 147 147 148 - static struct dmi_system_id asus_quirks[] = { 148 + static const struct dmi_system_id asus_quirks[] = { 149 149 { 150 150 .callback = dmi_matched, 151 151 .ident = "ASUSTeK Computer INC. 1000H",
+9 -10
drivers/platform/x86/fujitsu-laptop.c
··· 129 129 #define FUJLAPTOP_DBG_INFO 0x0004 130 130 #define FUJLAPTOP_DBG_TRACE 0x0008 131 131 132 - #define dbg_printk(a_dbg_level, format, arg...) \ 132 + #ifdef CONFIG_FUJITSU_LAPTOP_DEBUG 133 + #define vdbg_printk(a_dbg_level, format, arg...) \ 133 134 do { if (dbg_level & a_dbg_level) \ 134 135 printk(FUJLAPTOP_DEBUG "%s: " format, __func__ , ## arg); \ 135 136 } while (0) 136 - #ifdef CONFIG_FUJITSU_LAPTOP_DEBUG 137 - #define vdbg_printk(a_dbg_level, format, arg...) \ 138 - dbg_printk(a_dbg_level, format, ## arg) 139 137 #else 140 - #define vdbg_printk(a_dbg_level, format, arg...) 138 + #define vdbg_printk(a_dbg_level, format, arg...) \ 139 + do { } while (0) 141 140 #endif 142 141 143 142 /* Device controlling the backlight and associated keys */ ··· 563 564 } 564 565 }; 565 566 566 - static void dmi_check_cb_common(const struct dmi_system_id *id) 567 + static void __init dmi_check_cb_common(const struct dmi_system_id *id) 567 568 { 568 569 pr_info("Identified laptop model '%s'\n", id->ident); 569 570 if (use_alt_lcd_levels == -1) { ··· 577 578 } 578 579 } 579 580 580 - static int dmi_check_cb_s6410(const struct dmi_system_id *id) 581 + static int __init dmi_check_cb_s6410(const struct dmi_system_id *id) 581 582 { 582 583 dmi_check_cb_common(id); 583 584 fujitsu->keycode1 = KEY_SCREENLOCK; /* "Lock" */ ··· 585 586 return 1; 586 587 } 587 588 588 - static int dmi_check_cb_s6420(const struct dmi_system_id *id) 589 + static int __init dmi_check_cb_s6420(const struct dmi_system_id *id) 589 590 { 590 591 dmi_check_cb_common(id); 591 592 fujitsu->keycode1 = KEY_SCREENLOCK; /* "Lock" */ ··· 593 594 return 1; 594 595 } 595 596 596 - static int dmi_check_cb_p8010(const struct dmi_system_id *id) 597 + static int __init dmi_check_cb_p8010(const struct dmi_system_id *id) 597 598 { 598 599 dmi_check_cb_common(id); 599 600 fujitsu->keycode1 = KEY_HELP; /* "Support" */ ··· 602 603 return 1; 603 604 } 604 605 605 - static struct dmi_system_id fujitsu_dmi_table[] = { 606 + static const struct dmi_system_id fujitsu_dmi_table[] __initconst = { 606 607 { 607 608 .ident = "Fujitsu Siemens S6410", 608 609 .matches = {
+3 -3
drivers/platform/x86/fujitsu-tablet.c
··· 315 315 return IRQ_HANDLED; 316 316 } 317 317 318 - static void fujitsu_dmi_common(const struct dmi_system_id *dmi) 318 + static void __init fujitsu_dmi_common(const struct dmi_system_id *dmi) 319 319 { 320 320 pr_info("%s\n", dmi->ident); 321 321 memcpy(fujitsu.config.keymap, dmi->driver_data, 322 322 sizeof(fujitsu.config.keymap)); 323 323 } 324 324 325 - static int fujitsu_dmi_lifebook(const struct dmi_system_id *dmi) 325 + static int __init fujitsu_dmi_lifebook(const struct dmi_system_id *dmi) 326 326 { 327 327 fujitsu_dmi_common(dmi); 328 328 fujitsu.config.quirks |= INVERT_TABLET_MODE_BIT; 329 329 return 1; 330 330 } 331 331 332 - static int fujitsu_dmi_stylistic(const struct dmi_system_id *dmi) 332 + static int __init fujitsu_dmi_stylistic(const struct dmi_system_id *dmi) 333 333 { 334 334 fujitsu_dmi_common(dmi); 335 335 fujitsu.config.quirks |= FORCE_TABLET_MODE_IF_UNDOCK;
+3 -3
drivers/platform/x86/hp-wmi.c
··· 295 295 return (state & 0x4) ? 1 : 0; 296 296 } 297 297 298 - static int hp_wmi_bios_2009_later(void) 298 + static int __init hp_wmi_bios_2009_later(void) 299 299 { 300 300 int state = 0; 301 301 int ret = hp_wmi_perform_query(HPWMI_FEATURE_QUERY, 0, &state, ··· 704 704 device_remove_file(&device->dev, &dev_attr_postcode); 705 705 } 706 706 707 - static int hp_wmi_rfkill_setup(struct platform_device *device) 707 + static int __init hp_wmi_rfkill_setup(struct platform_device *device) 708 708 { 709 709 int err; 710 710 int wireless = 0; ··· 806 806 return err; 807 807 } 808 808 809 - static int hp_wmi_rfkill2_setup(struct platform_device *device) 809 + static int __init hp_wmi_rfkill2_setup(struct platform_device *device) 810 810 { 811 811 int err, i; 812 812 struct bios_rfkill2_state state;
+2 -2
drivers/platform/x86/hp_accel.c
··· 74 74 /* HP-specific accelerometer driver ------------------------------------ */ 75 75 76 76 /* For automatic insertion of the module */ 77 - static struct acpi_device_id lis3lv02d_device_ids[] = { 77 + static const struct acpi_device_id lis3lv02d_device_ids[] = { 78 78 {"HPQ0004", 0}, /* HP Mobile Data Protection System PNP */ 79 79 {"HPQ6000", 0}, /* HP Mobile Data Protection System PNP */ 80 80 {"HPQ6007", 0}, /* HP Mobile Data Protection System PNP */ ··· 192 192 }, \ 193 193 .driver_data = &lis3lv02d_axis_##_axis \ 194 194 } 195 - static struct dmi_system_id lis3lv02d_dmi_ids[] = { 195 + static const struct dmi_system_id lis3lv02d_dmi_ids[] = { 196 196 /* product names are truncated to match all kinds of a same model */ 197 197 AXIS_DMI_MATCH("NC64x0", "HP Compaq nc64", x_inverted), 198 198 AXIS_DMI_MATCH("NC84x0", "HP Compaq nc84", z_inverted),
+56 -16
drivers/platform/x86/ideapad-laptop.c
··· 87 87 struct backlight_device *blightdev; 88 88 struct dentry *debug; 89 89 unsigned long cfg; 90 + bool has_hw_rfkill_switch; 91 + bool has_touchpad_control; 90 92 }; 91 93 92 94 static bool no_bt_rfkill; ··· 441 439 return supported ? attr->mode : 0; 442 440 } 443 441 444 - static struct attribute_group ideapad_attribute_group = { 442 + static const struct attribute_group ideapad_attribute_group = { 445 443 .is_visible = ideapad_is_visible, 446 444 .attrs = ideapad_attributes 447 445 }; ··· 456 454 int type; 457 455 }; 458 456 459 - const struct ideapad_rfk_data ideapad_rfk_data[] = { 457 + const const struct ideapad_rfk_data ideapad_rfk_data[] = { 460 458 { "ideapad_wlan", CFG_WIFI_BIT, VPCCMD_W_WIFI, RFKILL_TYPE_WLAN }, 461 459 { "ideapad_bluetooth", CFG_BT_BIT, VPCCMD_W_BT, RFKILL_TYPE_BLUETOOTH }, 462 460 { "ideapad_3g", CFG_3G_BIT, VPCCMD_W_3G, RFKILL_TYPE_WWAN }, ··· 475 473 476 474 static void ideapad_sync_rfk_state(struct ideapad_private *priv) 477 475 { 478 - unsigned long hw_blocked; 476 + unsigned long hw_blocked = 0; 479 477 int i; 480 478 481 - if (read_ec_data(priv->adev->handle, VPCCMD_R_RF, &hw_blocked)) 482 - return; 483 - hw_blocked = !hw_blocked; 479 + if (priv->has_hw_rfkill_switch) { 480 + if (read_ec_data(priv->adev->handle, VPCCMD_R_RF, &hw_blocked)) 481 + return; 482 + hw_blocked = !hw_blocked; 483 + } 484 484 485 485 for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) 486 486 if (priv->rfk[i]) ··· 767 763 { 768 764 unsigned long value; 769 765 766 + if (!priv->has_touchpad_control) 767 + return; 768 + 770 769 /* Without reading from EC touchpad LED doesn't switch state */ 771 770 if (!read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &value)) { 772 771 /* Some IdeaPads don't really turn off touchpad - they only ··· 828 821 } 829 822 } 830 823 831 - /* Blacklist for devices where the ideapad rfkill interface does not work */ 832 - static struct dmi_system_id rfkill_blacklist[] = { 833 - /* The Lenovo Yoga 2 11 always reports everything as blocked */ 824 + /* 825 + * Some ideapads don't have a hardware rfkill switch, reading VPCCMD_R_RF 826 + * always results in 0 on these models, causing ideapad_laptop to wrongly 827 + * report all radios as hardware-blocked. 828 + */ 829 + static struct dmi_system_id no_hw_rfkill_list[] = { 834 830 { 835 - .ident = "Lenovo Yoga 2 11", 831 + .ident = "Lenovo Yoga 2 11 / 13 / Pro", 836 832 .matches = { 837 833 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 838 - DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Yoga 2 11"), 834 + DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Yoga 2"), 835 + }, 836 + }, 837 + {} 838 + }; 839 + 840 + /* 841 + * Some models don't offer touchpad ctrl through the ideapad interface, causing 842 + * ideapad_sync_touchpad_state to send wrong touchpad enable/disable events. 843 + */ 844 + static struct dmi_system_id no_touchpad_ctrl_list[] = { 845 + { 846 + .ident = "Lenovo Yoga 1 series", 847 + .matches = { 848 + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 849 + DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo IdeaPad Yoga"), 850 + }, 851 + }, 852 + { 853 + .ident = "Lenovo Yoga 2 11 / 13 / Pro", 854 + .matches = { 855 + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 856 + DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Yoga 2"), 839 857 }, 840 858 }, 841 859 {} ··· 888 856 priv->cfg = cfg; 889 857 priv->adev = adev; 890 858 priv->platform_device = pdev; 859 + priv->has_hw_rfkill_switch = !dmi_check_system(no_hw_rfkill_list); 860 + priv->has_touchpad_control = !dmi_check_system(no_touchpad_ctrl_list); 891 861 892 862 ret = ideapad_sysfs_init(priv); 893 863 if (ret) ··· 903 869 if (ret) 904 870 goto input_failed; 905 871 906 - if (!dmi_check_system(rfkill_blacklist)) { 907 - for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) 908 - if (test_bit(ideapad_rfk_data[i].cfgbit, &priv->cfg)) 909 - ideapad_register_rfkill(priv, i); 910 - } 872 + /* 873 + * On some models without a hw-switch (the yoga 2 13 at least) 874 + * VPCCMD_W_RF must be explicitly set to 1 for the wifi to work. 875 + */ 876 + if (!priv->has_hw_rfkill_switch) 877 + write_ec_cmd(priv->adev->handle, VPCCMD_W_RF, 1); 878 + 879 + for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) 880 + if (test_bit(ideapad_rfk_data[i].cfgbit, &priv->cfg)) 881 + ideapad_register_rfkill(priv, i); 882 + 911 883 ideapad_sync_rfk_state(priv); 912 884 ideapad_sync_touchpad_state(priv); 913 885
+3 -3
drivers/platform/x86/intel_ips.c
··· 269 269 270 270 /* Max temps are -10 degrees C to avoid PROCHOT# */ 271 271 272 - struct ips_mcp_limits ips_sv_limits = { 272 + static struct ips_mcp_limits ips_sv_limits = { 273 273 .mcp_power_limit = 35000, 274 274 .core_power_limit = 29000, 275 275 .mch_power_limit = 20000, ··· 277 277 .mch_temp_limit = 90 278 278 }; 279 279 280 - struct ips_mcp_limits ips_lv_limits = { 280 + static struct ips_mcp_limits ips_lv_limits = { 281 281 .mcp_power_limit = 25000, 282 282 .core_power_limit = 21000, 283 283 .mch_power_limit = 13000, ··· 285 285 .mch_temp_limit = 90 286 286 }; 287 287 288 - struct ips_mcp_limits ips_ulv_limits = { 288 + static struct ips_mcp_limits ips_ulv_limits = { 289 289 .mcp_power_limit = 18000, 290 290 .core_power_limit = 14000, 291 291 .mch_power_limit = 11000,
+1 -1
drivers/platform/x86/sony-laptop.c
··· 2389 2389 lid_ctl->attrs[LID_RESUME_S3].store = sony_nc_lid_resume_store; 2390 2390 } 2391 2391 for (i = 0; i < LID_RESUME_MAX && 2392 - lid_ctl->attrs[LID_RESUME_S3].attr.name; i++) { 2392 + lid_ctl->attrs[i].attr.name; i++) { 2393 2393 result = device_create_file(&pd->dev, &lid_ctl->attrs[i]); 2394 2394 if (result) 2395 2395 goto liderror;
+4 -4
drivers/platform/x86/thinkpad_acpi.c
··· 3174 3174 KEY_UNKNOWN, 3175 3175 3176 3176 /* Extra keys in use since the X240 / T440 / T540 */ 3177 - KEY_CONFIG, KEY_SEARCH, KEY_SCALE, KEY_COMPUTER, 3177 + KEY_CONFIG, KEY_SEARCH, KEY_SCALE, KEY_FILE, 3178 3178 }, 3179 3179 }; 3180 3180 ··· 6144 6144 { 6145 6145 int res; 6146 6146 6147 - if (value > bright_maxlvl || value < 0) 6147 + if (value > bright_maxlvl) 6148 6148 return -EINVAL; 6149 6149 6150 6150 vdbg_printk(TPACPI_DBG_BRGHT, ··· 6860 6860 return volume_alsa_set_mute(!ucontrol->value.integer.value[0]); 6861 6861 } 6862 6862 6863 - static struct snd_kcontrol_new volume_alsa_control_vol = { 6863 + static struct snd_kcontrol_new volume_alsa_control_vol __initdata = { 6864 6864 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 6865 6865 .name = "Console Playback Volume", 6866 6866 .index = 0, ··· 6869 6869 .get = volume_alsa_vol_get, 6870 6870 }; 6871 6871 6872 - static struct snd_kcontrol_new volume_alsa_control_mute = { 6872 + static struct snd_kcontrol_new volume_alsa_control_mute __initdata = { 6873 6873 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 6874 6874 .name = "Console Playback Switch", 6875 6875 .index = 0,
+25 -5
drivers/platform/x86/toshiba_acpi.c
··· 222 222 DMI_MATCH(DMI_PRODUCT_NAME, "Satellite M840"), 223 223 }, 224 224 }, 225 + { 226 + .matches = { 227 + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), 228 + DMI_MATCH(DMI_PRODUCT_NAME, "Qosmio X75-A"), 229 + }, 230 + }, 225 231 {} 226 232 }; 227 233 ··· 235 229 { KE_KEY, 0x157, { KEY_MUTE } }, 236 230 { KE_KEY, 0x102, { KEY_ZOOMOUT } }, 237 231 { KE_KEY, 0x103, { KEY_ZOOMIN } }, 232 + { KE_KEY, 0x12c, { KEY_KBDILLUMTOGGLE } }, 238 233 { KE_KEY, 0x139, { KEY_ZOOMRESET } }, 239 234 { KE_KEY, 0x13e, { KEY_SWITCHVIDEOMODE } }, 240 235 { KE_KEY, 0x13c, { KEY_BRIGHTNESSDOWN } }, ··· 879 872 880 873 static int set_lcd_brightness(struct toshiba_acpi_dev *dev, int value) 881 874 { 882 - u32 hci_result; 875 + u32 in[HCI_WORDS] = { HCI_SET, HCI_LCD_BRIGHTNESS, 0, 0, 0, 0 }; 876 + u32 out[HCI_WORDS]; 877 + acpi_status status; 883 878 884 879 if (dev->tr_backlight_supported) { 885 880 bool enable = !value; ··· 892 883 value--; 893 884 } 894 885 895 - value = value << HCI_LCD_BRIGHTNESS_SHIFT; 896 - hci_write1(dev, HCI_LCD_BRIGHTNESS, value, &hci_result); 897 - return hci_result == HCI_SUCCESS ? 0 : -EIO; 886 + in[2] = value << HCI_LCD_BRIGHTNESS_SHIFT; 887 + status = hci_raw(dev, in, out); 888 + if (ACPI_FAILURE(status) || out[0] == HCI_FAILURE) { 889 + pr_err("ACPI call to set brightness failed"); 890 + return -EIO; 891 + } 892 + /* Extra check for "incomplete" backlight method, where the AML code 893 + * doesn't check for HCI_SET or HCI_GET and returns HCI_SUCCESS, 894 + * the actual brightness, and in some cases the max brightness. 895 + */ 896 + if (out[2] > 0 || out[3] == 0xE000) 897 + return -ENODEV; 898 + 899 + return out[0] == HCI_SUCCESS ? 0 : -EIO; 898 900 } 899 901 900 902 static int set_lcd_status(struct backlight_device *bd) ··· 1258 1238 int mode = -1; 1259 1239 int time = -1; 1260 1240 1261 - if (sscanf(buf, "%i", &mode) != 1 && (mode != 2 || mode != 1)) 1241 + if (sscanf(buf, "%i", &mode) != 1 || (mode != 2 || mode != 1)) 1262 1242 return -EINVAL; 1263 1243 1264 1244 /* Set the Keyboard Backlight Mode where:
+265
drivers/platform/x86/toshiba_haps.c
··· 1 + /* 2 + * Toshiba HDD Active Protection Sensor (HAPS) driver 3 + * 4 + * Copyright (C) 2014 Azael Avalos <coproscefalo@gmail.com> 5 + * 6 + * This program is free software; you can redistribute it and/or modify 7 + * it under the terms of the GNU General Public License as published by 8 + * the Free Software Foundation; either version 2 of the License, or 9 + * (at your option) any later version. 10 + * 11 + * This program is distributed in the hope that it will be useful, 12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 + * GNU General Public License for more details. 15 + * 16 + */ 17 + 18 + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 19 + 20 + #include <linux/kernel.h> 21 + #include <linux/module.h> 22 + #include <linux/init.h> 23 + #include <linux/types.h> 24 + #include <linux/acpi.h> 25 + 26 + MODULE_AUTHOR("Azael Avalos <coproscefalo@gmail.com>"); 27 + MODULE_DESCRIPTION("Toshiba HDD Active Protection Sensor"); 28 + MODULE_LICENSE("GPL"); 29 + 30 + struct toshiba_haps_dev { 31 + struct acpi_device *acpi_dev; 32 + 33 + int protection_level; 34 + }; 35 + 36 + static struct toshiba_haps_dev *toshiba_haps; 37 + 38 + /* HAPS functions */ 39 + static int toshiba_haps_reset_protection(acpi_handle handle) 40 + { 41 + acpi_status status; 42 + 43 + status = acpi_evaluate_object(handle, "RSSS", NULL, NULL); 44 + if (ACPI_FAILURE(status)) { 45 + pr_err("Unable to reset the HDD protection\n"); 46 + return -EIO; 47 + } 48 + 49 + return 0; 50 + } 51 + 52 + static int toshiba_haps_protection_level(acpi_handle handle, int level) 53 + { 54 + acpi_status status; 55 + 56 + status = acpi_execute_simple_method(handle, "PTLV", level); 57 + if (ACPI_FAILURE(status)) { 58 + pr_err("Error while setting the protection level\n"); 59 + return -EIO; 60 + } 61 + 62 + pr_info("HDD protection level set to: %d\n", level); 63 + 64 + return 0; 65 + } 66 + 67 + /* sysfs files */ 68 + static ssize_t protection_level_show(struct device *dev, 69 + struct device_attribute *attr, char *buf) 70 + { 71 + struct toshiba_haps_dev *haps = dev_get_drvdata(dev); 72 + 73 + return sprintf(buf, "%i\n", haps->protection_level); 74 + } 75 + 76 + static ssize_t protection_level_store(struct device *dev, 77 + struct device_attribute *attr, 78 + const char *buf, size_t count) 79 + { 80 + struct toshiba_haps_dev *haps = dev_get_drvdata(dev); 81 + int level, ret; 82 + 83 + if (sscanf(buf, "%d", &level) != 1 || level < 0 || level > 3) 84 + return -EINVAL; 85 + 86 + /* Set the sensor level. 87 + * Acceptable levels are: 88 + * 0 - Disabled | 1 - Low | 2 - Medium | 3 - High 89 + */ 90 + ret = toshiba_haps_protection_level(haps->acpi_dev->handle, level); 91 + if (ret != 0) 92 + return ret; 93 + 94 + haps->protection_level = level; 95 + 96 + return count; 97 + } 98 + 99 + static ssize_t reset_protection_store(struct device *dev, 100 + struct device_attribute *attr, 101 + const char *buf, size_t count) 102 + { 103 + struct toshiba_haps_dev *haps = dev_get_drvdata(dev); 104 + int reset, ret; 105 + 106 + if (sscanf(buf, "%d", &reset) != 1 || reset != 1) 107 + return -EINVAL; 108 + 109 + /* Reset the protection interface */ 110 + ret = toshiba_haps_reset_protection(haps->acpi_dev->handle); 111 + if (ret != 0) 112 + return ret; 113 + 114 + return count; 115 + } 116 + 117 + static DEVICE_ATTR(protection_level, S_IRUGO | S_IWUSR, 118 + protection_level_show, protection_level_store); 119 + static DEVICE_ATTR(reset_protection, S_IWUSR, NULL, reset_protection_store); 120 + 121 + static struct attribute *haps_attributes[] = { 122 + &dev_attr_protection_level.attr, 123 + &dev_attr_reset_protection.attr, 124 + NULL, 125 + }; 126 + 127 + static struct attribute_group haps_attr_group = { 128 + .attrs = haps_attributes, 129 + }; 130 + 131 + /* 132 + * ACPI stuff 133 + */ 134 + static void toshiba_haps_notify(struct acpi_device *device, u32 event) 135 + { 136 + pr_info("Received event: 0x%x", event); 137 + 138 + acpi_bus_generate_netlink_event(device->pnp.device_class, 139 + dev_name(&device->dev), 140 + event, 0); 141 + } 142 + 143 + static int toshiba_haps_remove(struct acpi_device *device) 144 + { 145 + sysfs_remove_group(&device->dev.kobj, &haps_attr_group); 146 + 147 + if (toshiba_haps) 148 + toshiba_haps = NULL; 149 + 150 + return 0; 151 + } 152 + 153 + /* Helper function */ 154 + static int toshiba_haps_available(acpi_handle handle) 155 + { 156 + acpi_status status; 157 + u64 hdd_present; 158 + 159 + /* 160 + * A non existent device as well as having (only) 161 + * Solid State Drives can cause the call to fail. 162 + */ 163 + status = acpi_evaluate_integer(handle, "_STA", NULL, 164 + &hdd_present); 165 + if (ACPI_FAILURE(status) || !hdd_present) { 166 + pr_info("HDD protection not available or using SSD\n"); 167 + return 0; 168 + } 169 + 170 + return 1; 171 + } 172 + 173 + static int toshiba_haps_add(struct acpi_device *acpi_dev) 174 + { 175 + struct toshiba_haps_dev *haps; 176 + int ret; 177 + 178 + if (toshiba_haps) 179 + return -EBUSY; 180 + 181 + if (!toshiba_haps_available(acpi_dev->handle)) 182 + return -ENODEV; 183 + 184 + pr_info("Toshiba HDD Active Protection Sensor device\n"); 185 + 186 + haps = kzalloc(sizeof(struct toshiba_haps_dev), GFP_KERNEL); 187 + if (!haps) 188 + return -ENOMEM; 189 + 190 + haps->acpi_dev = acpi_dev; 191 + haps->protection_level = 2; 192 + acpi_dev->driver_data = haps; 193 + dev_set_drvdata(&acpi_dev->dev, haps); 194 + 195 + /* Set the protection level, currently at level 2 (Medium) */ 196 + ret = toshiba_haps_protection_level(acpi_dev->handle, 2); 197 + if (ret != 0) 198 + return ret; 199 + 200 + ret = sysfs_create_group(&acpi_dev->dev.kobj, &haps_attr_group); 201 + if (ret) 202 + return ret; 203 + 204 + toshiba_haps = haps; 205 + 206 + return 0; 207 + } 208 + 209 + #ifdef CONFIG_PM_SLEEP 210 + static int toshiba_haps_suspend(struct device *device) 211 + { 212 + struct toshiba_haps_dev *haps; 213 + int ret; 214 + 215 + haps = acpi_driver_data(to_acpi_device(device)); 216 + 217 + /* Deactivate the protection on suspend */ 218 + ret = toshiba_haps_protection_level(haps->acpi_dev->handle, 0); 219 + 220 + return ret; 221 + } 222 + 223 + static int toshiba_haps_resume(struct device *device) 224 + { 225 + struct toshiba_haps_dev *haps; 226 + int ret; 227 + 228 + haps = acpi_driver_data(to_acpi_device(device)); 229 + 230 + /* Set the stored protection level */ 231 + ret = toshiba_haps_protection_level(haps->acpi_dev->handle, 232 + haps->protection_level); 233 + 234 + /* Reset the protection on resume */ 235 + ret = toshiba_haps_reset_protection(haps->acpi_dev->handle); 236 + if (ret != 0) 237 + return ret; 238 + 239 + return ret; 240 + } 241 + #endif 242 + 243 + static SIMPLE_DEV_PM_OPS(toshiba_haps_pm, 244 + toshiba_haps_suspend, toshiba_haps_resume); 245 + 246 + static const struct acpi_device_id haps_device_ids[] = { 247 + {"TOS620A", 0}, 248 + {"", 0}, 249 + }; 250 + MODULE_DEVICE_TABLE(acpi, haps_device_ids); 251 + 252 + static struct acpi_driver toshiba_haps_driver = { 253 + .name = "Toshiba HAPS", 254 + .owner = THIS_MODULE, 255 + .ids = haps_device_ids, 256 + .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS, 257 + .ops = { 258 + .add = toshiba_haps_add, 259 + .remove = toshiba_haps_remove, 260 + .notify = toshiba_haps_notify, 261 + }, 262 + .drv.pm = &toshiba_haps_pm, 263 + }; 264 + 265 + module_acpi_driver(toshiba_haps_driver);
-4
drivers/platform/x86/wmi.c
··· 256 256 block = &wblock->gblock; 257 257 handle = wblock->handle; 258 258 259 - if (!block) 260 - return AE_NOT_EXIST; 261 - 262 - 263 259 snprintf(method, 5, "WE%02X", block->notify_id); 264 260 status = acpi_execute_simple_method(handle, method, enable); 265 261