]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
dmaengine: ti: k3-udma-glue: Add function to request RX chan for thread ID
authorSiddharth Vadapalli <s-vadapalli@ti.com>
Wed, 24 Jan 2024 12:43:19 +0000 (18:13 +0530)
committerVinod Koul <vkoul@kernel.org>
Tue, 30 Jan 2024 16:43:52 +0000 (22:13 +0530)
The existing function k3_udma_glue_request_remote_rx_chn() supports
requesting an RX DMA channel and flow by the name of the RX DMA channel.
Add support to request RX DMA channel for a given thread ID in the form of
a new function named k3_udma_glue_request_remote_rx_chn_for_thread_id().
Also, export it for use by drivers which are probed by alternate methods
(non device-tree) but still wish to make use of the existing DMA APIs. Such
drivers could be informed about the thread ID corresponding to the RX DMA
channel by RPMsg for example.

Since the new function k3_udma_glue_request_remote_rx_chn_for_thread_id()
reuses most of the code in k3_udma_glue_request_remote_rx_chn(), create a
new function named k3_udma_glue_request_remote_rx_chn_common() for the
common code.

Signed-off-by: Siddharth Vadapalli <s-vadapalli@ti.com>
Acked-by: Peter Ujfalusi <peter.ujfalusi@gmail.com>
Link: https://lore.kernel.org/r/20240124124319.820002-5-s-vadapalli@ti.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
drivers/dma/ti/k3-udma-glue.c
include/linux/dma/k3-udma-glue.h

index a475bbea35ee153957309d6bbd4859fc314c0cb9..c9b93055dc9d3d7a003474b815317a9587401d47 100644 (file)
@@ -1073,12 +1073,59 @@ err:
        return ERR_PTR(ret);
 }
 
+static int
+k3_udma_glue_request_remote_rx_chn_common(struct k3_udma_glue_rx_channel *rx_chn,
+                                         struct k3_udma_glue_rx_channel_cfg *cfg,
+                                         struct device *dev)
+{
+       int ret, i;
+
+       rx_chn->common.hdesc_size = cppi5_hdesc_calc_size(rx_chn->common.epib,
+                                               rx_chn->common.psdata_size,
+                                               rx_chn->common.swdata_size);
+
+       rx_chn->flows = devm_kcalloc(dev, rx_chn->flow_num,
+                                    sizeof(*rx_chn->flows), GFP_KERNEL);
+       if (!rx_chn->flows)
+               return -ENOMEM;
+
+       rx_chn->common.chan_dev.class = &k3_udma_glue_devclass;
+       rx_chn->common.chan_dev.parent = xudma_get_device(rx_chn->common.udmax);
+       dev_set_name(&rx_chn->common.chan_dev, "rchan_remote-0x%04x-0x%02x",
+                    rx_chn->common.src_thread, rx_chn->flow_id_base);
+       ret = device_register(&rx_chn->common.chan_dev);
+       if (ret) {
+               dev_err(dev, "Channel Device registration failed %d\n", ret);
+               put_device(&rx_chn->common.chan_dev);
+               rx_chn->common.chan_dev.parent = NULL;
+               return ret;
+       }
+
+       if (xudma_is_pktdma(rx_chn->common.udmax)) {
+               /* prepare the channel device as coherent */
+               rx_chn->common.chan_dev.dma_coherent = true;
+               dma_coerce_mask_and_coherent(&rx_chn->common.chan_dev,
+                                            DMA_BIT_MASK(48));
+       }
+
+       ret = k3_udma_glue_allocate_rx_flows(rx_chn, cfg);
+       if (ret)
+               return ret;
+
+       for (i = 0; i < rx_chn->flow_num; i++)
+               rx_chn->flows[i].udma_rflow_id = rx_chn->flow_id_base + i;
+
+       k3_udma_glue_dump_rx_chn(rx_chn);
+
+       return 0;
+}
+
 static struct k3_udma_glue_rx_channel *
 k3_udma_glue_request_remote_rx_chn(struct device *dev, const char *name,
                                   struct k3_udma_glue_rx_channel_cfg *cfg)
 {
        struct k3_udma_glue_rx_channel *rx_chn;
-       int ret, i;
+       int ret;
 
        if (cfg->flow_id_num <= 0 ||
            cfg->flow_id_use_rxchan_id ||
@@ -1109,44 +1156,55 @@ k3_udma_glue_request_remote_rx_chn(struct device *dev, const char *name,
        if (ret)
                goto err;
 
-       rx_chn->common.hdesc_size = cppi5_hdesc_calc_size(rx_chn->common.epib,
-                                               rx_chn->common.psdata_size,
-                                               rx_chn->common.swdata_size);
-
-       rx_chn->flows = devm_kcalloc(dev, rx_chn->flow_num,
-                                    sizeof(*rx_chn->flows), GFP_KERNEL);
-       if (!rx_chn->flows) {
-               ret = -ENOMEM;
+       ret = k3_udma_glue_request_remote_rx_chn_common(rx_chn, cfg, dev);
+       if (ret)
                goto err;
-       }
 
-       rx_chn->common.chan_dev.class = &k3_udma_glue_devclass;
-       rx_chn->common.chan_dev.parent = xudma_get_device(rx_chn->common.udmax);
-       dev_set_name(&rx_chn->common.chan_dev, "rchan_remote-0x%04x-0x%02x",
-                    rx_chn->common.src_thread, rx_chn->flow_id_base);
-       ret = device_register(&rx_chn->common.chan_dev);
-       if (ret) {
-               dev_err(dev, "Channel Device registration failed %d\n", ret);
-               put_device(&rx_chn->common.chan_dev);
-               rx_chn->common.chan_dev.parent = NULL;
-               goto err;
-       }
+       return rx_chn;
 
-       if (xudma_is_pktdma(rx_chn->common.udmax)) {
-               /* prepare the channel device as coherent */
-               rx_chn->common.chan_dev.dma_coherent = true;
-               dma_coerce_mask_and_coherent(&rx_chn->common.chan_dev,
-                                            DMA_BIT_MASK(48));
-       }
+err:
+       k3_udma_glue_release_rx_chn(rx_chn);
+       return ERR_PTR(ret);
+}
 
-       ret = k3_udma_glue_allocate_rx_flows(rx_chn, cfg);
+struct k3_udma_glue_rx_channel *
+k3_udma_glue_request_remote_rx_chn_for_thread_id(struct device *dev,
+                                                struct k3_udma_glue_rx_channel_cfg *cfg,
+                                                struct device_node *udmax_np, u32 thread_id)
+{
+       struct k3_udma_glue_rx_channel *rx_chn;
+       int ret;
+
+       if (cfg->flow_id_num <= 0 ||
+           cfg->flow_id_use_rxchan_id ||
+           cfg->def_flow_cfg ||
+           cfg->flow_id_base < 0)
+               return ERR_PTR(-EINVAL);
+
+       /*
+        * Remote RX channel is under control of Remote CPU core, so
+        * Linux can only request and manipulate by dedicated RX flows
+        */
+
+       rx_chn = devm_kzalloc(dev, sizeof(*rx_chn), GFP_KERNEL);
+       if (!rx_chn)
+               return ERR_PTR(-ENOMEM);
+
+       rx_chn->common.dev = dev;
+       rx_chn->common.swdata_size = cfg->swdata_size;
+       rx_chn->remote = true;
+       rx_chn->udma_rchan_id = -1;
+       rx_chn->flow_num = cfg->flow_id_num;
+       rx_chn->flow_id_base = cfg->flow_id_base;
+       rx_chn->psil_paired = false;
+
+       ret = of_k3_udma_glue_parse_chn_by_id(udmax_np, &rx_chn->common, false, thread_id);
        if (ret)
                goto err;
 
-       for (i = 0; i < rx_chn->flow_num; i++)
-               rx_chn->flows[i].udma_rflow_id = rx_chn->flow_id_base + i;
-
-       k3_udma_glue_dump_rx_chn(rx_chn);
+       ret = k3_udma_glue_request_remote_rx_chn_common(rx_chn, cfg, dev);
+       if (ret)
+               goto err;
 
        return rx_chn;
 
@@ -1154,6 +1212,7 @@ err:
        k3_udma_glue_release_rx_chn(rx_chn);
        return ERR_PTR(ret);
 }
+EXPORT_SYMBOL_GPL(k3_udma_glue_request_remote_rx_chn_for_thread_id);
 
 struct k3_udma_glue_rx_channel *
 k3_udma_glue_request_rx_chn(struct device *dev, const char *name,
index c81386ceb1c1743a0e2c34649281e6118214d0e8..1e491c5dcac2d32080a0c72d058c4c5901c35597 100644 (file)
@@ -114,6 +114,11 @@ struct k3_udma_glue_rx_channel *k3_udma_glue_request_rx_chn(
                const char *name,
                struct k3_udma_glue_rx_channel_cfg *cfg);
 
+struct k3_udma_glue_rx_channel *
+k3_udma_glue_request_remote_rx_chn_for_thread_id(struct device *dev,
+                                                struct k3_udma_glue_rx_channel_cfg *cfg,
+                                                struct device_node *udmax_np, u32 thread_id);
+
 void k3_udma_glue_release_rx_chn(struct k3_udma_glue_rx_channel *rx_chn);
 int k3_udma_glue_enable_rx_chn(struct k3_udma_glue_rx_channel *rx_chn);
 void k3_udma_glue_disable_rx_chn(struct k3_udma_glue_rx_channel *rx_chn);