]> git.baikalelectronics.ru Git - kernel.git/commitdiff
drm/etnaviv: request pages from DMA32 zone when needed
authorLucas Stach <l.stach@pengutronix.de>
Thu, 27 Feb 2020 11:09:25 +0000 (12:09 +0100)
committerLucas Stach <l.stach@pengutronix.de>
Fri, 20 Mar 2020 17:40:44 +0000 (18:40 +0100)
Some Vivante GPUs are found in systems that have interconnects restricted
to 32 address bits, but may have system memory mapped above the 4GB mark.
As this region isn't accessible to the GPU via DMA any GPU memory allocated
in the upper part needs to go through SWIOTLB bounce buffering. This kills
performance if it happens too often, as well as overrunning the available
bounce buffer space, as the GPU buffer may stay mapped for a long time.

Avoid bounce buffering by checking the addressing restrictions. If the
GPU is unable to access memory above the 4GB mark, request our SHM buffers
to be located in the DMA32 zone.

Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
drivers/gpu/drm/etnaviv/etnaviv_drv.c
drivers/gpu/drm/etnaviv/etnaviv_drv.h
drivers/gpu/drm/etnaviv/etnaviv_gem.c
drivers/gpu/drm/etnaviv/etnaviv_gpu.c

index 6b43c1c94e8f4c318b153dab1231be1c8dcaf379..a8685b2e1803cf91318fd2b50960915710426353 100644 (file)
@@ -551,6 +551,7 @@ static int etnaviv_bind(struct device *dev)
        mutex_init(&priv->gem_lock);
        INIT_LIST_HEAD(&priv->gem_list);
        priv->num_gpus = 0;
+       priv->shm_gfp_mask = GFP_HIGHUSER | __GFP_RETRY_MAYFAIL | __GFP_NOWARN;
 
        priv->cmdbuf_suballoc = etnaviv_cmdbuf_suballoc_new(drm->dev);
        if (IS_ERR(priv->cmdbuf_suballoc)) {
index efc656efeb0fd1a844796ace71d8a8ce100a3780..4d8dc9236e5fd6bdf9dd361343ce7a2b74ecbd6a 100644 (file)
@@ -35,6 +35,7 @@ struct etnaviv_drm_private {
        int num_gpus;
        struct device_dma_parameters dma_parms;
        struct etnaviv_gpu *gpu[ETNA_MAX_PIPES];
+       gfp_t shm_gfp_mask;
 
        struct etnaviv_cmdbuf_suballoc *cmdbuf_suballoc;
        struct etnaviv_iommu_global *mmu_global;
index 6adea180d62995717406da88f6bd3694be53d74a..dc9ef302f517607f7d0b7ef98595c8bfa393dbfd 100644 (file)
@@ -602,6 +602,7 @@ static int etnaviv_gem_new_impl(struct drm_device *dev, u32 size, u32 flags,
 int etnaviv_gem_new_handle(struct drm_device *dev, struct drm_file *file,
        u32 size, u32 flags, u32 *handle)
 {
+       struct etnaviv_drm_private *priv = dev->dev_private;
        struct drm_gem_object *obj = NULL;
        int ret;
 
@@ -624,8 +625,7 @@ int etnaviv_gem_new_handle(struct drm_device *dev, struct drm_file *file,
         * above new_inode() why this is required _and_ expected if you're
         * going to pin these pages.
         */
-       mapping_set_gfp_mask(obj->filp->f_mapping, GFP_HIGHUSER |
-                            __GFP_RETRY_MAYFAIL | __GFP_NOWARN);
+       mapping_set_gfp_mask(obj->filp->f_mapping, priv->shm_gfp_mask);
 
        etnaviv_gem_obj_add(dev, obj);
 
index 169db7cc0ec60cd24ebf56bd4ca64ad092ebd3e7..a31eeff2b297a5cb56bb4161a7c572c8948f7c2c 100644 (file)
@@ -781,6 +781,14 @@ int etnaviv_gpu_init(struct etnaviv_gpu *gpu)
                gpu->identity.features &= ~chipFeatures_FAST_CLEAR;
        }
 
+       /*
+        * If the GPU is part of a system with DMA addressing limitations,
+        * request pages for our SHM backend buffers from the DMA32 zone to
+        * hopefully avoid performance killing SWIOTLB bounce buffering.
+        */
+       if (dma_addressing_limited(gpu->dev))
+               priv->shm_gfp_mask |= GFP_DMA32;
+
        /* Create buffer: */
        ret = etnaviv_cmdbuf_init(priv->cmdbuf_suballoc, &gpu->buffer,
                                  PAGE_SIZE);