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

Merge tag 'platform-drivers-x86-v4.2-3' of git://git.infradead.org/users/dvhart/linux-platform-drivers-x86

Pull x86 platform driver fixes from Darren Hart:
"Fix SMBIOS call handling and hwswitch state coherency in the
dell-laptop driver. Cleanups for intel_*_ipc drivers. Details:

dell-laptop:
- Do not cache hwswitch state
- Check return value of each SMBIOS call
- Clear buffer before each SMBIOS call

intel_scu_ipc:
- Move local memory initialization out of a mutex

intel_pmc_ipc:
- Update kerneldoc formatting
- Fix compiler casting warnings"

* tag 'platform-drivers-x86-v4.2-3' of git://git.infradead.org/users/dvhart/linux-platform-drivers-x86:
intel_scu_ipc: move local memory initialization out of a mutex
intel_pmc_ipc: Update kerneldoc formatting
dell-laptop: Do not cache hwswitch state
dell-laptop: Check return value of each SMBIOS call
dell-laptop: Clear buffer before each SMBIOS call
intel_pmc_ipc: Fix compiler casting warnings

+176 -111
-27
arch/x86/include/asm/intel_pmc_ipc.h
··· 25 25 26 26 #if IS_ENABLED(CONFIG_INTEL_PMC_IPC) 27 27 28 - /* 29 - * intel_pmc_ipc_simple_command 30 - * @cmd: command 31 - * @sub: sub type 32 - */ 33 28 int intel_pmc_ipc_simple_command(int cmd, int sub); 34 - 35 - /* 36 - * intel_pmc_ipc_raw_cmd 37 - * @cmd: command 38 - * @sub: sub type 39 - * @in: input data 40 - * @inlen: input length in bytes 41 - * @out: output data 42 - * @outlen: output length in dwords 43 - * @sptr: data writing to SPTR register 44 - * @dptr: data writing to DPTR register 45 - */ 46 29 int intel_pmc_ipc_raw_cmd(u32 cmd, u32 sub, u8 *in, u32 inlen, 47 30 u32 *out, u32 outlen, u32 dptr, u32 sptr); 48 - 49 - /* 50 - * intel_pmc_ipc_command 51 - * @cmd: command 52 - * @sub: sub type 53 - * @in: input data 54 - * @inlen: input length in bytes 55 - * @out: output data 56 - * @outlen: output length in dwords 57 - */ 58 31 int intel_pmc_ipc_command(u32 cmd, u32 sub, u8 *in, u32 inlen, 59 32 u32 *out, u32 outlen); 60 33
+125 -46
drivers/platform/x86/dell-laptop.c
··· 309 309 static struct calling_interface_buffer *buffer; 310 310 static DEFINE_MUTEX(buffer_mutex); 311 311 312 - static int hwswitch_state; 312 + static void clear_buffer(void) 313 + { 314 + memset(buffer, 0, sizeof(struct calling_interface_buffer)); 315 + } 313 316 314 317 static void get_buffer(void) 315 318 { 316 319 mutex_lock(&buffer_mutex); 317 - memset(buffer, 0, sizeof(struct calling_interface_buffer)); 320 + clear_buffer(); 318 321 } 319 322 320 323 static void release_buffer(void) ··· 551 548 int disable = blocked ? 1 : 0; 552 549 unsigned long radio = (unsigned long)data; 553 550 int hwswitch_bit = (unsigned long)data - 1; 551 + int hwswitch; 552 + int status; 553 + int ret; 554 554 555 555 get_buffer(); 556 + 556 557 dell_send_request(buffer, 17, 11); 558 + ret = buffer->output[0]; 559 + status = buffer->output[1]; 560 + 561 + if (ret != 0) 562 + goto out; 563 + 564 + clear_buffer(); 565 + 566 + buffer->input[0] = 0x2; 567 + dell_send_request(buffer, 17, 11); 568 + ret = buffer->output[0]; 569 + hwswitch = buffer->output[1]; 557 570 558 571 /* If the hardware switch controls this radio, and the hardware 559 572 switch is disabled, always disable the radio */ 560 - if ((hwswitch_state & BIT(hwswitch_bit)) && 561 - !(buffer->output[1] & BIT(16))) 573 + if (ret == 0 && (hwswitch & BIT(hwswitch_bit)) && 574 + (status & BIT(0)) && !(status & BIT(16))) 562 575 disable = 1; 576 + 577 + clear_buffer(); 563 578 564 579 buffer->input[0] = (1 | (radio<<8) | (disable << 16)); 565 580 dell_send_request(buffer, 17, 11); 581 + ret = buffer->output[0]; 566 582 583 + out: 567 584 release_buffer(); 568 - return 0; 585 + return dell_smi_error(ret); 569 586 } 570 587 571 588 /* Must be called with the buffer held */ ··· 595 572 if (status & BIT(0)) { 596 573 /* Has hw-switch, sync sw_state to BIOS */ 597 574 int block = rfkill_blocked(rfkill); 575 + clear_buffer(); 598 576 buffer->input[0] = (1 | (radio << 8) | (block << 16)); 599 577 dell_send_request(buffer, 17, 11); 600 578 } else { ··· 605 581 } 606 582 607 583 static void dell_rfkill_update_hw_state(struct rfkill *rfkill, int radio, 608 - int status) 584 + int status, int hwswitch) 609 585 { 610 - if (hwswitch_state & (BIT(radio - 1))) 586 + if (hwswitch & (BIT(radio - 1))) 611 587 rfkill_set_hw_state(rfkill, !(status & BIT(16))); 612 588 } 613 589 614 590 static void dell_rfkill_query(struct rfkill *rfkill, void *data) 615 591 { 592 + int radio = ((unsigned long)data & 0xF); 593 + int hwswitch; 616 594 int status; 595 + int ret; 617 596 618 597 get_buffer(); 598 + 619 599 dell_send_request(buffer, 17, 11); 600 + ret = buffer->output[0]; 620 601 status = buffer->output[1]; 621 602 622 - dell_rfkill_update_hw_state(rfkill, (unsigned long)data, status); 603 + if (ret != 0 || !(status & BIT(0))) { 604 + release_buffer(); 605 + return; 606 + } 607 + 608 + clear_buffer(); 609 + 610 + buffer->input[0] = 0x2; 611 + dell_send_request(buffer, 17, 11); 612 + ret = buffer->output[0]; 613 + hwswitch = buffer->output[1]; 623 614 624 615 release_buffer(); 616 + 617 + if (ret != 0) 618 + return; 619 + 620 + dell_rfkill_update_hw_state(rfkill, radio, status, hwswitch); 625 621 } 626 622 627 623 static const struct rfkill_ops dell_rfkill_ops = { ··· 653 609 654 610 static int dell_debugfs_show(struct seq_file *s, void *data) 655 611 { 612 + int hwswitch_state; 613 + int hwswitch_ret; 656 614 int status; 615 + int ret; 657 616 658 617 get_buffer(); 618 + 659 619 dell_send_request(buffer, 17, 11); 620 + ret = buffer->output[0]; 660 621 status = buffer->output[1]; 622 + 623 + clear_buffer(); 624 + 625 + buffer->input[0] = 0x2; 626 + dell_send_request(buffer, 17, 11); 627 + hwswitch_ret = buffer->output[0]; 628 + hwswitch_state = buffer->output[1]; 629 + 661 630 release_buffer(); 662 631 632 + seq_printf(s, "return:\t%d\n", ret); 663 633 seq_printf(s, "status:\t0x%X\n", status); 664 634 seq_printf(s, "Bit 0 : Hardware switch supported: %lu\n", 665 635 status & BIT(0)); ··· 715 657 seq_printf(s, "Bit 21: WiGig is blocked: %lu\n", 716 658 (status & BIT(21)) >> 21); 717 659 718 - seq_printf(s, "\nhwswitch_state:\t0x%X\n", hwswitch_state); 660 + seq_printf(s, "\nhwswitch_return:\t%d\n", hwswitch_ret); 661 + seq_printf(s, "hwswitch_state:\t0x%X\n", hwswitch_state); 719 662 seq_printf(s, "Bit 0 : Wifi controlled by switch: %lu\n", 720 663 hwswitch_state & BIT(0)); 721 664 seq_printf(s, "Bit 1 : Bluetooth controlled by switch: %lu\n", ··· 752 693 753 694 static void dell_update_rfkill(struct work_struct *ignored) 754 695 { 696 + int hwswitch = 0; 755 697 int status; 698 + int ret; 756 699 757 700 get_buffer(); 701 + 758 702 dell_send_request(buffer, 17, 11); 703 + ret = buffer->output[0]; 759 704 status = buffer->output[1]; 760 705 706 + if (ret != 0) 707 + goto out; 708 + 709 + clear_buffer(); 710 + 711 + buffer->input[0] = 0x2; 712 + dell_send_request(buffer, 17, 11); 713 + ret = buffer->output[0]; 714 + 715 + if (ret == 0 && (status & BIT(0))) 716 + hwswitch = buffer->output[1]; 717 + 761 718 if (wifi_rfkill) { 762 - dell_rfkill_update_hw_state(wifi_rfkill, 1, status); 719 + dell_rfkill_update_hw_state(wifi_rfkill, 1, status, hwswitch); 763 720 dell_rfkill_update_sw_state(wifi_rfkill, 1, status); 764 721 } 765 722 if (bluetooth_rfkill) { 766 - dell_rfkill_update_hw_state(bluetooth_rfkill, 2, status); 723 + dell_rfkill_update_hw_state(bluetooth_rfkill, 2, status, 724 + hwswitch); 767 725 dell_rfkill_update_sw_state(bluetooth_rfkill, 2, status); 768 726 } 769 727 if (wwan_rfkill) { 770 - dell_rfkill_update_hw_state(wwan_rfkill, 3, status); 728 + dell_rfkill_update_hw_state(wwan_rfkill, 3, status, hwswitch); 771 729 dell_rfkill_update_sw_state(wwan_rfkill, 3, status); 772 730 } 773 731 732 + out: 774 733 release_buffer(); 775 734 } 776 735 static DECLARE_DELAYED_WORK(dell_rfkill_work, dell_update_rfkill); ··· 850 773 851 774 get_buffer(); 852 775 dell_send_request(buffer, 17, 11); 776 + ret = buffer->output[0]; 853 777 status = buffer->output[1]; 854 - buffer->input[0] = 0x2; 855 - dell_send_request(buffer, 17, 11); 856 - hwswitch_state = buffer->output[1]; 857 778 release_buffer(); 858 779 859 - if (!(status & BIT(0))) { 860 - if (force_rfkill) { 861 - /* No hwsitch, clear all hw-controlled bits */ 862 - hwswitch_state &= ~7; 863 - } else { 864 - /* rfkill is only tested on laptops with a hwswitch */ 865 - return 0; 866 - } 867 - } 780 + /* dell wireless info smbios call is not supported */ 781 + if (ret != 0) 782 + return 0; 783 + 784 + /* rfkill is only tested on laptops with a hwswitch */ 785 + if (!(status & BIT(0)) && !force_rfkill) 786 + return 0; 868 787 869 788 if ((status & (1<<2|1<<8)) == (1<<2|1<<8)) { 870 789 wifi_rfkill = rfkill_alloc("dell-wifi", &platform_device->dev, ··· 1005 932 1006 933 static int dell_send_intensity(struct backlight_device *bd) 1007 934 { 1008 - int ret = 0; 935 + int token; 936 + int ret; 937 + 938 + token = find_token_location(BRIGHTNESS_TOKEN); 939 + if (token == -1) 940 + return -ENODEV; 1009 941 1010 942 get_buffer(); 1011 - buffer->input[0] = find_token_location(BRIGHTNESS_TOKEN); 943 + buffer->input[0] = token; 1012 944 buffer->input[1] = bd->props.brightness; 1013 - 1014 - if (buffer->input[0] == -1) { 1015 - ret = -ENODEV; 1016 - goto out; 1017 - } 1018 945 1019 946 if (power_supply_is_system_supplied() > 0) 1020 947 dell_send_request(buffer, 1, 2); 1021 948 else 1022 949 dell_send_request(buffer, 1, 1); 1023 950 1024 - out: 951 + ret = dell_smi_error(buffer->output[0]); 952 + 1025 953 release_buffer(); 1026 954 return ret; 1027 955 } 1028 956 1029 957 static int dell_get_intensity(struct backlight_device *bd) 1030 958 { 1031 - int ret = 0; 959 + int token; 960 + int ret; 961 + 962 + token = find_token_location(BRIGHTNESS_TOKEN); 963 + if (token == -1) 964 + return -ENODEV; 1032 965 1033 966 get_buffer(); 1034 - buffer->input[0] = find_token_location(BRIGHTNESS_TOKEN); 1035 - 1036 - if (buffer->input[0] == -1) { 1037 - ret = -ENODEV; 1038 - goto out; 1039 - } 967 + buffer->input[0] = token; 1040 968 1041 969 if (power_supply_is_system_supplied() > 0) 1042 970 dell_send_request(buffer, 0, 2); 1043 971 else 1044 972 dell_send_request(buffer, 0, 1); 1045 973 1046 - ret = buffer->output[1]; 974 + if (buffer->output[0]) 975 + ret = dell_smi_error(buffer->output[0]); 976 + else 977 + ret = buffer->output[1]; 1047 978 1048 - out: 1049 979 release_buffer(); 1050 980 return ret; 1051 981 } ··· 2112 2036 static int __init dell_init(void) 2113 2037 { 2114 2038 int max_intensity = 0; 2039 + int token; 2115 2040 int ret; 2116 2041 2117 2042 if (!dmi_check_system(dell_device_table)) ··· 2171 2094 if (acpi_video_get_backlight_type() != acpi_backlight_vendor) 2172 2095 return 0; 2173 2096 2174 - get_buffer(); 2175 - buffer->input[0] = find_token_location(BRIGHTNESS_TOKEN); 2176 - if (buffer->input[0] != -1) { 2097 + token = find_token_location(BRIGHTNESS_TOKEN); 2098 + if (token != -1) { 2099 + get_buffer(); 2100 + buffer->input[0] = token; 2177 2101 dell_send_request(buffer, 0, 2); 2178 - max_intensity = buffer->output[3]; 2102 + if (buffer->output[0] == 0) 2103 + max_intensity = buffer->output[3]; 2104 + release_buffer(); 2179 2105 } 2180 - release_buffer(); 2181 2106 2182 2107 if (max_intensity) { 2183 2108 struct backlight_properties props;
+48 -35
drivers/platform/x86/intel_pmc_ipc.c
··· 96 96 struct completion cmd_complete; 97 97 98 98 /* The following PMC BARs share the same ACPI device with the IPC */ 99 - void *acpi_io_base; 99 + resource_size_t acpi_io_base; 100 100 int acpi_io_size; 101 101 struct platform_device *tco_dev; 102 102 103 103 /* gcr */ 104 - void *gcr_base; 104 + resource_size_t gcr_base; 105 105 int gcr_size; 106 106 107 107 /* punit */ 108 - void *punit_base; 108 + resource_size_t punit_base; 109 109 int punit_size; 110 - void *punit_base2; 110 + resource_size_t punit_base2; 111 111 int punit_size2; 112 112 struct platform_device *punit_dev; 113 113 } ipcdev; ··· 210 210 return ret; 211 211 } 212 212 213 - /* 214 - * intel_pmc_ipc_simple_command 215 - * @cmd: command 216 - * @sub: sub type 213 + /** 214 + * intel_pmc_ipc_simple_command() - Simple IPC command 215 + * @cmd: IPC command code. 216 + * @sub: IPC command sub type. 217 + * 218 + * Send a simple IPC command to PMC when don't need to specify 219 + * input/output data and source/dest pointers. 220 + * 221 + * Return: an IPC error code or 0 on success. 217 222 */ 218 223 int intel_pmc_ipc_simple_command(int cmd, int sub) 219 224 { ··· 237 232 } 238 233 EXPORT_SYMBOL_GPL(intel_pmc_ipc_simple_command); 239 234 240 - /* 241 - * intel_pmc_ipc_raw_cmd 242 - * @cmd: command 243 - * @sub: sub type 244 - * @in: input data 245 - * @inlen: input length in bytes 246 - * @out: output data 247 - * @outlen: output length in dwords 248 - * @sptr: data writing to SPTR register 249 - * @dptr: data writing to DPTR register 235 + /** 236 + * intel_pmc_ipc_raw_cmd() - IPC command with data and pointers 237 + * @cmd: IPC command code. 238 + * @sub: IPC command sub type. 239 + * @in: input data of this IPC command. 240 + * @inlen: input data length in bytes. 241 + * @out: output data of this IPC command. 242 + * @outlen: output data length in dwords. 243 + * @sptr: data writing to SPTR register. 244 + * @dptr: data writing to DPTR register. 245 + * 246 + * Send an IPC command to PMC with input/output data and source/dest pointers. 247 + * 248 + * Return: an IPC error code or 0 on success. 250 249 */ 251 250 int intel_pmc_ipc_raw_cmd(u32 cmd, u32 sub, u8 *in, u32 inlen, u32 *out, 252 251 u32 outlen, u32 dptr, u32 sptr) ··· 287 278 } 288 279 EXPORT_SYMBOL_GPL(intel_pmc_ipc_raw_cmd); 289 280 290 - /* 291 - * intel_pmc_ipc_command 292 - * @cmd: command 293 - * @sub: sub type 294 - * @in: input data 295 - * @inlen: input length in bytes 296 - * @out: output data 297 - * @outlen: output length in dwords 281 + /** 282 + * intel_pmc_ipc_command() - IPC command with input/output data 283 + * @cmd: IPC command code. 284 + * @sub: IPC command sub type. 285 + * @in: input data of this IPC command. 286 + * @inlen: input data length in bytes. 287 + * @out: output data of this IPC command. 288 + * @outlen: output data length in dwords. 289 + * 290 + * Send an IPC command to PMC with input/output data. 291 + * 292 + * Return: an IPC error code or 0 on success. 298 293 */ 299 294 int intel_pmc_ipc_command(u32 cmd, u32 sub, u8 *in, u32 inlen, 300 295 u32 *out, u32 outlen) ··· 493 480 pdev->dev.parent = ipcdev.dev; 494 481 495 482 res = punit_res; 496 - res->start = (resource_size_t)ipcdev.punit_base; 483 + res->start = ipcdev.punit_base; 497 484 res->end = res->start + ipcdev.punit_size - 1; 498 485 499 486 res = punit_res + PUNIT_RESOURCE_INTER; 500 - res->start = (resource_size_t)ipcdev.punit_base2; 487 + res->start = ipcdev.punit_base2; 501 488 res->end = res->start + ipcdev.punit_size2 - 1; 502 489 503 490 ret = platform_device_add_resources(pdev, punit_res, ··· 535 522 pdev->dev.parent = ipcdev.dev; 536 523 537 524 res = tco_res + TCO_RESOURCE_ACPI_IO; 538 - res->start = (resource_size_t)ipcdev.acpi_io_base + TCO_BASE_OFFSET; 525 + res->start = ipcdev.acpi_io_base + TCO_BASE_OFFSET; 539 526 res->end = res->start + TCO_REGS_SIZE - 1; 540 527 541 528 res = tco_res + TCO_RESOURCE_SMI_EN_IO; 542 - res->start = (resource_size_t)ipcdev.acpi_io_base + SMI_EN_OFFSET; 529 + res->start = ipcdev.acpi_io_base + SMI_EN_OFFSET; 543 530 res->end = res->start + SMI_EN_SIZE - 1; 544 531 545 532 res = tco_res + TCO_RESOURCE_GCR_MEM; 546 - res->start = (resource_size_t)ipcdev.gcr_base; 533 + res->start = ipcdev.gcr_base; 547 534 res->end = res->start + ipcdev.gcr_size - 1; 548 535 549 536 ret = platform_device_add_resources(pdev, tco_res, ARRAY_SIZE(tco_res)); ··· 602 589 return -ENXIO; 603 590 } 604 591 size = resource_size(res); 605 - ipcdev.acpi_io_base = (void *)res->start; 592 + ipcdev.acpi_io_base = res->start; 606 593 ipcdev.acpi_io_size = size; 607 594 dev_info(&pdev->dev, "io res: %llx %x\n", 608 595 (long long)res->start, (int)resource_size(res)); ··· 614 601 return -ENXIO; 615 602 } 616 603 size = resource_size(res); 617 - ipcdev.punit_base = (void *)res->start; 604 + ipcdev.punit_base = res->start; 618 605 ipcdev.punit_size = size; 619 606 dev_info(&pdev->dev, "punit data res: %llx %x\n", 620 607 (long long)res->start, (int)resource_size(res)); ··· 626 613 return -ENXIO; 627 614 } 628 615 size = resource_size(res); 629 - ipcdev.punit_base2 = (void *)res->start; 616 + ipcdev.punit_base2 = res->start; 630 617 ipcdev.punit_size2 = size; 631 618 dev_info(&pdev->dev, "punit interface res: %llx %x\n", 632 619 (long long)res->start, (int)resource_size(res)); ··· 650 637 } 651 638 ipcdev.ipc_base = addr; 652 639 653 - ipcdev.gcr_base = (void *)(res->start + size); 640 + ipcdev.gcr_base = res->start + size; 654 641 ipcdev.gcr_size = PLAT_RESOURCE_GCR_SIZE; 655 642 dev_info(&pdev->dev, "ipc res: %llx %x\n", 656 643 (long long)res->start, (int)resource_size(res));
+3 -3
drivers/platform/x86/intel_scu_ipc.c
··· 216 216 int nc; 217 217 u32 offset = 0; 218 218 int err; 219 - u8 cbuf[IPC_WWBUF_SIZE] = { }; 219 + u8 cbuf[IPC_WWBUF_SIZE]; 220 220 u32 *wbuf = (u32 *)&cbuf; 221 221 222 - mutex_lock(&ipclock); 223 - 224 222 memset(cbuf, 0, sizeof(cbuf)); 223 + 224 + mutex_lock(&ipclock); 225 225 226 226 if (ipcdev.pdev == NULL) { 227 227 mutex_unlock(&ipclock);