diff options
| author | Sachin Ahuja <sahuja@codeaurora.org> | 2017-03-07 19:07:24 +0530 |
|---|---|---|
| committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2017-03-17 12:23:56 -0700 |
| commit | f7007f8202b14ad87f9048ee326a69a717a5a7d1 (patch) | |
| tree | bf2850f91b69b68cd5bfa647d2819995487a634c | |
| parent | 14f469efb2c2206a5f2512a4a07899a8a5bd70b3 (diff) | |
qcacld-3.0: Add wait for timeout in state ctrl param
Currently wait for timeout happens in module_init which blocks
the driver loading in case of static driver
To mitigate this issue, wait is added in state ctrl param for DLKM,
static and load once and unload never driver types.
Change-Id: I1c2e427df3faa3cf68295868f6d98746e481987f
CRs-Fixed: 2012813
| -rw-r--r-- | core/cds/inc/cds_api.h | 12 | ||||
| -rw-r--r-- | core/hdd/inc/wlan_hdd_main.h | 12 | ||||
| -rw-r--r-- | core/hdd/src/wlan_hdd_main.c | 152 |
3 files changed, 169 insertions, 7 deletions
diff --git a/core/cds/inc/cds_api.h b/core/cds/inc/cds_api.h index f225f13a4328..b0f71a918bd8 100644 --- a/core/cds/inc/cds_api.h +++ b/core/cds/inc/cds_api.h @@ -210,6 +210,18 @@ static inline void cds_set_unload_in_progress(uint8_t value) cds_clear_driver_state(CDS_DRIVER_STATE_UNLOADING); } +/** + * cds_is_driver_loaded() - Is driver loaded + * + * Return: true if driver is loaded or false otherwise. + */ +static inline bool cds_is_driver_loaded(void) +{ + enum cds_driver_state state = cds_get_driver_state(); + + return __CDS_IS_DRIVER_STATE(state, CDS_DRIVER_STATE_LOADED); +} + v_CONTEXT_t cds_init(void); void cds_deinit(void); diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index fb055ea40c54..28cf0d988e91 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -2209,4 +2209,16 @@ static inline void hdd_init_nud_stats_ctx(hdd_context_t *hdd_ctx) init_completion(&hdd_ctx->nud_stats_context.response_event); return; } + +/** + * hdd_start_complete()- complete the start event + * @ret: return value for complete event. + * + * complete the startup event and set the return in + * global variable + * + * Return: void + */ + +void hdd_start_complete(int ret); #endif /* end #if !defined(WLAN_HDD_MAIN_H) */ diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index e4e135b7c5f3..48be0e56b683 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -131,6 +131,12 @@ #define MEMORY_DEBUG_STR "" #endif +int wlan_start_ret_val; +static DECLARE_COMPLETION(wlan_start_comp); +static unsigned int dev_num = 1; +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, @@ -199,11 +205,17 @@ static const struct wiphy_wowlan_support wowlan_support_reg_init = { /* internal function declaration */ struct sock *cesium_nl_srv_sock; -struct completion wlan_start_comp; #ifdef FEATURE_WLAN_AUTO_SHUTDOWN void wlan_hdd_auto_shutdown_cb(void); #endif +void hdd_start_complete(int ret) +{ + wlan_start_ret_val = ret; + + complete(&wlan_start_comp); +} + /** * hdd_set_rps_cpu_mask - set RPS CPU mask for interfaces * @hdd_ctx: pointer to hdd_context_t @@ -8738,7 +8750,7 @@ int hdd_wlan_startup(struct device *dev) qdf_mc_timer_start(&hdd_ctx->iface_change_timer, hdd_ctx->config->iface_change_wait_time); - complete(&wlan_start_comp); + hdd_start_complete(0); goto success; err_close_adapters: @@ -8770,11 +8782,11 @@ err_exit_nl_srv: cds_deinit_ini_config(); err_hdd_free_context: + hdd_start_complete(ret); qdf_mc_timer_destroy(&hdd_ctx->iface_change_timer); mutex_destroy(&hdd_ctx->iface_change_lock); hdd_context_destroy(hdd_ctx); QDF_BUG(1); - return -EIO; success: @@ -9783,6 +9795,121 @@ void hdd_deinit(void) #define HDD_WLAN_START_WAIT_TIME (CDS_WMA_TIMEOUT + 5000) +static int wlan_hdd_state_ctrl_param_open(struct inode *inode, + struct file *file) +{ + return 0; +} + +static ssize_t wlan_hdd_state_ctrl_param_write(struct file *filp, + const char __user *user_buf, + size_t count, + loff_t *f_pos) +{ + char buf; + static const char wlan_off_str[] = "OFF"; + static const char wlan_on_str[] = "ON"; + int ret; + unsigned long rc; + + if (copy_from_user(&buf, user_buf, 3)) { + pr_err("Failed to read buffer\n"); + return -EINVAL; + } + + if (strncmp(&buf, wlan_off_str, strlen(wlan_off_str)) == 0) { + pr_debug("Wifi turning off from UI\n"); + goto exit; + } + + if (strncmp(&buf, wlan_on_str, strlen(wlan_on_str)) != 0) { + pr_err("Invalid value received from framework"); + goto exit; + } + + if (!cds_is_driver_loaded()) { + rc = wait_for_completion_timeout(&wlan_start_comp, + msecs_to_jiffies(HDD_WLAN_START_WAIT_TIME)); + if (!rc) { + hdd_alert("Timed-out waiting in wlan_hdd_state_ctrl_param_write"); + ret = -EINVAL; + hdd_start_complete(ret); + return ret; + } + + hdd_start_complete(0); + } + +exit: + return count; +} + + +const struct file_operations wlan_hdd_state_fops = { + .owner = THIS_MODULE, + .open = wlan_hdd_state_ctrl_param_open, + .write = wlan_hdd_state_ctrl_param_write, +}; + +static int wlan_hdd_state_ctrl_param_create(void) +{ + unsigned int wlan_hdd_state_major = 0; + int ret; + struct device *dev; + + device = MKDEV(wlan_hdd_state_major, 0); + + ret = alloc_chrdev_region(&device, 0, dev_num, "qcwlanstate"); + if (ret) { + pr_err("Failed to register qcwlanstate"); + goto dev_alloc_err; + } + wlan_hdd_state_major = MAJOR(device); + + class = class_create(THIS_MODULE, WLAN_MODULE_NAME); + if (IS_ERR(class)) { + pr_err("wlan_hdd_state class_create error"); + goto class_err; + } + + dev = device_create(class, NULL, device, NULL, WLAN_MODULE_NAME); + if (IS_ERR(dev)) { + pr_err("wlan_hdd_statedevice_create error"); + goto err_class_destroy; + } + + cdev_init(&wlan_hdd_state_cdev, &wlan_hdd_state_fops); + ret = cdev_add(&wlan_hdd_state_cdev, device, dev_num); + if (ret) { + pr_err("Failed to add cdev error"); + goto cdev_add_err; + } + + pr_info("wlan_hdd_state %s major(%d) initialized", + WLAN_MODULE_NAME, wlan_hdd_state_major); + + return 0; + +cdev_add_err: + device_destroy(class, device); +err_class_destroy: + class_destroy(class); +class_err: + unregister_chrdev_region(device, dev_num); +dev_alloc_err: + return -ENODEV; +} + +static void wlan_hdd_state_ctrl_param_destroy(void) +{ + cdev_del(&wlan_hdd_state_cdev); + device_destroy(class, device); + class_destroy(class); + unregister_chrdev_region(device, dev_num); + + pr_info("Device node unregistered"); +} + /** * __hdd_module_init - Module init helper * @@ -9798,6 +9925,12 @@ static int __hdd_module_init(void) pr_err("%s: Loading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR); + ret = wlan_hdd_state_ctrl_param_create(); + if (ret) { + pr_err("wlan_hdd_state_create:%x\n", ret); + goto err_dev_state; + } + pld_init(); ret = hdd_init(); @@ -9818,11 +9951,14 @@ static int __hdd_module_init(void) goto out; } + /* + * This wait is temporarily introduced till + * boardconfig changes for dev node are merged + */ rc = wait_for_completion_timeout(&wlan_start_comp, - msecs_to_jiffies(HDD_WLAN_START_WAIT_TIME)); - + msecs_to_jiffies(HDD_WLAN_START_WAIT_TIME)); if (!rc) { - hdd_err("Timed-out waiting for wlan_hdd_register_driver"); + hdd_alert("Timed-out waiting for wlan_hdd_register_driver"); ret = -ETIMEDOUT; wlan_hdd_unregister_driver(); goto out; @@ -9836,6 +9972,8 @@ out: hdd_deinit(); err_hdd_init: pld_deinit(); + wlan_hdd_state_ctrl_param_destroy(); +err_dev_state: return ret; } @@ -9879,7 +10017,7 @@ static void __hdd_module_exit(void) hdd_deinit(); pld_deinit(); - + wlan_hdd_state_ctrl_param_destroy(); return; } |
