瀏覽代碼

qcacmn: Handle flow map/unmap HTT messages for WCN6450

In the case of WCN6450, sizes of the TX descriptor pools are not known
to the driver during load time. The sizes are shared by the firmware
post VDEV creation via HTT_T2H_MSG_TYPE_FLOW_POOL_MAP HTT message.
After the VDEV gets deleted in the firmware, a corresponding flow unmap
HTT message will be sent to the driver to clean up the TX descriptors
of a particular VDEV.

Add logic to handle the flow map/unmap HTT messages for WCN6450. These
messages are specific to WCN6450 and hence the logic is implemented in
arch specific HTT code.

Change-Id: I8edcabbec77abae2c238f487acb7a48b478fd149
CRs-Fixed: 3381751
Manikanta Pubbisetty 2 年之前
父節點
當前提交
cd50866740
共有 3 個文件被更改,包括 132 次插入0 次删除
  1. 2 0
      dp/wifi3.0/dp_main.c
  2. 1 0
      dp/wifi3.0/rh/dp_rh.h
  3. 129 0
      dp/wifi3.0/rh/dp_rh_htt.c

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

@@ -15253,8 +15253,10 @@ static struct cdp_misc_ops dp_ops_misc = {
 static struct cdp_flowctl_ops dp_ops_flowctl = {
 static struct cdp_flowctl_ops dp_ops_flowctl = {
 	/* WIFI 3.0 DP implement as required. */
 	/* WIFI 3.0 DP implement as required. */
 #ifdef QCA_LL_TX_FLOW_CONTROL_V2
 #ifdef QCA_LL_TX_FLOW_CONTROL_V2
+#ifndef WLAN_SOFTUMAC_SUPPORT
 	.flow_pool_map_handler = dp_tx_flow_pool_map,
 	.flow_pool_map_handler = dp_tx_flow_pool_map,
 	.flow_pool_unmap_handler = dp_tx_flow_pool_unmap,
 	.flow_pool_unmap_handler = dp_tx_flow_pool_unmap,
+#endif /*WLAN_SOFTUMAC_SUPPORT */
 	.register_pause_cb = dp_txrx_register_pause_cb,
 	.register_pause_cb = dp_txrx_register_pause_cb,
 	.dump_flow_pool_info = dp_tx_dump_flow_pool_info,
 	.dump_flow_pool_info = dp_tx_dump_flow_pool_info,
 	.tx_desc_thresh_reached = dp_tx_desc_thresh_reached,
 	.tx_desc_thresh_reached = dp_tx_desc_thresh_reached,

+ 1 - 0
dp/wifi3.0/rh/dp_rh.h

@@ -20,6 +20,7 @@
 
 
 #include <dp_types.h>
 #include <dp_types.h>
 #include <dp_mon.h>
 #include <dp_mon.h>
+#include <dp_htt.h>
 #include <hal_rh_tx.h>
 #include <hal_rh_tx.h>
 #include <hal_rh_rx.h>
 #include <hal_rh_rx.h>
 #include <qdf_pkt_add_timestamp.h>
 #include <qdf_pkt_add_timestamp.h>

+ 129 - 0
dp/wifi3.0/rh/dp_rh_htt.c

@@ -23,6 +23,7 @@
 #include "dp_rh_rx.h"
 #include "dp_rh_rx.h"
 #include "qdf_mem.h"
 #include "qdf_mem.h"
 #include "cdp_txrx_cmn_struct.h"
 #include "cdp_txrx_cmn_struct.h"
+#include "dp_tx_desc.h"
 
 
 #define HTT_MSG_BUF_SIZE(msg_bytes) \
 #define HTT_MSG_BUF_SIZE(msg_bytes) \
 	((msg_bytes) + HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING)
 	((msg_bytes) + HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING)
@@ -39,6 +40,86 @@
 					PCI_DMA_FROMDEVICE);		\
 					PCI_DMA_FROMDEVICE);		\
 	} while (0)
 	} while (0)
 
 
+/**
+ * dp_htt_flow_pool_map_handler_rh() - HTT_T2H_MSG_TYPE_FLOW_POOL_MAP handler
+ * @soc: Handle to DP Soc structure
+ * @flow_id: flow id
+ * @flow_type: flow type
+ * @flow_pool_id: pool id
+ * @flow_pool_size: pool size
+ *
+ * Return: QDF_STATUS_SUCCESS - success, others - failure
+ */
+static QDF_STATUS
+dp_htt_flow_pool_map_handler_rh(struct dp_soc *soc, uint8_t flow_id,
+				uint8_t flow_type, uint8_t flow_pool_id,
+				uint32_t flow_pool_size)
+{
+	struct dp_vdev *vdev;
+	struct dp_pdev *pdev;
+	QDF_STATUS status;
+
+	if (flow_pool_id >= MAX_TXDESC_POOLS) {
+		dp_err("invalid flow_pool_id %d", flow_pool_id);
+		return QDF_STATUS_E_INVAL;
+	}
+
+	vdev = dp_vdev_get_ref_by_id(soc, flow_id, DP_MOD_ID_HTT);
+	if (vdev) {
+		pdev = vdev->pdev;
+		dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_HTT);
+	} else {
+		pdev = soc->pdev_list[0];
+	}
+
+	status = dp_tx_flow_pool_map_handler(pdev, flow_id, flow_type,
+					     flow_pool_id, flow_pool_size);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		dp_err("failed to create tx flow pool %d\n", flow_pool_id);
+		goto err_out;
+	}
+
+	return QDF_STATUS_SUCCESS;
+
+err_out:
+	/* TODO: is assert needed ? */
+	qdf_assert_always(0);
+	return status;
+}
+
+/**
+ * dp_htt_flow_pool_unmap_handler_rh() - HTT_T2H_MSG_TYPE_FLOW_POOL_UNMAP handler
+ * @soc: Handle to DP Soc structure
+ * @flow_id: flow id
+ * @flow_type: flow type
+ * @flow_pool_id: pool id
+ *
+ * Return: none
+ */
+static void
+dp_htt_flow_pool_unmap_handler_rh(struct dp_soc *soc, uint8_t flow_id,
+				  uint8_t flow_type, uint8_t flow_pool_id)
+{
+	struct dp_vdev *vdev;
+	struct dp_pdev *pdev;
+
+	if (flow_pool_id >= MAX_TXDESC_POOLS) {
+		dp_err("invalid flow_pool_id %d", flow_pool_id);
+		return;
+	}
+
+	vdev = dp_vdev_get_ref_by_id(soc, flow_id, DP_MOD_ID_HTT);
+	if (vdev) {
+		pdev = vdev->pdev;
+		dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_HTT);
+	} else {
+		pdev = soc->pdev_list[0];
+	}
+
+	dp_tx_flow_pool_unmap_handler(pdev, flow_id, flow_type,
+				      flow_pool_id);
+}
+
 /*
 /*
  * dp_htt_h2t_send_complete_free_netbuf() - Free completed buffer
  * dp_htt_h2t_send_complete_free_netbuf() - Free completed buffer
  * @soc:	SOC handle
  * @soc:	SOC handle
@@ -265,6 +346,54 @@ dp_htt_t2h_msg_handler_fast(void *context, qdf_nbuf_t *cmpl_msdus,
 			dp_htt_t2h_msg_handler(context, &htc_pkt);
 			dp_htt_t2h_msg_handler(context, &htc_pkt);
 			break;
 			break;
 		}
 		}
+		case HTT_T2H_MSG_TYPE_FLOW_POOL_MAP:
+		{
+			uint8_t num_flows;
+			struct htt_flow_pool_map_payload_t *pool_map;
+
+			num_flows = HTT_FLOW_POOL_MAP_NUM_FLOWS_GET(*msg_word);
+
+			if (((HTT_FLOW_POOL_MAP_PAYLOAD_SZ /
+			      HTT_FLOW_POOL_MAP_HEADER_SZ) * num_flows + 1) * sizeof(*msg_word) > msg_len) {
+				dp_htt_err("Invalid flow count in flow pool map message");
+				WARN_ON(1);
+				break;
+			}
+
+			msg_word++;
+
+			while (num_flows) {
+				pool_map = (struct htt_flow_pool_map_payload_t *)msg_word;
+				dp_htt_flow_pool_map_handler_rh(
+					soc->dp_soc, pool_map->flow_id,
+					pool_map->flow_type,
+					pool_map->flow_pool_id,
+					pool_map->flow_pool_size);
+
+				msg_word += (HTT_FLOW_POOL_MAP_PAYLOAD_SZ /
+							 HTT_FLOW_POOL_MAP_HEADER_SZ);
+				num_flows--;
+			}
+
+			break;
+		}
+		case HTT_T2H_MSG_TYPE_FLOW_POOL_UNMAP:
+		{
+			struct htt_flow_pool_unmap_t *pool_unmap;
+
+			if (msg_len < sizeof(struct htt_flow_pool_unmap_t)) {
+				dp_htt_err("Invalid length in flow pool unmap message %d", msg_len);
+				WARN_ON(1);
+				break;
+			}
+
+			pool_unmap = (struct htt_flow_pool_unmap_t *)msg_word;
+			dp_htt_flow_pool_unmap_handler_rh(
+				soc->dp_soc, pool_unmap->flow_id,
+				pool_unmap->flow_type,
+				pool_unmap->flow_pool_id);
+			break;
+		}
 		default:
 		default:
 		{
 		{
 			HTC_PACKET htc_pkt = {0};
 			HTC_PACKET htc_pkt = {0};