Quellcode durchsuchen

qcacld-3.0: Add support to force disable/enable wifi

As part of protected dynamic interface control feature,
add support to force disable/enable wifi, by performing
a soft unload/load of the wlan driver.

Change-Id: I6f9ab99bf6a3124e1ffd3c8ffd6c2bd50322a3b6
CRs-Fixed: 3171854
Aditya Kodukula vor 3 Jahren
Ursprung
Commit
cc931d504b
2 geänderte Dateien mit 77 neuen und 6 gelöschten Zeilen
  1. 17 1
      core/hdd/inc/wlan_hdd_main.h
  2. 60 5
      core/hdd/src/wlan_hdd_main.c

+ 17 - 1
core/hdd/inc/wlan_hdd_main.h

@@ -1968,6 +1968,20 @@ struct hdd_rtpm_tput_policy_context {
 };
 #endif
 
+#ifdef FEATURE_WLAN_DYNAMIC_IFACE_CTRL
+/**
+ * hdd_get_wlan_driver_status() - get status of soft driver unload
+ *
+ * Return: true if wifi is disabled by soft driver unload, else false
+ */
+bool hdd_get_wlan_driver_status(void);
+#else
+static inline bool hdd_get_wlan_driver_status(void)
+{
+	return false;
+}
+#endif
+
 /**
  * enum wlan_state_ctrl_str_id - state contrl param string id
  * @WLAN_OFF_STR: Turn OFF WiFi
@@ -1975,13 +1989,15 @@ struct hdd_rtpm_tput_policy_context {
  * @WLAN_ENABLE_STR: Enable WiFi
  * @WLAN_DISABLE_STR: Disable Wifi
  * @WLAN_WAIT_FOR_READY_STR: Driver should wait for ongoing recovery
+ * @WLAN_FORCE_DISABLE_STR: Disable Wifi by soft driver unload
  */
 enum wlan_state_ctrl_str_id {
 	WLAN_OFF_STR   = 0,
 	WLAN_ON_STR,
 	WLAN_ENABLE_STR,
 	WLAN_DISABLE_STR,
-	WLAN_WAIT_FOR_READY_STR
+	WLAN_WAIT_FOR_READY_STR,
+	WLAN_FORCE_DISABLE_STR
 };
 
 /**

+ 60 - 5
core/hdd/src/wlan_hdd_main.c

@@ -17506,7 +17506,8 @@ static int hdd_validate_wlan_string(const char __user *user_buf)
 		[WLAN_ON_STR] = "ON",
 		[WLAN_ENABLE_STR] = "ENABLE",
 		[WLAN_DISABLE_STR] = "DISABLE",
-		[WLAN_WAIT_FOR_READY_STR] = "WAIT_FOR_READY"
+		[WLAN_WAIT_FOR_READY_STR] = "WAIT_FOR_READY",
+		[WLAN_FORCE_DISABLE_STR] = "FORCE_DISABLE"
 	};
 
 	if (copy_from_user(buf, user_buf, sizeof(buf))) {
@@ -17525,6 +17526,32 @@ static int hdd_validate_wlan_string(const char __user *user_buf)
 #ifdef FEATURE_WLAN_DYNAMIC_IFACE_CTRL
 #define WIFI_DISABLE_SLEEP (10)
 #define WIFI_DISABLE_MAX_RETRY_ATTEMPTS (10)
+static bool g_soft_unload;
+
+bool hdd_get_wlan_driver_status(void)
+{
+	return g_soft_unload;
+}
+
+static void hdd_wlan_soft_driver_load(void)
+{
+	if (g_soft_unload) {
+		hdd_driver_load();
+		g_soft_unload = false;
+	}
+	pr_info("Enabling WiFi\n");
+}
+
+static void hdd_wlan_soft_driver_unload(void)
+{
+	if (g_soft_unload) {
+		hdd_debug_rl("WiFi is already disabled");
+		return;
+	}
+	pr_info("Initiating soft driver unload\n");
+	g_soft_unload = true;
+	hdd_driver_unload();
+}
 
 static int hdd_disable_wifi(struct hdd_context *hdd_ctx)
 {
@@ -17532,6 +17559,11 @@ static int hdd_disable_wifi(struct hdd_context *hdd_ctx)
 	int retries = 0;
 	void *hif_ctx;
 
+	if (g_soft_unload) {
+		hdd_err_rl("WiFi is disabled");
+		return -EINVAL;
+	}
+
 	if (!hdd_ctx) {
 		hdd_err_rl("hdd_ctx is Null");
 		return -EINVAL;
@@ -17583,6 +17615,14 @@ static int hdd_disable_wifi(struct hdd_context *hdd_ctx)
 	return 0;
 }
 #else
+static void hdd_wlan_soft_driver_load(void)
+{
+}
+
+static void hdd_wlan_soft_driver_unload(void)
+{
+}
+
 static int hdd_disable_wifi(struct hdd_context *hdd_ctx)
 {
 	return 0;
@@ -17615,11 +17655,14 @@ static ssize_t wlan_hdd_state_ctrl_param_write(struct file *filp,
 		pr_info("Wifi wait for ready from UI\n");
 		break;
 	case WLAN_ENABLE_STR:
-		pr_info("Enabling WiFi\n");
+		hdd_wlan_soft_driver_load();
 		break;
 	case WLAN_DISABLE_STR:
 		pr_info("Disabling WiFi\n");
 		break;
+	case WLAN_FORCE_DISABLE_STR:
+		hdd_wlan_soft_driver_unload();
+		goto exit;
 	default:
 		hdd_err_rl("Invalid value received from framework");
 		return -EINVAL;
@@ -17667,7 +17710,6 @@ static ssize_t wlan_hdd_state_ctrl_param_write(struct file *filp,
 		}
 		hdd_ctx->is_wlan_disabled = false;
 	}
-
 exit:
 	return count;
 }
@@ -18636,6 +18678,7 @@ int hdd_driver_load(void)
 	struct osif_driver_sync *driver_sync;
 	QDF_STATUS status;
 	int errno;
+	bool soft_load;
 
 	pr_err("%s: Loading driver v%s\n", WLAN_MODULE_NAME,
 	       g_wlan_driver_version);
@@ -18708,12 +18751,21 @@ int hdd_driver_load(void)
 		goto pld_deinit;
 	}
 
+	/* If a soft unload of driver is done, we don't call
+	 * wlan_hdd_state_ctrl_param_destroy() to maintain sync
+	 * with userspace. In Symmetry, during soft load, avoid
+	 * calling wlan_hdd_state_ctrl_param_create().
+	 */
+	soft_load = hdd_get_wlan_driver_status();
+	if (soft_load)
+		goto out;
+
 	errno = wlan_hdd_state_ctrl_param_create();
 	if (errno) {
 		hdd_err("Failed to create ctrl param; errno:%d", errno);
 		goto unregister_driver;
 	}
-
+out:
 	hdd_debug("%s: driver loaded", WLAN_MODULE_NAME);
 	hdd_place_marker(NULL, "DRIVER LOADED", NULL);
 
@@ -18764,6 +18816,7 @@ void hdd_driver_unload(void)
 	struct hdd_context *hdd_ctx;
 	QDF_STATUS status;
 	void *hif_ctx;
+	bool soft_unload;
 
 	pr_info("%s: Unloading driver v%s\n", WLAN_MODULE_NAME,
 		QWLAN_VERSIONSTR);
@@ -18812,7 +18865,9 @@ void hdd_driver_unload(void)
 	 */
 	osif_driver_sync_trans_stop(driver_sync);
 
-	wlan_hdd_state_ctrl_param_destroy();
+	soft_unload = hdd_get_wlan_driver_status();
+	if (!soft_unload)
+		wlan_hdd_state_ctrl_param_destroy();
 
 	/* trigger SoC remove */
 	wlan_hdd_unregister_driver();