From da15920d5b4a3c9854e6ac3a95f6a08e6497f3c9 Mon Sep 17 00:00:00 2001 From: sumedh baikady Date: Thu, 1 Nov 2018 17:31:23 -0700 Subject: [PATCH] qcacmn: Support for smart monitor on HKv2 Add support for smart monitor feature on HKv2. For HKv2, NAC filtering is done by HW and NAC is programmed directly in the AST table. The NAC entries in AST table have monitor direct bit set and this is obtained by host via monitor status ring. host subscribes for packet header in MD packets. To these filtered packets radiotap header is added and delivered to the stack. Change-Id: I123f986531943e376ac5c492540e01f0b03348c4 --- dp/wifi3.0/dp_main.c | 23 ++++++++++++++++----- dp/wifi3.0/dp_rx.h | 38 +++++++++++++++++++++++++++++++++-- dp/wifi3.0/dp_rx_mon_status.c | 8 ++++---- 3 files changed, 58 insertions(+), 11 deletions(-) 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; }