Переглянути джерело

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
sumedh baikady 6 роки тому
батько
коміт
da15920d5b
3 змінених файлів з 58 додано та 11 видалено
  1. 18 5
      dp/wifi3.0/dp_main.c
  2. 36 2
      dp/wifi3.0/dp_rx.h
  3. 4 4
      dp/wifi3.0/dp_rx_mon_status.c

+ 18 - 5
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:

+ 36 - 2
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;
 	}
 
 

+ 4 - 4
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;
 }