Skip to content

Commit 3e87ee0

Browse files
committed
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
2 parents f85c712 + 8642d7f commit 3e87ee0

File tree

4 files changed

+176
-111
lines changed

4 files changed

+176
-111
lines changed

arch/x86/include/asm/intel_pmc_ipc.h

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -25,36 +25,9 @@
2525

2626
#if IS_ENABLED(CONFIG_INTEL_PMC_IPC)
2727

28-
/*
29-
* intel_pmc_ipc_simple_command
30-
* @cmd: command
31-
* @sub: sub type
32-
*/
3328
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-
*/
4629
int intel_pmc_ipc_raw_cmd(u32 cmd, u32 sub, u8 *in, u32 inlen,
4730
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-
*/
5831
int intel_pmc_ipc_command(u32 cmd, u32 sub, u8 *in, u32 inlen,
5932
u32 *out, u32 outlen);
6033

drivers/platform/x86/dell-laptop.c

Lines changed: 125 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -309,12 +309,15 @@ static const struct dmi_system_id dell_quirks[] __initconst = {
309309
static struct calling_interface_buffer *buffer;
310310
static DEFINE_MUTEX(buffer_mutex);
311311

312-
static int hwswitch_state;
312+
static void clear_buffer(void)
313+
{
314+
memset(buffer, 0, sizeof(struct calling_interface_buffer));
315+
}
313316

314317
static void get_buffer(void)
315318
{
316319
mutex_lock(&buffer_mutex);
317-
memset(buffer, 0, sizeof(struct calling_interface_buffer));
320+
clear_buffer();
318321
}
319322

320323
static void release_buffer(void)
@@ -548,21 +551,41 @@ static int dell_rfkill_set(void *data, bool blocked)
548551
int disable = blocked ? 1 : 0;
549552
unsigned long radio = (unsigned long)data;
550553
int hwswitch_bit = (unsigned long)data - 1;
554+
int hwswitch;
555+
int status;
556+
int ret;
551557

552558
get_buffer();
559+
560+
dell_send_request(buffer, 17, 11);
561+
ret = buffer->output[0];
562+
status = buffer->output[1];
563+
564+
if (ret != 0)
565+
goto out;
566+
567+
clear_buffer();
568+
569+
buffer->input[0] = 0x2;
553570
dell_send_request(buffer, 17, 11);
571+
ret = buffer->output[0];
572+
hwswitch = buffer->output[1];
554573

555574
/* If the hardware switch controls this radio, and the hardware
556575
switch is disabled, always disable the radio */
557-
if ((hwswitch_state & BIT(hwswitch_bit)) &&
558-
!(buffer->output[1] & BIT(16)))
576+
if (ret == 0 && (hwswitch & BIT(hwswitch_bit)) &&
577+
(status & BIT(0)) && !(status & BIT(16)))
559578
disable = 1;
560579

580+
clear_buffer();
581+
561582
buffer->input[0] = (1 | (radio<<8) | (disable << 16));
562583
dell_send_request(buffer, 17, 11);
584+
ret = buffer->output[0];
563585

586+
out:
564587
release_buffer();
565-
return 0;
588+
return dell_smi_error(ret);
566589
}
567590

568591
/* Must be called with the buffer held */
@@ -572,6 +595,7 @@ static void dell_rfkill_update_sw_state(struct rfkill *rfkill, int radio,
572595
if (status & BIT(0)) {
573596
/* Has hw-switch, sync sw_state to BIOS */
574597
int block = rfkill_blocked(rfkill);
598+
clear_buffer();
575599
buffer->input[0] = (1 | (radio << 8) | (block << 16));
576600
dell_send_request(buffer, 17, 11);
577601
} else {
@@ -581,23 +605,43 @@ static void dell_rfkill_update_sw_state(struct rfkill *rfkill, int radio,
581605
}
582606

583607
static void dell_rfkill_update_hw_state(struct rfkill *rfkill, int radio,
584-
int status)
608+
int status, int hwswitch)
585609
{
586-
if (hwswitch_state & (BIT(radio - 1)))
610+
if (hwswitch & (BIT(radio - 1)))
587611
rfkill_set_hw_state(rfkill, !(status & BIT(16)));
588612
}
589613

590614
static void dell_rfkill_query(struct rfkill *rfkill, void *data)
591615
{
616+
int radio = ((unsigned long)data & 0xF);
617+
int hwswitch;
592618
int status;
619+
int ret;
593620

594621
get_buffer();
622+
595623
dell_send_request(buffer, 17, 11);
624+
ret = buffer->output[0];
596625
status = buffer->output[1];
597626

598-
dell_rfkill_update_hw_state(rfkill, (unsigned long)data, status);
627+
if (ret != 0 || !(status & BIT(0))) {
628+
release_buffer();
629+
return;
630+
}
631+
632+
clear_buffer();
633+
634+
buffer->input[0] = 0x2;
635+
dell_send_request(buffer, 17, 11);
636+
ret = buffer->output[0];
637+
hwswitch = buffer->output[1];
599638

600639
release_buffer();
640+
641+
if (ret != 0)
642+
return;
643+
644+
dell_rfkill_update_hw_state(rfkill, radio, status, hwswitch);
601645
}
602646

603647
static const struct rfkill_ops dell_rfkill_ops = {
@@ -609,13 +653,27 @@ static struct dentry *dell_laptop_dir;
609653

610654
static int dell_debugfs_show(struct seq_file *s, void *data)
611655
{
656+
int hwswitch_state;
657+
int hwswitch_ret;
612658
int status;
659+
int ret;
613660

614661
get_buffer();
662+
615663
dell_send_request(buffer, 17, 11);
664+
ret = buffer->output[0];
616665
status = buffer->output[1];
666+
667+
clear_buffer();
668+
669+
buffer->input[0] = 0x2;
670+
dell_send_request(buffer, 17, 11);
671+
hwswitch_ret = buffer->output[0];
672+
hwswitch_state = buffer->output[1];
673+
617674
release_buffer();
618675

676+
seq_printf(s, "return:\t%d\n", ret);
619677
seq_printf(s, "status:\t0x%X\n", status);
620678
seq_printf(s, "Bit 0 : Hardware switch supported: %lu\n",
621679
status & BIT(0));
@@ -657,7 +715,8 @@ static int dell_debugfs_show(struct seq_file *s, void *data)
657715
seq_printf(s, "Bit 21: WiGig is blocked: %lu\n",
658716
(status & BIT(21)) >> 21);
659717

660-
seq_printf(s, "\nhwswitch_state:\t0x%X\n", hwswitch_state);
718+
seq_printf(s, "\nhwswitch_return:\t%d\n", hwswitch_ret);
719+
seq_printf(s, "hwswitch_state:\t0x%X\n", hwswitch_state);
661720
seq_printf(s, "Bit 0 : Wifi controlled by switch: %lu\n",
662721
hwswitch_state & BIT(0));
663722
seq_printf(s, "Bit 1 : Bluetooth controlled by switch: %lu\n",
@@ -693,25 +752,43 @@ static const struct file_operations dell_debugfs_fops = {
693752

694753
static void dell_update_rfkill(struct work_struct *ignored)
695754
{
755+
int hwswitch = 0;
696756
int status;
757+
int ret;
697758

698759
get_buffer();
760+
699761
dell_send_request(buffer, 17, 11);
762+
ret = buffer->output[0];
700763
status = buffer->output[1];
701764

765+
if (ret != 0)
766+
goto out;
767+
768+
clear_buffer();
769+
770+
buffer->input[0] = 0x2;
771+
dell_send_request(buffer, 17, 11);
772+
ret = buffer->output[0];
773+
774+
if (ret == 0 && (status & BIT(0)))
775+
hwswitch = buffer->output[1];
776+
702777
if (wifi_rfkill) {
703-
dell_rfkill_update_hw_state(wifi_rfkill, 1, status);
778+
dell_rfkill_update_hw_state(wifi_rfkill, 1, status, hwswitch);
704779
dell_rfkill_update_sw_state(wifi_rfkill, 1, status);
705780
}
706781
if (bluetooth_rfkill) {
707-
dell_rfkill_update_hw_state(bluetooth_rfkill, 2, status);
782+
dell_rfkill_update_hw_state(bluetooth_rfkill, 2, status,
783+
hwswitch);
708784
dell_rfkill_update_sw_state(bluetooth_rfkill, 2, status);
709785
}
710786
if (wwan_rfkill) {
711-
dell_rfkill_update_hw_state(wwan_rfkill, 3, status);
787+
dell_rfkill_update_hw_state(wwan_rfkill, 3, status, hwswitch);
712788
dell_rfkill_update_sw_state(wwan_rfkill, 3, status);
713789
}
714790

791+
out:
715792
release_buffer();
716793
}
717794
static DECLARE_DELAYED_WORK(dell_rfkill_work, dell_update_rfkill);
@@ -773,21 +850,17 @@ static int __init dell_setup_rfkill(void)
773850

774851
get_buffer();
775852
dell_send_request(buffer, 17, 11);
853+
ret = buffer->output[0];
776854
status = buffer->output[1];
777-
buffer->input[0] = 0x2;
778-
dell_send_request(buffer, 17, 11);
779-
hwswitch_state = buffer->output[1];
780855
release_buffer();
781856

782-
if (!(status & BIT(0))) {
783-
if (force_rfkill) {
784-
/* No hwsitch, clear all hw-controlled bits */
785-
hwswitch_state &= ~7;
786-
} else {
787-
/* rfkill is only tested on laptops with a hwswitch */
788-
return 0;
789-
}
790-
}
857+
/* dell wireless info smbios call is not supported */
858+
if (ret != 0)
859+
return 0;
860+
861+
/* rfkill is only tested on laptops with a hwswitch */
862+
if (!(status & BIT(0)) && !force_rfkill)
863+
return 0;
791864

792865
if ((status & (1<<2|1<<8)) == (1<<2|1<<8)) {
793866
wifi_rfkill = rfkill_alloc("dell-wifi", &platform_device->dev,
@@ -932,47 +1005,50 @@ static void dell_cleanup_rfkill(void)
9321005

9331006
static int dell_send_intensity(struct backlight_device *bd)
9341007
{
935-
int ret = 0;
1008+
int token;
1009+
int ret;
1010+
1011+
token = find_token_location(BRIGHTNESS_TOKEN);
1012+
if (token == -1)
1013+
return -ENODEV;
9361014

9371015
get_buffer();
938-
buffer->input[0] = find_token_location(BRIGHTNESS_TOKEN);
1016+
buffer->input[0] = token;
9391017
buffer->input[1] = bd->props.brightness;
9401018

941-
if (buffer->input[0] == -1) {
942-
ret = -ENODEV;
943-
goto out;
944-
}
945-
9461019
if (power_supply_is_system_supplied() > 0)
9471020
dell_send_request(buffer, 1, 2);
9481021
else
9491022
dell_send_request(buffer, 1, 1);
9501023

951-
out:
1024+
ret = dell_smi_error(buffer->output[0]);
1025+
9521026
release_buffer();
9531027
return ret;
9541028
}
9551029

9561030
static int dell_get_intensity(struct backlight_device *bd)
9571031
{
958-
int ret = 0;
1032+
int token;
1033+
int ret;
9591034

960-
get_buffer();
961-
buffer->input[0] = find_token_location(BRIGHTNESS_TOKEN);
1035+
token = find_token_location(BRIGHTNESS_TOKEN);
1036+
if (token == -1)
1037+
return -ENODEV;
9621038

963-
if (buffer->input[0] == -1) {
964-
ret = -ENODEV;
965-
goto out;
966-
}
1039+
get_buffer();
1040+
buffer->input[0] = token;
9671041

9681042
if (power_supply_is_system_supplied() > 0)
9691043
dell_send_request(buffer, 0, 2);
9701044
else
9711045
dell_send_request(buffer, 0, 1);
9721046

973-
ret = buffer->output[1];
1047+
if (buffer->output[0])
1048+
ret = dell_smi_error(buffer->output[0]);
1049+
else
1050+
ret = buffer->output[1];
9741051

975-
out:
9761052
release_buffer();
9771053
return ret;
9781054
}
@@ -2036,6 +2112,7 @@ static void kbd_led_exit(void)
20362112
static int __init dell_init(void)
20372113
{
20382114
int max_intensity = 0;
2115+
int token;
20392116
int ret;
20402117

20412118
if (!dmi_check_system(dell_device_table))
@@ -2094,13 +2171,15 @@ static int __init dell_init(void)
20942171
if (acpi_video_get_backlight_type() != acpi_backlight_vendor)
20952172
return 0;
20962173

2097-
get_buffer();
2098-
buffer->input[0] = find_token_location(BRIGHTNESS_TOKEN);
2099-
if (buffer->input[0] != -1) {
2174+
token = find_token_location(BRIGHTNESS_TOKEN);
2175+
if (token != -1) {
2176+
get_buffer();
2177+
buffer->input[0] = token;
21002178
dell_send_request(buffer, 0, 2);
2101-
max_intensity = buffer->output[3];
2179+
if (buffer->output[0] == 0)
2180+
max_intensity = buffer->output[3];
2181+
release_buffer();
21022182
}
2103-
release_buffer();
21042183

21052184
if (max_intensity) {
21062185
struct backlight_properties props;

0 commit comments

Comments
 (0)