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 1 ThinkPad ACPI Extras Driver 2 2 3 - Version 0.20 4 - April 09th, 2008 3 + Version 0.21 4 + May 29th, 2008 5 5 6 6 Borislav Deianov <borislav@users.sf.net> 7 7 Henrique de Moraes Holschuh <hmh@hmh.eng.br> ··· 621 621 --------- 622 622 623 623 procfs: /proc/acpi/ibm/bluetooth 624 - sysfs device attribute: bluetooth_enable 624 + sysfs device attribute: bluetooth_enable (deprecated) 625 + sysfs rfkill class: switch "tpacpi_bluetooth_sw" 625 626 626 627 This feature shows the presence and current state of a ThinkPad 627 628 Bluetooth device in the internal ThinkPad CDC slot. ··· 644 643 0: disables Bluetooth / Bluetooth is disabled 645 644 1: enables Bluetooth / Bluetooth is enabled. 646 645 647 - Note: this interface will be probably be superseded by the 648 - generic rfkill class, so it is NOT to be considered stable yet. 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. 649 652 650 653 Video output control -- /proc/acpi/ibm/video 651 654 -------------------------------------------- ··· 1379 1374 ----------------- 1380 1375 1381 1376 procfs: /proc/acpi/ibm/wan 1382 - sysfs device attribute: wwan_enable 1377 + sysfs device attribute: wwan_enable (deprecated) 1378 + sysfs rfkill class: switch "tpacpi_wwan_sw" 1383 1379 1384 1380 This feature is marked EXPERIMENTAL because the implementation 1385 1381 directly accesses hardware registers and may not work as expected. USE ··· 1410 1404 0: disables WWAN card / WWAN card is disabled 1411 1405 1: enables WWAN card / WWAN card is enabled. 1412 1406 1413 - Note: this interface will be probably be superseded by the 1414 - generic rfkill class, so it is NOT to be considered stable yet. 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. 1415 1413 1416 1414 Multiple Commands, Module Parameters 1417 1415 ------------------------------------
+8
drivers/acpi/namespace/nsnames.c
··· 137 137 /* Calculate required buffer size based on depth below root */ 138 138 139 139 size = acpi_ns_get_pathname_length(node); 140 + if (!size) { 141 + ACPI_ERROR((AE_INFO, "Invalid node failure")); 142 + return_PTR(NULL); 143 + } 140 144 141 145 /* Allocate a buffer to be returned to caller */ 142 146 ··· 233 229 /* Determine size required for the caller buffer */ 234 230 235 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 236 237 237 /* Validate/Allocate/Clear caller buffer */ 238 238
+20 -11
drivers/acpi/pci_link.c
··· 113 113 114 114 switch (resource->type) { 115 115 case ACPI_RESOURCE_TYPE_START_DEPENDENT: 116 + case ACPI_RESOURCE_TYPE_END_TAG: 116 117 return AE_OK; 117 118 case ACPI_RESOURCE_TYPE_IRQ: 118 119 { 119 120 struct acpi_resource_irq *p = &resource->data.irq; 120 121 if (!p || !p->interrupt_count) { 121 - printk(KERN_WARNING PREFIX "Blank IRQ resource\n"); 122 + ACPI_DEBUG_PRINT((ACPI_DB_INFO, 123 + "Blank _PRS IRQ resource\n")); 122 124 return AE_OK; 123 125 } 124 126 for (i = 0; 125 127 (i < p->interrupt_count 126 128 && i < ACPI_PCI_LINK_MAX_POSSIBLE); i++) { 127 129 if (!p->interrupts[i]) { 128 - printk(KERN_WARNING PREFIX "Invalid IRQ %d\n", 129 - p->interrupts[i]); 130 + printk(KERN_WARNING PREFIX 131 + "Invalid _PRS IRQ %d\n", 132 + p->interrupts[i]); 130 133 continue; 131 134 } 132 135 link->irq.possible[i] = p->interrupts[i]; ··· 146 143 &resource->data.extended_irq; 147 144 if (!p || !p->interrupt_count) { 148 145 printk(KERN_WARNING PREFIX 149 - "Blank EXT IRQ resource\n"); 146 + "Blank _PRS EXT IRQ resource\n"); 150 147 return AE_OK; 151 148 } 152 149 for (i = 0; 153 150 (i < p->interrupt_count 154 151 && i < ACPI_PCI_LINK_MAX_POSSIBLE); i++) { 155 152 if (!p->interrupts[i]) { 156 - printk(KERN_WARNING PREFIX "Invalid IRQ %d\n", 157 - p->interrupts[i]); 153 + printk(KERN_WARNING PREFIX 154 + "Invalid _PRS IRQ %d\n", 155 + p->interrupts[i]); 158 156 continue; 159 157 } 160 158 link->irq.possible[i] = p->interrupts[i]; ··· 167 163 break; 168 164 } 169 165 default: 170 - printk(KERN_ERR PREFIX "Resource is not an IRQ entry\n"); 166 + printk(KERN_ERR PREFIX "_PRS resource type 0x%x isn't an IRQ\n", 167 + resource->type); 171 168 return AE_OK; 172 169 } 173 170 ··· 204 199 205 200 206 201 switch (resource->type) { 202 + case ACPI_RESOURCE_TYPE_START_DEPENDENT: 203 + case ACPI_RESOURCE_TYPE_END_TAG: 204 + return AE_OK; 207 205 case ACPI_RESOURCE_TYPE_IRQ: 208 206 { 209 207 struct acpi_resource_irq *p = &resource->data.irq; ··· 216 208 * particularly those those w/ _STA disabled 217 209 */ 218 210 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 219 - "Blank IRQ resource\n")); 211 + "Blank _CRS IRQ resource\n")); 220 212 return AE_OK; 221 213 } 222 214 *irq = p->interrupts[0]; ··· 232 224 * return at least 1 IRQ 233 225 */ 234 226 printk(KERN_WARNING PREFIX 235 - "Blank EXT IRQ resource\n"); 227 + "Blank _CRS EXT IRQ resource\n"); 236 228 return AE_OK; 237 229 } 238 230 *irq = p->interrupts[0]; ··· 240 232 } 241 233 break; 242 234 default: 243 - printk(KERN_ERR PREFIX "Resource %d isn't an IRQ\n", resource->type); 244 - case ACPI_RESOURCE_TYPE_END_TAG: 235 + printk(KERN_ERR PREFIX "_CRS resource type 0x%x isn't an IRQ\n", 236 + resource->type); 245 237 return AE_OK; 246 238 } 239 + 247 240 return AE_CTRL_TERMINATE; 248 241 } 249 242
+6 -11
drivers/acpi/tables/tbfadt.c
··· 124 124 125 125 static void inline 126 126 acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, 127 - u8 byte_width, u64 address) 127 + u8 bit_width, u64 address) 128 128 { 129 129 130 130 /* ··· 136 136 /* All other fields are byte-wide */ 137 137 138 138 generic_address->space_id = ACPI_ADR_SPACE_SYSTEM_IO; 139 - generic_address->bit_width = byte_width << 3; 139 + generic_address->bit_width = bit_width; 140 140 generic_address->bit_offset = 0; 141 141 generic_address->access_width = 0; 142 142 } ··· 343 343 * 344 344 * The PM event blocks are split into two register blocks, first is the 345 345 * PM Status Register block, followed immediately by the PM Enable Register 346 - * block. Each is of length (xpm1x_event_block.bit_width/2) 346 + * block. Each is of length (pm1_event_length/2) 347 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); 348 + pm1_register_length = (u8) ACPI_DIV_2(acpi_gbl_FADT.pm1_event_length); 351 349 352 350 /* The PM1A register block is required */ 353 351 ··· 360 362 /* The PM1B register block is optional, ignore if not present */ 361 363 362 364 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 365 acpi_tb_init_generic_address(&acpi_gbl_xpm1b_enable, 368 366 pm1_register_length, 369 367 (acpi_gbl_FADT.xpm1b_event_block. 370 368 address + pm1_register_length)); 371 369 /* Don't forget to copy space_id of the GAS */ 372 370 acpi_gbl_xpm1b_enable.space_id = 373 - acpi_gbl_FADT.xpm1b_event_block.space_id; 371 + acpi_gbl_FADT.xpm1a_event_block.space_id; 372 + 374 373 } 375 374 } 376 375
+43
drivers/acpi/thermal.c
··· 769 769 acpi_os_execute(OSL_GPE_HANDLER, acpi_thermal_check, (void *)data); 770 770 } 771 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 + 772 813 static void acpi_thermal_check(void *data) 773 814 { 774 815 int result = 0; ··· 1664 1623 goto unregister_thermal_zone; 1665 1624 1666 1625 init_timer(&tz->timer); 1626 + 1627 + acpi_thermal_active_off(tz); 1667 1628 1668 1629 acpi_thermal_check(tz); 1669 1630
+4
drivers/acpi/utilities/utalloc.c
··· 242 242 { 243 243 acpi_status status = AE_OK; 244 244 245 + if (!required_length) { 246 + WARN_ON(1); 247 + return AE_ERROR; 248 + } 245 249 switch (buffer->length) { 246 250 case ACPI_NO_BUFFER: 247 251
+12 -2
drivers/acpi/video.c
··· 741 741 742 742 max_level = acpi_video_init_brightness(device); 743 743 744 - if (device->cap._BCL && device->cap._BCM && device->cap._BQC && max_level > 0){ 744 + if (device->cap._BCL && device->cap._BCM && max_level > 0) { 745 745 int result; 746 746 static int count = 0; 747 747 char *name; ··· 753 753 device->backlight = backlight_device_register(name, 754 754 NULL, device, &acpi_backlight_ops); 755 755 device->backlight->props.max_brightness = device->brightness->count-3; 756 - device->backlight->props.brightness = acpi_video_get_brightness(device->backlight); 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; 757 767 backlight_update_status(device->backlight); 758 768 kfree(name); 759 769
+2
drivers/misc/Kconfig
··· 279 279 select INPUT 280 280 select NEW_LEDS 281 281 select LEDS_CLASS 282 + select NET 283 + select RFKILL 282 284 ---help--- 283 285 This is a driver for the IBM and Lenovo ThinkPad laptops. It adds 284 286 support for Fn-Fx key combinations, Bluetooth control, video
+333 -142
drivers/misc/thinkpad_acpi.c
··· 21 21 * 02110-1301, USA. 22 22 */ 23 23 24 - #define TPACPI_VERSION "0.20" 24 + #define TPACPI_VERSION "0.21" 25 25 #define TPACPI_SYSFS_VERSION 0x020200 26 26 27 27 /* ··· 68 68 #include <linux/hwmon-sysfs.h> 69 69 #include <linux/input.h> 70 70 #include <linux/leds.h> 71 + #include <linux/rfkill.h> 71 72 #include <asm/uaccess.h> 72 73 73 74 #include <linux/dmi.h> ··· 144 143 #define TPACPI_WORKQUEUE_NAME "ktpacpid" 145 144 146 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 + }; 147 152 148 153 /* Debugging */ 149 154 #define TPACPI_LOG TPACPI_FILE ": " ··· 912 905 return 0; 913 906 } 914 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 + 915 945 /************************************************************************* 916 946 * thinkpad-acpi driver attributes 917 947 */ ··· 1327 1283 return -EIO; 1328 1284 1329 1285 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 1286 } 1346 1287 1347 1288 static void tpacpi_input_send_tabletsw(void) ··· 1950 1921 &dev_attr_hotkey_wakeup_hotunplug_complete.attr, 1951 1922 }; 1952 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 + 1953 1948 static void hotkey_exit(void) 1954 1949 { 1955 1950 #ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL ··· 2220 2167 printk(TPACPI_INFO 2221 2168 "radio switch found; radios are %s\n", 2222 2169 enabled(status, 0)); 2170 + } 2171 + if (tp_features.hotkey_wlsw) 2223 2172 res = add_to_attr_set(hotkey_dev_attributes, 2224 2173 &dev_attr_hotkey_radio_sw.attr); 2225 - } 2226 2174 2227 2175 /* For X41t, X60t, X61t Tablets... */ 2228 2176 if (!res && acpi_evalf(hkey_handle, &status, "MHKG", "qd")) { ··· 2341 2287 tpacpi_inputdev->close = &hotkey_inputdev_close; 2342 2288 2343 2289 hotkey_poll_setup_safe(1); 2344 - tpacpi_input_send_radiosw(); 2290 + tpacpi_send_radiosw_update(); 2345 2291 tpacpi_input_send_tabletsw(); 2346 2292 2347 2293 return 0; ··· 2473 2419 case 7: 2474 2420 /* 0x7000-0x7FFF: misc */ 2475 2421 if (tp_features.hotkey_wlsw && hkey == 0x7000) { 2476 - tpacpi_input_send_radiosw(); 2477 - hotkey_radio_sw_notify_change(); 2422 + tpacpi_send_radiosw_update(); 2478 2423 send_acpi_ev = 0; 2479 2424 break; 2480 2425 } ··· 2516 2463 printk(TPACPI_ERR 2517 2464 "error while trying to read hot key mask " 2518 2465 "from firmware\n"); 2519 - tpacpi_input_send_radiosw(); 2520 - hotkey_radio_sw_notify_change(); 2466 + tpacpi_send_radiosw_update(); 2521 2467 hotkey_tablet_mode_notify_change(); 2522 2468 hotkey_wakeup_reason_notify_change(); 2523 2469 hotkey_wakeup_hotunplug_complete_notify_change(); ··· 2633 2581 TP_ACPI_BLUETOOTH_UNK = 0x04, /* unknown function */ 2634 2582 }; 2635 2583 2636 - static int bluetooth_get_radiosw(void); 2637 - static int bluetooth_set_radiosw(int radio_on); 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 + } 2638 2644 2639 2645 /* sysfs bluetooth enable ---------------------------------------------- */ 2640 2646 static ssize_t bluetooth_enable_show(struct device *dev, ··· 2705 2595 if (status < 0) 2706 2596 return status; 2707 2597 2708 - return snprintf(buf, PAGE_SIZE, "%d\n", status ? 1 : 0); 2598 + return snprintf(buf, PAGE_SIZE, "%d\n", 2599 + (status == RFKILL_STATE_UNBLOCKED) ? 1 : 0); 2709 2600 } 2710 2601 2711 2602 static ssize_t bluetooth_enable_store(struct device *dev, ··· 2719 2608 if (parse_strtoul(buf, 1, &t)) 2720 2609 return -EINVAL; 2721 2610 2722 - res = bluetooth_set_radiosw(t); 2611 + res = bluetooth_set_radiosw(t, 1); 2723 2612 2724 2613 return (res) ? res : count; 2725 2614 } ··· 2739 2628 .attrs = bluetooth_attributes, 2740 2629 }; 2741 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 + 2742 2656 static int __init bluetooth_init(struct ibm_init_struct *iibm) 2743 2657 { 2744 2658 int res; ··· 2782 2646 str_supported(tp_features.bluetooth), 2783 2647 status); 2784 2648 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 - } 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"); 2797 2655 } 2798 2656 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 2657 if (!tp_features.bluetooth) 2813 - return -ENODEV; 2658 + return 1; 2814 2659 2815 - if (!acpi_evalf(hkey_handle, &status, "GBDC", "d")) 2816 - return -EIO; 2660 + res = sysfs_create_group(&tpacpi_pdev->dev.kobj, 2661 + &bluetooth_attr_group); 2662 + if (res) 2663 + return res; 2817 2664 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; 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 + } 2836 2675 2837 2676 return 0; 2838 2677 } ··· 2822 2711 len += sprintf(p + len, "status:\t\tnot supported\n"); 2823 2712 else { 2824 2713 len += sprintf(p + len, "status:\t\t%s\n", 2825 - (status)? "enabled" : "disabled"); 2714 + (status == RFKILL_STATE_UNBLOCKED) ? 2715 + "enabled" : "disabled"); 2826 2716 len += sprintf(p + len, "commands:\tenable, disable\n"); 2827 2717 } 2828 2718 ··· 2839 2727 2840 2728 while ((cmd = next_cmd(&buf))) { 2841 2729 if (strlencmp(cmd, "enable") == 0) { 2842 - bluetooth_set_radiosw(1); 2730 + bluetooth_set_radiosw(1, 1); 2843 2731 } else if (strlencmp(cmd, "disable") == 0) { 2844 - bluetooth_set_radiosw(0); 2732 + bluetooth_set_radiosw(0, 1); 2845 2733 } else 2846 2734 return -EINVAL; 2847 2735 } ··· 2867 2755 TP_ACPI_WANCARD_UNK = 0x04, /* unknown function */ 2868 2756 }; 2869 2757 2870 - static int wan_get_radiosw(void); 2871 - static int wan_set_radiosw(int radio_on); 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 + } 2872 2818 2873 2819 /* sysfs wan enable ---------------------------------------------------- */ 2874 2820 static ssize_t wan_enable_show(struct device *dev, ··· 2939 2769 if (status < 0) 2940 2770 return status; 2941 2771 2942 - return snprintf(buf, PAGE_SIZE, "%d\n", status ? 1 : 0); 2772 + return snprintf(buf, PAGE_SIZE, "%d\n", 2773 + (status == RFKILL_STATE_UNBLOCKED) ? 1 : 0); 2943 2774 } 2944 2775 2945 2776 static ssize_t wan_enable_store(struct device *dev, ··· 2953 2782 if (parse_strtoul(buf, 1, &t)) 2954 2783 return -EINVAL; 2955 2784 2956 - res = wan_set_radiosw(t); 2785 + res = wan_set_radiosw(t, 1); 2957 2786 2958 2787 return (res) ? res : count; 2959 2788 } ··· 2973 2802 .attrs = wan_attributes, 2974 2803 }; 2975 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 + 2976 2830 static int __init wan_init(struct ibm_init_struct *iibm) 2977 2831 { 2978 2832 int res; ··· 3014 2818 str_supported(tp_features.wan), 3015 2819 status); 3016 2820 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 - } 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"); 3029 2827 } 3030 2828 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 2829 if (!tp_features.wan) 3045 - return -ENODEV; 2830 + return 1; 3046 2831 3047 - if (!acpi_evalf(hkey_handle, &status, "GWAN", "d")) 3048 - return -EIO; 2832 + res = sysfs_create_group(&tpacpi_pdev->dev.kobj, 2833 + &wan_attr_group); 2834 + if (res) 2835 + return res; 3049 2836 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; 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 + } 3068 2847 3069 2848 return 0; 3070 2849 } ··· 3054 2883 len += sprintf(p + len, "status:\t\tnot supported\n"); 3055 2884 else { 3056 2885 len += sprintf(p + len, "status:\t\t%s\n", 3057 - (status)? "enabled" : "disabled"); 2886 + (status == RFKILL_STATE_UNBLOCKED) ? 2887 + "enabled" : "disabled"); 3058 2888 len += sprintf(p + len, "commands:\tenable, disable\n"); 3059 2889 } 3060 2890 ··· 3071 2899 3072 2900 while ((cmd = next_cmd(&buf))) { 3073 2901 if (strlencmp(cmd, "enable") == 0) { 3074 - wan_set_radiosw(1); 2902 + wan_set_radiosw(1, 1); 3075 2903 } else if (strlencmp(cmd, "disable") == 0) { 3076 - wan_set_radiosw(0); 2904 + wan_set_radiosw(0, 1); 3077 2905 } else 3078 2906 return -EINVAL; 3079 2907 } ··· 6340 6168 6341 6169 /* Probing */ 6342 6170 6343 - static void __init get_thinkpad_model_data(struct thinkpad_id_data *tp) 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) 6344 6176 { 6345 6177 const struct dmi_device *dev = NULL; 6346 6178 char ec_fw_string[18]; 6179 + char const *s; 6347 6180 6348 6181 if (!tp) 6349 - return; 6182 + return -EINVAL; 6350 6183 6351 6184 memset(tp, 0, sizeof(*tp)); 6352 6185 ··· 6360 6183 else if (dmi_name_in_vendors("LENOVO")) 6361 6184 tp->vendor = PCI_VENDOR_ID_LENOVO; 6362 6185 else 6363 - return; 6186 + return 0; 6364 6187 6365 - tp->bios_version_str = kstrdup(dmi_get_system_info(DMI_BIOS_VERSION), 6366 - GFP_KERNEL); 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; 6367 6192 if (!tp->bios_version_str) 6368 - return; 6193 + return 0; 6369 6194 tp->bios_model = tp->bios_version_str[0] 6370 6195 | (tp->bios_version_str[1] << 8); 6371 6196 ··· 6386 6207 ec_fw_string[strcspn(ec_fw_string, " ]")] = 0; 6387 6208 6388 6209 tp->ec_version_str = kstrdup(ec_fw_string, GFP_KERNEL); 6210 + if (!tp->ec_version_str) 6211 + return -ENOMEM; 6389 6212 tp->ec_model = ec_fw_string[0] 6390 6213 | (ec_fw_string[1] << 8); 6391 6214 break; 6392 6215 } 6393 6216 } 6394 6217 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; 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; 6400 6223 } 6401 6224 6402 - tp->nummodel_str = kstrdup(dmi_get_system_info(DMI_PRODUCT_NAME), 6403 - GFP_KERNEL); 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; 6404 6231 } 6405 6232 6406 6233 static int __init probe_for_thinkpad(void) ··· 6669 6484 6670 6485 /* Driver-level probe */ 6671 6486 6672 - get_thinkpad_model_data(&thinkpad_id); 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 + } 6673 6494 ret = probe_for_thinkpad(); 6674 6495 if (ret) { 6675 6496 thinkpad_acpi_module_exit();