dmaengine: dmatest: prevent using swiotlb buffer with nobounce parameter
authorAmelie Delaunay <amelie.delaunay@foss.st.com>
Fri, 24 Nov 2023 16:02:35 +0000 (17:02 +0100)
committerVinod Koul <vkoul@kernel.org>
Mon, 11 Dec 2023 14:45:27 +0000 (20:15 +0530)
Source and destination data buffers are allocated with GPF_KERNEL flag.
It means that, if the DDR is more than 2GB, buffers can be allocated above
the 32-bit addressable space. In this case, and if the dma controller is
only 32-bit compatible, swiotlb bounce buffer, located in the 32-bit
addressable space, is used and introduces a memcpy.

To prevent this extra memcpy, due to swiotlb bounce buffer use because
source or destination data buffer is allocated above the 32-bit addressable
space, force source and destination data buffers allocation with GPF_DMA
instead, when nobounce parameter is true.

Signed-off-by: Amelie Delaunay <amelie.delaunay@foss.st.com>
Link: https://lore.kernel.org/r/20231124160235.2459326-1-amelie.delaunay@foss.st.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
drivers/dma/dmatest.c

index ffe621695e472b6b6d96e2a06a85ff514ee65651..a4f6088378492d0338fe65edc86ec51c4a9c0a10 100644 (file)
 #include <linux/slab.h>
 #include <linux/wait.h>
 
+static bool nobounce;
+module_param(nobounce, bool, 0644);
+MODULE_PARM_DESC(nobounce, "Prevent using swiotlb buffer (default: use swiotlb buffer)");
+
 static unsigned int test_buf_size = 16384;
 module_param(test_buf_size, uint, 0644);
 MODULE_PARM_DESC(test_buf_size, "Size of the memcpy test buffer");
@@ -90,6 +94,7 @@ MODULE_PARM_DESC(polled, "Use polling for completion instead of interrupts");
 
 /**
  * struct dmatest_params - test parameters.
+ * @nobounce:          prevent using swiotlb buffer
  * @buf_size:          size of the memcpy test buffer
  * @channel:           bus ID of the channel to test
  * @device:            bus ID of the DMA Engine to test
@@ -106,6 +111,7 @@ MODULE_PARM_DESC(polled, "Use polling for completion instead of interrupts");
  * @polled:            use polling for completion instead of interrupts
  */
 struct dmatest_params {
+       bool            nobounce;
        unsigned int    buf_size;
        char            channel[20];
        char            device[32];
@@ -215,6 +221,7 @@ struct dmatest_done {
 struct dmatest_data {
        u8              **raw;
        u8              **aligned;
+       gfp_t           gfp_flags;
        unsigned int    cnt;
        unsigned int    off;
 };
@@ -533,7 +540,7 @@ static int dmatest_alloc_test_data(struct dmatest_data *d,
                goto err;
 
        for (i = 0; i < d->cnt; i++) {
-               d->raw[i] = kmalloc(buf_size + align, GFP_KERNEL);
+               d->raw[i] = kmalloc(buf_size + align, d->gfp_flags);
                if (!d->raw[i])
                        goto err;
 
@@ -655,6 +662,13 @@ static int dmatest_func(void *data)
                goto err_free_coefs;
        }
 
+       src->gfp_flags = GFP_KERNEL;
+       dst->gfp_flags = GFP_KERNEL;
+       if (params->nobounce) {
+               src->gfp_flags = GFP_DMA;
+               dst->gfp_flags = GFP_DMA;
+       }
+
        if (dmatest_alloc_test_data(src, buf_size, align) < 0)
                goto err_free_coefs;
 
@@ -1093,6 +1107,7 @@ static void add_threaded_test(struct dmatest_info *info)
        struct dmatest_params *params = &info->params;
 
        /* Copy test parameters */
+       params->nobounce = nobounce;
        params->buf_size = test_buf_size;
        strscpy(params->channel, strim(test_channel), sizeof(params->channel));
        strscpy(params->device, strim(test_device), sizeof(params->device));