tuxedo_keyboard: Fix possible race condition on driver init

Modified patch from https://github.com/ftufo

https://github.com/tuxedocomputers/tuxedo-keyboard/issues/75
This commit is contained in:
Christoffer Sandberg 2021-03-15 11:30:45 +01:00
parent 852c28cec4
commit f4622e28f1
No known key found for this signature in database
GPG key ID: BF563F71B6C7A96D

View file

@ -21,6 +21,7 @@
#include "tuxedo_keyboard_common.h" #include "tuxedo_keyboard_common.h"
#include "clevo_keyboard.h" #include "clevo_keyboard.h"
#include "uniwill_keyboard.h" #include "uniwill_keyboard.h"
#include <linux/mutex.h>
MODULE_AUTHOR("TUXEDO Computers GmbH <tux@tuxedocomputers.com>"); MODULE_AUTHOR("TUXEDO Computers GmbH <tux@tuxedocomputers.com>");
MODULE_DESCRIPTION("TUXEDO Computers keyboard & keyboard backlight Driver"); MODULE_DESCRIPTION("TUXEDO Computers keyboard & keyboard backlight Driver");
@ -33,6 +34,8 @@ MODULE_ALIAS("wmi:" UNIWILL_WMI_EVENT_GUID_2);
MODULE_SOFTDEP("pre: tuxedo-cc-wmi"); MODULE_SOFTDEP("pre: tuxedo-cc-wmi");
static DEFINE_MUTEX(tuxedo_keyboard_init_driver_lock);
static struct tuxedo_keyboard_driver *driver_list[] = { static struct tuxedo_keyboard_driver *driver_list[] = {
&uniwill_keyboard_driver &uniwill_keyboard_driver
}; };
@ -79,35 +82,40 @@ struct platform_device *tuxedo_keyboard_init_driver(struct tuxedo_keyboard_drive
int err; int err;
TUXEDO_DEBUG("init driver start\n"); TUXEDO_DEBUG("init driver start\n");
// If already initiated don't do anything further mutex_lock(&tuxedo_keyboard_init_driver_lock);
if (!IS_ERR_OR_NULL(tuxedo_platform_device)) { if (!IS_ERR_OR_NULL(tuxedo_platform_device)) {
return tuxedo_platform_device; // If already initialized, don't proceed
} TUXEDO_DEBUG("platform device already initialized\n");
goto init_driver_exit;
} else {
// Otherwise, attempt to initialize structures
TUXEDO_DEBUG("create platform bundle\n");
tuxedo_platform_device = platform_create_bundle(
tk_driver->platform_driver, tk_driver->probe, NULL, 0, NULL, 0);
TUXEDO_DEBUG("create platform bundle\n"); if (IS_ERR_OR_NULL(tuxedo_platform_device)) {
// Normal case probe failed, no init
tuxedo_platform_device = platform_create_bundle( goto init_driver_exit;
tk_driver->platform_driver, tk_driver->probe, NULL, 0, NULL, 0);
if (IS_ERR_OR_NULL(tuxedo_platform_device))
return tuxedo_platform_device;
TUXEDO_DEBUG("platform device created\n");
TUXEDO_DEBUG("initialize input device\n");
if (tk_driver->key_map != NULL) {
err = tuxedo_input_init(tk_driver->key_map);
if (unlikely(err)) {
TUXEDO_ERROR("Could not register input device\n");
tk_driver->input_device = NULL;
} else {
TUXEDO_DEBUG("input device registered\n");
tk_driver->input_device = tuxedo_input_device;
} }
TUXEDO_DEBUG("initialize input device\n");
if (tk_driver->key_map != NULL) {
err = tuxedo_input_init(tk_driver->key_map);
if (unlikely(err)) {
TUXEDO_ERROR("Could not register input device\n");
tk_driver->input_device = NULL;
} else {
TUXEDO_DEBUG("input device registered\n");
tk_driver->input_device = tuxedo_input_device;
}
}
current_driver = tk_driver;
} }
current_driver = tk_driver; init_driver_exit:
mutex_unlock(&tuxedo_keyboard_init_driver_lock);
return tuxedo_platform_device; return tuxedo_platform_device;
} }
EXPORT_SYMBOL(tuxedo_keyboard_init_driver); EXPORT_SYMBOL(tuxedo_keyboard_init_driver);
@ -124,7 +132,7 @@ static void __exit tuxedo_input_exit(void)
} }
} }
static int __init tuxdeo_keyboard_init(void) static int __init tuxedo_keyboard_init(void)
{ {
int i; int i;
int num_drivers = sizeof(driver_list) / sizeof(*driver_list); int num_drivers = sizeof(driver_list) / sizeof(*driver_list);
@ -138,7 +146,7 @@ static int __init tuxdeo_keyboard_init(void)
i = 0; i = 0;
while (IS_ERR_OR_NULL(tuxedo_platform_device) && i < num_drivers) { while (IS_ERR_OR_NULL(tuxedo_platform_device) && i < num_drivers) {
current_driver = driver_list[i]; current_driver = driver_list[i];
tuxedo_keyboard_init_driver(current_driver); tuxedo_keyboard_init_driver(current_driver);
++i; ++i;
} }
@ -150,7 +158,7 @@ static int __init tuxdeo_keyboard_init(void)
return 0; return 0;
} }
static void __exit tuxdeo_keyboard_exit(void) static void __exit tuxedo_keyboard_exit(void)
{ {
TUXEDO_DEBUG("tuxedo_input_exit()\n"); TUXEDO_DEBUG("tuxedo_input_exit()\n");
tuxedo_input_exit(); tuxedo_input_exit();
@ -164,5 +172,5 @@ static void __exit tuxdeo_keyboard_exit(void)
TUXEDO_DEBUG("exit\n"); TUXEDO_DEBUG("exit\n");
} }
module_init(tuxdeo_keyboard_init); module_init(tuxedo_keyboard_init);
module_exit(tuxdeo_keyboard_exit); module_exit(tuxedo_keyboard_exit);