Browse Source

qcacmn: MEC loopback check even when sa_is_valid not set

There is a case when the multicast/broadcast frame gets loop backed
even before a MEC WDS entry gets added, in this case
the MEC check based on sa_is_valid will fail, hence added
another ast lookup check.

Also fix the ast entry iterator to use _safe option, since
we are deleting ast entries in the same iterations

Change-Id: I0567893783649d991c3623a61c60fbc63d1a24ef
Tallapragada Kalyan 7 years ago
parent
commit
1c14d5d8e9
5 changed files with 39 additions and 25 deletions
  1. 5 5
      dp/wifi3.0/dp_main.c
  2. 6 2
      dp/wifi3.0/dp_peer.c
  3. 7 2
      dp/wifi3.0/dp_peer.h
  4. 19 14
      dp/wifi3.0/dp_rx_err.c
  5. 2 2
      dp/wifi3.0/dp_types.h

+ 5 - 5
dp/wifi3.0/dp_main.c

@@ -1476,7 +1476,7 @@ static void dp_wds_aging_timer_fn(void *soc_hdl)
 	struct dp_pdev *pdev;
 	struct dp_vdev *vdev;
 	struct dp_peer *peer;
-	struct dp_ast_entry *ase;
+	struct dp_ast_entry *ase, *temp_ase;
 	int i;
 
 	qdf_spin_lock_bh(&soc->ast_lock);
@@ -1485,7 +1485,7 @@ static void dp_wds_aging_timer_fn(void *soc_hdl)
 		pdev = soc->pdev_list[i];
 		DP_PDEV_ITERATE_VDEV_LIST(pdev, vdev) {
 			DP_VDEV_ITERATE_PEER_LIST(vdev, peer) {
-				DP_PEER_ITERATE_ASE_LIST(peer, ase) {
+				DP_PEER_ITERATE_ASE_LIST(peer, ase, temp_ase) {
 					/*
 					 * Do not expire static ast entries
 					 */
@@ -4730,12 +4730,12 @@ static struct cdp_wds_ops dp_ops_wds = {
 static inline void dp_peer_delete_ast_entries(struct dp_soc *soc,
 		struct dp_peer *peer)
 {
-	struct dp_ast_entry *ast_entry;
+	struct dp_ast_entry *ast_entry, *temp_ast_entry;
 	qdf_spin_lock_bh(&soc->ast_lock);
-	DP_PEER_ITERATE_ASE_LIST(peer, ast_entry) {
+	DP_PEER_ITERATE_ASE_LIST(peer, ast_entry, temp_ast_entry) {
 		if (ast_entry->next_hop) {
 			soc->cdp_soc.ol_ops->peer_del_wds_entry(
-					soc->osif_soc,
+					peer->vdev->pdev->osif_pdev,
 					ast_entry->mac_addr.raw);
 		}
 

+ 6 - 2
dp/wifi3.0/dp_peer.c

@@ -375,10 +375,10 @@ static inline void dp_peer_map_ast(struct dp_soc *soc,
 	TAILQ_FOREACH(ast_entry, &peer->ast_entry_list, ase_list_elem) {
 		if (!(qdf_mem_cmp(mac_addr, ast_entry->mac_addr.raw,
 				DP_MAC_ADDR_LEN))) {
-			qdf_spin_unlock_bh(&soc->ast_lock);
 			ast_entry->ast_idx = hw_peer_id;
 			soc->ast_table[hw_peer_id] = ast_entry;
 			ast_entry->is_active = TRUE;
+			qdf_spin_unlock_bh(&soc->ast_lock);
 			return;
 		}
 	}
@@ -415,7 +415,11 @@ int dp_peer_add_ast(struct dp_soc *soc, struct dp_peer *peer,
 	qdf_spin_lock_bh(&soc->ast_lock);
 
 	/* If AST entry already exists , just return from here */
-	if (dp_peer_ast_hash_find(soc, mac_addr, 0)) {
+	ast_entry = dp_peer_ast_hash_find(soc, mac_addr, 0);
+	if (ast_entry) {
+		if (ast_entry->is_mec)
+			ast_entry->is_active = TRUE;
+
 		qdf_spin_unlock_bh(&soc->ast_lock);
 		return 1;
 	}

+ 7 - 2
dp/wifi3.0/dp_peer.h

@@ -54,14 +54,14 @@ void dp_rx_sec_ind_handler(void *soc_handle, uint16_t peer_id,
 uint8_t dp_get_peer_mac_addr_frm_id(struct cdp_soc_t *soc_handle,
 		uint16_t peer_id, uint8_t *peer_mac);
 
-struct dp_ast_entry *dp_peer_ast_hash_find(struct dp_soc *soc,
-		uint8_t *ast_mac_addr, int mac_addr_is_aligned);
 
 #ifdef FEATURE_WDS
 int dp_peer_add_ast(struct dp_soc *soc, struct dp_peer *peer,
 		uint8_t *mac_addr, uint8_t is_self);
 void dp_peer_del_ast(struct dp_soc *soc,
 		struct dp_ast_entry *ast_entry);
+struct dp_ast_entry *dp_peer_ast_hash_find(struct dp_soc *soc,
+		uint8_t *ast_mac_addr, int mac_addr_is_aligned);
 #else
 static inline int dp_peer_add_ast(struct dp_soc *soc, struct dp_peer *peer,
 		uint8_t *mac_addr, uint8_t is_self)
@@ -72,6 +72,11 @@ static inline void dp_peer_del_ast(struct dp_soc *soc,
 		struct dp_ast_entry *ast_entry)
 {
 }
+static inline struct dp_ast_entry *dp_peer_ast_hash_find(struct dp_soc *soc,
+		uint8_t *ast_mac_addr, int mac_addr_is_aligned)
+{
+	return NULL;
+}
 #endif
 
 #ifdef DP_LFR

+ 19 - 14
dp/wifi3.0/dp_rx_err.c

@@ -274,6 +274,9 @@ dp_rx_null_q_desc_handle(struct dp_soc *soc, struct dp_rx_desc *rx_desc,
 	uint16_t peer_id = 0xFFFF;
 	struct dp_peer *peer = NULL;
 	uint32_t sgi, rate_mcs, tid;
+	struct dp_ast_entry *ase;
+	uint16_t sa_idx;
+	uint8_t *data;
 
 	rx_bufs_used++;
 
@@ -353,13 +356,11 @@ dp_rx_null_q_desc_handle(struct dp_soc *soc, struct dp_rx_desc *rx_desc,
 	 * This is a Multicast echo check, drop the pkt if we meet
 	 * the Multicast Echo Check condition
 	 */
+	data = qdf_nbuf_data(nbuf);
+	qdf_spin_lock_bh(&soc->ast_lock);
 	if (hal_rx_msdu_end_sa_is_valid_get(rx_desc->rx_buf_start)) {
-		struct dp_ast_entry *ase;
-		uint16_t sa_idx;
-		uint8_t *nbuf_data = NULL;
-
-		nbuf_data = qdf_nbuf_data(nbuf);
 		sa_idx = hal_rx_msdu_end_sa_idx_get(rx_desc->rx_buf_start);
+
 		if ((sa_idx < 0) || (sa_idx > (WLAN_UMAC_PSOC_MAX_PEERS * 2))) {
 			QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
 					"invalid sa_idx: %d", sa_idx);
@@ -367,18 +368,22 @@ dp_rx_null_q_desc_handle(struct dp_soc *soc, struct dp_rx_desc *rx_desc,
 		}
 
 		ase = soc->ast_table[sa_idx];
-		if (ase) {
-			if (ase->is_mec || (ase->peer != peer)) {
-				QDF_TRACE(QDF_MODULE_ID_DP,
-					QDF_TRACE_LEVEL_INFO,
-					"received pkt with same src mac %pM",
-					&nbuf_data[DP_MAC_ADDR_LEN]);
+	} else
+		ase = dp_peer_ast_hash_find(soc, &data[DP_MAC_ADDR_LEN], 0);
 
-				qdf_nbuf_free(nbuf);
-				goto fail;
-			}
+	if (ase) {
+		if (ase->is_mec || (ase->peer != peer)) {
+			qdf_spin_unlock_bh(&soc->ast_lock);
+			QDF_TRACE(QDF_MODULE_ID_DP,
+				QDF_TRACE_LEVEL_INFO,
+				"received pkt with same src mac %pM",
+				&data[DP_MAC_ADDR_LEN]);
+
+			qdf_nbuf_free(nbuf);
+			goto fail;
 		}
 	}
+	qdf_spin_unlock_bh(&soc->ast_lock);
 
 	/* WDS Source Port Learning */
 	if (qdf_likely(vdev->rx_decap_type == htt_cmn_pkt_type_ethernet))

+ 2 - 2
dp/wifi3.0/dp_types.h

@@ -105,8 +105,8 @@ union dp_rx_desc_list_elem_t;
 #define DP_VDEV_ITERATE_PEER_LIST(_vdev, _peer) \
 	TAILQ_FOREACH((_peer), &(_vdev)->peer_list, peer_list_elem)
 
-#define DP_PEER_ITERATE_ASE_LIST(_peer, _ase) \
-	TAILQ_FOREACH((_ase), &peer->ast_entry_list, ase_list_elem)
+#define DP_PEER_ITERATE_ASE_LIST(_peer, _ase, _temp_ase) \
+	TAILQ_FOREACH_SAFE((_ase), &peer->ast_entry_list, ase_list_elem, (_temp_ase))
 
 #define DP_MUTEX_TYPE qdf_spinlock_t