diff --git a/core/dp/txrx/ol_ctrl_txrx_api.h b/core/dp/txrx/ol_ctrl_txrx_api.h index 7ec9c103ec6b..129ba98b8f83 100644 --- a/core/dp/txrx/ol_ctrl_txrx_api.h +++ b/core/dp/txrx/ol_ctrl_txrx_api.h @@ -108,6 +108,16 @@ ol_rx_err(struct cdp_cfg *cfg_pdev, enum ol_rx_err_type err_type, qdf_nbuf_t rx_frame, uint64_t *pn, uint8_t key_id); +#ifdef HL_RX_AGGREGATION_HOLE_DETECTION +/** + * ol_rx_aggregation_hole - ol rx aggregation hole report + * @hole_info: hole_info + * + * Return: void + */ +void ol_rx_aggregation_hole(uint32_t hole_info); +#endif + enum ol_rx_notify_type { OL_RX_NOTIFY_IPV4_IGMP, }; diff --git a/core/dp/txrx/ol_rx.c b/core/dp/txrx/ol_rx.c index 2b1a57fb22e4..f2e28415bd63 100644 --- a/core/dp/txrx/ol_rx.c +++ b/core/dp/txrx/ol_rx.c @@ -1401,6 +1401,9 @@ void ol_rx_peer_init(struct ol_txrx_pdev_t *pdev, struct ol_txrx_peer_t *peer) /* invalid sequence number */ peer->tids_last_seq[tid] = IEEE80211_SEQ_MAX; + /* invalid reorder index number */ + peer->tids_next_rel_idx[tid] = INVALID_REORDER_INDEX; + } /* * Set security defaults: no PN check, no security. diff --git a/core/dp/txrx/ol_rx_reorder.c b/core/dp/txrx/ol_rx_reorder.c index fa1aefb2f7a4..aa1fe958169f 100644 --- a/core/dp/txrx/ol_rx_reorder.c +++ b/core/dp/txrx/ol_rx_reorder.c @@ -452,6 +452,61 @@ ol_rx_reorder_first_hole(struct ol_txrx_peer_t *peer, *idx_end = tmp_idx; } +#ifdef HL_RX_AGGREGATION_HOLE_DETECTION + +/** + * ol_rx_reorder_detect_hole - ol rx reorder detect hole + * @peer: ol_txrx_peer_t + * @tid: tid + * @idx_start: idx_start + * + * Return: void + */ +static void ol_rx_reorder_detect_hole(struct ol_txrx_peer_t *peer, + uint32_t tid, + uint32_t idx_start) +{ + uint32_t win_sz_mask, next_rel_idx, hole_size; + + if (peer->tids_next_rel_idx[tid] == INVALID_REORDER_INDEX) + return; + + win_sz_mask = peer->tids_rx_reorder[tid].win_sz_mask; + /* Return directly if block-ack not enable */ + if (win_sz_mask == 0) + return; + + idx_start &= win_sz_mask; + next_rel_idx = peer->tids_next_rel_idx[tid] & win_sz_mask; + + if (idx_start != next_rel_idx) { + hole_size = ((int)idx_start - (int)next_rel_idx) & win_sz_mask; + + ol_rx_aggregation_hole(hole_size); + } + + return; +} + +#else + +/** + * ol_rx_reorder_detect_hole - ol rx reorder detect hole + * @peer: ol_txrx_peer_t + * @tid: tid + * @idx_start: idx_start + * + * Return: void + */ +static void ol_rx_reorder_detect_hole(struct ol_txrx_peer_t *peer, + uint32_t tid, + uint32_t idx_start) +{ + /* no-op */ +} + +#endif + void ol_rx_reorder_peer_cleanup(struct ol_txrx_vdev_t *vdev, struct ol_txrx_peer_t *peer) @@ -518,7 +573,7 @@ ol_rx_delba_handler(ol_txrx_pdev_handle pdev, uint16_t peer_id, uint8_t tid) if (peer == NULL) return; - peer->tids_next_rel_idx[tid] = 0xffff; /* invalid value */ + peer->tids_next_rel_idx[tid] = INVALID_REORDER_INDEX; rx_reorder = &peer->tids_rx_reorder[tid]; /* check that there really was a block ack agreement */ @@ -579,6 +634,10 @@ ol_rx_flush_handler(ol_txrx_pdev_handle pdev, return; } } + + if (action == htt_rx_flush_release) + ol_rx_reorder_detect_hole(peer, tid, idx_start); + ol_rx_reorder_flush(vdev, peer, tid, idx_start, idx_end, action); /* * If the rx reorder timeout is handled by host SW, see if there are diff --git a/core/dp/txrx/ol_txrx_types.h b/core/dp/txrx/ol_txrx_types.h index e04859795bed..c7d77db8218b 100644 --- a/core/dp/txrx/ol_txrx_types.h +++ b/core/dp/txrx/ol_txrx_types.h @@ -1322,4 +1322,6 @@ struct ol_rx_remote_data { uint8_t mac_id; }; +#define INVALID_REORDER_INDEX 0xFFFF + #endif /* _OL_TXRX_TYPES__H_ */ diff --git a/core/wma/src/wma_data.c b/core/wma/src/wma_data.c index bf7c71819837..c934378a01fb 100644 --- a/core/wma/src/wma_data.c +++ b/core/wma/src/wma_data.c @@ -2871,6 +2871,38 @@ QDF_STATUS wma_ds_peek_rx_packet_info(cds_pkt_t *pkt, void **pkt_meta, return QDF_STATUS_SUCCESS; } +#ifdef HL_RX_AGGREGATION_HOLE_DETECTION +void ol_rx_aggregation_hole(uint32_t hole_info) +{ + struct sir_sme_rx_aggr_hole_ind *rx_aggr_hole_event; + uint32_t alloc_len; + cds_msg_t cds_msg = { 0 }; + QDF_STATUS status; + + alloc_len = sizeof(*rx_aggr_hole_event) + + sizeof(rx_aggr_hole_event->hole_info_array[0]); + rx_aggr_hole_event = qdf_mem_malloc(alloc_len); + if (NULL == rx_aggr_hole_event) { + WMA_LOGE("%s: Memory allocation failure", __func__); + return; + } + + rx_aggr_hole_event->hole_cnt = 1; + rx_aggr_hole_event->hole_info_array[0] = hole_info; + + cds_msg.type = eWNI_SME_RX_AGGR_HOLE_IND; + cds_msg.bodyptr = rx_aggr_hole_event; + cds_msg.bodyval = 0; + + status = cds_mq_post_message(CDS_MQ_ID_SME, &cds_msg); + if (status != QDF_STATUS_SUCCESS) { + WMA_LOGE("%s: Failed to post aggr event to SME", __func__); + qdf_mem_free(rx_aggr_hole_event); + return; + } +} +#endif + /** * ol_rx_err() - ol rx err handler * @pdev: ol pdev