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
This commit is contained in:
Aditya Kodukula
2022-04-11 16:41:46 -07:00
committed by Madan Koyyalamudi
parent c4ca02df28
commit cc931d504b
2 changed files with 77 additions and 6 deletions

View File

@@ -1968,6 +1968,20 @@ struct hdd_rtpm_tput_policy_context {
}; };
#endif #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 * enum wlan_state_ctrl_str_id - state contrl param string id
* @WLAN_OFF_STR: Turn OFF WiFi * @WLAN_OFF_STR: Turn OFF WiFi
@@ -1975,13 +1989,15 @@ struct hdd_rtpm_tput_policy_context {
* @WLAN_ENABLE_STR: Enable WiFi * @WLAN_ENABLE_STR: Enable WiFi
* @WLAN_DISABLE_STR: Disable Wifi * @WLAN_DISABLE_STR: Disable Wifi
* @WLAN_WAIT_FOR_READY_STR: Driver should wait for ongoing recovery * @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 { enum wlan_state_ctrl_str_id {
WLAN_OFF_STR = 0, WLAN_OFF_STR = 0,
WLAN_ON_STR, WLAN_ON_STR,
WLAN_ENABLE_STR, WLAN_ENABLE_STR,
WLAN_DISABLE_STR, WLAN_DISABLE_STR,
WLAN_WAIT_FOR_READY_STR WLAN_WAIT_FOR_READY_STR,
WLAN_FORCE_DISABLE_STR
}; };
/** /**

View File

@@ -17506,7 +17506,8 @@ static int hdd_validate_wlan_string(const char __user *user_buf)
[WLAN_ON_STR] = "ON", [WLAN_ON_STR] = "ON",
[WLAN_ENABLE_STR] = "ENABLE", [WLAN_ENABLE_STR] = "ENABLE",
[WLAN_DISABLE_STR] = "DISABLE", [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))) { 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 #ifdef FEATURE_WLAN_DYNAMIC_IFACE_CTRL
#define WIFI_DISABLE_SLEEP (10) #define WIFI_DISABLE_SLEEP (10)
#define WIFI_DISABLE_MAX_RETRY_ATTEMPTS (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) 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; int retries = 0;
void *hif_ctx; void *hif_ctx;
if (g_soft_unload) {
hdd_err_rl("WiFi is disabled");
return -EINVAL;
}
if (!hdd_ctx) { if (!hdd_ctx) {
hdd_err_rl("hdd_ctx is Null"); hdd_err_rl("hdd_ctx is Null");
return -EINVAL; return -EINVAL;
@@ -17583,6 +17615,14 @@ static int hdd_disable_wifi(struct hdd_context *hdd_ctx)
return 0; return 0;
} }
#else #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) static int hdd_disable_wifi(struct hdd_context *hdd_ctx)
{ {
return 0; 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"); pr_info("Wifi wait for ready from UI\n");
break; break;
case WLAN_ENABLE_STR: case WLAN_ENABLE_STR:
pr_info("Enabling WiFi\n"); hdd_wlan_soft_driver_load();
break; break;
case WLAN_DISABLE_STR: case WLAN_DISABLE_STR:
pr_info("Disabling WiFi\n"); pr_info("Disabling WiFi\n");
break; break;
case WLAN_FORCE_DISABLE_STR:
hdd_wlan_soft_driver_unload();
goto exit;
default: default:
hdd_err_rl("Invalid value received from framework"); hdd_err_rl("Invalid value received from framework");
return -EINVAL; return -EINVAL;
@@ -17667,7 +17710,6 @@ static ssize_t wlan_hdd_state_ctrl_param_write(struct file *filp,
} }
hdd_ctx->is_wlan_disabled = false; hdd_ctx->is_wlan_disabled = false;
} }
exit: exit:
return count; return count;
} }
@@ -18636,6 +18678,7 @@ int hdd_driver_load(void)
struct osif_driver_sync *driver_sync; struct osif_driver_sync *driver_sync;
QDF_STATUS status; QDF_STATUS status;
int errno; int errno;
bool soft_load;
pr_err("%s: Loading driver v%s\n", WLAN_MODULE_NAME, pr_err("%s: Loading driver v%s\n", WLAN_MODULE_NAME,
g_wlan_driver_version); g_wlan_driver_version);
@@ -18708,12 +18751,21 @@ int hdd_driver_load(void)
goto pld_deinit; 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(); errno = wlan_hdd_state_ctrl_param_create();
if (errno) { if (errno) {
hdd_err("Failed to create ctrl param; errno:%d", errno); hdd_err("Failed to create ctrl param; errno:%d", errno);
goto unregister_driver; goto unregister_driver;
} }
out:
hdd_debug("%s: driver loaded", WLAN_MODULE_NAME); hdd_debug("%s: driver loaded", WLAN_MODULE_NAME);
hdd_place_marker(NULL, "DRIVER LOADED", NULL); hdd_place_marker(NULL, "DRIVER LOADED", NULL);
@@ -18764,6 +18816,7 @@ void hdd_driver_unload(void)
struct hdd_context *hdd_ctx; struct hdd_context *hdd_ctx;
QDF_STATUS status; QDF_STATUS status;
void *hif_ctx; void *hif_ctx;
bool soft_unload;
pr_info("%s: Unloading driver v%s\n", WLAN_MODULE_NAME, pr_info("%s: Unloading driver v%s\n", WLAN_MODULE_NAME,
QWLAN_VERSIONSTR); QWLAN_VERSIONSTR);
@@ -18812,7 +18865,9 @@ void hdd_driver_unload(void)
*/ */
osif_driver_sync_trans_stop(driver_sync); 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 */ /* trigger SoC remove */
wlan_hdd_unregister_driver(); wlan_hdd_unregister_driver();