diff --git a/dp/wifi3.0/dp_htt.c b/dp/wifi3.0/dp_htt.c index b8b6eecb6a..09a402aad7 100644 --- a/dp/wifi3.0/dp_htt.c +++ b/dp/wifi3.0/dp_htt.c @@ -4347,6 +4347,27 @@ static void dp_htt_t2h_msg_handler(void *context, HTC_PACKET *pkt) is_wds); break; } + case HTT_T2H_MSG_TYPE_RX_DELBA: + { + uint16_t peer_id; + uint8_t tid; + uint8_t win_sz; + QDF_STATUS status; + + peer_id = HTT_RX_DELBA_PEER_ID_GET(*msg_word); + tid = HTT_RX_DELBA_TID_GET(*msg_word); + win_sz = HTT_RX_DELBA_WIN_SIZE_GET(*msg_word); + + status = dp_rx_delba_ind_handler( + soc->dp_soc, + peer_id, tid, win_sz); + + QDF_TRACE(QDF_MODULE_ID_TXRX, + QDF_TRACE_LEVEL_INFO, + FL("DELBA PeerID %d BAW %d TID %d stat %d"), + peer_id, win_sz, tid, status); + break; + } default: break; }; diff --git a/dp/wifi3.0/dp_htt.h b/dp/wifi3.0/dp_htt.h index c071b9139d..28c486f95c 100644 --- a/dp/wifi3.0/dp_htt.h +++ b/dp/wifi3.0/dp_htt.h @@ -95,6 +95,12 @@ int htt_wbm_event_record(struct htt_logger *h, uint8_t tx_status, #define HTT_PPDU_DESC_MAX_DEPTH 16 #define DP_SCAN_PEER_ID 0xFFFF +#define HTT_RX_DELBA_WIN_SIZE_M 0x0000FC00 +#define HTT_RX_DELBA_WIN_SIZE_S 10 + +#define HTT_RX_DELBA_WIN_SIZE_GET(word) \ + (((word) & HTT_RX_DELBA_WIN_SIZE_M) >> HTT_RX_DELBA_WIN_SIZE_S) + /* * Set the base misclist size to HTT copy engine source ring size * to guarantee that a packet on the misclist wont be freed while it diff --git a/dp/wifi3.0/dp_peer.c b/dp/wifi3.0/dp_peer.c index 1ac912ef4d..3a448fe090 100644 --- a/dp/wifi3.0/dp_peer.c +++ b/dp/wifi3.0/dp_peer.c @@ -2812,6 +2812,8 @@ static void dp_check_ba_buffersize(struct dp_peer *peer, } } +#define DP_RX_BA_SESSION_DISABLE 1 + /* * dp_addba_requestprocess_wifi3() - Process ADDBA request from peer * @@ -2863,6 +2865,25 @@ int dp_addba_requestprocess_wifi3(struct cdp_soc_t *cdp_soc, status = QDF_STATUS_E_FAILURE; goto fail; } + + if (rx_tid->rx_ba_win_size_override == DP_RX_BA_SESSION_DISABLE) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, + "%s disable BA session", + __func__); + + buffersize = 1; + } else if (rx_tid->rx_ba_win_size_override) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, + "%s override BA win to %d", __func__, + rx_tid->rx_ba_win_size_override); + + buffersize = rx_tid->rx_ba_win_size_override; + } else { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, + "%s restore BA win %d based on addba req", + __func__, buffersize); + } + dp_check_ba_buffersize(peer, tid, buffersize); if (dp_rx_tid_setup_wifi3(peer, tid, @@ -2882,6 +2903,9 @@ int dp_addba_requestprocess_wifi3(struct cdp_soc_t *cdp_soc, else rx_tid->statuscode = IEEE80211_STATUS_SUCCESS; + if (rx_tid->rx_ba_win_size_override == DP_RX_BA_SESSION_DISABLE) + rx_tid->statuscode = IEEE80211_STATUS_REFUSED; + qdf_spin_unlock_bh(&rx_tid->tid_lock); fail: @@ -3279,6 +3303,65 @@ dp_rx_sec_ind_handler(struct dp_soc *soc, uint16_t peer_id, dp_peer_unref_del_find_by_id(peer); } +QDF_STATUS +dp_rx_delba_ind_handler(void *soc_handle, uint16_t peer_id, + uint8_t tid, uint16_t win_sz) +{ + struct dp_soc *soc = (struct dp_soc *)soc_handle; + struct dp_peer *peer; + struct dp_rx_tid *rx_tid; + QDF_STATUS status = QDF_STATUS_SUCCESS; + + peer = dp_peer_find_by_id(soc, peer_id); + + if (!peer) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, + "Couldn't find peer from ID %d", + peer_id); + return QDF_STATUS_E_FAILURE; + } + + qdf_assert_always(tid < DP_MAX_TIDS); + + rx_tid = &peer->rx_tid[tid]; + + if (rx_tid->hw_qdesc_vaddr_unaligned) { + if (!rx_tid->delba_tx_status) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, + "%s: PEER_ID: %d TID: %d, BA win: %d ", + __func__, peer_id, tid, win_sz); + + qdf_spin_lock_bh(&rx_tid->tid_lock); + + rx_tid->delba_tx_status = 1; + + rx_tid->rx_ba_win_size_override = + qdf_min((uint16_t)63, win_sz); + + rx_tid->delba_rcode = + IEEE80211_REASON_QOS_SETUP_REQUIRED; + + qdf_spin_unlock_bh(&rx_tid->tid_lock); + + if (soc->cdp_soc.ol_ops->send_delba) + soc->cdp_soc.ol_ops->send_delba( + peer->vdev->pdev->soc->ctrl_psoc, + peer->vdev->vdev_id, + peer->mac_addr.raw, + tid, + rx_tid->delba_rcode); + } + } else { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, + "BA session is not setup for TID:%d ", tid); + status = QDF_STATUS_E_FAILURE; + } + + dp_peer_unref_del_find_by_id(peer); + + return status; +} + #ifdef DP_PEER_EXTENDED_API QDF_STATUS dp_register_peer(struct cdp_soc_t *soc_hdl, uint8_t pdev_id, struct ol_txrx_desc_type *sta_desc) diff --git a/dp/wifi3.0/dp_peer.h b/dp/wifi3.0/dp_peer.h index e2794d3d20..be62b4fa77 100644 --- a/dp/wifi3.0/dp_peer.h +++ b/dp/wifi3.0/dp_peer.h @@ -100,6 +100,10 @@ void dp_rx_peer_unmap_handler(struct dp_soc *soc, uint16_t peer_id, void dp_rx_sec_ind_handler(struct dp_soc *soc, uint16_t peer_id, enum cdp_sec_type sec_type, int is_unicast, u_int32_t *michael_key, u_int32_t *rx_pn); + +QDF_STATUS dp_rx_delba_ind_handler(void *soc_handle, uint16_t peer_id, + uint8_t tid, uint16_t win_sz); + uint8_t dp_get_peer_mac_addr_frm_id(struct cdp_soc_t *soc_handle, uint16_t peer_id, uint8_t *peer_mac); diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index a238233dd0..f8d644c6ef 100644 --- a/dp/wifi3.0/dp_types.h +++ b/dp/wifi3.0/dp_types.h @@ -600,6 +600,9 @@ struct dp_rx_tid { /* Delba reason code for retries */ uint8_t delba_rcode; + /* Coex Override preserved windows size 1 based */ + uint16_t rx_ba_win_size_override; + #ifdef WLAN_PEER_JITTER /* Tx Jitter stats */ uint32_t tx_avg_jitter;