diff options
| -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; } |
