summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNitesh Shah <niteshs@codeaurora.org>2017-02-13 18:02:25 +0530
committerqcabuildsw <qcabuildsw@localhost>2017-02-16 13:48:22 -0800
commit0e770c87bd636510a63acb3be28d40d5dd7e4cea (patch)
tree2cbb669689a53de3bb7a3e274368271d26ef1b8d
parenta76b88e6589a7e747c743db02746ba74128e420c (diff)
qcacld-3.0: Avoid sending frame before ready on channel event
If the ROC is requested from the supplicant, the driver sends scan request to the firmware. The driver start the timeout after receiving ready on channel event from the firmware. While packet transmission, if the channel is same and timer is not running, the driver assumes that it is in the listen channel and thus transmits the frame. But this condition even meets while the driver waits for ready on channel event, and thus, it sends the frame in the wrong channel. The fix is to wait for the ready on channel event if the timer is not running. The change also address that ROC is dequeued only after cancel ROC is completed. Change-Id: If35c75e4bda4f11913a1326896754f29ac43946a CRs-Fixed: 2005917
-rw-r--r--core/hdd/src/wlan_hdd_p2p.c43
1 files changed, 31 insertions, 12 deletions
diff --git a/core/hdd/src/wlan_hdd_p2p.c b/core/hdd/src/wlan_hdd_p2p.c
index 79f1cb01b8df..7e6f7267744d 100644
--- a/core/hdd/src/wlan_hdd_p2p.c
+++ b/core/hdd/src/wlan_hdd_p2p.c
@@ -225,15 +225,6 @@ QDF_STATUS wlan_hdd_remain_on_channel_callback(tHalHandle hHal, void *pCtx,
req_type = pRemainChanCtx->rem_on_chan_request;
mutex_unlock(&cfgState->remain_on_chan_ctx_lock);
- /* Schedule any pending RoC: Any new roc request during this time
- * would have got queued in 'wlan_hdd_request_remain_on_channel'
- * since the queue is not empty. So, the roc at the head of the
- * queue will only get the priority. Scheduling the work queue
- * after sending any cancel remain on channel event will also
- * ensure that the cancel roc is sent without any delays.
- */
- schedule_delayed_work(&hdd_ctx->roc_req_work, 0);
-
if ((QDF_STA_MODE == pAdapter->device_mode) ||
(QDF_P2P_CLIENT_MODE == pAdapter->device_mode) ||
(QDF_P2P_DEVICE_MODE == pAdapter->device_mode)
@@ -270,6 +261,17 @@ QDF_STATUS wlan_hdd_remain_on_channel_callback(tHalHandle hHal, void *pCtx,
complete(&pAdapter->cancel_rem_on_chan_var);
if (QDF_STATUS_SUCCESS != status)
complete(&pAdapter->rem_on_chan_ready_event);
+
+ /* If we schedule work queue to start new RoC before completing
+ * cancel_rem_on_chan_var then the work queue may immediately get
+ * scheduled and update cfgState->remain_on_chan_ctx which is referred
+ * in mgmt_tx. Due to this update the the mgmt_tx may extend the roc
+ * which was already completed. This will lead to mgmt tx failure.
+ * Always schedule below work queue only after completing the
+ * cancel_rem_on_chan_var event.
+ */
+ schedule_delayed_work(&hdd_ctx->roc_req_work, 0);
+
return QDF_STATUS_SUCCESS;
}
@@ -1506,9 +1508,26 @@ static int __wlan_hdd_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
mutex_unlock(&cfgState->remain_on_chan_ctx_lock);
mutex_lock(&cfgState->remain_on_chan_ctx_lock);
- if ((cfgState->remain_on_chan_ctx != NULL) &&
- (cfgState->current_freq == chan->center_freq)
- ) {
+ pRemainChanCtx = cfgState->remain_on_chan_ctx;
+
+ /* At this point if remain_on_chan_ctx exists but timer not
+ * running means that roc workqueue requested a new RoC and it
+ * is in progress. So wait for Ready on channel indication */
+ if ((pRemainChanCtx) &&
+ (QDF_TIMER_STATE_RUNNING !=
+ qdf_mc_timer_get_current_state(
+ &pRemainChanCtx->hdd_remain_on_chan_timer))) {
+ hdd_notice("remain_on_chan_ctx exists but RoC timer not running. wait for ready on channel");
+ rc = wait_for_completion_timeout(&pAdapter->
+ rem_on_chan_ready_event,
+ msecs_to_jiffies
+ (WAIT_REM_CHAN_READY));
+ if (!rc)
+ hdd_err("timeout waiting for remain on channel ready indication");
+ }
+
+ if ((pRemainChanCtx != NULL) &&
+ (cfgState->current_freq == chan->center_freq)) {
mutex_unlock(&cfgState->remain_on_chan_ctx_lock);
hdd_notice("action frame: extending the wait time");
extendedWait = (uint16_t) wait;