Pārlūkot izejas kodu

qcacld-3.0: add FISA flush when vdev detach

  In some case, FISA flush for one FISA entry is missed which
lead to some RX frames stay at FISA entry forever, this will
cause skb leak.
  Do FISA flush per vdev when vdev detach to avoid skb leak.

Change-Id: Ie6bdf885c740a99b089290257ea6936d5804d142
CRs-Fixed: 2679221
Jinwei Chen 4 gadi atpakaļ
vecāks
revīzija
6409e4a8c5

+ 49 - 18
core/dp/txrx3.0/dp_fisa_rx.c

@@ -1104,13 +1104,30 @@ QDF_STATUS dp_rx_dump_fisa_stats(struct dp_soc *soc)
 }
 
 /**
- * dp_rx_fisa_flush() - Flush function to end of context flushing of aggregates
- * @soc: core txrx main context
- * @napi_id: REO number to flush the flow Rxed on the REO
+ * dp_rx_fisa_flush_flow_wrap() - flush fisa flow by invoking
+ *				  dp_rx_fisa_flush_flow()
+ * @sw_ft: fisa flow for which aggregates to be flushed
  *
- * Return: Success on flushing the flows for the REO
+ * Return: None.
  */
-QDF_STATUS dp_rx_fisa_flush(struct dp_soc *soc, int napi_id)
+static void dp_rx_fisa_flush_flow_wrap(struct dp_fisa_rx_sw_ft *sw_ft)
+{
+	/* Save the ip_len and checksum as hardware assist is
+	 * always based on his start of aggregation
+	 */
+	sw_ft->napi_flush_cumulative_l4_checksum =
+				sw_ft->cumulative_l4_checksum;
+	sw_ft->napi_flush_cumulative_ip_length =
+				sw_ft->hal_cumultive_ip_len;
+	dp_fisa_debug("napi_flush_cumulative_ip_length 0x%x",
+		      sw_ft->napi_flush_cumulative_ip_length);
+
+	dp_rx_fisa_flush_flow(sw_ft->vdev,
+			      sw_ft);
+	sw_ft->cur_aggr = 0;
+}
+
+QDF_STATUS dp_rx_fisa_flush_by_ctx_id(struct dp_soc *soc, int napi_id)
 {
 	struct dp_rx_fst *fisa_hdl = soc->rx_fst;
 	struct dp_fisa_rx_sw_ft *sw_ft_entry =
@@ -1123,19 +1140,33 @@ QDF_STATUS dp_rx_fisa_flush(struct dp_soc *soc, int napi_id)
 		    sw_ft_entry[i].is_populated) {
 			dp_fisa_debug("flushing %d %pK napi_id %d", i,
 				      &sw_ft_entry[i], napi_id);
-			/* Save the ip_len and checksum as hardware assist is
-			 * always based on his start of aggregation
-			 */
-			sw_ft_entry[i].napi_flush_cumulative_l4_checksum =
-					sw_ft_entry[i].cumulative_l4_checksum;
-			sw_ft_entry[i].napi_flush_cumulative_ip_length =
-					sw_ft_entry[i].hal_cumultive_ip_len;
-			dp_fisa_debug("napi_flush_cumulative_ip_length 0x%x",
-				sw_ft_entry[i].napi_flush_cumulative_ip_length);
-
-			dp_rx_fisa_flush_flow(sw_ft_entry[i].vdev,
-					      &sw_ft_entry[i]);
-			sw_ft_entry[i].cur_aggr = 0;
+			dp_rx_fisa_flush_flow_wrap(&sw_ft_entry[i]);
+		}
+	}
+
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS dp_rx_fisa_flush_by_vdev_id(struct dp_soc *soc, uint8_t vdev_id)
+{
+	struct dp_rx_fst *fisa_hdl = soc->rx_fst;
+	struct dp_fisa_rx_sw_ft *sw_ft_entry =
+		(struct dp_fisa_rx_sw_ft *)fisa_hdl->base;
+	int ft_size = fisa_hdl->max_entries;
+	int i;
+	struct dp_vdev *vdev;
+
+	vdev = dp_get_vdev_from_soc_vdev_id_wifi3(soc, vdev_id);
+	if (qdf_unlikely(!vdev)) {
+		dp_err("null vdev by vdev_id %d", vdev_id);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	for (i = 0; i < ft_size; i++) {
+		if (vdev == sw_ft_entry[i].vdev) {
+			dp_fisa_debug("flushing %d %pk vdev %pK", i,
+				      &sw_ft_entry[i], vdev);
+			dp_rx_fisa_flush_flow_wrap(&sw_ft_entry[i]);
 		}
 	}
 

+ 11 - 3
core/dp/txrx3.0/dp_fisa_rx.h

@@ -46,15 +46,23 @@ QDF_STATUS dp_fisa_rx(struct dp_soc *dp_fisa_rx_hdl, struct dp_vdev *vdev,
 		      qdf_nbuf_t nbuf_list);
 
 /**
- * dp_rx_fisa_flush() - FISA Rx flush function to flush aggregation at end of
- *			NAPI
+ * dp_rx_fisa_flush_by_ctx_id() - FISA Rx flush function to flush
+ *				  aggregation at end of NAPI
  * @soc: core txrx main context
  * @napi_id: Flows which are rxed on the NAPI ID to be flushed
  *
  * Return: QDF_STATUS
  */
-QDF_STATUS dp_rx_fisa_flush(struct dp_soc *soc, int napi_id);
+QDF_STATUS dp_rx_fisa_flush_by_ctx_id(struct dp_soc *soc, int napi_id);
 
+/**
+ * dp_rx_fisa_flush_by_vdev_id() - Flush fisa aggregates per vdev id
+ * @soc: core txrx main context
+ * @vdev_id: vdev ID
+ *
+ * Return: Success on flushing the flows for the vdev
+ */
+QDF_STATUS dp_rx_fisa_flush_by_vdev_id(struct dp_soc *soc, uint8_t vdev_id);
 #else
 static QDF_STATUS dp_rx_dump_fisa_stats(struct dp_soc *soc)
 {

+ 19 - 3
core/hdd/inc/wlan_hdd_tx_rx.h

@@ -127,13 +127,29 @@ QDF_STATUS hdd_rx_packet_cbk(void *adapter_context, qdf_nbuf_t rxBuf);
 QDF_STATUS hdd_rx_fisa_cbk(void *dp_soc, void *dp_vdev, qdf_nbuf_t rxbuf_list);
 
 /**
- * hdd_rx_fisa_flush() - Flush function to end of context flushing of aggregates
+ * hdd_rx_fisa_flush_by_ctx_id() - Flush function to end of context
+ *				   flushing of aggregates
  * @soc: core txrx main context
- * @napi_id: REO number to flush the flow Rxed on the REO
+ * @ring_num: REO number to flush the flow Rxed on the REO
  *
  * Return: Success on flushing the flows for the REO
  */
-QDF_STATUS hdd_rx_fisa_flush(void *dp_soc, int ring_num);
+QDF_STATUS hdd_rx_fisa_flush_by_ctx_id(void *dp_soc, int ring_num);
+
+/**
+ * hdd_rx_fisa_flush_by_vdev_id() - Flush fisa aggregates per vdev id
+ * @soc: core txrx main context
+ * @vdev_id: vdev ID
+ *
+ * Return: Success on flushing the flows for the vdev
+ */
+QDF_STATUS hdd_rx_fisa_flush_by_vdev_id(void *dp_soc, uint8_t vdev_id);
+#else
+static inline QDF_STATUS hdd_rx_fisa_flush_by_vdev_id(void *dp_soc,
+						      uint8_t vdev_id)
+{
+	return QDF_STATUS_SUCCESS;
+}
 #endif
 
 /**

+ 1 - 1
core/hdd/src/wlan_hdd_assoc.c

@@ -2151,7 +2151,7 @@ static inline void
 hdd_rx_register_fisa_ops(struct ol_txrx_ops *txrx_ops)
 {
 	txrx_ops->rx.osif_fisa_rx = hdd_rx_fisa_cbk;
-	txrx_ops->rx.osif_fisa_flush = hdd_rx_fisa_flush;
+	txrx_ops->rx.osif_fisa_flush = hdd_rx_fisa_flush_by_ctx_id;
 }
 #else
 static inline void

+ 10 - 2
core/hdd/src/wlan_hdd_tx_rx.c

@@ -2062,6 +2062,9 @@ QDF_STATUS hdd_rx_flush_packet_cbk(void *adapter_context, uint8_t vdev_id)
 		return QDF_STATUS_E_FAILURE;
 	}
 
+	/* do fisa flush for this vdev */
+	hdd_rx_fisa_flush_by_vdev_id(soc, vdev_id);
+
 	if (hdd_ctx->enable_dp_rx_threads)
 		dp_txrx_flush_pkts_by_vdev_id(soc, vdev_id);
 
@@ -2077,9 +2080,14 @@ QDF_STATUS hdd_rx_fisa_cbk(void *dp_soc, void *dp_vdev, qdf_nbuf_t nbuf_list)
 			  nbuf_list);
 }
 
-QDF_STATUS hdd_rx_fisa_flush(void *dp_soc, int ring_num)
+QDF_STATUS hdd_rx_fisa_flush_by_ctx_id(void *dp_soc, int ring_num)
+{
+	return dp_rx_fisa_flush_by_ctx_id((struct dp_soc *)dp_soc, ring_num);
+}
+
+QDF_STATUS hdd_rx_fisa_flush_by_vdev_id(void *dp_soc, uint8_t vdev_id)
 {
-	return dp_rx_fisa_flush((struct dp_soc *)dp_soc, ring_num);
+	return dp_rx_fisa_flush_by_vdev_id((struct dp_soc *)dp_soc, vdev_id);
 }
 #endif