summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArun Khandavalli <akhandav@qti.qualcomm.com>2016-08-26 17:33:13 +0530
committerqcabuildsw <qcabuildsw@localhost>2016-09-02 17:22:01 -0700
commita172c3e090a3cba9daefad539bb3578b155d8ff9 (patch)
treeb6ded978824965aa9a7a4a444d855e18752f5c84
parent5e4efbec75c9135f58eba684f778ddb95da28401 (diff)
qcacld-3.0: Add check to validate the start/stop modules
With Dynamic mode changes there can be a new race-condition a user-request comes during start/stop modules. When any request from the North bound add check to see if we are in any driver state transition and return failure to the upper layer during the starting/stopping of the modules. Change-Id: I8718bd2293b05a825a791775118d2379cf8f33d2 CRs-Fixed: 1058938
-rw-r--r--core/hdd/inc/wlan_hdd_main.h2
-rw-r--r--core/hdd/src/wlan_hdd_main.c40
2 files changed, 31 insertions, 11 deletions
diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h
index c40aaa33336b..45935579f5dc 100644
--- a/core/hdd/inc/wlan_hdd_main.h
+++ b/core/hdd/inc/wlan_hdd_main.h
@@ -1473,6 +1473,8 @@ struct hdd_context_s {
bool rps;
bool enableRxThread;
bool napi_enable;
+ bool stop_modules_in_progress;
+ bool start_modules_in_progress;
};
/*---------------------------------------------------------------------------
diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c
index 701c9f9c0a1c..37ba53ae5ccd 100644
--- a/core/hdd/src/wlan_hdd_main.c
+++ b/core/hdd/src/wlan_hdd_main.c
@@ -582,6 +582,14 @@ int wlan_hdd_validate_context(hdd_context_t *hdd_ctx)
(void *)_RET_IP_, cds_get_driver_state());
return -EAGAIN;
}
+
+ if (hdd_ctx->start_modules_in_progress ||
+ hdd_ctx->stop_modules_in_progress) {
+ hdd_err("%pS Start/Stop Modules in progress. Ignore!!!",
+ (void *)_RET_IP_);
+ return -EAGAIN;
+ }
+
return 0;
}
@@ -1689,6 +1697,7 @@ int hdd_wlan_start_modules(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
}
mutex_lock(&hdd_ctx->iface_change_lock);
+ hdd_ctx->start_modules_in_progress = true;
if (QDF_TIMER_STATE_RUNNING ==
qdf_mc_timer_get_current_state(&hdd_ctx->iface_change_timer)) {
@@ -1783,6 +1792,7 @@ int hdd_wlan_start_modules(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
hdd_ctx->driver_status);
goto release_lock;
}
+ hdd_ctx->start_modules_in_progress = false;
mutex_unlock(&hdd_ctx->iface_change_lock);
EXIT();
return 0;
@@ -1799,7 +1809,9 @@ power_down:
if (!reinit && !unint)
pld_power_off(qdf_dev->dev);
release_lock:
+ hdd_ctx->start_modules_in_progress = false;
mutex_unlock(&hdd_ctx->iface_change_lock);
+ EXIT();
return -EINVAL;
}
@@ -7246,11 +7258,12 @@ int hdd_wlan_stop_modules(hdd_context_t *hdd_ctx, bool shutdown)
void *hif_ctx;
qdf_device_t qdf_ctx;
QDF_STATUS qdf_status;
- int ret;
+ int ret = 0;
p_cds_sched_context cds_sched_context = NULL;
ENTER();
+
qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
if (!qdf_ctx) {
hdd_err("QDF device context NULL");
@@ -7262,21 +7275,24 @@ int hdd_wlan_stop_modules(hdd_context_t *hdd_ctx, bool shutdown)
hdd_err("cds scheduler context NULL");
return -EINVAL;
}
+ mutex_lock(&hdd_ctx->iface_change_lock);
+ hdd_ctx->stop_modules_in_progress = true;
hdd_info("Present Driver Status: %d", hdd_ctx->driver_status);
switch (hdd_ctx->driver_status) {
case DRIVER_MODULES_UNINITIALIZED:
hdd_info("Modules not initialized just return");
- return 0;
+ goto done;
case DRIVER_MODULES_CLOSED:
hdd_info("Modules already closed");
- return 0;
+ goto done;
case DRIVER_MODULES_ENABLED:
if (hdd_deconfigure_cds(hdd_ctx)) {
hdd_alert("Failed to de-configure CDS");
QDF_ASSERT(0);
- return -EINVAL;
+ ret = -EINVAL;
+ goto done;
}
hdd_info("successfully Disabled the CDS modules!");
hdd_ctx->driver_status = DRIVER_MODULES_OPENED;
@@ -7288,7 +7304,8 @@ int hdd_wlan_stop_modules(hdd_context_t *hdd_ctx, bool shutdown)
hdd_err("Trying to stop wlan in a wrong state: %d",
hdd_ctx->driver_status);
QDF_ASSERT(0);
- return -EINVAL;
+ ret = -EINVAL;
+ goto done;
}
qdf_status = cds_close(hdd_ctx->pcds_context);
@@ -7302,7 +7319,8 @@ int hdd_wlan_stop_modules(hdd_context_t *hdd_ctx, bool shutdown)
hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
if (!hif_ctx) {
hdd_err("Hif context is Null");
- return -EINVAL;
+ ret = -EINVAL;
+ goto done;
}
hdd_hif_close(hif_ctx);
@@ -7317,9 +7335,12 @@ int hdd_wlan_stop_modules(hdd_context_t *hdd_ctx, bool shutdown)
}
hdd_ctx->driver_status = DRIVER_MODULES_CLOSED;
+done:
+ hdd_ctx->stop_modules_in_progress = false;
+ mutex_unlock(&hdd_ctx->iface_change_lock);
EXIT();
- return 0;
+ return ret;
}
@@ -7343,11 +7364,9 @@ static void hdd_iface_change_callback(void *priv)
ENTER();
hdd_info("Interface change timer expired close the modules!");
- mutex_lock(&hdd_ctx->iface_change_lock);
ret = hdd_wlan_stop_modules(hdd_ctx, false);
if (ret)
hdd_alert("Failed to stop modules");
- mutex_unlock(&hdd_ctx->iface_change_lock);
EXIT();
}
@@ -8697,9 +8716,8 @@ static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
hdd_err("Hdd context Null return!");
return -EINVAL;
}
- mutex_lock(&hdd_ctx->iface_change_lock);
+
ret = hdd_wlan_stop_modules(hdd_ctx, false);
- mutex_unlock(&hdd_ctx->iface_change_lock);
if (ret) {
hdd_err("Stop wlan modules failed");
return -EINVAL;