diff mbox series

[RFC,net-next,09/28] net: ethernet: ti: cpsw-proxy-client: add helper to init TX DMA Channels

Message ID 20240518124234.2671651-10-s-vadapalli@ti.com (mailing list archive)
State New
Headers show
Series Add CPSW Proxy Client driver | expand

Commit Message

Siddharth Vadapalli May 18, 2024, 12:42 p.m. UTC
Add the "init_tx_chans()" function to initialize the TX DMA Channels.
With the knowledge of the PSI-L Thread IDs allocated to the Client for
each Virtual Port, the TX DMA Channels can be setup using the DMA APIs.

Signed-off-by: Siddharth Vadapalli <s-vadapalli@ti.com>
---
 drivers/net/ethernet/ti/cpsw-proxy-client.c | 115 ++++++++++++++++++++
 1 file changed, 115 insertions(+)
diff mbox series

Patch

diff --git a/drivers/net/ethernet/ti/cpsw-proxy-client.c b/drivers/net/ethernet/ti/cpsw-proxy-client.c
index b057cf4b7bea..efb44ff04b6a 100644
--- a/drivers/net/ethernet/ti/cpsw-proxy-client.c
+++ b/drivers/net/ethernet/ti/cpsw-proxy-client.c
@@ -9,11 +9,20 @@ 
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/rpmsg.h>
+#include <linux/dma/k3-udma-glue.h>
 
 #include "ethfw_abi.h"
+#include "k3-cppi-desc-pool.h"
 
 #define ETHFW_RESPONSE_TIMEOUT_MS	500
 
+#define PS_DATA_SIZE	16
+#define SW_DATA_SIZE	16
+
+#define MAX_TX_DESC	500
+
+#define CHAN_NAME_LEN	128
+
 enum virtual_port_type {
 	VIRT_SWITCH_PORT,
 	VIRT_MAC_ONLY_PORT,
@@ -46,8 +55,14 @@  struct rx_dma_chan {
 
 struct tx_dma_chan {
 	struct virtual_port		*vport;
+	struct device			*dev;
+	struct k3_cppi_desc_pool	*desc_pool;
+	struct k3_udma_glue_tx_channel	*tx_chan;
 	u32				rel_chan_idx;
 	u32				thread_id;
+	u32				num_descs;
+	unsigned int			irq;
+	char				tx_chan_name[CHAN_NAME_LEN];
 	bool				in_use;
 };
 
@@ -68,6 +83,7 @@  struct virtual_port {
 struct cpsw_proxy_priv {
 	struct rpmsg_device		*rpdev;
 	struct device			*dev;
+	struct device_node		*dma_node;
 	struct virtual_port		*virt_ports;
 	struct cpsw_proxy_req_params	req_params;
 	struct mutex			req_params_mutex; /* Request params mutex */
@@ -79,6 +95,7 @@  struct cpsw_proxy_priv {
 	u32				num_switch_ports;
 	u32				num_mac_ports;
 	u32				num_virt_ports;
+	u32				num_active_tx_chans;
 };
 
 static int cpsw_proxy_client_cb(struct rpmsg_device *rpdev, void *data,
@@ -605,6 +622,104 @@  static int allocate_port_resources(struct cpsw_proxy_priv *proxy_priv)
 	return -EIO;
 }
 
+static void free_tx_chns(void *data)
+{
+	struct cpsw_proxy_priv *proxy_priv = data;
+	struct tx_dma_chan *tx_chn;
+	struct virtual_port *vport;
+	u32 i, j;
+
+	for (i = 0; i < proxy_priv->num_virt_ports; i++) {
+		vport = &proxy_priv->virt_ports[i];
+		for (j = 0; j < vport->num_tx_chan; j++) {
+			tx_chn = &vport->tx_chans[j];
+
+			if (!IS_ERR_OR_NULL(tx_chn->desc_pool))
+				k3_cppi_desc_pool_destroy(tx_chn->desc_pool);
+
+			if (!IS_ERR_OR_NULL(tx_chn->tx_chan))
+				k3_udma_glue_release_tx_chn(tx_chn->tx_chan);
+
+			memset(tx_chn, 0, sizeof(*tx_chn));
+		}
+	}
+}
+
+static int init_tx_chans(struct cpsw_proxy_priv *proxy_priv)
+{
+	u32 max_desc_num = ALIGN(MAX_TX_DESC, MAX_SKB_FRAGS);
+	struct k3_udma_glue_tx_channel_cfg tx_cfg = { 0 };
+	struct device *dev = proxy_priv->dev;
+	u32 hdesc_size, tx_chn_num, i, j;
+	char tx_chn_name[CHAN_NAME_LEN];
+	struct k3_ring_cfg ring_cfg = {
+		.elm_size = K3_RINGACC_RING_ELSIZE_8,
+		.mode = K3_RINGACC_RING_MODE_RING,
+		.flags = 0
+	};
+	struct tx_dma_chan *tx_chn;
+	struct virtual_port *vport;
+	int ret = 0, ret1;
+
+	for (i = 0; i < proxy_priv->num_virt_ports; i++) {
+		vport = &proxy_priv->virt_ports[i];
+
+		for (j = 0; j < vport->num_tx_chan; j++) {
+			tx_chn = &vport->tx_chans[j];
+
+			tx_chn_num = proxy_priv->num_active_tx_chans++;
+			snprintf(tx_chn_name, sizeof(tx_chn_name), "tx%u-virt-port-%u",
+				 tx_chn_num, vport->port_id);
+			strscpy(tx_chn->tx_chan_name, tx_chn_name, sizeof(tx_chn->tx_chan_name));
+
+			hdesc_size = cppi5_hdesc_calc_size(true, PS_DATA_SIZE, SW_DATA_SIZE);
+
+			tx_cfg.swdata_size = SW_DATA_SIZE;
+			tx_cfg.tx_cfg = ring_cfg;
+			tx_cfg.txcq_cfg = ring_cfg;
+			tx_cfg.tx_cfg.size = max_desc_num;
+			tx_cfg.txcq_cfg.size = max_desc_num;
+
+			tx_chn->dev = dev;
+			tx_chn->num_descs = max_desc_num;
+			tx_chn->desc_pool = k3_cppi_desc_pool_create_name(dev,
+									  tx_chn->num_descs,
+									  hdesc_size,
+									  tx_chn_name);
+			if (IS_ERR(tx_chn->desc_pool)) {
+				ret = PTR_ERR(tx_chn->desc_pool);
+				dev_err(dev, "failed to create tx pool %d\n", ret);
+				goto err;
+			}
+
+			tx_chn->tx_chan =
+				k3_udma_glue_request_tx_chn_for_thread_id(dev, &tx_cfg,
+									  proxy_priv->dma_node,
+									  tx_chn->thread_id);
+			if (IS_ERR(tx_chn->tx_chan)) {
+				ret = PTR_ERR(tx_chn->tx_chan);
+				dev_err(dev, "Failed to request tx dma channel %d\n", ret);
+				goto err;
+			}
+
+			tx_chn->irq = k3_udma_glue_tx_get_irq(tx_chn->tx_chan);
+			if (tx_chn->irq <= 0) {
+				dev_err(dev, "Failed to get tx dma irq %d\n", tx_chn->irq);
+				ret = -ENXIO;
+			}
+		}
+	}
+
+err:
+	ret1 = devm_add_action(dev, free_tx_chns, proxy_priv);
+	if (ret1) {
+		dev_err(dev, "failed to add free_tx_chns action %d", ret1);
+		return ret1;
+	}
+
+	return ret;
+}
+
 static int cpsw_proxy_client_probe(struct rpmsg_device *rpdev)
 {
 	struct cpsw_proxy_priv *proxy_priv;