summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/cds/inc/cds_api.h12
-rw-r--r--core/hdd/inc/wlan_hdd_main.h12
-rw-r--r--core/hdd/src/wlan_hdd_main.c152
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;
}