From 1c61e0664dab2e53a8adbc58cee84fdbd9d07702 Mon Sep 17 00:00:00 2001 From: Sumedh Baikady Date: Mon, 12 Feb 2018 22:25:47 -0800 Subject: [PATCH] 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 --- dp/inc/cdp_txrx_cmn.h | 29 ++++++++++ dp/inc/cdp_txrx_ops.h | 8 ++- dp/wifi3.0/dp_internal.h | 2 + dp/wifi3.0/dp_main.c | 4 +- dp/wifi3.0/dp_peer.c | 119 ++++++++++++++++++++++++++++++++------- dp/wifi3.0/dp_types.h | 13 +++++ 6 files changed, 153 insertions(+), 22 deletions(-) diff --git a/dp/inc/cdp_txrx_cmn.h b/dp/inc/cdp_txrx_cmn.h index a984ce63b7fb..a984ec5d894c 100644 --- a/dp/inc/cdp_txrx_cmn.h +++ b/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) diff --git a/dp/inc/cdp_txrx_ops.h b/dp/inc/cdp_txrx_ops.h index 0bddb60da755..0e0b772fb2fd 100644 --- a/dp/inc/cdp_txrx_ops.h +++ b/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, diff --git a/dp/wifi3.0/dp_internal.h b/dp/wifi3.0/dp_internal.h index 3bb13aa460a6..c71110f53f9e 100644 --- a/dp/wifi3.0/dp_internal.h +++ b/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); diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index f367d807998c..0d8a99ce9645 100644 --- a/dp/wifi3.0/dp_main.c +++ b/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, diff --git a/dp/wifi3.0/dp_peer.c b/dp/wifi3.0/dp_peer.c index 3969c4b3abcd..f56d82a1e208 100644 --- a/dp/wifi3.0/dp_peer.c +++ b/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(¶ms, 0); dp_reo_send_cmd(soc, CMD_UPDATE_RX_REO_QUEUE, ¶ms, 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); } } diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index 95610deccb84..b341de8194a5 100644 --- a/dp/wifi3.0/dp_types.h +++ b/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;