Merge branch 'release-2.6.27' of git://git.kernel.org/pub/scm/linux/kernel/git/ak/linux-acpi-2.6

* 'release-2.6.27' of git://git.kernel.org/pub/scm/linux/kernel/git/ak/linux-acpi-2.6:
acpi: fix crash in core ACPI code, triggered by CONFIG_ACPI_PCI_SLOT=y
ACPI: thinkpad-acpi: don't misdetect in get_thinkpad_model_data() on -ENOMEM
ACPI: thinkpad-acpi: bump up version to 0.21
ACPI: thinkpad-acpi: add bluetooth and WWAN rfkill support
ACPI: thinkpad-acpi: WLSW overrides other rfkill switches
ACPI: thinkpad-acpi: prepare for bluetooth and wwan rfkill support
ACPI: thinkpad-acpi: consolidate wlsw notification function
ACPI: thinkpad-acpi: minor refactor on radio switch init
Revert "ACPI: don't walk tables if ACPI was disabled"
Revert "dock: bay: Don't call acpi_walk_namespace() when ACPI is disabled."
Revert "Fix FADT parsing"
ACPI : Set FAN device to correct state in boot phase
ACPI: Ignore _BQC object when registering backlight device
ACPI: stop complaints about interrupt link End Tags and blank IRQ descriptors

+446 -174
+18 -8
Documentation/laptops/thinkpad-acpi.txt
··· 1 ThinkPad ACPI Extras Driver 2 3 - Version 0.20 4 - April 09th, 2008 5 6 Borislav Deianov <borislav@users.sf.net> 7 Henrique de Moraes Holschuh <hmh@hmh.eng.br> ··· 621 --------- 622 623 procfs: /proc/acpi/ibm/bluetooth 624 - sysfs device attribute: bluetooth_enable 625 626 This feature shows the presence and current state of a ThinkPad 627 Bluetooth device in the internal ThinkPad CDC slot. ··· 644 0: disables Bluetooth / Bluetooth is disabled 645 1: enables Bluetooth / Bluetooth is enabled. 646 647 - Note: this interface will be probably be superseded by the 648 - generic rfkill class, so it is NOT to be considered stable yet. 649 650 Video output control -- /proc/acpi/ibm/video 651 -------------------------------------------- ··· 1379 ----------------- 1380 1381 procfs: /proc/acpi/ibm/wan 1382 - sysfs device attribute: wwan_enable 1383 1384 This feature is marked EXPERIMENTAL because the implementation 1385 directly accesses hardware registers and may not work as expected. USE ··· 1410 0: disables WWAN card / WWAN card is disabled 1411 1: enables WWAN card / WWAN card is enabled. 1412 1413 - Note: this interface will be probably be superseded by the 1414 - generic rfkill class, so it is NOT to be considered stable yet. 1415 1416 Multiple Commands, Module Parameters 1417 ------------------------------------
··· 1 ThinkPad ACPI Extras Driver 2 3 + Version 0.21 4 + May 29th, 2008 5 6 Borislav Deianov <borislav@users.sf.net> 7 Henrique de Moraes Holschuh <hmh@hmh.eng.br> ··· 621 --------- 622 623 procfs: /proc/acpi/ibm/bluetooth 624 + sysfs device attribute: bluetooth_enable (deprecated) 625 + sysfs rfkill class: switch "tpacpi_bluetooth_sw" 626 627 This feature shows the presence and current state of a ThinkPad 628 Bluetooth device in the internal ThinkPad CDC slot. ··· 643 0: disables Bluetooth / Bluetooth is disabled 644 1: enables Bluetooth / Bluetooth is enabled. 645 646 + Note: this interface has been superseded by the generic rfkill 647 + class. It has been deprecated, and it will be removed in year 648 + 2010. 649 + 650 + rfkill controller switch "tpacpi_bluetooth_sw": refer to 651 + Documentation/rfkill.txt for details. 652 653 Video output control -- /proc/acpi/ibm/video 654 -------------------------------------------- ··· 1374 ----------------- 1375 1376 procfs: /proc/acpi/ibm/wan 1377 + sysfs device attribute: wwan_enable (deprecated) 1378 + sysfs rfkill class: switch "tpacpi_wwan_sw" 1379 1380 This feature is marked EXPERIMENTAL because the implementation 1381 directly accesses hardware registers and may not work as expected. USE ··· 1404 0: disables WWAN card / WWAN card is disabled 1405 1: enables WWAN card / WWAN card is enabled. 1406 1407 + Note: this interface has been superseded by the generic rfkill 1408 + class. It has been deprecated, and it will be removed in year 1409 + 2010. 1410 + 1411 + rfkill controller switch "tpacpi_wwan_sw": refer to 1412 + Documentation/rfkill.txt for details. 1413 1414 Multiple Commands, Module Parameters 1415 ------------------------------------
+8
drivers/acpi/namespace/nsnames.c
··· 137 /* Calculate required buffer size based on depth below root */ 138 139 size = acpi_ns_get_pathname_length(node); 140 141 /* Allocate a buffer to be returned to caller */ 142 ··· 233 /* Determine size required for the caller buffer */ 234 235 required_size = acpi_ns_get_pathname_length(node); 236 237 /* Validate/Allocate/Clear caller buffer */ 238
··· 137 /* Calculate required buffer size based on depth below root */ 138 139 size = acpi_ns_get_pathname_length(node); 140 + if (!size) { 141 + ACPI_ERROR((AE_INFO, "Invalid node failure")); 142 + return_PTR(NULL); 143 + } 144 145 /* Allocate a buffer to be returned to caller */ 146 ··· 229 /* Determine size required for the caller buffer */ 230 231 required_size = acpi_ns_get_pathname_length(node); 232 + if (!required_size) { 233 + ACPI_ERROR((AE_INFO, "Invalid node failure")); 234 + return_ACPI_STATUS(AE_ERROR); 235 + } 236 237 /* Validate/Allocate/Clear caller buffer */ 238
+20 -11
drivers/acpi/pci_link.c
··· 113 114 switch (resource->type) { 115 case ACPI_RESOURCE_TYPE_START_DEPENDENT: 116 return AE_OK; 117 case ACPI_RESOURCE_TYPE_IRQ: 118 { 119 struct acpi_resource_irq *p = &resource->data.irq; 120 if (!p || !p->interrupt_count) { 121 - printk(KERN_WARNING PREFIX "Blank IRQ resource\n"); 122 return AE_OK; 123 } 124 for (i = 0; 125 (i < p->interrupt_count 126 && i < ACPI_PCI_LINK_MAX_POSSIBLE); i++) { 127 if (!p->interrupts[i]) { 128 - printk(KERN_WARNING PREFIX "Invalid IRQ %d\n", 129 - p->interrupts[i]); 130 continue; 131 } 132 link->irq.possible[i] = p->interrupts[i]; ··· 146 &resource->data.extended_irq; 147 if (!p || !p->interrupt_count) { 148 printk(KERN_WARNING PREFIX 149 - "Blank EXT IRQ resource\n"); 150 return AE_OK; 151 } 152 for (i = 0; 153 (i < p->interrupt_count 154 && i < ACPI_PCI_LINK_MAX_POSSIBLE); i++) { 155 if (!p->interrupts[i]) { 156 - printk(KERN_WARNING PREFIX "Invalid IRQ %d\n", 157 - p->interrupts[i]); 158 continue; 159 } 160 link->irq.possible[i] = p->interrupts[i]; ··· 167 break; 168 } 169 default: 170 - printk(KERN_ERR PREFIX "Resource is not an IRQ entry\n"); 171 return AE_OK; 172 } 173 ··· 204 205 206 switch (resource->type) { 207 case ACPI_RESOURCE_TYPE_IRQ: 208 { 209 struct acpi_resource_irq *p = &resource->data.irq; ··· 216 * particularly those those w/ _STA disabled 217 */ 218 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 219 - "Blank IRQ resource\n")); 220 return AE_OK; 221 } 222 *irq = p->interrupts[0]; ··· 232 * return at least 1 IRQ 233 */ 234 printk(KERN_WARNING PREFIX 235 - "Blank EXT IRQ resource\n"); 236 return AE_OK; 237 } 238 *irq = p->interrupts[0]; ··· 240 } 241 break; 242 default: 243 - printk(KERN_ERR PREFIX "Resource %d isn't an IRQ\n", resource->type); 244 - case ACPI_RESOURCE_TYPE_END_TAG: 245 return AE_OK; 246 } 247 return AE_CTRL_TERMINATE; 248 } 249
··· 113 114 switch (resource->type) { 115 case ACPI_RESOURCE_TYPE_START_DEPENDENT: 116 + case ACPI_RESOURCE_TYPE_END_TAG: 117 return AE_OK; 118 case ACPI_RESOURCE_TYPE_IRQ: 119 { 120 struct acpi_resource_irq *p = &resource->data.irq; 121 if (!p || !p->interrupt_count) { 122 + ACPI_DEBUG_PRINT((ACPI_DB_INFO, 123 + "Blank _PRS IRQ resource\n")); 124 return AE_OK; 125 } 126 for (i = 0; 127 (i < p->interrupt_count 128 && i < ACPI_PCI_LINK_MAX_POSSIBLE); i++) { 129 if (!p->interrupts[i]) { 130 + printk(KERN_WARNING PREFIX 131 + "Invalid _PRS IRQ %d\n", 132 + p->interrupts[i]); 133 continue; 134 } 135 link->irq.possible[i] = p->interrupts[i]; ··· 143 &resource->data.extended_irq; 144 if (!p || !p->interrupt_count) { 145 printk(KERN_WARNING PREFIX 146 + "Blank _PRS EXT IRQ resource\n"); 147 return AE_OK; 148 } 149 for (i = 0; 150 (i < p->interrupt_count 151 && i < ACPI_PCI_LINK_MAX_POSSIBLE); i++) { 152 if (!p->interrupts[i]) { 153 + printk(KERN_WARNING PREFIX 154 + "Invalid _PRS IRQ %d\n", 155 + p->interrupts[i]); 156 continue; 157 } 158 link->irq.possible[i] = p->interrupts[i]; ··· 163 break; 164 } 165 default: 166 + printk(KERN_ERR PREFIX "_PRS resource type 0x%x isn't an IRQ\n", 167 + resource->type); 168 return AE_OK; 169 } 170 ··· 199 200 201 switch (resource->type) { 202 + case ACPI_RESOURCE_TYPE_START_DEPENDENT: 203 + case ACPI_RESOURCE_TYPE_END_TAG: 204 + return AE_OK; 205 case ACPI_RESOURCE_TYPE_IRQ: 206 { 207 struct acpi_resource_irq *p = &resource->data.irq; ··· 208 * particularly those those w/ _STA disabled 209 */ 210 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 211 + "Blank _CRS IRQ resource\n")); 212 return AE_OK; 213 } 214 *irq = p->interrupts[0]; ··· 224 * return at least 1 IRQ 225 */ 226 printk(KERN_WARNING PREFIX 227 + "Blank _CRS EXT IRQ resource\n"); 228 return AE_OK; 229 } 230 *irq = p->interrupts[0]; ··· 232 } 233 break; 234 default: 235 + printk(KERN_ERR PREFIX "_CRS resource type 0x%x isn't an IRQ\n", 236 + resource->type); 237 return AE_OK; 238 } 239 + 240 return AE_CTRL_TERMINATE; 241 } 242
+6 -11
drivers/acpi/tables/tbfadt.c
··· 124 125 static void inline 126 acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, 127 - u8 byte_width, u64 address) 128 { 129 130 /* ··· 136 /* All other fields are byte-wide */ 137 138 generic_address->space_id = ACPI_ADR_SPACE_SYSTEM_IO; 139 - generic_address->bit_width = byte_width << 3; 140 generic_address->bit_offset = 0; 141 generic_address->access_width = 0; 142 } ··· 343 * 344 * The PM event blocks are split into two register blocks, first is the 345 * PM Status Register block, followed immediately by the PM Enable Register 346 - * block. Each is of length (xpm1x_event_block.bit_width/2) 347 */ 348 - WARN_ON(ACPI_MOD_16(acpi_gbl_FADT.xpm1a_event_block.bit_width)); 349 - pm1_register_length = (u8) ACPI_DIV_16(acpi_gbl_FADT 350 - .xpm1a_event_block.bit_width); 351 352 /* The PM1A register block is required */ 353 ··· 360 /* The PM1B register block is optional, ignore if not present */ 361 362 if (acpi_gbl_FADT.xpm1b_event_block.address) { 363 - WARN_ON(ACPI_MOD_16(acpi_gbl_FADT.xpm1b_event_block.bit_width)); 364 - pm1_register_length = (u8) ACPI_DIV_16(acpi_gbl_FADT 365 - .xpm1b_event_block 366 - .bit_width); 367 acpi_tb_init_generic_address(&acpi_gbl_xpm1b_enable, 368 pm1_register_length, 369 (acpi_gbl_FADT.xpm1b_event_block. 370 address + pm1_register_length)); 371 /* Don't forget to copy space_id of the GAS */ 372 acpi_gbl_xpm1b_enable.space_id = 373 - acpi_gbl_FADT.xpm1b_event_block.space_id; 374 } 375 } 376
··· 124 125 static void inline 126 acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, 127 + u8 bit_width, u64 address) 128 { 129 130 /* ··· 136 /* All other fields are byte-wide */ 137 138 generic_address->space_id = ACPI_ADR_SPACE_SYSTEM_IO; 139 + generic_address->bit_width = bit_width; 140 generic_address->bit_offset = 0; 141 generic_address->access_width = 0; 142 } ··· 343 * 344 * The PM event blocks are split into two register blocks, first is the 345 * PM Status Register block, followed immediately by the PM Enable Register 346 + * block. Each is of length (pm1_event_length/2) 347 */ 348 + pm1_register_length = (u8) ACPI_DIV_2(acpi_gbl_FADT.pm1_event_length); 349 350 /* The PM1A register block is required */ 351 ··· 362 /* The PM1B register block is optional, ignore if not present */ 363 364 if (acpi_gbl_FADT.xpm1b_event_block.address) { 365 acpi_tb_init_generic_address(&acpi_gbl_xpm1b_enable, 366 pm1_register_length, 367 (acpi_gbl_FADT.xpm1b_event_block. 368 address + pm1_register_length)); 369 /* Don't forget to copy space_id of the GAS */ 370 acpi_gbl_xpm1b_enable.space_id = 371 + acpi_gbl_FADT.xpm1a_event_block.space_id; 372 + 373 } 374 } 375
+43
drivers/acpi/thermal.c
··· 769 acpi_os_execute(OSL_GPE_HANDLER, acpi_thermal_check, (void *)data); 770 } 771 772 static void acpi_thermal_check(void *data) 773 { 774 int result = 0; ··· 1664 goto unregister_thermal_zone; 1665 1666 init_timer(&tz->timer); 1667 1668 acpi_thermal_check(tz); 1669
··· 769 acpi_os_execute(OSL_GPE_HANDLER, acpi_thermal_check, (void *)data); 770 } 771 772 + static void acpi_thermal_active_off(void *data) 773 + { 774 + int result = 0; 775 + struct acpi_thermal *tz = data; 776 + int i = 0; 777 + int j = 0; 778 + struct acpi_thermal_active *active = NULL; 779 + 780 + if (!tz) { 781 + printk(KERN_ERR PREFIX "Invalid (NULL) context\n"); 782 + return; 783 + } 784 + 785 + result = acpi_thermal_get_temperature(tz); 786 + if (result) 787 + return; 788 + 789 + for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { 790 + active = &(tz->trips.active[i]); 791 + if (!active || !active->flags.valid) 792 + break; 793 + if (tz->temperature >= active->temperature) { 794 + /* 795 + * If the thermal temperature is greater than the 796 + * active threshod, unnecessary to turn off the 797 + * the active cooling device. 798 + */ 799 + continue; 800 + } 801 + /* 802 + * Below Threshold? 803 + * ---------------- 804 + * Turn OFF all cooling devices associated with this 805 + * threshold. 806 + */ 807 + for (j = 0; j < active->devices.count; j++) 808 + result = acpi_bus_set_power(active->devices.handles[j], 809 + ACPI_STATE_D3); 810 + } 811 + } 812 + 813 static void acpi_thermal_check(void *data) 814 { 815 int result = 0; ··· 1623 goto unregister_thermal_zone; 1624 1625 init_timer(&tz->timer); 1626 + 1627 + acpi_thermal_active_off(tz); 1628 1629 acpi_thermal_check(tz); 1630
+4
drivers/acpi/utilities/utalloc.c
··· 242 { 243 acpi_status status = AE_OK; 244 245 switch (buffer->length) { 246 case ACPI_NO_BUFFER: 247
··· 242 { 243 acpi_status status = AE_OK; 244 245 + if (!required_length) { 246 + WARN_ON(1); 247 + return AE_ERROR; 248 + } 249 switch (buffer->length) { 250 case ACPI_NO_BUFFER: 251
+12 -2
drivers/acpi/video.c
··· 741 742 max_level = acpi_video_init_brightness(device); 743 744 - if (device->cap._BCL && device->cap._BCM && device->cap._BQC && max_level > 0){ 745 int result; 746 static int count = 0; 747 char *name; ··· 753 device->backlight = backlight_device_register(name, 754 NULL, device, &acpi_backlight_ops); 755 device->backlight->props.max_brightness = device->brightness->count-3; 756 - device->backlight->props.brightness = acpi_video_get_brightness(device->backlight); 757 backlight_update_status(device->backlight); 758 kfree(name); 759
··· 741 742 max_level = acpi_video_init_brightness(device); 743 744 + if (device->cap._BCL && device->cap._BCM && max_level > 0) { 745 int result; 746 static int count = 0; 747 char *name; ··· 753 device->backlight = backlight_device_register(name, 754 NULL, device, &acpi_backlight_ops); 755 device->backlight->props.max_brightness = device->brightness->count-3; 756 + /* 757 + * If there exists the _BQC object, the _BQC object will be 758 + * called to get the current backlight brightness. Otherwise 759 + * the brightness will be set to the maximum. 760 + */ 761 + if (device->cap._BQC) 762 + device->backlight->props.brightness = 763 + acpi_video_get_brightness(device->backlight); 764 + else 765 + device->backlight->props.brightness = 766 + device->backlight->props.max_brightness; 767 backlight_update_status(device->backlight); 768 kfree(name); 769
+2
drivers/misc/Kconfig
··· 279 select INPUT 280 select NEW_LEDS 281 select LEDS_CLASS 282 ---help--- 283 This is a driver for the IBM and Lenovo ThinkPad laptops. It adds 284 support for Fn-Fx key combinations, Bluetooth control, video
··· 279 select INPUT 280 select NEW_LEDS 281 select LEDS_CLASS 282 + select NET 283 + select RFKILL 284 ---help--- 285 This is a driver for the IBM and Lenovo ThinkPad laptops. It adds 286 support for Fn-Fx key combinations, Bluetooth control, video
+333 -142
drivers/misc/thinkpad_acpi.c
··· 21 * 02110-1301, USA. 22 */ 23 24 - #define TPACPI_VERSION "0.20" 25 #define TPACPI_SYSFS_VERSION 0x020200 26 27 /* ··· 68 #include <linux/hwmon-sysfs.h> 69 #include <linux/input.h> 70 #include <linux/leds.h> 71 #include <asm/uaccess.h> 72 73 #include <linux/dmi.h> ··· 144 #define TPACPI_WORKQUEUE_NAME "ktpacpid" 145 146 #define TPACPI_MAX_ACPI_ARGS 3 147 148 /* Debugging */ 149 #define TPACPI_LOG TPACPI_FILE ": " ··· 912 return 0; 913 } 914 915 /************************************************************************* 916 * thinkpad-acpi driver attributes 917 */ ··· 1327 return -EIO; 1328 1329 return 0; 1330 - } 1331 - 1332 - static void tpacpi_input_send_radiosw(void) 1333 - { 1334 - int wlsw; 1335 - 1336 - if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&wlsw)) { 1337 - mutex_lock(&tpacpi_inputdev_send_mutex); 1338 - 1339 - input_report_switch(tpacpi_inputdev, 1340 - SW_RFKILL_ALL, !!wlsw); 1341 - input_sync(tpacpi_inputdev); 1342 - 1343 - mutex_unlock(&tpacpi_inputdev_send_mutex); 1344 - } 1345 } 1346 1347 static void tpacpi_input_send_tabletsw(void) ··· 1950 &dev_attr_hotkey_wakeup_hotunplug_complete.attr, 1951 }; 1952 1953 static void hotkey_exit(void) 1954 { 1955 #ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL ··· 2220 printk(TPACPI_INFO 2221 "radio switch found; radios are %s\n", 2222 enabled(status, 0)); 2223 res = add_to_attr_set(hotkey_dev_attributes, 2224 &dev_attr_hotkey_radio_sw.attr); 2225 - } 2226 2227 /* For X41t, X60t, X61t Tablets... */ 2228 if (!res && acpi_evalf(hkey_handle, &status, "MHKG", "qd")) { ··· 2341 tpacpi_inputdev->close = &hotkey_inputdev_close; 2342 2343 hotkey_poll_setup_safe(1); 2344 - tpacpi_input_send_radiosw(); 2345 tpacpi_input_send_tabletsw(); 2346 2347 return 0; ··· 2473 case 7: 2474 /* 0x7000-0x7FFF: misc */ 2475 if (tp_features.hotkey_wlsw && hkey == 0x7000) { 2476 - tpacpi_input_send_radiosw(); 2477 - hotkey_radio_sw_notify_change(); 2478 send_acpi_ev = 0; 2479 break; 2480 } ··· 2516 printk(TPACPI_ERR 2517 "error while trying to read hot key mask " 2518 "from firmware\n"); 2519 - tpacpi_input_send_radiosw(); 2520 - hotkey_radio_sw_notify_change(); 2521 hotkey_tablet_mode_notify_change(); 2522 hotkey_wakeup_reason_notify_change(); 2523 hotkey_wakeup_hotunplug_complete_notify_change(); ··· 2633 TP_ACPI_BLUETOOTH_UNK = 0x04, /* unknown function */ 2634 }; 2635 2636 - static int bluetooth_get_radiosw(void); 2637 - static int bluetooth_set_radiosw(int radio_on); 2638 2639 /* sysfs bluetooth enable ---------------------------------------------- */ 2640 static ssize_t bluetooth_enable_show(struct device *dev, ··· 2705 if (status < 0) 2706 return status; 2707 2708 - return snprintf(buf, PAGE_SIZE, "%d\n", status ? 1 : 0); 2709 } 2710 2711 static ssize_t bluetooth_enable_store(struct device *dev, ··· 2719 if (parse_strtoul(buf, 1, &t)) 2720 return -EINVAL; 2721 2722 - res = bluetooth_set_radiosw(t); 2723 2724 return (res) ? res : count; 2725 } ··· 2739 .attrs = bluetooth_attributes, 2740 }; 2741 2742 static int __init bluetooth_init(struct ibm_init_struct *iibm) 2743 { 2744 int res; ··· 2782 str_supported(tp_features.bluetooth), 2783 status); 2784 2785 - if (tp_features.bluetooth) { 2786 - if (!(status & TP_ACPI_BLUETOOTH_HWPRESENT)) { 2787 - /* no bluetooth hardware present in system */ 2788 - tp_features.bluetooth = 0; 2789 - dbg_printk(TPACPI_DBG_INIT, 2790 - "bluetooth hardware not installed\n"); 2791 - } else { 2792 - res = sysfs_create_group(&tpacpi_pdev->dev.kobj, 2793 - &bluetooth_attr_group); 2794 - if (res) 2795 - return res; 2796 - } 2797 } 2798 2799 - return (tp_features.bluetooth)? 0 : 1; 2800 - } 2801 - 2802 - static void bluetooth_exit(void) 2803 - { 2804 - sysfs_remove_group(&tpacpi_pdev->dev.kobj, 2805 - &bluetooth_attr_group); 2806 - } 2807 - 2808 - static int bluetooth_get_radiosw(void) 2809 - { 2810 - int status; 2811 - 2812 if (!tp_features.bluetooth) 2813 - return -ENODEV; 2814 2815 - if (!acpi_evalf(hkey_handle, &status, "GBDC", "d")) 2816 - return -EIO; 2817 2818 - return ((status & TP_ACPI_BLUETOOTH_RADIOSSW) != 0); 2819 - } 2820 - 2821 - static int bluetooth_set_radiosw(int radio_on) 2822 - { 2823 - int status; 2824 - 2825 - if (!tp_features.bluetooth) 2826 - return -ENODEV; 2827 - 2828 - if (!acpi_evalf(hkey_handle, &status, "GBDC", "d")) 2829 - return -EIO; 2830 - if (radio_on) 2831 - status |= TP_ACPI_BLUETOOTH_RADIOSSW; 2832 - else 2833 - status &= ~TP_ACPI_BLUETOOTH_RADIOSSW; 2834 - if (!acpi_evalf(hkey_handle, NULL, "SBDC", "vd", status)) 2835 - return -EIO; 2836 2837 return 0; 2838 } ··· 2822 len += sprintf(p + len, "status:\t\tnot supported\n"); 2823 else { 2824 len += sprintf(p + len, "status:\t\t%s\n", 2825 - (status)? "enabled" : "disabled"); 2826 len += sprintf(p + len, "commands:\tenable, disable\n"); 2827 } 2828 ··· 2839 2840 while ((cmd = next_cmd(&buf))) { 2841 if (strlencmp(cmd, "enable") == 0) { 2842 - bluetooth_set_radiosw(1); 2843 } else if (strlencmp(cmd, "disable") == 0) { 2844 - bluetooth_set_radiosw(0); 2845 } else 2846 return -EINVAL; 2847 } ··· 2867 TP_ACPI_WANCARD_UNK = 0x04, /* unknown function */ 2868 }; 2869 2870 - static int wan_get_radiosw(void); 2871 - static int wan_set_radiosw(int radio_on); 2872 2873 /* sysfs wan enable ---------------------------------------------------- */ 2874 static ssize_t wan_enable_show(struct device *dev, ··· 2939 if (status < 0) 2940 return status; 2941 2942 - return snprintf(buf, PAGE_SIZE, "%d\n", status ? 1 : 0); 2943 } 2944 2945 static ssize_t wan_enable_store(struct device *dev, ··· 2953 if (parse_strtoul(buf, 1, &t)) 2954 return -EINVAL; 2955 2956 - res = wan_set_radiosw(t); 2957 2958 return (res) ? res : count; 2959 } ··· 2973 .attrs = wan_attributes, 2974 }; 2975 2976 static int __init wan_init(struct ibm_init_struct *iibm) 2977 { 2978 int res; ··· 3014 str_supported(tp_features.wan), 3015 status); 3016 3017 - if (tp_features.wan) { 3018 - if (!(status & TP_ACPI_WANCARD_HWPRESENT)) { 3019 - /* no wan hardware present in system */ 3020 - tp_features.wan = 0; 3021 - dbg_printk(TPACPI_DBG_INIT, 3022 - "wan hardware not installed\n"); 3023 - } else { 3024 - res = sysfs_create_group(&tpacpi_pdev->dev.kobj, 3025 - &wan_attr_group); 3026 - if (res) 3027 - return res; 3028 - } 3029 } 3030 3031 - return (tp_features.wan)? 0 : 1; 3032 - } 3033 - 3034 - static void wan_exit(void) 3035 - { 3036 - sysfs_remove_group(&tpacpi_pdev->dev.kobj, 3037 - &wan_attr_group); 3038 - } 3039 - 3040 - static int wan_get_radiosw(void) 3041 - { 3042 - int status; 3043 - 3044 if (!tp_features.wan) 3045 - return -ENODEV; 3046 3047 - if (!acpi_evalf(hkey_handle, &status, "GWAN", "d")) 3048 - return -EIO; 3049 3050 - return ((status & TP_ACPI_WANCARD_RADIOSSW) != 0); 3051 - } 3052 - 3053 - static int wan_set_radiosw(int radio_on) 3054 - { 3055 - int status; 3056 - 3057 - if (!tp_features.wan) 3058 - return -ENODEV; 3059 - 3060 - if (!acpi_evalf(hkey_handle, &status, "GWAN", "d")) 3061 - return -EIO; 3062 - if (radio_on) 3063 - status |= TP_ACPI_WANCARD_RADIOSSW; 3064 - else 3065 - status &= ~TP_ACPI_WANCARD_RADIOSSW; 3066 - if (!acpi_evalf(hkey_handle, NULL, "SWAN", "vd", status)) 3067 - return -EIO; 3068 3069 return 0; 3070 } ··· 3054 len += sprintf(p + len, "status:\t\tnot supported\n"); 3055 else { 3056 len += sprintf(p + len, "status:\t\t%s\n", 3057 - (status)? "enabled" : "disabled"); 3058 len += sprintf(p + len, "commands:\tenable, disable\n"); 3059 } 3060 ··· 3071 3072 while ((cmd = next_cmd(&buf))) { 3073 if (strlencmp(cmd, "enable") == 0) { 3074 - wan_set_radiosw(1); 3075 } else if (strlencmp(cmd, "disable") == 0) { 3076 - wan_set_radiosw(0); 3077 } else 3078 return -EINVAL; 3079 } ··· 6340 6341 /* Probing */ 6342 6343 - static void __init get_thinkpad_model_data(struct thinkpad_id_data *tp) 6344 { 6345 const struct dmi_device *dev = NULL; 6346 char ec_fw_string[18]; 6347 6348 if (!tp) 6349 - return; 6350 6351 memset(tp, 0, sizeof(*tp)); 6352 ··· 6360 else if (dmi_name_in_vendors("LENOVO")) 6361 tp->vendor = PCI_VENDOR_ID_LENOVO; 6362 else 6363 - return; 6364 6365 - tp->bios_version_str = kstrdup(dmi_get_system_info(DMI_BIOS_VERSION), 6366 - GFP_KERNEL); 6367 if (!tp->bios_version_str) 6368 - return; 6369 tp->bios_model = tp->bios_version_str[0] 6370 | (tp->bios_version_str[1] << 8); 6371 ··· 6386 ec_fw_string[strcspn(ec_fw_string, " ]")] = 0; 6387 6388 tp->ec_version_str = kstrdup(ec_fw_string, GFP_KERNEL); 6389 tp->ec_model = ec_fw_string[0] 6390 | (ec_fw_string[1] << 8); 6391 break; 6392 } 6393 } 6394 6395 - tp->model_str = kstrdup(dmi_get_system_info(DMI_PRODUCT_VERSION), 6396 - GFP_KERNEL); 6397 - if (tp->model_str && strnicmp(tp->model_str, "ThinkPad", 8) != 0) { 6398 - kfree(tp->model_str); 6399 - tp->model_str = NULL; 6400 } 6401 6402 - tp->nummodel_str = kstrdup(dmi_get_system_info(DMI_PRODUCT_NAME), 6403 - GFP_KERNEL); 6404 } 6405 6406 static int __init probe_for_thinkpad(void) ··· 6669 6670 /* Driver-level probe */ 6671 6672 - get_thinkpad_model_data(&thinkpad_id); 6673 ret = probe_for_thinkpad(); 6674 if (ret) { 6675 thinkpad_acpi_module_exit();
··· 21 * 02110-1301, USA. 22 */ 23 24 + #define TPACPI_VERSION "0.21" 25 #define TPACPI_SYSFS_VERSION 0x020200 26 27 /* ··· 68 #include <linux/hwmon-sysfs.h> 69 #include <linux/input.h> 70 #include <linux/leds.h> 71 + #include <linux/rfkill.h> 72 #include <asm/uaccess.h> 73 74 #include <linux/dmi.h> ··· 143 #define TPACPI_WORKQUEUE_NAME "ktpacpid" 144 145 #define TPACPI_MAX_ACPI_ARGS 3 146 + 147 + /* rfkill switches */ 148 + enum { 149 + TPACPI_RFK_BLUETOOTH_SW_ID = 0, 150 + TPACPI_RFK_WWAN_SW_ID, 151 + }; 152 153 /* Debugging */ 154 #define TPACPI_LOG TPACPI_FILE ": " ··· 905 return 0; 906 } 907 908 + static int __init tpacpi_new_rfkill(const unsigned int id, 909 + struct rfkill **rfk, 910 + const enum rfkill_type rfktype, 911 + const char *name, 912 + int (*toggle_radio)(void *, enum rfkill_state), 913 + int (*get_state)(void *, enum rfkill_state *)) 914 + { 915 + int res; 916 + enum rfkill_state initial_state; 917 + 918 + *rfk = rfkill_allocate(&tpacpi_pdev->dev, rfktype); 919 + if (!*rfk) { 920 + printk(TPACPI_ERR 921 + "failed to allocate memory for rfkill class\n"); 922 + return -ENOMEM; 923 + } 924 + 925 + (*rfk)->name = name; 926 + (*rfk)->get_state = get_state; 927 + (*rfk)->toggle_radio = toggle_radio; 928 + 929 + if (!get_state(NULL, &initial_state)) 930 + (*rfk)->state = initial_state; 931 + 932 + res = rfkill_register(*rfk); 933 + if (res < 0) { 934 + printk(TPACPI_ERR 935 + "failed to register %s rfkill switch: %d\n", 936 + name, res); 937 + rfkill_free(*rfk); 938 + *rfk = NULL; 939 + return res; 940 + } 941 + 942 + return 0; 943 + } 944 + 945 /************************************************************************* 946 * thinkpad-acpi driver attributes 947 */ ··· 1283 return -EIO; 1284 1285 return 0; 1286 } 1287 1288 static void tpacpi_input_send_tabletsw(void) ··· 1921 &dev_attr_hotkey_wakeup_hotunplug_complete.attr, 1922 }; 1923 1924 + static void bluetooth_update_rfk(void); 1925 + static void wan_update_rfk(void); 1926 + static void tpacpi_send_radiosw_update(void) 1927 + { 1928 + int wlsw; 1929 + 1930 + /* Sync these BEFORE sending any rfkill events */ 1931 + if (tp_features.bluetooth) 1932 + bluetooth_update_rfk(); 1933 + if (tp_features.wan) 1934 + wan_update_rfk(); 1935 + 1936 + if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&wlsw)) { 1937 + mutex_lock(&tpacpi_inputdev_send_mutex); 1938 + 1939 + input_report_switch(tpacpi_inputdev, 1940 + SW_RFKILL_ALL, !!wlsw); 1941 + input_sync(tpacpi_inputdev); 1942 + 1943 + mutex_unlock(&tpacpi_inputdev_send_mutex); 1944 + } 1945 + hotkey_radio_sw_notify_change(); 1946 + } 1947 + 1948 static void hotkey_exit(void) 1949 { 1950 #ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL ··· 2167 printk(TPACPI_INFO 2168 "radio switch found; radios are %s\n", 2169 enabled(status, 0)); 2170 + } 2171 + if (tp_features.hotkey_wlsw) 2172 res = add_to_attr_set(hotkey_dev_attributes, 2173 &dev_attr_hotkey_radio_sw.attr); 2174 2175 /* For X41t, X60t, X61t Tablets... */ 2176 if (!res && acpi_evalf(hkey_handle, &status, "MHKG", "qd")) { ··· 2287 tpacpi_inputdev->close = &hotkey_inputdev_close; 2288 2289 hotkey_poll_setup_safe(1); 2290 + tpacpi_send_radiosw_update(); 2291 tpacpi_input_send_tabletsw(); 2292 2293 return 0; ··· 2419 case 7: 2420 /* 0x7000-0x7FFF: misc */ 2421 if (tp_features.hotkey_wlsw && hkey == 0x7000) { 2422 + tpacpi_send_radiosw_update(); 2423 send_acpi_ev = 0; 2424 break; 2425 } ··· 2463 printk(TPACPI_ERR 2464 "error while trying to read hot key mask " 2465 "from firmware\n"); 2466 + tpacpi_send_radiosw_update(); 2467 hotkey_tablet_mode_notify_change(); 2468 hotkey_wakeup_reason_notify_change(); 2469 hotkey_wakeup_hotunplug_complete_notify_change(); ··· 2581 TP_ACPI_BLUETOOTH_UNK = 0x04, /* unknown function */ 2582 }; 2583 2584 + static struct rfkill *tpacpi_bluetooth_rfkill; 2585 + 2586 + static int bluetooth_get_radiosw(void) 2587 + { 2588 + int status; 2589 + 2590 + if (!tp_features.bluetooth) 2591 + return -ENODEV; 2592 + 2593 + /* WLSW overrides bluetooth in firmware/hardware, reflect that */ 2594 + if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&status) && !status) 2595 + return RFKILL_STATE_HARD_BLOCKED; 2596 + 2597 + if (!acpi_evalf(hkey_handle, &status, "GBDC", "d")) 2598 + return -EIO; 2599 + 2600 + return ((status & TP_ACPI_BLUETOOTH_RADIOSSW) != 0) ? 2601 + RFKILL_STATE_UNBLOCKED : RFKILL_STATE_SOFT_BLOCKED; 2602 + } 2603 + 2604 + static void bluetooth_update_rfk(void) 2605 + { 2606 + int status; 2607 + 2608 + if (!tpacpi_bluetooth_rfkill) 2609 + return; 2610 + 2611 + status = bluetooth_get_radiosw(); 2612 + if (status < 0) 2613 + return; 2614 + rfkill_force_state(tpacpi_bluetooth_rfkill, status); 2615 + } 2616 + 2617 + static int bluetooth_set_radiosw(int radio_on, int update_rfk) 2618 + { 2619 + int status; 2620 + 2621 + if (!tp_features.bluetooth) 2622 + return -ENODEV; 2623 + 2624 + /* WLSW overrides bluetooth in firmware/hardware, but there is no 2625 + * reason to risk weird behaviour. */ 2626 + if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&status) && !status 2627 + && radio_on) 2628 + return -EPERM; 2629 + 2630 + if (!acpi_evalf(hkey_handle, &status, "GBDC", "d")) 2631 + return -EIO; 2632 + if (radio_on) 2633 + status |= TP_ACPI_BLUETOOTH_RADIOSSW; 2634 + else 2635 + status &= ~TP_ACPI_BLUETOOTH_RADIOSSW; 2636 + if (!acpi_evalf(hkey_handle, NULL, "SBDC", "vd", status)) 2637 + return -EIO; 2638 + 2639 + if (update_rfk) 2640 + bluetooth_update_rfk(); 2641 + 2642 + return 0; 2643 + } 2644 2645 /* sysfs bluetooth enable ---------------------------------------------- */ 2646 static ssize_t bluetooth_enable_show(struct device *dev, ··· 2595 if (status < 0) 2596 return status; 2597 2598 + return snprintf(buf, PAGE_SIZE, "%d\n", 2599 + (status == RFKILL_STATE_UNBLOCKED) ? 1 : 0); 2600 } 2601 2602 static ssize_t bluetooth_enable_store(struct device *dev, ··· 2608 if (parse_strtoul(buf, 1, &t)) 2609 return -EINVAL; 2610 2611 + res = bluetooth_set_radiosw(t, 1); 2612 2613 return (res) ? res : count; 2614 } ··· 2628 .attrs = bluetooth_attributes, 2629 }; 2630 2631 + static int tpacpi_bluetooth_rfk_get(void *data, enum rfkill_state *state) 2632 + { 2633 + int bts = bluetooth_get_radiosw(); 2634 + 2635 + if (bts < 0) 2636 + return bts; 2637 + 2638 + *state = bts; 2639 + return 0; 2640 + } 2641 + 2642 + static int tpacpi_bluetooth_rfk_set(void *data, enum rfkill_state state) 2643 + { 2644 + return bluetooth_set_radiosw((state == RFKILL_STATE_UNBLOCKED), 0); 2645 + } 2646 + 2647 + static void bluetooth_exit(void) 2648 + { 2649 + if (tpacpi_bluetooth_rfkill) 2650 + rfkill_unregister(tpacpi_bluetooth_rfkill); 2651 + 2652 + sysfs_remove_group(&tpacpi_pdev->dev.kobj, 2653 + &bluetooth_attr_group); 2654 + } 2655 + 2656 static int __init bluetooth_init(struct ibm_init_struct *iibm) 2657 { 2658 int res; ··· 2646 str_supported(tp_features.bluetooth), 2647 status); 2648 2649 + if (tp_features.bluetooth && 2650 + !(status & TP_ACPI_BLUETOOTH_HWPRESENT)) { 2651 + /* no bluetooth hardware present in system */ 2652 + tp_features.bluetooth = 0; 2653 + dbg_printk(TPACPI_DBG_INIT, 2654 + "bluetooth hardware not installed\n"); 2655 } 2656 2657 if (!tp_features.bluetooth) 2658 + return 1; 2659 2660 + res = sysfs_create_group(&tpacpi_pdev->dev.kobj, 2661 + &bluetooth_attr_group); 2662 + if (res) 2663 + return res; 2664 2665 + res = tpacpi_new_rfkill(TPACPI_RFK_BLUETOOTH_SW_ID, 2666 + &tpacpi_bluetooth_rfkill, 2667 + RFKILL_TYPE_BLUETOOTH, 2668 + "tpacpi_bluetooth_sw", 2669 + tpacpi_bluetooth_rfk_set, 2670 + tpacpi_bluetooth_rfk_get); 2671 + if (res) { 2672 + bluetooth_exit(); 2673 + return res; 2674 + } 2675 2676 return 0; 2677 } ··· 2711 len += sprintf(p + len, "status:\t\tnot supported\n"); 2712 else { 2713 len += sprintf(p + len, "status:\t\t%s\n", 2714 + (status == RFKILL_STATE_UNBLOCKED) ? 2715 + "enabled" : "disabled"); 2716 len += sprintf(p + len, "commands:\tenable, disable\n"); 2717 } 2718 ··· 2727 2728 while ((cmd = next_cmd(&buf))) { 2729 if (strlencmp(cmd, "enable") == 0) { 2730 + bluetooth_set_radiosw(1, 1); 2731 } else if (strlencmp(cmd, "disable") == 0) { 2732 + bluetooth_set_radiosw(0, 1); 2733 } else 2734 return -EINVAL; 2735 } ··· 2755 TP_ACPI_WANCARD_UNK = 0x04, /* unknown function */ 2756 }; 2757 2758 + static struct rfkill *tpacpi_wan_rfkill; 2759 + 2760 + static int wan_get_radiosw(void) 2761 + { 2762 + int status; 2763 + 2764 + if (!tp_features.wan) 2765 + return -ENODEV; 2766 + 2767 + /* WLSW overrides WWAN in firmware/hardware, reflect that */ 2768 + if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&status) && !status) 2769 + return RFKILL_STATE_HARD_BLOCKED; 2770 + 2771 + if (!acpi_evalf(hkey_handle, &status, "GWAN", "d")) 2772 + return -EIO; 2773 + 2774 + return ((status & TP_ACPI_WANCARD_RADIOSSW) != 0) ? 2775 + RFKILL_STATE_UNBLOCKED : RFKILL_STATE_SOFT_BLOCKED; 2776 + } 2777 + 2778 + static void wan_update_rfk(void) 2779 + { 2780 + int status; 2781 + 2782 + if (!tpacpi_wan_rfkill) 2783 + return; 2784 + 2785 + status = wan_get_radiosw(); 2786 + if (status < 0) 2787 + return; 2788 + rfkill_force_state(tpacpi_wan_rfkill, status); 2789 + } 2790 + 2791 + static int wan_set_radiosw(int radio_on, int update_rfk) 2792 + { 2793 + int status; 2794 + 2795 + if (!tp_features.wan) 2796 + return -ENODEV; 2797 + 2798 + /* WLSW overrides bluetooth in firmware/hardware, but there is no 2799 + * reason to risk weird behaviour. */ 2800 + if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&status) && !status 2801 + && radio_on) 2802 + return -EPERM; 2803 + 2804 + if (!acpi_evalf(hkey_handle, &status, "GWAN", "d")) 2805 + return -EIO; 2806 + if (radio_on) 2807 + status |= TP_ACPI_WANCARD_RADIOSSW; 2808 + else 2809 + status &= ~TP_ACPI_WANCARD_RADIOSSW; 2810 + if (!acpi_evalf(hkey_handle, NULL, "SWAN", "vd", status)) 2811 + return -EIO; 2812 + 2813 + if (update_rfk) 2814 + wan_update_rfk(); 2815 + 2816 + return 0; 2817 + } 2818 2819 /* sysfs wan enable ---------------------------------------------------- */ 2820 static ssize_t wan_enable_show(struct device *dev, ··· 2769 if (status < 0) 2770 return status; 2771 2772 + return snprintf(buf, PAGE_SIZE, "%d\n", 2773 + (status == RFKILL_STATE_UNBLOCKED) ? 1 : 0); 2774 } 2775 2776 static ssize_t wan_enable_store(struct device *dev, ··· 2782 if (parse_strtoul(buf, 1, &t)) 2783 return -EINVAL; 2784 2785 + res = wan_set_radiosw(t, 1); 2786 2787 return (res) ? res : count; 2788 } ··· 2802 .attrs = wan_attributes, 2803 }; 2804 2805 + static int tpacpi_wan_rfk_get(void *data, enum rfkill_state *state) 2806 + { 2807 + int wans = wan_get_radiosw(); 2808 + 2809 + if (wans < 0) 2810 + return wans; 2811 + 2812 + *state = wans; 2813 + return 0; 2814 + } 2815 + 2816 + static int tpacpi_wan_rfk_set(void *data, enum rfkill_state state) 2817 + { 2818 + return wan_set_radiosw((state == RFKILL_STATE_UNBLOCKED), 0); 2819 + } 2820 + 2821 + static void wan_exit(void) 2822 + { 2823 + if (tpacpi_wan_rfkill) 2824 + rfkill_unregister(tpacpi_wan_rfkill); 2825 + 2826 + sysfs_remove_group(&tpacpi_pdev->dev.kobj, 2827 + &wan_attr_group); 2828 + } 2829 + 2830 static int __init wan_init(struct ibm_init_struct *iibm) 2831 { 2832 int res; ··· 2818 str_supported(tp_features.wan), 2819 status); 2820 2821 + if (tp_features.wan && 2822 + !(status & TP_ACPI_WANCARD_HWPRESENT)) { 2823 + /* no wan hardware present in system */ 2824 + tp_features.wan = 0; 2825 + dbg_printk(TPACPI_DBG_INIT, 2826 + "wan hardware not installed\n"); 2827 } 2828 2829 if (!tp_features.wan) 2830 + return 1; 2831 2832 + res = sysfs_create_group(&tpacpi_pdev->dev.kobj, 2833 + &wan_attr_group); 2834 + if (res) 2835 + return res; 2836 2837 + res = tpacpi_new_rfkill(TPACPI_RFK_WWAN_SW_ID, 2838 + &tpacpi_wan_rfkill, 2839 + RFKILL_TYPE_WWAN, 2840 + "tpacpi_wwan_sw", 2841 + tpacpi_wan_rfk_set, 2842 + tpacpi_wan_rfk_get); 2843 + if (res) { 2844 + wan_exit(); 2845 + return res; 2846 + } 2847 2848 return 0; 2849 } ··· 2883 len += sprintf(p + len, "status:\t\tnot supported\n"); 2884 else { 2885 len += sprintf(p + len, "status:\t\t%s\n", 2886 + (status == RFKILL_STATE_UNBLOCKED) ? 2887 + "enabled" : "disabled"); 2888 len += sprintf(p + len, "commands:\tenable, disable\n"); 2889 } 2890 ··· 2899 2900 while ((cmd = next_cmd(&buf))) { 2901 if (strlencmp(cmd, "enable") == 0) { 2902 + wan_set_radiosw(1, 1); 2903 } else if (strlencmp(cmd, "disable") == 0) { 2904 + wan_set_radiosw(0, 1); 2905 } else 2906 return -EINVAL; 2907 } ··· 6168 6169 /* Probing */ 6170 6171 + /* returns 0 - probe ok, or < 0 - probe error. 6172 + * Probe ok doesn't mean thinkpad found. 6173 + * On error, kfree() cleanup on tp->* is not performed, caller must do it */ 6174 + static int __must_check __init get_thinkpad_model_data( 6175 + struct thinkpad_id_data *tp) 6176 { 6177 const struct dmi_device *dev = NULL; 6178 char ec_fw_string[18]; 6179 + char const *s; 6180 6181 if (!tp) 6182 + return -EINVAL; 6183 6184 memset(tp, 0, sizeof(*tp)); 6185 ··· 6183 else if (dmi_name_in_vendors("LENOVO")) 6184 tp->vendor = PCI_VENDOR_ID_LENOVO; 6185 else 6186 + return 0; 6187 6188 + s = dmi_get_system_info(DMI_BIOS_VERSION); 6189 + tp->bios_version_str = kstrdup(s, GFP_KERNEL); 6190 + if (s && !tp->bios_version_str) 6191 + return -ENOMEM; 6192 if (!tp->bios_version_str) 6193 + return 0; 6194 tp->bios_model = tp->bios_version_str[0] 6195 | (tp->bios_version_str[1] << 8); 6196 ··· 6207 ec_fw_string[strcspn(ec_fw_string, " ]")] = 0; 6208 6209 tp->ec_version_str = kstrdup(ec_fw_string, GFP_KERNEL); 6210 + if (!tp->ec_version_str) 6211 + return -ENOMEM; 6212 tp->ec_model = ec_fw_string[0] 6213 | (ec_fw_string[1] << 8); 6214 break; 6215 } 6216 } 6217 6218 + s = dmi_get_system_info(DMI_PRODUCT_VERSION); 6219 + if (s && !strnicmp(s, "ThinkPad", 8)) { 6220 + tp->model_str = kstrdup(s, GFP_KERNEL); 6221 + if (!tp->model_str) 6222 + return -ENOMEM; 6223 } 6224 6225 + s = dmi_get_system_info(DMI_PRODUCT_NAME); 6226 + tp->nummodel_str = kstrdup(s, GFP_KERNEL); 6227 + if (s && !tp->nummodel_str) 6228 + return -ENOMEM; 6229 + 6230 + return 0; 6231 } 6232 6233 static int __init probe_for_thinkpad(void) ··· 6484 6485 /* Driver-level probe */ 6486 6487 + ret = get_thinkpad_model_data(&thinkpad_id); 6488 + if (ret) { 6489 + printk(TPACPI_ERR 6490 + "unable to get DMI data: %d\n", ret); 6491 + thinkpad_acpi_module_exit(); 6492 + return ret; 6493 + } 6494 ret = probe_for_thinkpad(); 6495 if (ret) { 6496 thinkpad_acpi_module_exit();