Ver Fonte

qcacmn: Fix peer id mismatch on Tx completion

Peer id mismatch is observed when prefetch of HW
descriptor exceeds the last valid descriptor.
To fix this issue, add check to limit prefetch to
the last valid descriptor.

Change-Id: I01582892d55ed1f300d6806e1d8def46f747516b
CRs-Fixed: 3671814
Ripan Deuri há 1 ano atrás
pai
commit
855046f89d
5 ficheiros alterados com 37 adições e 21 exclusões
  1. 3 2
      dp/wifi3.0/be/dp_be_tx.c
  2. 10 8
      dp/wifi3.0/dp_internal.h
  3. 5 2
      dp/wifi3.0/dp_tx.c
  4. 9 2
      dp/wifi3.0/dp_tx.h
  5. 10 7
      hal/wifi3.0/hal_api.h

+ 3 - 2
dp/wifi3.0/be/dp_be_tx.c

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -1238,7 +1238,8 @@ next_desc:
 						       num_avail_for_reap,
 						       hal_ring_hdl,
 						       &last_prefetch_hw_desc,
-						       &last_prefetch_sw_desc);
+						       &last_prefetch_sw_desc,
+						       NULL);
 		}
 	}
 

+ 10 - 8
dp/wifi3.0/dp_internal.h

@@ -4082,15 +4082,16 @@ static inline void *dp_srng_dst_get_next(struct dp_soc *dp_soc,
  * @hal_ring_hdl: opaque pointer to the HAL Rx Destination ring
  * @num_entries: Entry count
  *
- * Return: None
+ * Return: HAL ring descriptor
  */
-static inline void dp_srng_dst_inv_cached_descs(struct dp_soc *dp_soc,
-						hal_ring_handle_t hal_ring_hdl,
-						uint32_t num_entries)
+static inline void *dp_srng_dst_inv_cached_descs(struct dp_soc *dp_soc,
+						 hal_ring_handle_t hal_ring_hdl,
+						 uint32_t num_entries)
 {
 	hal_soc_handle_t hal_soc = dp_soc->hal_soc;
 
-	hal_srng_dst_inv_cached_descs(hal_soc, hal_ring_hdl, num_entries);
+	return hal_srng_dst_inv_cached_descs(hal_soc, hal_ring_hdl,
+					     num_entries);
 }
 #else
 static inline void *dp_srng_dst_get_next(struct dp_soc *dp_soc,
@@ -4101,10 +4102,11 @@ static inline void *dp_srng_dst_get_next(struct dp_soc *dp_soc,
 	return hal_srng_dst_get_next(hal_soc, hal_ring_hdl);
 }
 
-static inline void dp_srng_dst_inv_cached_descs(struct dp_soc *dp_soc,
-						hal_ring_handle_t hal_ring_hdl,
-						uint32_t num_entries)
+static inline void *dp_srng_dst_inv_cached_descs(struct dp_soc *dp_soc,
+						 hal_ring_handle_t hal_ring_hdl,
+						 uint32_t num_entries)
 {
+	return NULL;
 }
 #endif /* QCA_CACHED_RING_DESC */
 

+ 5 - 2
dp/wifi3.0/dp_tx.c

@@ -6704,6 +6704,7 @@ uint32_t dp_tx_comp_handler(struct dp_intr *int_ctx, struct dp_soc *soc,
 {
 	void *tx_comp_hal_desc;
 	void *last_prefetched_hw_desc = NULL;
+	void *last_hw_desc = NULL;
 	struct dp_tx_desc_s *last_prefetched_sw_desc = NULL;
 	hal_soc_handle_t hal_soc;
 	uint8_t buffer_src;
@@ -6753,7 +6754,8 @@ more_data:
 	if (num_avail_for_reap >= quota)
 		num_avail_for_reap = quota;
 
-	dp_srng_dst_inv_cached_descs(soc, hal_ring_hdl, num_avail_for_reap);
+	last_hw_desc = dp_srng_dst_inv_cached_descs(soc, hal_ring_hdl,
+						    num_avail_for_reap);
 	last_prefetched_hw_desc = dp_srng_dst_prefetch_32_byte_desc(hal_soc,
 							    hal_ring_hdl,
 							    num_avail_for_reap);
@@ -6954,7 +6956,8 @@ next_desc:
 					       num_avail_for_reap,
 					       hal_ring_hdl,
 					       &last_prefetched_hw_desc,
-					       &last_prefetched_sw_desc);
+					       &last_prefetched_sw_desc,
+					       last_hw_desc);
 
 		if (dp_tx_comp_loop_pkt_limit_hit(soc, count, max_reap_limit))
 			break;

+ 9 - 2
dp/wifi3.0/dp_tx.h

@@ -781,6 +781,7 @@ static inline QDF_STATUS dp_tx_pdev_init(struct dp_pdev *pdev)
  * @hal_ring_hdl: ring pointer
  * @last_prefetched_hw_desc: pointer to the last prefetched HW descriptor
  * @last_prefetched_sw_desc: pointer to last prefetch SW desc
+ * @last_hw_desc: pointer to last HW desc
  *
  * Return: None
  */
@@ -792,13 +793,18 @@ void dp_tx_prefetch_hw_sw_nbuf_desc(struct dp_soc *soc,
 				    hal_ring_handle_t hal_ring_hdl,
 				    void **last_prefetched_hw_desc,
 				    struct dp_tx_desc_s
-				    **last_prefetched_sw_desc)
+				    **last_prefetched_sw_desc,
+				    void *last_hw_desc)
 {
 	if (*last_prefetched_sw_desc) {
 		qdf_prefetch((uint8_t *)(*last_prefetched_sw_desc)->nbuf);
 		qdf_prefetch((uint8_t *)(*last_prefetched_sw_desc)->nbuf + 64);
 	}
 
+	if (qdf_unlikely(last_hw_desc &&
+			 (*last_prefetched_hw_desc == last_hw_desc)))
+		return;
+
 	if (num_avail_for_reap && *last_prefetched_hw_desc) {
 		soc->arch_ops.tx_comp_get_params_from_hal_desc(soc,
 						       *last_prefetched_hw_desc,
@@ -825,7 +831,8 @@ void dp_tx_prefetch_hw_sw_nbuf_desc(struct dp_soc *soc,
 				    hal_ring_handle_t hal_ring_hdl,
 				    void **last_prefetched_hw_desc,
 				    struct dp_tx_desc_s
-				    **last_prefetched_sw_desc)
+				    **last_prefetched_sw_desc,
+				    void *last_hw_desc)
 {
 }
 #endif

+ 10 - 7
hal/wifi3.0/hal_api.h

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -1810,11 +1810,12 @@ uint32_t hal_srng_dst_num_valid(void *hal_soc,
  *
  * Invalidates a set of cached descriptors starting from TP to cached_HP
  *
- * Return: None
+ * Return: HAL ring descriptor
  */
-static inline void hal_srng_dst_inv_cached_descs(void *hal_soc,
-						 hal_ring_handle_t hal_ring_hdl,
-						 uint32_t entry_count)
+static inline void *
+hal_srng_dst_inv_cached_descs(void *hal_soc,
+			      hal_ring_handle_t hal_ring_hdl,
+			      uint32_t entry_count)
 {
 	struct hal_srng *srng = (struct hal_srng *)hal_ring_hdl;
 	uint32_t *first_desc;
@@ -1826,10 +1827,10 @@ static inline void hal_srng_dst_inv_cached_descs(void *hal_soc,
 	 * API call should be a no op
 	 */
 	if (!(srng->flags & HAL_SRNG_CACHED_DESC))
-		return;
+		return NULL;
 
 	if (!entry_count)
-		return;
+		return NULL;
 
 	first_desc = &srng->ring_base_vaddr[srng->u.dst_ring.tp];
 
@@ -1853,6 +1854,8 @@ static inline void hal_srng_dst_inv_cached_descs(void *hal_soc,
 					      (void *)last_desc);
 	}
 	qdf_dsb();
+
+	return last_desc;
 }
 
 /**