From 5055221eea348302a46086c3870f9f40341a6915 Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Wed, 28 Sep 2022 19:23:16 +0200 Subject: [PATCH 1/7] Implement new fan control --- src/tuxedo_io/tuxedo_io.c | 122 +++++++++++++++++++++++++++++++------- 1 file changed, 101 insertions(+), 21 deletions(-) diff --git a/src/tuxedo_io/tuxedo_io.c b/src/tuxedo_io/tuxedo_io.c index 22f51e4..5d8d627 100644 --- a/src/tuxedo_io/tuxedo_io.c +++ b/src/tuxedo_io/tuxedo_io.c @@ -156,6 +156,67 @@ static long clevo_ioctl_interface(struct file *file, unsigned int cmd, unsigned return 0; } +static int has_universal_ec_fan_control(void) { + int ret; + u8 data; + + ret = uniwill_read_ec_ram(0x0751, &data); + if (ret < 0) { + return ret; + } + return (data >> 6) & 1; +} + +static bool fans_initialized = false; + +static int uw_init_fan(void) { + int i; + + u16 addr_use_custom_fan_table_0 = 0x07c5; + u16 addr_use_custom_fan_table_1 = 0x07c6; + u8 offset_use_custom_fan_table_0 = 7; + u8 offset_use_custom_fan_table_1 = 2; + u8 value_use_custom_fan_table_0; + u8 value_use_custom_fan_table_1; + u16 addr_cpu_custom_fan_table_end_temp = 0x0f00; + u16 addr_cpu_custom_fan_table_start_temp = 0x0f10; + u16 addr_cpu_custom_fan_table_fan_speed = 0x0f20; + u16 addr_gpu_custom_fan_table_end_temp = 0x0f30; + u16 addr_gpu_custom_fan_table_start_temp = 0x0f40; + u16 addr_gpu_custom_fan_table_fan_speed = 0x0f50; + + if (!fans_initialized && (has_universal_ec_fan_control() == 1)) { + uniwill_read_ec_ram(addr_use_custom_fan_table_0, &value_use_custom_fan_table_0); + uniwill_read_ec_ram(addr_use_custom_fan_table_1, &value_use_custom_fan_table_1); + + if (!((value_use_custom_fan_table_0 >> offset_use_custom_fan_table_0) & 1)) { + uniwill_write_ec_ram(addr_use_custom_fan_table_0, value_use_custom_fan_table_0 + (1 << offset_use_custom_fan_table_0)); + } + if (!((value_use_custom_fan_table_1 >> offset_use_custom_fan_table_1) & 1)) { + uniwill_write_ec_ram(addr_use_custom_fan_table_1, value_use_custom_fan_table_1 + (1 << offset_use_custom_fan_table_1)); + } + + uniwill_write_ec_ram(addr_cpu_custom_fan_table_end_temp, 0xff); + uniwill_write_ec_ram(addr_cpu_custom_fan_table_start_temp, 0x00); + uniwill_write_ec_ram(addr_cpu_custom_fan_table_fan_speed, 0x00); + uniwill_write_ec_ram(addr_gpu_custom_fan_table_end_temp, 0xff); + uniwill_write_ec_ram(addr_gpu_custom_fan_table_start_temp, 0x00); + uniwill_write_ec_ram(addr_gpu_custom_fan_table_fan_speed, 0x00); + for (i = 0x1; i <= 0xf; ++i) { + uniwill_write_ec_ram(addr_cpu_custom_fan_table_end_temp + i, 0xff); + uniwill_write_ec_ram(addr_cpu_custom_fan_table_start_temp + i, 0xff); + uniwill_write_ec_ram(addr_cpu_custom_fan_table_fan_speed + i, 0x00); + uniwill_write_ec_ram(addr_gpu_custom_fan_table_end_temp + i, 0xff); + uniwill_write_ec_ram(addr_gpu_custom_fan_table_start_temp + i, 0xff); + uniwill_write_ec_ram(addr_gpu_custom_fan_table_fan_speed + i, 0x00); + } + } + + fans_initialized = true; + + return 0; // TODO Sensefull error handling +} + static u32 uw_set_fan(u32 fan_index, u8 fan_speed) { u32 i; @@ -164,30 +225,49 @@ static u32 uw_set_fan(u32 fan_index, u8 fan_speed) u16 addr_fan1 = 0x1809; u16 addr_for_fan; - if (fan_index == 0) - addr_for_fan = addr_fan0; - else if (fan_index == 1) - addr_for_fan = addr_fan1; - else - return -EINVAL; + u16 addr_cpu_custom_fan_table_fan_speed = 0x0f20; + u16 addr_gpu_custom_fan_table_fan_speed = 0x0f50; + + if (has_universal_ec_fan_control() == 1) { + uw_init_fan(); + + // TODO Disable full fan mode + + if (fan_index == 0) + addr_for_fan = addr_cpu_custom_fan_table_fan_speed; + else if (fan_index == 1) + addr_for_fan = addr_gpu_custom_fan_table_fan_speed; + else + return -EINVAL; - // Check current mode - uniwill_read_ec_ram(0x0751, &mode_data); - if (!(mode_data & 0x40)) { - // If not "full fan mode" (i.e. 0x40 bit set) switch to it (required for fancontrol) - uniwill_write_ec_ram(0x0751, mode_data | 0x40); - // Attempt to write both fans as quick as possible before complete ramp-up - pr_debug("prevent ramp-up start\n"); - for (i = 0; i < 10; ++i) { - uniwill_write_ec_ram(addr_fan0, fan_speed & 0xff); - uniwill_write_ec_ram(addr_fan1, fan_speed & 0xff); - msleep(10); - } - pr_debug("prevent ramp-up done\n"); - } else { - // Otherwise just set the chosen fan uniwill_write_ec_ram(addr_for_fan, fan_speed & 0xff); } + else { // old workaround using full fan mode + if (fan_index == 0) + addr_for_fan = addr_fan0; + else if (fan_index == 1) + addr_for_fan = addr_fan1; + else + return -EINVAL; + + // Check current mode + uniwill_read_ec_ram(0x0751, &mode_data); + if (!(mode_data & 0x40)) { + // If not "full fan mode" (i.e. 0x40 bit set) switch to it (required for fancontrol) + uniwill_write_ec_ram(0x0751, mode_data | 0x40); + // Attempt to write both fans as quick as possible before complete ramp-up + pr_debug("prevent ramp-up start\n"); + for (i = 0; i < 10; ++i) { + uniwill_write_ec_ram(addr_fan0, fan_speed & 0xff); + uniwill_write_ec_ram(addr_fan1, fan_speed & 0xff); + msleep(10); + } + pr_debug("prevent ramp-up done\n"); + } else { + // Otherwise just set the chosen fan + uniwill_write_ec_ram(addr_for_fan, fan_speed & 0xff); + } + } return 0; } From d3a8c76aa6a4967783804aeca23f69fd41e847d7 Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Thu, 29 Sep 2022 15:15:14 +0200 Subject: [PATCH 2/7] Fix wrong address --- src/tuxedo_io/tuxedo_io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tuxedo_io/tuxedo_io.c b/src/tuxedo_io/tuxedo_io.c index 5d8d627..0c0fee0 100644 --- a/src/tuxedo_io/tuxedo_io.c +++ b/src/tuxedo_io/tuxedo_io.c @@ -160,7 +160,7 @@ static int has_universal_ec_fan_control(void) { int ret; u8 data; - ret = uniwill_read_ec_ram(0x0751, &data); + ret = uniwill_read_ec_ram(0x078e, &data); if (ret < 0) { return ret; } From e92bbccbe06a97245c989abb89b6994dcde95e90 Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Thu, 29 Sep 2022 15:16:04 +0200 Subject: [PATCH 3/7] Make sure full fan mode is (un-)set correctly --- src/tuxedo_io/tuxedo_io.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/src/tuxedo_io/tuxedo_io.c b/src/tuxedo_io/tuxedo_io.c index 0c0fee0..b7311bb 100644 --- a/src/tuxedo_io/tuxedo_io.c +++ b/src/tuxedo_io/tuxedo_io.c @@ -167,6 +167,23 @@ static int has_universal_ec_fan_control(void) { return (data >> 6) & 1; } +static int set_full_fan_mode(bool enable) { + u8 mode_data; + + uniwill_read_ec_ram(0x0751, &mode_data); + + if (enable && !(mode_data & 0x40)) { + // If not "full fan mode" (i.e. 0x40 bit not set) switch to it (required for old fancontrol) + return uniwill_write_ec_ram(0x0751, mode_data | 0x40); + } + else if (mode_data & 0x40){ + // If "full fan mode" (i.e. 0x40 bit set) turn it off (required for new fancontrol) + return uniwill_write_ec_ram(0x0751, mode_data & ~0x40); + } + + return 0; +} + static bool fans_initialized = false; static int uw_init_fan(void) { @@ -186,6 +203,8 @@ static int uw_init_fan(void) { u16 addr_gpu_custom_fan_table_fan_speed = 0x0f50; if (!fans_initialized && (has_universal_ec_fan_control() == 1)) { + set_full_fan_mode(false); + uniwill_read_ec_ram(addr_use_custom_fan_table_0, &value_use_custom_fan_table_0); uniwill_read_ec_ram(addr_use_custom_fan_table_1, &value_use_custom_fan_table_1); @@ -231,8 +250,6 @@ static u32 uw_set_fan(u32 fan_index, u8 fan_speed) if (has_universal_ec_fan_control() == 1) { uw_init_fan(); - // TODO Disable full fan mode - if (fan_index == 0) addr_for_fan = addr_cpu_custom_fan_table_fan_speed; else if (fan_index == 1) @@ -254,7 +271,7 @@ static u32 uw_set_fan(u32 fan_index, u8 fan_speed) uniwill_read_ec_ram(0x0751, &mode_data); if (!(mode_data & 0x40)) { // If not "full fan mode" (i.e. 0x40 bit set) switch to it (required for fancontrol) - uniwill_write_ec_ram(0x0751, mode_data | 0x40); + set_full_fan_mode(true); // Attempt to write both fans as quick as possible before complete ramp-up pr_debug("prevent ramp-up start\n"); for (i = 0; i < 10; ++i) { From 47bbd14ca0ad06b95739bc0fbc1e886043a357d7 Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Thu, 29 Sep 2022 15:16:43 +0200 Subject: [PATCH 4/7] Remove useless comment, there few to no error handling in the whole module --- src/tuxedo_io/tuxedo_io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tuxedo_io/tuxedo_io.c b/src/tuxedo_io/tuxedo_io.c index b7311bb..ad84fc7 100644 --- a/src/tuxedo_io/tuxedo_io.c +++ b/src/tuxedo_io/tuxedo_io.c @@ -233,7 +233,7 @@ static int uw_init_fan(void) { fans_initialized = true; - return 0; // TODO Sensefull error handling + return 0; } static u32 uw_set_fan(u32 fan_index, u8 fan_speed) From 44f7fd0151aeb3cd96764c99535d103c781ece10 Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Tue, 4 Oct 2022 13:59:13 +0200 Subject: [PATCH 5/7] Expose fan control limitations to userspace --- src/tuxedo_io/tuxedo_io.c | 22 +++++++++++++++++++++- src/tuxedo_io/tuxedo_io_ioctl.h | 2 ++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/tuxedo_io/tuxedo_io.c b/src/tuxedo_io/tuxedo_io.c index ad84fc7..c8f087c 100644 --- a/src/tuxedo_io/tuxedo_io.c +++ b/src/tuxedo_io/tuxedo_io.c @@ -32,7 +32,7 @@ MODULE_DESCRIPTION("Hardware interface for TUXEDO laptops"); MODULE_AUTHOR("TUXEDO Computers GmbH "); -MODULE_VERSION("0.2.4"); +MODULE_VERSION("0.2.5"); MODULE_LICENSE("GPL"); MODULE_ALIAS_CLEVO_INTERFACES(); @@ -358,6 +358,26 @@ static long uniwill_ioctl_interface(struct file *file, unsigned int cmd, unsigne result = byte_data; copy_result = copy_to_user((void *) arg, &result, sizeof(result)); break; + case R_UW_FANS_OFF_POSSIBLE: + result = has_universal_ec_fan_control(); + if (result == 1) { + result = 0; + } + else if (result == 0) { + result = 1; + } + copy_result = copy_to_user((void *) arg, &result, sizeof(result)); + break; + case R_UW_FANSPEED_MIN: + result = has_universal_ec_fan_control(); + if (result == 1) { + result = 20; + } + else if (result == 0) { + result = 0; + } + copy_result = copy_to_user((void *) arg, &result, sizeof(result)); + break; #ifdef DEBUG case R_TF_BC: copy_result = copy_from_user(&uw_arg, (void *) arg, sizeof(uw_arg)); diff --git a/src/tuxedo_io/tuxedo_io_ioctl.h b/src/tuxedo_io/tuxedo_io_ioctl.h index f271707..a829753 100644 --- a/src/tuxedo_io/tuxedo_io_ioctl.h +++ b/src/tuxedo_io/tuxedo_io_ioctl.h @@ -79,6 +79,8 @@ #define R_UW_MODE _IOR(MAGIC_READ_UW, 0x14, int32_t*) #define R_UW_MODE_ENABLE _IOR(MAGIC_READ_UW, 0x15, int32_t*) +#define R_UW_FANS_OFF_POSSIBLE _IOR(MAGIC_READ_UW, 0x16, int32_t*) +#define R_UW_FANSPEED_MIN _IOR(MAGIC_READ_UW, 0x17, int32_t*) // Write #define W_UW_FANSPEED _IOW(MAGIC_WRITE_UW, 0x10, int32_t*) From a8b3cb6dc38272c6602709a83dedc4db34ede1c7 Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Tue, 4 Oct 2022 19:00:27 +0200 Subject: [PATCH 6/7] Fix define names --- src/tuxedo_io/tuxedo_io.c | 4 ++-- src/tuxedo_io/tuxedo_io_ioctl.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/tuxedo_io/tuxedo_io.c b/src/tuxedo_io/tuxedo_io.c index c8f087c..71edfcf 100644 --- a/src/tuxedo_io/tuxedo_io.c +++ b/src/tuxedo_io/tuxedo_io.c @@ -358,7 +358,7 @@ static long uniwill_ioctl_interface(struct file *file, unsigned int cmd, unsigne result = byte_data; copy_result = copy_to_user((void *) arg, &result, sizeof(result)); break; - case R_UW_FANS_OFF_POSSIBLE: + case R_UW_FANS_OFF_AVAILABLE: result = has_universal_ec_fan_control(); if (result == 1) { result = 0; @@ -368,7 +368,7 @@ static long uniwill_ioctl_interface(struct file *file, unsigned int cmd, unsigne } copy_result = copy_to_user((void *) arg, &result, sizeof(result)); break; - case R_UW_FANSPEED_MIN: + case R_UW_FANS_MIN_SPEED: result = has_universal_ec_fan_control(); if (result == 1) { result = 20; diff --git a/src/tuxedo_io/tuxedo_io_ioctl.h b/src/tuxedo_io/tuxedo_io_ioctl.h index a829753..d506232 100644 --- a/src/tuxedo_io/tuxedo_io_ioctl.h +++ b/src/tuxedo_io/tuxedo_io_ioctl.h @@ -79,8 +79,8 @@ #define R_UW_MODE _IOR(MAGIC_READ_UW, 0x14, int32_t*) #define R_UW_MODE_ENABLE _IOR(MAGIC_READ_UW, 0x15, int32_t*) -#define R_UW_FANS_OFF_POSSIBLE _IOR(MAGIC_READ_UW, 0x16, int32_t*) -#define R_UW_FANSPEED_MIN _IOR(MAGIC_READ_UW, 0x17, int32_t*) +#define R_UW_FANS_OFF_AVAILABLE _IOR(MAGIC_READ_UW, 0x16, int32_t*) +#define R_UW_FANS_MIN_SPEED _IOR(MAGIC_READ_UW, 0x17, int32_t*) // Write #define W_UW_FANSPEED _IOW(MAGIC_WRITE_UW, 0x10, int32_t*) From 19642a2496752d2e666170ef0dc4f296cf04236d Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Wed, 5 Oct 2022 16:25:37 +0200 Subject: [PATCH 7/7] Add retries for ex write and move enable custom fan table to end because of possible external race condition --- src/tuxedo_io/tuxedo_io.c | 53 +++++++++++++++++++++------------------ src/uniwill_interfaces.h | 2 ++ src/uniwill_keyboard.h | 26 +++++++++++++++++++ 3 files changed, 57 insertions(+), 24 deletions(-) diff --git a/src/tuxedo_io/tuxedo_io.c b/src/tuxedo_io/tuxedo_io.c index 71edfcf..d52db86 100644 --- a/src/tuxedo_io/tuxedo_io.c +++ b/src/tuxedo_io/tuxedo_io.c @@ -189,8 +189,8 @@ static bool fans_initialized = false; static int uw_init_fan(void) { int i; - u16 addr_use_custom_fan_table_0 = 0x07c5; - u16 addr_use_custom_fan_table_1 = 0x07c6; + u16 addr_use_custom_fan_table_0 = 0x07c5; // use different tables for both fans (0x0f00-0x0f2f and 0x0f30-0x0f5f respectivly) + u16 addr_use_custom_fan_table_1 = 0x07c6; // enable 0x0fxx fantables u8 offset_use_custom_fan_table_0 = 7; u8 offset_use_custom_fan_table_1 = 2; u8 value_use_custom_fan_table_0; @@ -206,28 +206,28 @@ static int uw_init_fan(void) { set_full_fan_mode(false); uniwill_read_ec_ram(addr_use_custom_fan_table_0, &value_use_custom_fan_table_0); - uniwill_read_ec_ram(addr_use_custom_fan_table_1, &value_use_custom_fan_table_1); - if (!((value_use_custom_fan_table_0 >> offset_use_custom_fan_table_0) & 1)) { - uniwill_write_ec_ram(addr_use_custom_fan_table_0, value_use_custom_fan_table_0 + (1 << offset_use_custom_fan_table_0)); - } - if (!((value_use_custom_fan_table_1 >> offset_use_custom_fan_table_1) & 1)) { - uniwill_write_ec_ram(addr_use_custom_fan_table_1, value_use_custom_fan_table_1 + (1 << offset_use_custom_fan_table_1)); + uniwill_write_ec_ram_with_retry(addr_use_custom_fan_table_0, value_use_custom_fan_table_0 + (1 << offset_use_custom_fan_table_0), 3); } - uniwill_write_ec_ram(addr_cpu_custom_fan_table_end_temp, 0xff); - uniwill_write_ec_ram(addr_cpu_custom_fan_table_start_temp, 0x00); - uniwill_write_ec_ram(addr_cpu_custom_fan_table_fan_speed, 0x00); - uniwill_write_ec_ram(addr_gpu_custom_fan_table_end_temp, 0xff); - uniwill_write_ec_ram(addr_gpu_custom_fan_table_start_temp, 0x00); - uniwill_write_ec_ram(addr_gpu_custom_fan_table_fan_speed, 0x00); + uniwill_write_ec_ram_with_retry(addr_cpu_custom_fan_table_end_temp, 0xff, 3); + uniwill_write_ec_ram_with_retry(addr_cpu_custom_fan_table_start_temp, 0x00, 3); + uniwill_write_ec_ram_with_retry(addr_cpu_custom_fan_table_fan_speed, 0x00, 3); + uniwill_write_ec_ram_with_retry(addr_gpu_custom_fan_table_end_temp, 0xff, 3); + uniwill_write_ec_ram_with_retry(addr_gpu_custom_fan_table_start_temp, 0x00, 3); + uniwill_write_ec_ram_with_retry(addr_gpu_custom_fan_table_fan_speed, 0x00, 3); for (i = 0x1; i <= 0xf; ++i) { - uniwill_write_ec_ram(addr_cpu_custom_fan_table_end_temp + i, 0xff); - uniwill_write_ec_ram(addr_cpu_custom_fan_table_start_temp + i, 0xff); - uniwill_write_ec_ram(addr_cpu_custom_fan_table_fan_speed + i, 0x00); - uniwill_write_ec_ram(addr_gpu_custom_fan_table_end_temp + i, 0xff); - uniwill_write_ec_ram(addr_gpu_custom_fan_table_start_temp + i, 0xff); - uniwill_write_ec_ram(addr_gpu_custom_fan_table_fan_speed + i, 0x00); + uniwill_write_ec_ram_with_retry(addr_cpu_custom_fan_table_end_temp + i, 0xff, 3); + uniwill_write_ec_ram_with_retry(addr_cpu_custom_fan_table_start_temp + i, 0xff, 3); + uniwill_write_ec_ram_with_retry(addr_cpu_custom_fan_table_fan_speed + i, 0x00, 3); + uniwill_write_ec_ram_with_retry(addr_gpu_custom_fan_table_end_temp + i, 0xff, 3); + uniwill_write_ec_ram_with_retry(addr_gpu_custom_fan_table_start_temp + i, 0xff, 3); + uniwill_write_ec_ram_with_retry(addr_gpu_custom_fan_table_fan_speed + i, 0x00, 3); + } + + uniwill_read_ec_ram(addr_use_custom_fan_table_1, &value_use_custom_fan_table_1); + if (!((value_use_custom_fan_table_1 >> offset_use_custom_fan_table_1) & 1)) { + uniwill_write_ec_ram_with_retry(addr_use_custom_fan_table_1, value_use_custom_fan_table_1 + (1 << offset_use_custom_fan_table_1), 3); } } @@ -292,10 +292,15 @@ static u32 uw_set_fan(u32 fan_index, u8 fan_speed) static u32 uw_set_fan_auto(void) { u8 mode_data; - // Get current mode - uniwill_read_ec_ram(0x0751, &mode_data); - // Switch off "full fan mode" (i.e. unset 0x40 bit) - uniwill_write_ec_ram(0x0751, mode_data & 0xbf); + + if (has_universal_ec_fan_control() == 1) { + } + else { + // Get current mode + uniwill_read_ec_ram(0x0751, &mode_data); + // Switch off "full fan mode" (i.e. unset 0x40 bit) + uniwill_write_ec_ram(0x0751, mode_data & 0xbf); + } return 0; } diff --git a/src/uniwill_interfaces.h b/src/uniwill_interfaces.h index 3c1bf45..3ecd155 100644 --- a/src/uniwill_interfaces.h +++ b/src/uniwill_interfaces.h @@ -37,6 +37,7 @@ typedef u32 (uniwill_read_ec_ram_t)(u16, u8*); typedef u32 (uniwill_write_ec_ram_t)(u16, u8); +typedef u32 (uniwill_write_ec_ram_with_retry_t)(u16, u8, int); typedef void (uniwill_event_callb_t)(u32); struct uniwill_interface_t { @@ -50,6 +51,7 @@ u32 uniwill_add_interface(struct uniwill_interface_t *new_interface); u32 uniwill_remove_interface(struct uniwill_interface_t *interface); uniwill_read_ec_ram_t uniwill_read_ec_ram; uniwill_write_ec_ram_t uniwill_write_ec_ram; +uniwill_write_ec_ram_with_retry_t uniwill_write_ec_ram_with_retry; u32 uniwill_get_active_interface_id(char **id_str); union uw_ec_read_return { diff --git a/src/uniwill_keyboard.h b/src/uniwill_keyboard.h index 41f7b8d..00e227f 100644 --- a/src/uniwill_keyboard.h +++ b/src/uniwill_keyboard.h @@ -124,6 +124,32 @@ u32 uniwill_write_ec_ram(u16 address, u8 data) } EXPORT_SYMBOL(uniwill_write_ec_ram); +u32 uniwill_write_ec_ram_with_retry(u16 address, u8 data, int retries) +{ + u32 status; + int i; + u8 control_data; + + for (i = 0; i < retries; ++i) { + status = uniwill_write_ec_ram(address, data); + if (status != 0) { + msleep(50); + continue; + } + else { + status = uniwill_read_ec_ram(address, &control_data); + if (status != 0 || data != control_data) { + msleep(50); + continue; + } + break; + } + } + + return status; +} +EXPORT_SYMBOL(uniwill_write_ec_ram_with_retry); + static DEFINE_MUTEX(uniwill_interface_modification_lock); u32 uniwill_add_interface(struct uniwill_interface_t *interface)