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:
parent
29b22f6662
commit
3cb431c1a5
1 changed files with 20 additions and 166 deletions
|
@ -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.");
|
||||
|
|
Loading…
Add table
Reference in a new issue