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
This commit is contained in:
Sumedh Baikady 2018-02-12 22:25:47 -08:00 • committed by nshrivas
commit 1c61e0664d
6 changed files with 153 additions and 22 deletions

View file

@ -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)

View file

@ -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,

View file

@ -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);

View file

@ -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,

View file

@ -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);
}
}

View file

@ -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;