Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/etnaviv: request pages from DMA32 zone when needed

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>

+12 -2
+1
drivers/gpu/drm/etnaviv/etnaviv_drv.c
··· 551 551 mutex_init(&priv->gem_lock); 552 552 INIT_LIST_HEAD(&priv->gem_list); 553 553 priv->num_gpus = 0; 554 + priv->shm_gfp_mask = GFP_HIGHUSER | __GFP_RETRY_MAYFAIL | __GFP_NOWARN; 554 555 555 556 priv->cmdbuf_suballoc = etnaviv_cmdbuf_suballoc_new(drm->dev); 556 557 if (IS_ERR(priv->cmdbuf_suballoc)) {
+1
drivers/gpu/drm/etnaviv/etnaviv_drv.h
··· 35 35 int num_gpus; 36 36 struct device_dma_parameters dma_parms; 37 37 struct etnaviv_gpu *gpu[ETNA_MAX_PIPES]; 38 + gfp_t shm_gfp_mask; 38 39 39 40 struct etnaviv_cmdbuf_suballoc *cmdbuf_suballoc; 40 41 struct etnaviv_iommu_global *mmu_global;
+2 -2
drivers/gpu/drm/etnaviv/etnaviv_gem.c
··· 602 602 int etnaviv_gem_new_handle(struct drm_device *dev, struct drm_file *file, 603 603 u32 size, u32 flags, u32 *handle) 604 604 { 605 + struct etnaviv_drm_private *priv = dev->dev_private; 605 606 struct drm_gem_object *obj = NULL; 606 607 int ret; 607 608 ··· 625 624 * above new_inode() why this is required _and_ expected if you're 626 625 * going to pin these pages. 627 626 */ 628 - mapping_set_gfp_mask(obj->filp->f_mapping, GFP_HIGHUSER | 629 - __GFP_RETRY_MAYFAIL | __GFP_NOWARN); 627 + mapping_set_gfp_mask(obj->filp->f_mapping, priv->shm_gfp_mask); 630 628 631 629 etnaviv_gem_obj_add(dev, obj); 632 630
+8
drivers/gpu/drm/etnaviv/etnaviv_gpu.c
··· 781 781 gpu->identity.features &= ~chipFeatures_FAST_CLEAR; 782 782 } 783 783 784 + /* 785 + * If the GPU is part of a system with DMA addressing limitations, 786 + * request pages for our SHM backend buffers from the DMA32 zone to 787 + * hopefully avoid performance killing SWIOTLB bounce buffering. 788 + */ 789 + if (dma_addressing_limited(gpu->dev)) 790 + priv->shm_gfp_mask |= GFP_DMA32; 791 + 784 792 /* Create buffer: */ 785 793 ret = etnaviv_cmdbuf_init(priv->cmdbuf_suballoc, &gpu->buffer, 786 794 PAGE_SIZE);