Browse Source

qcacld-3.0: Wait for peer delete in case of del bss

In case of join failure during auth and assoc phase scenario
join response is sent to umac before peer delete response is
received from firmware.

Defer the join response till the peer delete response
is received from firmware.

Change-Id: I380b969d76f4b86508c0523bf7879d8504a5f207
CRs-Fixed: 2036890
Abhishek Singh 7 years ago
parent
commit
e8be9a6950
2 changed files with 157 additions and 55 deletions
  1. 1 0
      core/wma/inc/wma.h
  2. 156 55
      core/wma/src/wma_dev_if.c

+ 1 - 0
core/wma/inc/wma.h

@@ -263,6 +263,7 @@ enum ds_mode {
 
 #define WMA_DEL_P2P_SELF_STA_RSP_START 0x03
 #define WMA_SET_LINK_PEER_RSP 0x04
+#define WMA_DELETE_PEER_RSP 0x05
 #define WMA_VDEV_START_REQUEST_TIMEOUT (6000)   /* 6 seconds */
 #define WMA_VDEV_STOP_REQUEST_TIMEOUT  (6000)   /* 6 seconds */
 

+ 156 - 55
core/wma/src/wma_dev_if.c

@@ -1344,6 +1344,7 @@ static int wma_remove_bss_peer(tp_wma_handle wma, void *pdev,
 	uint8_t peer_id;
 	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
 	uint8_t *mac_addr = NULL;
+	struct wma_target_req *del_req;
 
 	vdev = cdp_get_vdev_from_vdev_id(soc, pdev, vdev_id);
 	if (!vdev) {
@@ -1373,7 +1374,24 @@ static int wma_remove_bss_peer(tp_wma_handle wma, void *pdev,
 	}
 
 	wma_remove_peer(wma, mac_addr, vdev_id, peer, false);
-
+	if (WMI_SERVICE_IS_ENABLED(
+	   wma->wmi_service_bitmap,
+	   WMI_SERVICE_SYNC_DELETE_CMDS)) {
+		WMA_LOGD(FL("Wait for the peer delete. vdev_id %d"),
+				 req_msg->vdev_id);
+		del_req = wma_fill_hold_req(wma,
+				   req_msg->vdev_id,
+				   WMA_DELETE_STA_REQ,
+				   WMA_DELETE_PEER_RSP,
+				   params,
+				   WMA_DELETE_STA_TIMEOUT);
+		if (!del_req) {
+			WMA_LOGE(FL("Failed to allocate request. vdev_id %d"),
+				 req_msg->vdev_id);
+			params->status = QDF_STATUS_E_NOMEM;
+			return -EINVAL;
+		}
+	}
 	return 0;
 }
 
@@ -1421,6 +1439,126 @@ static QDF_STATUS wma_config_active_bpf_mode(t_wma_handle *wma, uint8_t vdev_id)
 						   uc_mode, mcbc_mode);
 }
 
+#ifdef FEATURE_AP_MCC_CH_AVOIDANCE
+/**
+ * wma_check_and_find_mcc_ap() - finds if device is operating AP
+ * in MCC mode or not
+ * @wma: wma handle.
+ * @vdev_id: vdev ID of device for which MCC has to be checked
+ *
+ * This function internally calls wma_find_mcc_ap finds if
+ * device is operating AP in MCC mode or not
+ *
+ * Return: none
+ */
+static void
+wma_check_and_find_mcc_ap(tp_wma_handle wma, uint8_t vdev_id)
+{
+	tpAniSirGlobal mac_ctx = cds_get_context(QDF_MODULE_ID_PE);
+
+	if (NULL == mac_ctx) {
+		WMA_LOGE("%s: Failed to get mac_ctx", __func__);
+		return;
+	}
+	if (mac_ctx->sap.sap_channel_avoidance)
+		wma_find_mcc_ap(wma, vdev_id, false);
+}
+#else
+static inline void
+wma_check_and_find_mcc_ap(tp_wma_handle wma, uint8_t vdev_id)
+{}
+#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */
+
+/**
+ * wma_send_del_bss_response() - send del bss resp to upper layer
+ * @wma: wma handle.
+ * @vdev_id: vdev ID of device for which MCC has to be checked
+ *
+ * This function sends del bss resp to upper layer
+ *
+ * Return: none
+ */
+static void
+wma_send_del_bss_response(tp_wma_handle wma, struct wma_target_req *req,
+	uint8_t vdev_id)
+{
+	struct wma_txrx_node *iface;
+	struct beacon_info *bcn;
+	tpDeleteBssParams params;
+	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
+
+	if (!req) {
+		WMA_LOGE("%s req is NULL", __func__);
+		return;
+	}
+
+	iface = &wma->interfaces[vdev_id];
+	if (!iface->handle) {
+		WMA_LOGE("%s vdev id %d is already deleted",
+			 __func__, vdev_id);
+		if (req->user_data)
+			qdf_mem_free(req->user_data);
+		req->user_data = NULL;
+		return;
+	}
+	params = (tpDeleteBssParams) req->user_data;
+
+	if (wmi_unified_vdev_down_send(wma->wmi_handle,
+	   vdev_id) !=
+	   QDF_STATUS_SUCCESS) {
+		WMA_LOGE("Failed to send vdev down cmd: vdev %d",
+			 vdev_id);
+	} else {
+		wma_vdev_set_mlme_state(wma, vdev_id,
+				WLAN_VDEV_S_STOP);
+		wma_check_and_find_mcc_ap(wma, vdev_id);
+	}
+
+	cdp_fc_vdev_flush(soc, iface->handle);
+	WMA_LOGD("%s, vdev_id: %d, un-pausing tx_ll_queue for VDEV_STOP rsp",
+		 __func__, vdev_id);
+	cdp_fc_vdev_unpause(soc, iface->handle,
+		OL_TXQ_PAUSE_REASON_VDEV_STOP);
+	wma_vdev_clear_pause_bit(vdev_id, PAUSE_TYPE_HOST);
+	qdf_atomic_set(&iface->bss_status, WMA_BSS_STATUS_STOPPED);
+	WMA_LOGD("%s: (type %d subtype %d) BSS is stopped",
+		 __func__, iface->type, iface->sub_type);
+
+	bcn = wma->interfaces[vdev_id].beacon;
+	if (bcn) {
+		WMA_LOGD("%s: Freeing beacon struct %p, template memory %p",
+			 __func__, bcn, bcn->buf);
+		if (bcn->dma_mapped)
+			qdf_nbuf_unmap_single(wma->qdf_dev, bcn->buf,
+					  QDF_DMA_TO_DEVICE);
+			qdf_nbuf_free(bcn->buf);
+			qdf_mem_free(bcn);
+			wma->interfaces[vdev_id].beacon = NULL;
+	}
+
+	/* Timeout status means its WMA generated DEL BSS REQ when ADD
+	 * BSS REQ was timed out to stop the VDEV in this case no need
+	 * to send response to UMAC
+	 */
+	if (params->status == QDF_STATUS_FW_MSG_TIMEDOUT) {
+		qdf_mem_free(req->user_data);
+		req->user_data = NULL;
+		WMA_LOGE("%s: DEL BSS from ADD BSS timeout do not send resp to UMAC (vdev id %x)",
+			 __func__, vdev_id);
+	} else {
+		params->status = QDF_STATUS_SUCCESS;
+		wma_send_msg(wma, WMA_DELETE_BSS_RSP, (void *)params,
+			 0);
+	}
+
+	if (iface->del_staself_req != NULL) {
+		WMA_LOGA("scheduling defered deletion (vdev id %x)",
+			 vdev_id);
+		wma_vdev_detach(wma, iface->del_staself_req, 1);
+	}
+}
+
+
 /**
  * wma_vdev_stop_resp_handler() - vdev stop response handler
  * @handle: wma handle
@@ -1507,7 +1645,6 @@ int wma_vdev_stop_resp_handler(void *handle, uint8_t *cmd_param_info,
 	if (req_msg->msg_type == WMA_DELETE_BSS_REQ) {
 		tpDeleteBssParams params =
 			(tpDeleteBssParams) req_msg->user_data;
-		struct beacon_info *bcn;
 
 		if (resp_event->vdev_id > wma->max_bssid) {
 			WMA_LOGE("%s: Invalid vdev_id %d", __func__,
@@ -1538,60 +1675,12 @@ int wma_vdev_stop_resp_handler(void *handle, uint8_t *cmd_param_info,
 		if (status != 0)
 			goto free_req_msg;
 
-		if (wmi_unified_vdev_down_send(wma->wmi_handle,
-						resp_event->vdev_id) !=
-						QDF_STATUS_SUCCESS) {
-			WMA_LOGE("Failed to send vdev down cmd: vdev %d",
-				 resp_event->vdev_id);
-		} else {
-			wma_vdev_set_mlme_state(wma, resp_event->vdev_id,
-				WLAN_VDEV_S_STOP);
-#ifdef FEATURE_AP_MCC_CH_AVOIDANCE
-		if (mac_ctx->sap.sap_channel_avoidance)
-			wma_find_mcc_ap(wma, resp_event->vdev_id, false);
-#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */
-		}
-		cdp_fc_vdev_flush(soc, iface->handle);
-		WMA_LOGD("%s, vdev_id: %d, un-pausing tx_ll_queue for VDEV_STOP rsp",
-			 __func__, resp_event->vdev_id);
-		cdp_fc_vdev_unpause(soc, iface->handle,
-				     OL_TXQ_PAUSE_REASON_VDEV_STOP);
-		wma_vdev_clear_pause_bit(resp_event->vdev_id, PAUSE_TYPE_HOST);
-		qdf_atomic_set(&iface->bss_status, WMA_BSS_STATUS_STOPPED);
-		WMA_LOGD("%s: (type %d subtype %d) BSS is stopped",
-			 __func__, iface->type, iface->sub_type);
-		bcn = wma->interfaces[resp_event->vdev_id].beacon;
-
-		if (bcn) {
-			WMA_LOGD("%s: Freeing beacon struct %p, template memory %p",
-				 __func__, bcn, bcn->buf);
-			if (bcn->dma_mapped)
-				qdf_nbuf_unmap_single(wma->qdf_dev, bcn->buf,
-						      QDF_DMA_TO_DEVICE);
-			qdf_nbuf_free(bcn->buf);
-			qdf_mem_free(bcn);
-			wma->interfaces[resp_event->vdev_id].beacon = NULL;
-		}
-
-		/* Timeout status means its WMA generated DEL BSS REQ when ADD
-		 * BSS REQ was timed out to stop the VDEV in this case no need
-		 * to send response to UMAC
-		 */
-		if (params->status == QDF_STATUS_FW_MSG_TIMEDOUT) {
-			wma_cleanup_target_req_param(req_msg);
-			WMA_LOGE("%s: DEL BSS from ADD BSS timeout do not send resp to UMAC (vdev id %x)",
-				 __func__, resp_event->vdev_id);
-		} else {
-			params->status = QDF_STATUS_SUCCESS;
-			wma_send_msg(wma, WMA_DELETE_BSS_RSP, (void *)params,
-				     0);
-		}
+		if (WMI_SERVICE_IS_ENABLED(
+		   wma->wmi_service_bitmap,
+		   WMI_SERVICE_SYNC_DELETE_CMDS))
+			goto free_req_msg;
 
-		if (iface->del_staself_req != NULL) {
-			WMA_LOGA("scheduling defered deletion (vdev id %x)",
-				 resp_event->vdev_id);
-			wma_vdev_detach(wma, iface->del_staself_req, 1);
-		}
+		wma_send_del_bss_response(wma, req_msg, resp_event->vdev_id);
 	} else if (req_msg->msg_type == WMA_SET_LINK_STATE) {
 		tpLinkStateParams params =
 			(tpLinkStateParams) req_msg->user_data;
@@ -2368,6 +2457,8 @@ int wma_peer_delete_handler(void *handle, uint8_t *cmd_param_info,
 					req_msg->vdev_id);
 		}
 		wma_send_msg(wma, WMA_SET_LINK_STATE_RSP, (void *)params, 0);
+	} else if (req_msg->type == WMA_DELETE_PEER_RSP) {
+		wma_send_del_bss_response(wma, req_msg, req_msg->vdev_id);
 	}
 	qdf_mem_free(req_msg);
 	return status;
@@ -2465,6 +2556,11 @@ void wma_hold_req_timer(void *data)
 		WMA_LOGA(FL("wma delete peer for set link timed out"));
 		if (wma_crash_on_fw_timeout(wma->fw_timeout_crash) == true)
 			QDF_BUG(0);
+	} else if ((tgt_req->msg_type == WMA_DELETE_STA_REQ) &&
+			(tgt_req->type == WMA_DELETE_PEER_RSP)) {
+		 WMA_LOGE(FL("wma delete peer for del bss req timed out"));
+		if (wma_crash_on_fw_timeout(wma->fw_timeout_crash) == true)
+			QDF_BUG(0);
 	} else {
 		WMA_LOGE(FL("Unhandled timeout for msg_type:%d and type:%d"),
 				tgt_req->msg_type, tgt_req->type);
@@ -2648,6 +2744,11 @@ void wma_vdev_resp_timer(void *data)
 		if (status != 0)
 			goto free_tgt_req;
 
+		if (WMI_SERVICE_IS_ENABLED(
+		   wma->wmi_service_bitmap,
+		   WMI_SERVICE_SYNC_DELETE_CMDS))
+			goto free_tgt_req;
+
 		if (wmi_unified_vdev_down_send(wma->wmi_handle,
 				tgt_req->vdev_id) != QDF_STATUS_SUCCESS) {
 			WMA_LOGE("Failed to send vdev down cmd: vdev %d",