qcacld-3.0: Load driver on device initcall when not built as a module

Requiring userspace to write to /sys/kernel/boot_wlan/boot_wlan to boot
up the wlan device is unnecessary and blocks userspace for the large
amount of time it takes for wlan boot to finish.

Instead, load the driver asynchronously on device_initcall.

Change-Id: I4d696b9d46de032158fd223c60d9a7dbde26cc3f
Signed-off-by: Sultanxda <sultanxda@gmail.com>
Signed-off-by: Nathan Chancellor <natechancellor@gmail.com>
Signed-off-by: Jami Kettunen <jami.kettunen@protonmail.com>

Combines:
071d5c9cb3
aded485ca7
494bc76e6e
This commit is contained in:
Sultanxda 2018-01-03 12:40:12 -08:00 committed by Jami Kettunen
parent 29b22f6662
commit 3cb431c1a5
No known key found for this signature in database
GPG key ID: F77FA91FBBBB4A77

View file

@ -146,25 +146,7 @@ static struct cdev wlan_hdd_state_cdev;
static struct class *class;
static dev_t device;
#ifndef MODULE
static struct gwlan_loader *wlan_loader;
static ssize_t wlan_boot_cb(struct kobject *kobj,
struct kobj_attribute *attr,
const char *buf, size_t count);
struct gwlan_loader {
bool loaded_state;
struct kobject *boot_wlan_obj;
struct attribute_group *attr_group;
};
static struct kobj_attribute wlan_boot_attribute =
__ATTR(boot_wlan, 0220, NULL, wlan_boot_cb);
static struct attribute *attrs[] = {
&wlan_boot_attribute.attr,
NULL,
};
#define MODULE_INITIALIZED 1
static struct work_struct boot_work;
#endif
#define HDD_OPS_INACTIVITY_TIMEOUT (120000)
@ -399,6 +381,7 @@ int hdd_validate_channel_and_bandwidth(hdd_adapter_t *adapter,
return 0;
}
#ifdef MODULE
/**
* hdd_wait_for_recovery_completion() - Wait for cds recovery completion
*
@ -438,6 +421,7 @@ static bool hdd_wait_for_recovery_completion(void)
hdd_info("Recovery completed successfully!");
return true;
}
#endif
static int __hdd_netdev_notifier_call(struct notifier_block *nb,
@ -12688,6 +12672,7 @@ dev_alloc_err:
return -ENODEV;
}
#ifdef MODULE
static void wlan_hdd_state_ctrl_param_destroy(void)
{
cdev_del(&wlan_hdd_state_cdev);
@ -12697,6 +12682,7 @@ static void wlan_hdd_state_ctrl_param_destroy(void)
pr_info("Device node unregistered");
}
#endif
/**
* __hdd_module_init - Module init helper
@ -12750,7 +12736,7 @@ err_hdd_init:
return ret;
}
#ifdef MODULE
/**
* __hdd_module_exit - Module exit helper
*
@ -12780,135 +12766,6 @@ static void __hdd_module_exit(void)
wlan_hdd_state_ctrl_param_destroy();
}
#ifndef MODULE
/**
* wlan_boot_cb() - Wlan boot callback
* @kobj: object whose directory we're creating the link in.
* @attr: attribute the user is interacting with
* @buff: the buffer containing the user data
* @count: number of bytes in the buffer
*
* This callback is invoked when the fs is ready to start the
* wlan driver initialization.
*
* Return: 'count' on success or a negative error code in case of failure
*/
static ssize_t wlan_boot_cb(struct kobject *kobj,
struct kobj_attribute *attr,
const char *buf,
size_t count)
{
if (wlan_loader->loaded_state) {
pr_err("%s: wlan driver already initialized\n", __func__);
return -EALREADY;
}
if (__hdd_module_init()) {
pr_err("%s: wlan driver initialization failed\n", __func__);
return -EIO;
}
wlan_loader->loaded_state = MODULE_INITIALIZED;
return count;
}
/**
* hdd_sysfs_cleanup() - cleanup sysfs
*
* Return: None
*
*/
static void hdd_sysfs_cleanup(void)
{
/* remove from group */
if (wlan_loader->boot_wlan_obj && wlan_loader->attr_group)
sysfs_remove_group(wlan_loader->boot_wlan_obj,
wlan_loader->attr_group);
/* unlink the object from parent */
kobject_del(wlan_loader->boot_wlan_obj);
/* free the object */
kobject_put(wlan_loader->boot_wlan_obj);
kfree(wlan_loader->attr_group);
kfree(wlan_loader);
wlan_loader = NULL;
}
/**
* wlan_init_sysfs() - Creates the sysfs to be invoked when the fs is
* ready
*
* This is creates the syfs entry boot_wlan. Which shall be invoked
* when the filesystem is ready.
*
* QDF API cannot be used here since this function is called even before
* initializing WLAN driver.
*
* Return: 0 for success, errno on failure
*/
static int wlan_init_sysfs(void)
{
int ret = -ENOMEM;
wlan_loader = kzalloc(sizeof(*wlan_loader), GFP_KERNEL);
if (!wlan_loader)
return -ENOMEM;
wlan_loader->boot_wlan_obj = NULL;
wlan_loader->attr_group = kzalloc(sizeof(*(wlan_loader->attr_group)),
GFP_KERNEL);
if (!wlan_loader->attr_group)
goto error_return;
wlan_loader->loaded_state = 0;
wlan_loader->attr_group->attrs = attrs;
wlan_loader->boot_wlan_obj = kobject_create_and_add("boot_wlan",
kernel_kobj);
if (!wlan_loader->boot_wlan_obj) {
pr_err("%s: sysfs create and add failed\n", __func__);
goto error_return;
}
ret = sysfs_create_group(wlan_loader->boot_wlan_obj,
wlan_loader->attr_group);
if (ret) {
pr_err("%s: sysfs create group failed %d\n", __func__, ret);
goto error_return;
}
return 0;
error_return:
hdd_sysfs_cleanup();
return ret;
}
/**
* wlan_deinit_sysfs() - Removes the sysfs created to initialize the wlan
*
* Return: 0 on success or errno on failure
*/
static int wlan_deinit_sysfs(void)
{
if (!wlan_loader) {
hdd_err("wlan loader context is Null!");
return -EINVAL;
}
hdd_sysfs_cleanup();
return 0;
}
#endif /* MODULE */
#ifdef MODULE
/**
* __hdd_module_init - Module init helper
*
@ -12925,21 +12782,7 @@ static int hdd_module_init(void)
return 0;
}
#else
static int __init hdd_module_init(void)
{
int ret = -EINVAL;
ret = wlan_init_sysfs();
if (ret)
pr_err("Failed to create sysfs entry for loading wlan");
return ret;
}
#endif
#ifdef MODULE
/**
* hdd_module_exit() - Exit function
*
@ -12952,10 +12795,17 @@ static void __exit hdd_module_exit(void)
__hdd_module_exit();
}
#else
static void __exit hdd_module_exit(void)
static void wlan_hdd_boot_fn(struct work_struct *work)
{
__hdd_module_exit();
wlan_deinit_sysfs();
__hdd_module_init();
}
static int __init hdd_module_init(void)
{
INIT_WORK(&boot_work, wlan_hdd_boot_fn);
schedule_work(&boot_work);
return 0;
}
#endif
@ -13747,8 +13597,12 @@ void hdd_drv_ops_inactivity_handler(unsigned long arg)
}
/* Register the module init/exit functions */
#ifdef MODULE
module_init(hdd_module_init);
module_exit(hdd_module_exit);
#else
device_initcall(hdd_module_init);
#endif
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Qualcomm Atheros, Inc.");