Add mutex protection around cases where an operation needs multiple WMI calls - e.g. setting password. Signed-off-by: Mark Pearson <mpearson-lenovo@xxxxxxxxx> --- Changes in V2: New commit added after review of other patches in series. drivers/platform/x86/think-lmi.c | 46 ++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 11 deletions(-) diff --git a/drivers/platform/x86/think-lmi.c b/drivers/platform/x86/think-lmi.c index 64cd453d6e7d..f3e1e4dacba2 100644 --- a/drivers/platform/x86/think-lmi.c +++ b/drivers/platform/x86/think-lmi.c @@ -14,6 +14,7 @@ #include <linux/acpi.h> #include <linux/errno.h> #include <linux/fs.h> +#include <linux/mutex.h> #include <linux/string.h> #include <linux/types.h> #include <linux/dmi.h> @@ -195,6 +196,7 @@ static const char * const level_options[] = { }; static struct think_lmi tlmi_priv; static struct class *fw_attr_class; +static DEFINE_MUTEX(tlmi_mutex); /* ------ Utility functions ------------*/ /* Strip out CR if one is present */ @@ -463,23 +465,32 @@ static ssize_t new_password_store(struct kobject *kobj, sprintf(pwd_type, "%s", setting->pwd_type); } + mutex_lock(&tlmi_mutex); ret = tlmi_opcode_setting("WmiOpcodePasswordType", pwd_type); - if (ret) + if (ret) { + mutex_unlock(&tlmi_mutex); goto out; - + } if (tlmi_priv.pwd_admin->valid) { ret = tlmi_opcode_setting("WmiOpcodePasswordAdmin", tlmi_priv.pwd_admin->password); - if (ret) + if (ret) { + mutex_unlock(&tlmi_mutex); goto out; + } } ret = tlmi_opcode_setting("WmiOpcodePasswordCurrent01", setting->password); - if (ret) + if (ret) { + mutex_unlock(&tlmi_mutex); goto out; + } ret = tlmi_opcode_setting("WmiOpcodePasswordNew01", new_pwd); - if (ret) + if (ret) { + mutex_unlock(&tlmi_mutex); goto out; + } ret = tlmi_simple_call(LENOVO_OPCODE_IF_GUID, "WmiOpcodePasswordSetUpdate;"); + mutex_unlock(&tlmi_mutex); } else { /* Format: 'PasswordType,CurrentPw,NewPw,Encoding,KbdLang;' */ auth_str = kasprintf(GFP_KERNEL, "%s,%s,%s,%s,%s;", @@ -1000,11 +1011,16 @@ static ssize_t current_value_store(struct kobject *kobj, goto out; } + mutex_lock(&tlmi_mutex); ret = tlmi_simple_call(LENOVO_SET_BIOS_SETTING_CERT_GUID, set_str); - if (ret) + if (ret) { + mutex_unlock(&tlmi_mutex); goto out; + } ret = tlmi_simple_call(LENOVO_SAVE_BIOS_SETTING_CERT_GUID, tlmi_priv.pwd_admin->save_signature); + + mutex_unlock(&tlmi_mutex); if (ret) goto out; } else if (tlmi_priv.opcode_support) { @@ -1021,18 +1037,23 @@ static ssize_t current_value_store(struct kobject *kobj, goto out; } + mutex_lock(&tlmi_mutex); ret = tlmi_simple_call(LENOVO_SET_BIOS_SETTINGS_GUID, set_str); - if (ret) + if (ret) { + mutex_unlock(&tlmi_mutex); goto out; + } if (tlmi_priv.pwd_admin->valid && tlmi_priv.pwd_admin->password[0]) { ret = tlmi_opcode_setting("WmiOpcodePasswordAdmin", tlmi_priv.pwd_admin->password); - if (ret) + if (ret) { + mutex_unlock(&tlmi_mutex); goto out; + } } - ret = tlmi_save_bios_settings(""); + mutex_unlock(&tlmi_mutex); } else { /* old non opcode based authentication method (deprecated)*/ if (tlmi_priv.pwd_admin->valid && tlmi_priv.pwd_admin->password[0]) { auth_str = kasprintf(GFP_KERNEL, "%s,%s,%s;", @@ -1056,14 +1077,17 @@ static ssize_t current_value_store(struct kobject *kobj, goto out; } + mutex_lock(&tlmi_mutex); ret = tlmi_simple_call(LENOVO_SET_BIOS_SETTINGS_GUID, set_str); - if (ret) + if (ret) { + mutex_unlock(&tlmi_mutex); goto out; - + } if (auth_str) ret = tlmi_save_bios_settings(auth_str); else ret = tlmi_save_bios_settings(""); + mutex_unlock(&tlmi_mutex); } if (!ret && !tlmi_priv.pending_changes) { tlmi_priv.pending_changes = true; -- 2.40.1