diff --git a/dp/wifi3.0/dp_rx.c b/dp/wifi3.0/dp_rx.c index 9696f2a084..b086966304 100644 --- a/dp/wifi3.0/dp_rx.c +++ b/dp/wifi3.0/dp_rx.c @@ -27,6 +27,7 @@ #include "if_meta_hdr.h" #endif #include "dp_internal.h" +#include "dp_rx_mon.h" /* * dp_rx_buffers_replenish() - replenish rxdma ring with rx nbufs @@ -497,14 +498,56 @@ QDF_STATUS dp_rx_filter_mesh_packets(struct dp_vdev *vdev, qdf_nbuf_t nbuf) #endif #ifdef CONFIG_WIN +/** + * dp_rx_nac_filter(): Function to perform filtering of non-associated + * clients + * @pdev: DP pdev handle + * @rx_pkt_hdr: Rx packet Header + * + * return: dp_vdev* + */ +static +struct dp_vdev *dp_rx_nac_filter(struct dp_pdev *pdev, + uint8_t *rx_pkt_hdr) +{ + struct ieee80211_frame *wh; + struct dp_neighbour_peer *peer = NULL; + + wh = (struct ieee80211_frame *)rx_pkt_hdr; + + if ((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) != IEEE80211_FC1_DIR_TODS) + return NULL; + + qdf_spin_lock_bh(&pdev->neighbour_peer_mutex); + TAILQ_FOREACH(peer, &pdev->neighbour_peers_list, + neighbour_peer_list_elem) { + if (qdf_mem_cmp(&peer->neighbour_peers_macaddr.raw[0], + wh->i_addr2, DP_MAC_ADDR_LEN) == 0) { + QDF_TRACE( + QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, + FL("NAC configuration matched for mac-%2x:%2x:%2x:%2x:%2x:%2x"), + peer->neighbour_peers_macaddr.raw[0], + peer->neighbour_peers_macaddr.raw[1], + peer->neighbour_peers_macaddr.raw[2], + peer->neighbour_peers_macaddr.raw[3], + peer->neighbour_peers_macaddr.raw[4], + peer->neighbour_peers_macaddr.raw[5]); + return pdev->monitor_vdev; + } + } + qdf_spin_unlock_bh(&pdev->neighbour_peer_mutex); + + return NULL; +} + /** * dp_rx_process_invalid_peer(): Function to pass invalid peer list to umac * @soc: DP SOC handle - * @nbuf: nbuf for which peer is invalid + * @mpdu: mpdu for which peer is invalid * * return: integer type */ -uint8_t dp_rx_process_invalid_peer(struct dp_soc *soc, qdf_nbuf_t nbuf) +uint8_t dp_rx_process_invalid_peer(struct dp_soc *soc, qdf_nbuf_t mpdu) { struct dp_invalid_peer_msg msg; struct dp_vdev *vdev = NULL; @@ -513,7 +556,7 @@ uint8_t dp_rx_process_invalid_peer(struct dp_soc *soc, qdf_nbuf_t nbuf) uint8_t i; uint8_t *rx_pkt_hdr; - rx_pkt_hdr = qdf_nbuf_data(nbuf); + rx_pkt_hdr = hal_rx_pkt_hdr_get(qdf_nbuf_data(mpdu)); wh = (struct ieee80211_frame *)rx_pkt_hdr; if (!DP_FRAME_IS_DATA(wh)) { @@ -522,7 +565,7 @@ uint8_t dp_rx_process_invalid_peer(struct dp_soc *soc, qdf_nbuf_t nbuf) return 1; } - if (qdf_nbuf_len(nbuf) < sizeof(struct ieee80211_frame)) { + if (qdf_nbuf_len(mpdu) < sizeof(struct ieee80211_frame)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, "Invalid nbuf length"); return 1; @@ -537,6 +580,16 @@ uint8_t dp_rx_process_invalid_peer(struct dp_soc *soc, qdf_nbuf_t nbuf) continue; } + if (pdev->filter_neighbour_peers) { + /* Next Hop scenario not yet handle */ + vdev = dp_rx_nac_filter(pdev, rx_pkt_hdr); + if (vdev) { + dp_rx_mon_deliver(soc, i, + soc->invalid_peer_head_msdu, + soc->invalid_peer_tail_msdu); + return 0; + } + } TAILQ_FOREACH(vdev, &pdev->vdev_list, vdev_list_elem) { if (qdf_mem_cmp(wh->i_addr1, vdev->mac_addr.raw, DP_MAC_ADDR_LEN) == 0) { @@ -553,7 +606,8 @@ uint8_t dp_rx_process_invalid_peer(struct dp_soc *soc, qdf_nbuf_t nbuf) out: msg.wh = wh; - msg.nbuf = nbuf; + qdf_nbuf_pull_head(mpdu, RX_PKT_TLVS_LEN); + msg.nbuf = mpdu; msg.vdev_id = vdev->vdev_id; if (pdev->soc->cdp_soc.ol_ops->rx_invalid_peer) return pdev->soc->cdp_soc.ol_ops->rx_invalid_peer( @@ -562,7 +616,7 @@ out: return 0; } #else -uint8_t dp_rx_process_invalid_peer(struct dp_soc *soc, qdf_nbuf_t nbuf) +uint8_t dp_rx_process_invalid_peer(struct dp_soc *soc, qdf_nbuf_t mpdu) { return 0; } @@ -863,7 +917,6 @@ done: */ /* Peer lookup failed */ if (!peer && !vdev) { - dp_rx_process_invalid_peer(soc, nbuf); DP_STATS_INC_PKT(soc, rx.err.rx_invalid_peer, 1, qdf_nbuf_len(nbuf)); diff --git a/dp/wifi3.0/dp_rx_err.c b/dp/wifi3.0/dp_rx_err.c index 30dd9e82ce..d5022b2229 100644 --- a/dp/wifi3.0/dp_rx_err.c +++ b/dp/wifi3.0/dp_rx_err.c @@ -199,6 +199,30 @@ dp_rx_2k_jump_handle(struct dp_soc *soc, void *ring_desc, head, tail, quota); } +static bool +dp_rx_chain_msdus(struct dp_soc *soc, qdf_nbuf_t nbuf, + struct dp_rx_desc *rx_desc) +{ + bool mpdu_done = false; + + if (hal_rx_msdu_end_first_msdu_get(rx_desc->rx_buf_start)) { + qdf_nbuf_set_chfrag_start(rx_desc->nbuf, 1); + soc->invalid_peer_head_msdu = NULL; + soc->invalid_peer_tail_msdu = NULL; + } + + if (hal_rx_msdu_end_last_msdu_get(rx_desc->rx_buf_start)) { + qdf_nbuf_set_chfrag_end(rx_desc->nbuf, 1); + mpdu_done = true; + } + + DP_RX_LIST_APPEND(soc->invalid_peer_head_msdu, + soc->invalid_peer_tail_msdu, + nbuf); + + return mpdu_done; +} + /** * dp_rx_null_q_desc_handle() - Function to handle NULL Queue * descriptor violation on either a @@ -271,11 +295,17 @@ dp_rx_null_q_desc_handle(struct dp_soc *soc, struct dp_rx_desc *rx_desc, peer = dp_peer_find_by_id(soc, peer_id); if (!peer) { + bool mpdu_done = false; + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, FL("peer is NULL")); - qdf_nbuf_pull_head(nbuf, RX_PKT_TLVS_LEN); - dp_rx_process_invalid_peer(soc, nbuf); - goto fail; + + mpdu_done = dp_rx_chain_msdus(soc, nbuf, rx_desc); + if (mpdu_done) + dp_rx_process_invalid_peer(soc, nbuf); + + dp_rx_add_to_free_desc_list(head, tail, rx_desc); + return rx_bufs_used; } vdev = peer->vdev; diff --git a/dp/wifi3.0/dp_rx_mon.h b/dp/wifi3.0/dp_rx_mon.h index 88801d2eb4..7bf371760e 100644 --- a/dp/wifi3.0/dp_rx_mon.h +++ b/dp/wifi3.0/dp_rx_mon.h @@ -46,4 +46,6 @@ QDF_STATUS dp_rx_pdev_mon_status_attach(struct dp_pdev *pdev); QDF_STATUS dp_rx_pdev_mon_status_detach(struct dp_pdev *pdev); uint32_t dp_mon_process(struct dp_soc *soc, uint32_t mac_id, uint32_t quota); +QDF_STATUS dp_rx_mon_deliver(struct dp_soc *soc, uint32_t mac_id, + qdf_nbuf_t head_msdu, qdf_nbuf_t tail_msdu); #endif diff --git a/dp/wifi3.0/dp_rx_mon_dest.c b/dp/wifi3.0/dp_rx_mon_dest.c index fb6b97e230..206de87477 100644 --- a/dp/wifi3.0/dp_rx_mon_dest.c +++ b/dp/wifi3.0/dp_rx_mon_dest.c @@ -609,7 +609,6 @@ void dp_rx_extract_radiotap_info(struct cdp_mon_status *rx_status, /* TODO: rx_mon_status->vht_flag_values1 */ } -static inline QDF_STATUS dp_rx_mon_deliver(struct dp_soc *soc, uint32_t mac_id, qdf_nbuf_t head_msdu, qdf_nbuf_t tail_msdu) { @@ -728,7 +727,6 @@ void dp_rx_mon_dest_process(struct dp_soc *soc, uint32_t mac_id, uint32_t quota) &head_msdu, &tail_msdu, &npackets, &ppdu_id, &head, &tail); - #if 0 /* Temporary only handle destination ring */ if (ppdu_id != pdev->mon_ppdu_id) { diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index aea2566429..bf9591403f 100644 --- a/dp/wifi3.0/dp_types.h +++ b/dp/wifi3.0/dp_types.h @@ -679,6 +679,9 @@ struct dp_soc { /* Obj Mgr SoC */ struct wlan_objmgr_psoc *psoc; + + qdf_nbuf_t invalid_peer_head_msdu; + qdf_nbuf_t invalid_peer_tail_msdu; }; #define MAX_RX_MAC_RINGS 2 diff --git a/dp/wifi3.0/hal_rx.h b/dp/wifi3.0/hal_rx.h index 125f853f0a..73bd64b48c 100644 --- a/dp/wifi3.0/hal_rx.h +++ b/dp/wifi3.0/hal_rx.h @@ -529,6 +529,15 @@ struct rx_pkt_tlvs { #define RX_PKT_TLVS_LEN (sizeof(struct rx_pkt_tlvs)) +static inline uint8_t +*hal_rx_pkt_hdr_get(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + + return pkt_tlvs->pkt_hdr_tlv.rx_pkt_hdr; + +} + /* * Get msdu_done bit from the RX_ATTENTION TLV */ @@ -1416,6 +1425,55 @@ hal_rx_msdu_end_da_is_mcbc_get(uint8_t *buf) return da_is_mcbc; } +#define HAL_RX_MSDU_END_FIRST_MSDU_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_5_FIRST_MSDU_OFFSET)), \ + RX_MSDU_END_5_FIRST_MSDU_MASK, \ + RX_MSDU_END_5_FIRST_MSDU_LSB)) + + /** + * hal_rx_msdu_end_first_msdu_get: API to get first msdu status + * from rx_msdu_end TLV + * + * @ buf: pointer to the start of RX PKT TLV headers + * Return: first_msdu + */ +static inline uint8_t +hal_rx_msdu_end_first_msdu_get(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + uint8_t first_msdu; + + first_msdu = HAL_RX_MSDU_END_FIRST_MSDU_GET(msdu_end); + + return first_msdu; +} + +#define HAL_RX_MSDU_END_LAST_MSDU_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_5_LAST_MSDU_OFFSET)), \ + RX_MSDU_END_5_LAST_MSDU_MASK, \ + RX_MSDU_END_5_LAST_MSDU_LSB)) + + /** + * hal_rx_msdu_end_last_msdu_get: API to get last msdu status + * from rx_msdu_end TLV + * + * @ buf: pointer to the start of RX PKT TLV headers + * Return: last_msdu + */ +static inline uint8_t +hal_rx_msdu_end_last_msdu_get(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + uint8_t last_msdu; + + last_msdu = HAL_RX_MSDU_END_LAST_MSDU_GET(msdu_end); + + return last_msdu; +} /******************************************************************************* * RX ERROR APIS ******************************************************************************/ @@ -1839,6 +1897,22 @@ enum hal_rx_wbm_rxdma_push_reason { WBM_RELEASE_RING_2_RXDMA_ERROR_CODE_MASK) >> \ WBM_RELEASE_RING_2_RXDMA_ERROR_CODE_LSB) +#define HAL_RX_WBM_FIRST_MSDU_GET(wbm_desc) \ + (((*(((uint32_t *) wbm_desc) + \ + (WBM_RELEASE_RING_4_FIRST_MSDU_OFFSET >> 2))) & \ + WBM_RELEASE_RING_4_FIRST_MSDU_MASK) >> \ + WBM_RELEASE_RING_4_FIRST_MSDU_LSB) + +#define HAL_RX_WBM_LAST_MSDU_GET(wbm_desc) \ + (((*(((uint32_t *) wbm_desc) + \ + (WBM_RELEASE_RING_4_LAST_MSDU_OFFSET >> 2))) & \ + WBM_RELEASE_RING_4_LAST_MSDU_MASK) >> \ + WBM_RELEASE_RING_4_LAST_MSDU_LSB) + +#define HAL_RX_WBM_BUF_COOKIE_GET(wbm_desc) \ + HAL_RX_BUF_COOKIE_GET(&((struct wbm_release_ring *) \ + wbm_desc)->released_buff_or_desc_addr_info) + #define HAL_RX_WBM_BUF_COOKIE_GET(wbm_desc) \ HAL_RX_BUF_COOKIE_GET(&((struct wbm_release_ring *) \ wbm_desc)->released_buff_or_desc_addr_info)