diff mbox series

ideapad-laptop incorrectly sets RF-kill block on initialization

Message ID CAJ4FQ9A=Xcom1d0fWVw+dRLX+yKAg3ACeXW=LgQEo9W-D7EfrQ@mail.gmail.com (mailing list archive)
State Changes Requested, archived
Headers show
Series ideapad-laptop incorrectly sets RF-kill block on initialization | expand

Commit Message

Ambrož Bizjak March 17, 2021, 8:39 p.m. UTC
Hi,

I have found an issue in the ideapad-laptop driver which causes WiFi
to not work on the Lenovo Legion Y720 laptop. It seems the issue is
generally present on this laptop as can be found by googling and
finding that the workaround is to blacklist ideapad-laptop.

In the code comment here:
https://github.com/torvalds/linux/blob/1df27313f50a57497c1faeb6a6ae4ca939c85a7d/drivers/platform/x86/ideapad-laptop.c#L1462
it is explained that the driver has a list of devices which are known
to have an RF-kill switch and for other devices it assumes that it
does not have one. Since the list is in fact empty, one would conclude
that the driver should never cause an RF-kill block. However on this
laptop loading the driver has this exact effect.

The reason is what seems to be a bug here:
https://github.com/torvalds/linux/blob/1df27313f50a57497c1faeb6a6ae4ca939c85a7d/drivers/platform/x86/ideapad-laptop.c#L1001
At initialization, ideapad_register_rfkill() sets the initial RF-kill
block state based on reading the state of the possibly nonexisting
RF-kill switch without considering priv->features.hw_rfkill_switch.
This is inconsistent with ideapad_sync_rfk_state() which sets
unblocked if hw_rfkill_switch is false. The result is that
ideapad_register_rfkill() would block but ideapad_sync_rfk_state()
would unblock as soon as it is called. But on my laptop
ideapad_sync_rfk_state() is presumably never called and the blocked
state persists indefinitely. I have verified this by changing
ideapad_register_rfkill() to use the same logic as
ideapad_sync_rfk_state() which has fixed the problem.

I am attaching a patch for master and 5.4, I have only tested the latter.

Comments

Barnabás Pőcze March 17, 2021, 9:11 p.m. UTC | #1
Hi

> I have found an issue in the ideapad-laptop driver which causes WiFi
> to not work on the Lenovo Legion Y720 laptop. It seems the issue is
> generally present on this laptop as can be found by googling and
> finding that the workaround is to blacklist ideapad-laptop.
>
> In the code comment here:
> https://github.com/torvalds/linux/blob/1df27313f50a57497c1faeb6a6ae4ca939c85a7d/drivers/platform/x86/ideapad-laptop.c#L1462
> it is explained that the driver has a list of devices which are known
> to have an RF-kill switch and for other devices it assumes that it
> does not have one. Since the list is in fact empty, one would conclude
> that the driver should never cause an RF-kill block. However on this
> laptop loading the driver has this exact effect.
>
> The reason is what seems to be a bug here:
> https://github.com/torvalds/linux/blob/1df27313f50a57497c1faeb6a6ae4ca939c85a7d/drivers/platform/x86/ideapad-laptop.c#L1001
> At initialization, ideapad_register_rfkill() sets the initial RF-kill
> block state based on reading the state of the possibly nonexisting
> RF-kill switch without considering priv->features.hw_rfkill_switch.

Note, that there are two distinct things at play here: hard and soft blocking.
The part of the code you're referring to here is concerned about the soft blocking
state. Therefore it makes sense that it does not consider the value of
features.hw_rfkill_switch.


> This is inconsistent with ideapad_sync_rfk_state() which sets
> unblocked if hw_rfkill_switch is false. The result is that
> ideapad_register_rfkill() would block but ideapad_sync_rfk_state()
> would unblock as soon as it is called. But on my laptop
> ideapad_sync_rfk_state() is presumably never called and the blocked
> state persists indefinitely. I have verified this by changing
> ideapad_register_rfkill() to use the same logic as
> ideapad_sync_rfk_state() which has fixed the problem.
>
> I am attaching a patch for master and 5.4, I have only tested the latter.
>

It seems from those patches that simply reading from that address causes
wifi not to work. Could you please add some printing to the driver without the patches
to check the value of sw_blocked? (e.g. pr_info("sw_blocked = %lu\n", sw_blocked); )
And also attach the output of the `rfkill` utility after the module loads
and wifi does not work?


Regards,
Barnabás Pőcze
diff mbox series

Patch

diff -urN linux-5.4.104.orig/drivers/platform/x86/ideapad-laptop.c linux-5.4.104/drivers/platform/x86/ideapad-laptop.c
--- linux-5.4.104.orig/drivers/platform/x86/ideapad-laptop.c	2021-03-16 19:02:12.126383099 +0100
+++ linux-5.4.104/drivers/platform/x86/ideapad-laptop.c	2021-03-16 19:07:04.380961129 +0100
@@ -616,7 +616,8 @@ 
 	if (!priv->rfk[dev])
 		return -ENOMEM;
 
-	if (read_ec_data(priv->adev->handle, ideapad_rfk_data[dev].opcode-1,
+	if (!priv->has_hw_rfkill_switch ||
+            read_ec_data(priv->adev->handle, ideapad_rfk_data[dev].opcode-1,
 			 &sw_blocked)) {
 		rfkill_init_sw_state(priv->rfk[dev], 0);
 	} else {