Store the supported features in the driver private data, and modify the is_visible() callback to use it, and create ideapad_check_features() to populate it. Signed-off-by: Barnabás Pőcze <pobrn@xxxxxxxxxxxxxx> diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c index 795978e0d13e..d61710ad8803 100644 --- a/drivers/platform/x86/ideapad-laptop.c +++ b/drivers/platform/x86/ideapad-laptop.c @@ -104,8 +104,13 @@ struct ideapad_private { struct backlight_device *blightdev; struct dentry *debug; unsigned long cfg; - bool has_hw_rfkill_switch; const char *fnesc_guid; + struct { + bool fan_mode : 1, + conservation_mode : 1, + fn_lock : 1, + hw_rfkill_switch : 1; + } features; }; static bool no_bt_rfkill; @@ -543,22 +548,16 @@ static umode_t ideapad_is_visible(struct kobject *kobj, { struct device *dev = container_of(kobj, struct device, kobj); struct ideapad_private *priv = dev_get_drvdata(dev); - bool supported; + bool supported = true; if (attr == &dev_attr_camera_power.attr) supported = test_bit(CFG_CAP_CAM_BIT, &priv->cfg); - else if (attr == &dev_attr_fan_mode.attr) { - unsigned long value; - supported = !read_ec_data(priv->adev->handle, VPCCMD_R_FAN, - &value); - } else if (attr == &dev_attr_conservation_mode.attr) { - supported = acpi_has_method(priv->adev->handle, "GBMD") && - acpi_has_method(priv->adev->handle, "SBMC"); - } else if (attr == &dev_attr_fn_lock.attr) { - supported = acpi_has_method(priv->adev->handle, "HALS") && - acpi_has_method(priv->adev->handle, "SALS"); - } else - supported = true; + else if (attr == &dev_attr_fan_mode.attr) + supported = priv->features.fan_mode; + else if (attr == &dev_attr_conservation_mode.attr) + supported = priv->features.conservation_mode; + else if (attr == &dev_attr_fn_lock.attr) + supported = priv->features.fn_lock; return supported ? attr->mode : 0; } @@ -601,7 +600,7 @@ static void ideapad_sync_rfk_state(struct ideapad_private *priv) unsigned long hw_blocked = 0; int i; - if (priv->has_hw_rfkill_switch) { + if (priv->features.hw_rfkill_switch) { if (read_ec_data(priv->adev->handle, VPCCMD_R_RF, &hw_blocked)) return; hw_blocked = !hw_blocked; @@ -1001,6 +1000,23 @@ static const struct dmi_system_id hw_rfkill_list[] = { {} }; +static void ideapad_check_features(struct ideapad_private *priv) +{ + acpi_handle handle = priv->adev->handle; + unsigned long val; + + priv->features.hw_rfkill_switch = dmi_check_system(hw_rfkill_list); + + if (!read_ec_data(handle, VPCCMD_R_FAN, &val)) + priv->features.fan_mode = true; + + if (acpi_has_method(handle, "GBMD") && acpi_has_method(handle, "SBMC")) + priv->features.conservation_mode = true; + + if (acpi_has_method(handle, "HALS") && acpi_has_method(handle, "SALS")) + priv->features.fn_lock = true; +} + static int ideapad_acpi_add(struct platform_device *pdev) { int ret, i; @@ -1024,7 +1040,8 @@ static int ideapad_acpi_add(struct platform_device *pdev) priv->cfg = cfg; priv->adev = adev; priv->platform_device = pdev; - priv->has_hw_rfkill_switch = dmi_check_system(hw_rfkill_list); + + ideapad_check_features(priv); ret = ideapad_sysfs_init(priv); if (ret) @@ -1040,7 +1057,7 @@ static int ideapad_acpi_add(struct platform_device *pdev) * On some models without a hw-switch (the yoga 2 13 at least) * VPCCMD_W_RF must be explicitly set to 1 for the wifi to work. */ - if (!priv->has_hw_rfkill_switch) + if (!priv->features.hw_rfkill_switch) write_ec_cmd(priv->adev->handle, VPCCMD_W_RF, 1); for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) -- 2.29.2