drm/mediatek: set DMA max segment size [Linux 4.14.143]

This Linux kernel change "drm/mediatek: set DMA max segment size" is included in the Linux 4.14.143 release. This change is authored by Alexandre Courbot <acourbot [at] chromium.org> on Mon Jul 29 14:33:35 2019 +0900. The commit for this change in Linux stable tree is 91910cc (patch) which is from upstream commit 0709555. The same Linux upstream change may have been applied to various maintained Linux releases and you can find all Linux releases containing changes from upstream 0709555.

drm/mediatek: set DMA max segment size

[ Upstream commit 070955558e820b9a89c570b91b1f21762f62b288 ]

This driver requires imported PRIME buffers to appear contiguously in
its IO address space. Make sure this is the case by setting the maximum
DMA segment size to a more suitable value than the default 64KB.

Signed-off-by: Alexandre Courbot <acourbot@chromium.org>
Reviewed-by: Tomasz Figa <tfiga@chromium.org>
Signed-off-by: CK Hu <ck.hu@mediatek.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>

There are 37 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 drivers/gpu/drm/mediatek/mtk_drm_drv.c | 35 ++++++++++++++++++++++++++++++++--
 drivers/gpu/drm/mediatek/mtk_drm_drv.h |  2 ++
 2 files changed, 35 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
index 4a89cd2..034b500 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -185,6 +185,7 @@ static int mtk_drm_kms_init(struct drm_device *drm)
    struct mtk_drm_private *private = drm->dev_private;
    struct platform_device *pdev;
    struct device_node *np;
+   struct device *dma_dev;
    int ret;

    if (!iommu_present(&platform_bus_type))
@@ -242,7 +243,29 @@ static int mtk_drm_kms_init(struct drm_device *drm)
        goto err_component_unbind;
    }

-   private->dma_dev = &pdev->dev;
+   dma_dev = &pdev->dev;
+   private->dma_dev = dma_dev;
+
+   /*
+    * Configure the DMA segment size to make sure we get contiguous IOVA
+    * when importing PRIME buffers.
+    */
+   if (!dma_dev->dma_parms) {
+       private->dma_parms_allocated = true;
+       dma_dev->dma_parms =
+           devm_kzalloc(drm->dev, sizeof(*dma_dev->dma_parms),
+                    GFP_KERNEL);
+   }
+   if (!dma_dev->dma_parms) {
+       ret = -ENOMEM;
+       goto err_component_unbind;
+   }
+
+   ret = dma_set_max_seg_size(dma_dev, (unsigned int)DMA_BIT_MASK(32));
+   if (ret) {
+       dev_err(dma_dev, "Failed to set DMA segment size\n");
+       goto err_unset_dma_parms;
+   }

    /*
     * We don't use the drm_irq_install() helpers provided by the DRM
@@ -252,13 +275,16 @@ static int mtk_drm_kms_init(struct drm_device *drm)
    drm->irq_enabled = true;
    ret = drm_vblank_init(drm, MAX_CRTC);
    if (ret < 0)
-       goto err_component_unbind;
+       goto err_unset_dma_parms;

    drm_kms_helper_poll_init(drm);
    drm_mode_config_reset(drm);

    return 0;

+err_unset_dma_parms:
+   if (private->dma_parms_allocated)
+       dma_dev->dma_parms = NULL;
 err_component_unbind:
    component_unbind_all(drm->dev, drm);
 err_config_cleanup:
@@ -269,9 +295,14 @@ static int mtk_drm_kms_init(struct drm_device *drm)

 static void mtk_drm_kms_deinit(struct drm_device *drm)
 {
+   struct mtk_drm_private *private = drm->dev_private;
+
    drm_kms_helper_poll_fini(drm);
    drm_atomic_helper_shutdown(drm);

+   if (private->dma_parms_allocated)
+       private->dma_dev->dma_parms = NULL;
+
    component_unbind_all(drm->dev, drm);
    drm_mode_config_cleanup(drm);
 }
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.h b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
index c3378c4..445dd45 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.h
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
@@ -56,6 +56,8 @@ struct mtk_drm_private {
    } commit;

    struct drm_atomic_state *suspend_state;
+
+   bool dma_parms_allocated;
 };

 extern struct platform_driver mtk_ddp_driver;

Leave a Reply

Your email address will not be published. Required fields are marked *