aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2014-06-23 10:45:51 -0400
committerMatthew Garrett <matthew.garrett@nebula.com>2014-08-16 04:23:50 -0400
commitce363c2bcb2303e7fad3a79398db739c6995141b (patch)
treee0af64ef67de1ad756bfddfbd391de23c77e25ba /drivers/platform
parent4beb81d12d7c386fac4abb1603db4bb79ea05e04 (diff)
ideapad-laptop: Change Lenovo Yoga 2 series rfkill handling
It seems that the same problems which lead to adding an rfkill blacklist and putting the Lenovo Yoga 2 11 on it are also present on the Lenovo Yoga 2 13 and Lenovo Yoga 2 Pro too: https://bugzilla.redhat.com/show_bug.cgi?id=1021036 https://forums.lenovo.com/t5/Linux-Discussion/Yoga-2-13-not-Pro-Linux-Warning/m-p/1517612 Testing has shown that the firmware rfkill settings are persistent over reboots. So blacklisting the driver is not good enough, if the wifi is blocked at the firmware level the wifi needs to be explictly unblocked through the ideapad-laptop interface. And at least on the Lenovo Yoga 2 13 the VPCCMD_RF register which on devices with hardware kill switch reports the hardware switch state, needs to be explictly set to 1 (radio enabled / not blocked). So this patch does 3 things to get proper rfkill handling on these models: 1) Instead of blacklisting the rfkill functionality, which means that people with a firmware blocked wifi get stuck in that situation, ignore the value reported by the not present hardware rfkill switch, as this is what is causing ideapad-laptop to wrongly report all radios as hardware blocks. But do register the rfkill interfaces so that the user can soft [un]block them. 2) On models without a hardware rfkill switch, explictly set VPCCMD_RF to 1 3) Drop the " 11" postfix from the dmi match string, as the entire Yoga 2 series is affected. Yoga 2 11: Reported-and-tested-by: Vincent Gerris <vgerris@gmail.com> Yoga 2 13: Tested-by: madls05 <http://ubuntuforums.org/showthread.php?t=2215044> Yoga 2 Pro: Reported-and-tested-by: Peter F. Patel-Schneider <pfpschneider@gmail.com> Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
Diffstat (limited to 'drivers/platform')
-rw-r--r--drivers/platform/x86/ideapad-laptop.c41
1 files changed, 27 insertions, 14 deletions
diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c
index b4c495a62eec..b0e3a2eef0ac 100644
--- a/drivers/platform/x86/ideapad-laptop.c
+++ b/drivers/platform/x86/ideapad-laptop.c
@@ -87,6 +87,7 @@ struct ideapad_private {
87 struct backlight_device *blightdev; 87 struct backlight_device *blightdev;
88 struct dentry *debug; 88 struct dentry *debug;
89 unsigned long cfg; 89 unsigned long cfg;
90 bool has_hw_rfkill_switch;
90}; 91};
91 92
92static bool no_bt_rfkill; 93static bool no_bt_rfkill;
@@ -473,12 +474,14 @@ static struct rfkill_ops ideapad_rfk_ops = {
473 474
474static void ideapad_sync_rfk_state(struct ideapad_private *priv) 475static void ideapad_sync_rfk_state(struct ideapad_private *priv)
475{ 476{
476 unsigned long hw_blocked; 477 unsigned long hw_blocked = 0;
477 int i; 478 int i;
478 479
479 if (read_ec_data(priv->adev->handle, VPCCMD_R_RF, &hw_blocked)) 480 if (priv->has_hw_rfkill_switch) {
480 return; 481 if (read_ec_data(priv->adev->handle, VPCCMD_R_RF, &hw_blocked))
481 hw_blocked = !hw_blocked; 482 return;
483 hw_blocked = !hw_blocked;
484 }
482 485
483 for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) 486 for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
484 if (priv->rfk[i]) 487 if (priv->rfk[i])
@@ -821,14 +824,17 @@ static void ideapad_acpi_notify(acpi_handle handle, u32 event, void *data)
821 } 824 }
822} 825}
823 826
824/* Blacklist for devices where the ideapad rfkill interface does not work */ 827/*
825static struct dmi_system_id rfkill_blacklist[] = { 828 * Some ideapads don't have a hardware rfkill switch, reading VPCCMD_R_RF
826 /* The Lenovo Yoga 2 11 always reports everything as blocked */ 829 * always results in 0 on these models, causing ideapad_laptop to wrongly
830 * report all radios as hardware-blocked.
831 */
832static struct dmi_system_id no_hw_rfkill_list[] = {
827 { 833 {
828 .ident = "Lenovo Yoga 2 11", 834 .ident = "Lenovo Yoga 2 11 / 13 / Pro",
829 .matches = { 835 .matches = {
830 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 836 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
831 DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Yoga 2 11"), 837 DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Yoga 2"),
832 }, 838 },
833 }, 839 },
834 {} 840 {}
@@ -856,6 +862,7 @@ static int ideapad_acpi_add(struct platform_device *pdev)
856 priv->cfg = cfg; 862 priv->cfg = cfg;
857 priv->adev = adev; 863 priv->adev = adev;
858 priv->platform_device = pdev; 864 priv->platform_device = pdev;
865 priv->has_hw_rfkill_switch = !dmi_check_system(no_hw_rfkill_list);
859 866
860 ret = ideapad_sysfs_init(priv); 867 ret = ideapad_sysfs_init(priv);
861 if (ret) 868 if (ret)
@@ -869,11 +876,17 @@ static int ideapad_acpi_add(struct platform_device *pdev)
869 if (ret) 876 if (ret)
870 goto input_failed; 877 goto input_failed;
871 878
872 if (!dmi_check_system(rfkill_blacklist)) { 879 /*
873 for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) 880 * On some models without a hw-switch (the yoga 2 13 at least)
874 if (test_bit(ideapad_rfk_data[i].cfgbit, &priv->cfg)) 881 * VPCCMD_W_RF must be explicitly set to 1 for the wifi to work.
875 ideapad_register_rfkill(priv, i); 882 */
876 } 883 if (!priv->has_hw_rfkill_switch)
884 write_ec_cmd(priv->adev->handle, VPCCMD_W_RF, 1);
885
886 for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
887 if (test_bit(ideapad_rfk_data[i].cfgbit, &priv->cfg))
888 ideapad_register_rfkill(priv, i);
889
877 ideapad_sync_rfk_state(priv); 890 ideapad_sync_rfk_state(priv);
878 ideapad_sync_touchpad_state(priv); 891 ideapad_sync_touchpad_state(priv);
879 892