diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index 7071835e93..4d6aeb2431 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -4297,6 +4297,7 @@ static void dp_vdev_detach_wifi3(struct cdp_vdev *vdev_handle, struct dp_pdev *pdev = vdev->pdev; struct dp_soc *soc = pdev->soc; struct dp_neighbour_peer *peer = NULL; + struct dp_neighbour_peer *temp_peer = NULL; /* preconditions */ qdf_assert(vdev); @@ -4337,9 +4338,20 @@ static void dp_vdev_detach_wifi3(struct cdp_vdev *vdev_handle, qdf_spin_unlock_bh(&soc->peer_ref_mutex); qdf_spin_lock_bh(&pdev->neighbour_peer_mutex); - TAILQ_FOREACH(peer, &pdev->neighbour_peers_list, - neighbour_peer_list_elem) { - QDF_ASSERT(peer->vdev != vdev); + if (!soc->hw_nac_monitor_support) { + TAILQ_FOREACH(peer, &pdev->neighbour_peers_list, + neighbour_peer_list_elem) { + QDF_ASSERT(peer->vdev != vdev); + } + } else { + TAILQ_FOREACH_SAFE(peer, &pdev->neighbour_peers_list, + neighbour_peer_list_elem, temp_peer) { + if (peer->vdev == vdev) { + TAILQ_REMOVE(&pdev->neighbour_peers_list, peer, + neighbour_peer_list_elem); + qdf_mem_free(peer); + } + } } qdf_spin_unlock_bh(&pdev->neighbour_peer_mutex); @@ -4937,8 +4949,10 @@ static int dp_update_filter_neighbour_peers(struct cdp_vdev *vdev_handle, } } /* last neighbour deleted */ - if (TAILQ_EMPTY(&pdev->neighbour_peers_list)) + if (TAILQ_EMPTY(&pdev->neighbour_peers_list)) { pdev->neighbour_peers_added = false; + dp_ppdu_ring_cfg(pdev); + } qdf_spin_unlock_bh(&pdev->neighbour_peer_mutex); @@ -9405,7 +9419,6 @@ void *dp_soc_init(void *dpsoc, HTC_HANDLE htc_handle, void *hif_handle) wlan_cfg_set_reo_dst_ring_size(soc->wlan_cfg_ctx, REO_DST_RING_SIZE_QCA8074); wlan_cfg_set_raw_mode_war(soc->wlan_cfg_ctx, true); - soc->hw_nac_monitor_support = 1; break; case TARGET_TYPE_QCA8074V2: case TARGET_TYPE_QCA6018: diff --git a/dp/wifi3.0/dp_rx.h b/dp/wifi3.0/dp_rx.h index 8db9135c6b..ec12336379 100644 --- a/dp/wifi3.0/dp_rx.h +++ b/dp/wifi3.0/dp_rx.h @@ -405,6 +405,9 @@ dp_rx_wds_srcport_learn(struct dp_soc *soc, struct dp_ast_entry *ast; uint16_t sa_idx; bool del_in_progress; + uint8_t sa_is_valid; + struct dp_neighbour_peer *neighbour_peer = NULL; + struct dp_pdev *pdev = ta_peer->vdev->pdev; if (qdf_unlikely(!ta_peer)) return; @@ -432,7 +435,8 @@ dp_rx_wds_srcport_learn(struct dp_soc *soc, memcpy(wds_src_mac, (qdf_nbuf_data(nbuf) + IEEE80211_ADDR_LEN), IEEE80211_ADDR_LEN); - if (qdf_unlikely(!hal_rx_msdu_end_sa_is_valid_get(rx_tlv_hdr))) { + sa_is_valid = hal_rx_msdu_end_sa_is_valid_get(rx_tlv_hdr); + if (qdf_unlikely(!sa_is_valid)) { ret = dp_peer_add_ast(soc, ta_peer, wds_src_mac, @@ -486,8 +490,38 @@ dp_rx_wds_srcport_learn(struct dp_soc *soc, wds_src_mac, CDP_TXRX_AST_TYPE_WDS, flags); + return; + } else { + /* In HKv2 smart monitor case, when NAC client is + * added first and this client roams within BSS to + * connect to RE, since we have an AST entry for + * NAC we get sa_is_valid bit set. So we check if + * smart monitor is enabled and send add_ast command + * to FW. + */ + if (pdev->neighbour_peers_added) { + qdf_spin_lock_bh(&pdev->neighbour_peer_mutex); + TAILQ_FOREACH(neighbour_peer, + &pdev->neighbour_peers_list, + neighbour_peer_list_elem) { + if (!qdf_mem_cmp(&neighbour_peer->neighbour_peers_macaddr, + wds_src_mac, + DP_MAC_ADDR_LEN)) { + ret = dp_peer_add_ast(soc, + ta_peer, + wds_src_mac, + CDP_TXRX_AST_TYPE_WDS, + flags); + QDF_TRACE(QDF_MODULE_ID_DP, + QDF_TRACE_LEVEL_INFO, + "sa valid and nac roamed to wds"); + break; + } + } + qdf_spin_unlock_bh(&pdev->neighbour_peer_mutex); + } + return; } - return; } diff --git a/dp/wifi3.0/dp_rx_mon_status.c b/dp/wifi3.0/dp_rx_mon_status.c index a6425dd49e..10d1bfc39d 100644 --- a/dp/wifi3.0/dp_rx_mon_status.c +++ b/dp/wifi3.0/dp_rx_mon_status.c @@ -333,9 +333,9 @@ dp_rx_handle_smart_mesh_mode(struct dp_soc *soc, struct dp_pdev *pdev, return 1; } - /* Include 2 bytes of reserved space appended to the msdu payload */ + /* Adding 4 bytes to get to start of 802.11 frame after phy_ppdu_id */ size = (ppdu_info->msdu_info.first_msdu_payload - - qdf_nbuf_data(nbuf)) + 2; + qdf_nbuf_data(nbuf)) + 4; ppdu_info->msdu_info.first_msdu_payload = NULL; if (qdf_nbuf_pull_head(nbuf, size) == NULL) { @@ -345,14 +345,14 @@ dp_rx_handle_smart_mesh_mode(struct dp_soc *soc, struct dp_pdev *pdev, return 1; } - /* only retain RX MSDU payload in the skb */ + /* Only retain RX MSDU payload in the skb */ qdf_nbuf_trim_tail(nbuf, qdf_nbuf_len(nbuf) - ppdu_info->msdu_info.payload_len); qdf_nbuf_update_radiotap(&(pdev->ppdu_info.rx_status), nbuf, sizeof(struct rx_pkt_tlvs)); pdev->monitor_vdev->osif_rx_mon(pdev->monitor_vdev->osif_vdev, nbuf, NULL); - + pdev->ppdu_info.rx_status.monitor_direct_used = 0; return 0; }