Bladeren bron

qcacmn: Block Ack state machine enhancement in DP

Move the state to in_progress when we process addba
request and upon tx comletion of addba response, move
the state to active. Any addba request received during
in_progress is ignored and reo queue is updated with
window size 1 and set to inactive.

Change-Id: I69cfbc162d873f9e6842ca3e7971146dafba2695
Crs-fixed: 2188927
Sumedh Baikady 7 jaren geleden
bovenliggende
commit
1c61e0664d
6 gewijzigde bestanden met toevoegingen van 153 en 22 verwijderingen
  1. 29 0
      dp/inc/cdp_txrx_cmn.h
  2. 6 2
      dp/inc/cdp_txrx_ops.h
  3. 2 0
      dp/wifi3.0/dp_internal.h
  4. 3 1
      dp/wifi3.0/dp_main.c
  5. 100 19
      dp/wifi3.0/dp_peer.c
  6. 13 0
      dp/wifi3.0/dp_types.h

+ 29 - 0
dp/inc/cdp_txrx_cmn.h

@@ -951,6 +951,35 @@ cdp_soc_detach(ol_txrx_soc_handle soc)
 	soc->ops->cmn_drv_ops->txrx_soc_detach((void *)soc);
 }
 
+/**
+ * cdp_addba_resp_tx_completion() - Indicate addba response tx
+ * completion to dp to change tid state.
+ * @soc: soc handle
+ * @peer_handle: peer handle
+ * @tid: tid
+ * @status: Tx completion status
+ *
+ * Return: success/failure of tid update
+ */
+static inline int cdp_addba_resp_tx_completion(ol_txrx_soc_handle soc,
+					       void *peer_handle,
+					       uint8_t tid, int status)
+{
+	if (!soc || !soc->ops) {
+		QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG,
+			  "%s: Invalid Instance:", __func__);
+		QDF_BUG(0);
+		return 0;
+	}
+
+	if (!soc->ops->cmn_drv_ops ||
+	    !soc->ops->cmn_drv_ops->addba_resp_tx_completion)
+		return 0;
+
+	return soc->ops->cmn_drv_ops->addba_resp_tx_completion(peer_handle, tid,
+					status);
+}
+
 static inline int cdp_addba_requestprocess(ol_txrx_soc_handle soc,
 	void *peer_handle, uint8_t dialogtoken, uint16_t tid,
 	uint16_t batimeout, uint16_t buffersize, uint16_t startseqnum)

+ 6 - 2
dp/inc/cdp_txrx_ops.h

@@ -250,9 +250,13 @@ struct cdp_cmn_ops {
 
 	void (*txrx_soc_detach)(void *soc);
 
+	int (*addba_resp_tx_completion)(void *peer_handle, uint8_t tid,
+					int status);
+
 	int (*addba_requestprocess)(void *peer_handle, uint8_t dialogtoken,
-		uint16_t tid, uint16_t batimeout, uint16_t buffersize,
-		uint16_t startseqnum);
+				   uint16_t tid, uint16_t batimeout,
+				   uint16_t buffersize,
+				   uint16_t startseqnum);
 
 	void (*addba_responsesetup)(void *peer_handle, uint8_t tid,
 		uint8_t *dialogtoken, uint16_t *statuscode,

+ 2 - 0
dp/wifi3.0/dp_internal.h

@@ -383,6 +383,8 @@ void dp_local_peer_id_free(struct dp_pdev *pdev, struct dp_peer *peer)
 {
 }
 #endif
+int dp_addba_resp_tx_completion_wifi3(void *peer_handle, uint8_t tid,
+	int status);
 extern int dp_addba_requestprocess_wifi3(void *peer_handle,
 	uint8_t dialogtoken, uint16_t tid, uint16_t batimeout,
 	uint16_t buffersize, uint16_t startseqnum);

+ 3 - 1
dp/wifi3.0/dp_main.c

@@ -3879,7 +3879,8 @@ static void *dp_peer_create_wifi3(struct cdp_vdev *vdev_handle,
 		peer->bss_peer = 1;
 		vdev->vap_bss_peer = peer;
 	}
-
+	for (i = 0; i < DP_MAX_TIDS; i++)
+		qdf_spinlock_create(&peer->rx_tid[i].tid_lock);
 
 	dp_local_peer_id_alloc(pdev, peer);
 	DP_STATS_INIT(peer);
@@ -7335,6 +7336,7 @@ static struct cdp_cmn_ops dp_ops_cmn = {
 	.txrx_ath_getstats = dp_get_device_stats,
 	.addba_requestprocess = dp_addba_requestprocess_wifi3,
 	.addba_responsesetup = dp_addba_responsesetup_wifi3,
+	.addba_resp_tx_completion = dp_addba_resp_tx_completion_wifi3,
 	.delba_process = dp_delba_process_wifi3,
 	.set_addba_response = dp_set_addba_response,
 	.get_peer_mac_addr_frm_id = dp_get_peer_mac_addr_frm_id,

+ 100 - 19
dp/wifi3.0/dp_peer.c

@@ -892,6 +892,10 @@ void dp_rx_tid_stats_cb(struct dp_soc *soc, void *cb_ctxt,
 
 	DP_PRINT_STATS("Num of Addba Req = %d\n", rx_tid->num_of_addba_req);
 	DP_PRINT_STATS("Num of Addba Resp = %d\n", rx_tid->num_of_addba_resp);
+	DP_PRINT_STATS("Num of Addba Resp successful = %d\n",
+		       rx_tid->num_addba_rsp_success);
+	DP_PRINT_STATS("Num of Addba Resp failed = %d\n",
+		       rx_tid->num_addba_rsp_failed);
 	DP_PRINT_STATS("Num of Delba Req = %d\n", rx_tid->num_of_delba_req);
 	DP_PRINT_STATS("BA window size   = %d\n", rx_tid->ba_win_size);
 	DP_PRINT_STATS("Pn size = %d\n", rx_tid->pn_size);
@@ -1132,6 +1136,8 @@ static int dp_rx_tid_update_wifi3(struct dp_peer *peer, int tid, uint32_t
 	dp_set_ssn_valid_flag(&params, 0);
 
 	dp_reo_send_cmd(soc, CMD_UPDATE_RX_REO_QUEUE, &params, dp_rx_tid_update_cb, rx_tid);
+
+	rx_tid->ba_win_size = ba_window_size;
 	return 0;
 }
 
@@ -1219,6 +1225,8 @@ int dp_rx_tid_setup_wifi3(struct dp_peer *peer, int tid,
 	rx_tid->num_of_addba_req = 0;
 	rx_tid->num_of_delba_req = 0;
 	rx_tid->num_of_addba_resp = 0;
+	rx_tid->num_addba_rsp_failed = 0;
+	rx_tid->num_addba_rsp_success = 0;
 #ifdef notyet
 	hw_qdesc_size = hal_get_reo_qdesc_size(soc->hal_soc, ba_window_size);
 #else
@@ -1570,6 +1578,9 @@ void dp_peer_rx_cleanup(struct dp_vdev *vdev, struct dp_peer *peer)
 	int tid;
 	uint32_t tid_delete_mask = 0;
 	for (tid = 0; tid < DP_MAX_TIDS; tid++) {
+		struct dp_rx_tid *rx_tid = &peer->rx_tid[tid];
+
+		qdf_spin_lock_bh(&rx_tid->tid_lock);
 		if (peer->rx_tid[tid].hw_qdesc_vaddr_unaligned != NULL) {
 			dp_rx_tid_delete_wifi3(peer, tid);
 
@@ -1579,6 +1590,7 @@ void dp_peer_rx_cleanup(struct dp_vdev *vdev, struct dp_peer *peer)
 
 			tid_delete_mask |= (1 << tid);
 		}
+		qdf_spin_unlock_bh(&rx_tid->tid_lock);
 	}
 #ifdef notyet /* See if FW can remove queues as part of peer cleanup */
 	if (soc->ol_ops->peer_rx_reorder_queue_remove) {
@@ -1587,6 +1599,8 @@ void dp_peer_rx_cleanup(struct dp_vdev *vdev, struct dp_peer *peer)
 			tid_delete_mask);
 	}
 #endif
+	for (tid = 0; tid < DP_MAX_TIDS; tid++)
+		qdf_spinlock_destroy(&peer->rx_tid[tid].tid_lock);
 }
 
 /*
@@ -1606,42 +1620,52 @@ void dp_peer_cleanup(struct dp_vdev *vdev, struct dp_peer *peer)
 }
 
 /*
-* dp_rx_addba_requestprocess_wifi3() – Process ADDBA request from peer
+* dp_rx_addba_resp_tx_completion_wifi3() – Update Rx Tid State
 *
 * @peer: Datapath peer handle
-* @dialogtoken: dialogtoken from ADDBA frame
 * @tid: TID number
-* @startseqnum: Start seq. number received in BA sequence control
-* in ADDBA frame
-*
+* @status: tx completion status
 * Return: 0 on success, error code on failure
 */
-int dp_addba_requestprocess_wifi3(void *peer_handle,
-	uint8_t dialogtoken, uint16_t tid, uint16_t batimeout,
-	uint16_t buffersize, uint16_t startseqnum)
+int dp_addba_resp_tx_completion_wifi3(void *peer_handle,
+				      uint8_t tid, int status)
 {
 	struct dp_peer *peer = (struct dp_peer *)peer_handle;
 	struct dp_rx_tid *rx_tid = &peer->rx_tid[tid];
 
-	if ((rx_tid->ba_status == DP_RX_BA_ACTIVE) &&
-			(rx_tid->hw_qdesc_vaddr_unaligned != NULL))
+	qdf_spin_lock_bh(&rx_tid->tid_lock);
+	if (status) {
+		rx_tid->num_addba_rsp_failed++;
+		dp_rx_tid_update_wifi3(peer, tid, 1, 0);
 		rx_tid->ba_status = DP_RX_BA_INACTIVE;
+		qdf_spin_unlock_bh(&rx_tid->tid_lock);
+		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
+			  "%s: Rx Tid- %d addba rsp tx completion failed!",
+			 __func__, tid);
+		return 0;
+	}
 
-	if (dp_rx_tid_setup_wifi3(peer, tid, buffersize,
-		startseqnum)) {
-		/* TODO: Should we send addba reject in this case */
+	rx_tid->num_addba_rsp_success++;
+	if (rx_tid->ba_status == DP_RX_BA_INACTIVE) {
+		qdf_spin_unlock_bh(&rx_tid->tid_lock);
+		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
+			  "%s: Rx Tid- %d hw qdesc is not in IN_PROGRESS",
+			__func__, tid);
 		return QDF_STATUS_E_FAILURE;
 	}
 
+	if (dp_rx_tid_update_wifi3(peer, tid, rx_tid->ba_win_size,
+				   rx_tid->startseqnum)) {
+		qdf_spin_unlock_bh(&rx_tid->tid_lock);
+		return QDF_STATUS_E_FAILURE;
+	}
 	if (rx_tid->userstatuscode != IEEE80211_STATUS_SUCCESS)
 		rx_tid->statuscode = rx_tid->userstatuscode;
 	else
 		rx_tid->statuscode = IEEE80211_STATUS_SUCCESS;
 
-	rx_tid->dialogtoken = dialogtoken;
 	rx_tid->ba_status = DP_RX_BA_ACTIVE;
-	rx_tid->num_of_addba_req++;
-
+	qdf_spin_unlock_bh(&rx_tid->tid_lock);
 	return 0;
 }
 
@@ -1662,12 +1686,63 @@ void dp_addba_responsesetup_wifi3(void *peer_handle, uint8_t tid,
 	struct dp_peer *peer = (struct dp_peer *)peer_handle;
 	struct dp_rx_tid *rx_tid = &peer->rx_tid[tid];
 
+	qdf_spin_lock_bh(&rx_tid->tid_lock);
 	rx_tid->num_of_addba_resp++;
 	/* setup ADDBA response parameters */
 	*dialogtoken = rx_tid->dialogtoken;
 	*statuscode = rx_tid->statuscode;
 	*buffersize = rx_tid->ba_win_size;
 	*batimeout  = 0;
+	qdf_spin_unlock_bh(&rx_tid->tid_lock);
+}
+
+/*
+ * dp_addba_requestprocess_wifi3() - Process ADDBA request from peer
+ *
+ * @peer: Datapath peer handle
+ * @dialogtoken: dialogtoken from ADDBA frame
+ * @tid: TID number
+ * @batimeout: BA timeout
+ * @buffersize: BA window size
+ * @startseqnum: Start seq. number received in BA sequence control
+ *
+ * Return: 0 on success, error code on failure
+ */
+int dp_addba_requestprocess_wifi3(void *peer_handle,
+				  uint8_t dialogtoken,
+				  uint16_t tid, uint16_t batimeout,
+				  uint16_t buffersize,
+				  uint16_t startseqnum)
+{
+	struct dp_peer *peer = (struct dp_peer *)peer_handle;
+	struct dp_rx_tid *rx_tid = &peer->rx_tid[tid];
+
+	qdf_spin_lock_bh(&rx_tid->tid_lock);
+	rx_tid->num_of_addba_req++;
+	if ((rx_tid->ba_status == DP_RX_BA_ACTIVE &&
+	     rx_tid->hw_qdesc_vaddr_unaligned != NULL) ||
+	    (rx_tid->ba_status == DP_RX_BA_IN_PROGRESS)) {
+		dp_rx_tid_update_wifi3(peer, tid, 1, 0);
+		rx_tid->ba_status = DP_RX_BA_INACTIVE;
+		qdf_spin_unlock_bh(&rx_tid->tid_lock);
+		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
+			  "%s: Rx Tid- %d hw qdesc is already setup",
+			__func__, tid);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	if (dp_rx_tid_setup_wifi3(peer, tid, 1, 0)) {
+		rx_tid->ba_status = DP_RX_BA_INACTIVE;
+		qdf_spin_unlock_bh(&rx_tid->tid_lock);
+		return QDF_STATUS_E_FAILURE;
+	}
+	rx_tid->ba_status = DP_RX_BA_IN_PROGRESS;
+
+	rx_tid->ba_win_size = buffersize;
+	rx_tid->dialogtoken = dialogtoken;
+	rx_tid->startseqnum = startseqnum;
+	qdf_spin_unlock_bh(&rx_tid->tid_lock);
+	return 0;
 }
 
 /*
@@ -1683,7 +1758,9 @@ void dp_set_addba_response(void *peer_handle, uint8_t tid,
 	struct dp_peer *peer = (struct dp_peer *)peer_handle;
 	struct dp_rx_tid *rx_tid = &peer->rx_tid[tid];
 
+	qdf_spin_lock_bh(&rx_tid->tid_lock);
 	rx_tid->userstatuscode = statuscode;
+	qdf_spin_unlock_bh(&rx_tid->tid_lock);
 }
 
 /*
@@ -1700,9 +1777,11 @@ int dp_delba_process_wifi3(void *peer_handle,
 	struct dp_peer *peer = (struct dp_peer *)peer_handle;
 	struct dp_rx_tid *rx_tid = &peer->rx_tid[tid];
 
-	if (rx_tid->ba_status != DP_RX_BA_ACTIVE)
+	qdf_spin_lock_bh(&rx_tid->tid_lock);
+	if (rx_tid->ba_status == DP_RX_BA_INACTIVE) {
+		qdf_spin_unlock_bh(&rx_tid->tid_lock);
 		return QDF_STATUS_E_FAILURE;
-
+	}
 	/* TODO: See if we can delete the existing REO queue descriptor and
 	 * replace with a new one without queue extenstion descript to save
 	 * memory
@@ -1711,7 +1790,7 @@ int dp_delba_process_wifi3(void *peer_handle,
 	dp_rx_tid_update_wifi3(peer, tid, 1, 0);
 
 	rx_tid->ba_status = DP_RX_BA_INACTIVE;
-
+	qdf_spin_unlock_bh(&rx_tid->tid_lock);
 	return 0;
 }
 
@@ -1805,6 +1884,7 @@ dp_set_pn_check_wifi3(struct cdp_vdev *vdev_handle, struct cdp_peer *peer_handle
 
 	for (i = 0; i < DP_MAX_TIDS; i++) {
 		struct dp_rx_tid *rx_tid = &peer->rx_tid[i];
+		qdf_spin_lock_bh(&rx_tid->tid_lock);
 		if (rx_tid->hw_qdesc_vaddr_unaligned != NULL) {
 			params.std.addr_lo =
 				rx_tid->hw_qdesc_paddr & 0xffffffff;
@@ -1832,6 +1912,7 @@ dp_set_pn_check_wifi3(struct cdp_vdev *vdev_handle, struct cdp_peer *peer_handle
 			QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_HIGH,
 				"PN Check not setup for TID :%d \n", i);
 		}
+		qdf_spin_unlock_bh(&rx_tid->tid_lock);
 	}
 }
 

+ 13 - 0
dp/wifi3.0/dp_types.h

@@ -410,6 +410,7 @@ struct dp_rx_reorder_array_elem {
 
 #define DP_RX_BA_INACTIVE 0
 #define DP_RX_BA_ACTIVE 1
+#define DP_RX_BA_IN_PROGRESS 2
 struct dp_reo_cmd_info {
 	uint16_t cmd;
 	enum hal_reo_cmd_type cmd_type;
@@ -432,6 +433,12 @@ struct dp_rx_tid {
 	/* Num of delba requests */
 	uint32_t num_of_delba_req;
 
+	/* Num of addba responses successful */
+	uint32_t num_addba_rsp_success;
+
+	/* Num of addba responses failed */
+	uint32_t num_addba_rsp_failed;
+
 	/* pn size */
 	uint8_t pn_size;
 	/* REO TID queue descriptors */
@@ -446,6 +453,9 @@ struct dp_rx_tid {
 	/* RX BA window size */
 	uint16_t ba_win_size;
 
+	/* Starting sequence number in Addba request */
+	uint16_t startseqnum;
+
 	/* TODO: Check the following while adding defragmentation support */
 	struct dp_rx_reorder_array_elem *array;
 	/* base - single rx reorder element used for non-aggr cases */
@@ -458,6 +468,9 @@ struct dp_rx_tid {
 	void *dst_ring_desc;
 	struct dp_rx_desc *head_frag_desc;
 
+	/* rx_tid lock */
+	qdf_spinlock_t tid_lock;
+
 	/* Sequence and fragments that are being processed currently */
 	uint32_t curr_seq_num;
 	uint32_t curr_frag_num;