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

drm/etnaviv: share a single cmdbuf suballoc region across all GPUs

There is no need for each GPU to have it's own cmdbuf suballocation
region. Only allocate a single one for the the etnaviv virtual device
and share it across all GPUs.

As the suballoc space is now potentially shared by more hardware jobs
running in parallel, double its size to 512KB to avoid contention.

Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de>
Reviewed-by: Guido Günther <agx@sigxcpu.org>

+31 -28
+7 -7
drivers/gpu/drm/etnaviv/etnaviv_cmdbuf.c
··· 13 13 #include "etnaviv_mmu.h" 14 14 #include "etnaviv_perfmon.h" 15 15 16 - #define SUBALLOC_SIZE SZ_256K 16 + #define SUBALLOC_SIZE SZ_512K 17 17 #define SUBALLOC_GRANULE SZ_4K 18 18 #define SUBALLOC_GRANULES (SUBALLOC_SIZE / SUBALLOC_GRANULE) 19 19 20 20 struct etnaviv_cmdbuf_suballoc { 21 21 /* suballocated dma buffer properties */ 22 - struct etnaviv_gpu *gpu; 22 + struct device *dev; 23 23 void *vaddr; 24 24 dma_addr_t paddr; 25 25 ··· 31 31 }; 32 32 33 33 struct etnaviv_cmdbuf_suballoc * 34 - etnaviv_cmdbuf_suballoc_new(struct etnaviv_gpu * gpu) 34 + etnaviv_cmdbuf_suballoc_new(struct device *dev) 35 35 { 36 36 struct etnaviv_cmdbuf_suballoc *suballoc; 37 37 int ret; ··· 40 40 if (!suballoc) 41 41 return ERR_PTR(-ENOMEM); 42 42 43 - suballoc->gpu = gpu; 43 + suballoc->dev = dev; 44 44 mutex_init(&suballoc->lock); 45 45 init_waitqueue_head(&suballoc->free_event); 46 46 47 - suballoc->vaddr = dma_alloc_wc(gpu->dev, SUBALLOC_SIZE, 47 + suballoc->vaddr = dma_alloc_wc(dev, SUBALLOC_SIZE, 48 48 &suballoc->paddr, GFP_KERNEL); 49 49 if (!suballoc->vaddr) { 50 50 ret = -ENOMEM; ··· 76 76 77 77 void etnaviv_cmdbuf_suballoc_destroy(struct etnaviv_cmdbuf_suballoc *suballoc) 78 78 { 79 - dma_free_wc(suballoc->gpu->dev, SUBALLOC_SIZE, suballoc->vaddr, 79 + dma_free_wc(suballoc->dev, SUBALLOC_SIZE, suballoc->vaddr, 80 80 suballoc->paddr); 81 81 kfree(suballoc); 82 82 } ··· 101 101 suballoc->free_space, 102 102 msecs_to_jiffies(10 * 1000)); 103 103 if (!ret) { 104 - dev_err(suballoc->gpu->dev, 104 + dev_err(suballoc->dev, 105 105 "Timeout waiting for cmdbuf space\n"); 106 106 return -ETIMEDOUT; 107 107 }
+2 -2
drivers/gpu/drm/etnaviv/etnaviv_cmdbuf.h
··· 8 8 9 9 #include <linux/types.h> 10 10 11 - struct etnaviv_gpu; 11 + struct device; 12 12 struct etnaviv_iommu; 13 13 struct etnaviv_vram_mapping; 14 14 struct etnaviv_cmdbuf_suballoc; ··· 25 25 }; 26 26 27 27 struct etnaviv_cmdbuf_suballoc * 28 - etnaviv_cmdbuf_suballoc_new(struct etnaviv_gpu * gpu); 28 + etnaviv_cmdbuf_suballoc_new(struct device *dev); 29 29 void etnaviv_cmdbuf_suballoc_destroy(struct etnaviv_cmdbuf_suballoc *suballoc); 30 30 int etnaviv_cmdbuf_suballoc_map(struct etnaviv_cmdbuf_suballoc *suballoc, 31 31 struct etnaviv_iommu *mmu,
+15 -4
drivers/gpu/drm/etnaviv/etnaviv_drv.c
··· 530 530 INIT_LIST_HEAD(&priv->gem_list); 531 531 priv->num_gpus = 0; 532 532 533 + priv->cmdbuf_suballoc = etnaviv_cmdbuf_suballoc_new(drm->dev); 534 + if (IS_ERR(priv->cmdbuf_suballoc)) { 535 + dev_err(drm->dev, "Failed to create cmdbuf suballocator\n"); 536 + ret = PTR_ERR(priv->cmdbuf_suballoc); 537 + goto out_free_priv; 538 + } 539 + 533 540 dev_set_drvdata(dev, drm); 534 541 535 542 ret = component_bind_all(dev, drm); 536 543 if (ret < 0) 537 - goto out_bind; 544 + goto out_destroy_suballoc; 538 545 539 546 load_gpu(drm); 540 547 541 548 ret = drm_dev_register(drm, 0); 542 549 if (ret) 543 - goto out_register; 550 + goto out_unbind; 544 551 545 552 return 0; 546 553 547 - out_register: 554 + out_unbind: 548 555 component_unbind_all(dev, drm); 549 - out_bind: 556 + out_destroy_suballoc: 557 + etnaviv_cmdbuf_suballoc_destroy(priv->cmdbuf_suballoc); 558 + out_free_priv: 550 559 kfree(priv); 551 560 out_put: 552 561 drm_dev_put(drm); ··· 573 564 component_unbind_all(dev, drm); 574 565 575 566 dev->dma_parms = NULL; 567 + 568 + etnaviv_cmdbuf_suballoc_destroy(priv->cmdbuf_suballoc); 576 569 577 570 drm->dev_private = NULL; 578 571 kfree(priv);
+2
drivers/gpu/drm/etnaviv/etnaviv_drv.h
··· 36 36 struct device_dma_parameters dma_parms; 37 37 struct etnaviv_gpu *gpu[ETNA_MAX_PIPES]; 38 38 39 + struct etnaviv_cmdbuf_suballoc *cmdbuf_suballoc; 40 + 39 41 /* list of GEM objects: */ 40 42 struct mutex gem_lock; 41 43 struct list_head gem_list;
+1 -1
drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c
··· 496 496 goto err_submit_ww_acquire; 497 497 } 498 498 499 - ret = etnaviv_cmdbuf_init(gpu->cmdbuf_suballoc, &submit->cmdbuf, 499 + ret = etnaviv_cmdbuf_init(priv->cmdbuf_suballoc, &submit->cmdbuf, 500 500 ALIGN(args->stream_size, 8) + 8); 501 501 if (ret) 502 502 goto err_submit_objects;
+4 -13
drivers/gpu/drm/etnaviv/etnaviv_gpu.c
··· 693 693 694 694 int etnaviv_gpu_init(struct etnaviv_gpu *gpu) 695 695 { 696 + struct etnaviv_drm_private *priv = gpu->drm->dev_private; 696 697 int ret, i; 697 698 698 699 ret = pm_runtime_get_sync(gpu->dev); ··· 761 760 goto fail; 762 761 } 763 762 764 - gpu->cmdbuf_suballoc = etnaviv_cmdbuf_suballoc_new(gpu); 765 - if (IS_ERR(gpu->cmdbuf_suballoc)) { 766 - dev_err(gpu->dev, "Failed to create cmdbuf suballocator\n"); 767 - ret = PTR_ERR(gpu->cmdbuf_suballoc); 768 - goto destroy_iommu; 769 - } 770 - 771 - ret = etnaviv_cmdbuf_suballoc_map(gpu->cmdbuf_suballoc, gpu->mmu, 763 + ret = etnaviv_cmdbuf_suballoc_map(priv->cmdbuf_suballoc, gpu->mmu, 772 764 &gpu->cmdbuf_mapping, 773 765 gpu->memory_base); 774 766 if (ret) { 775 767 dev_err(gpu->dev, "failed to map cmdbuf suballoc\n"); 776 - goto destroy_suballoc; 768 + goto destroy_iommu; 777 769 } 778 770 779 771 /* Create buffer: */ 780 - ret = etnaviv_cmdbuf_init(gpu->cmdbuf_suballoc, &gpu->buffer, 772 + ret = etnaviv_cmdbuf_init(priv->cmdbuf_suballoc, &gpu->buffer, 781 773 PAGE_SIZE); 782 774 if (ret) { 783 775 dev_err(gpu->dev, "could not create command buffer\n"); ··· 809 815 etnaviv_cmdbuf_free(&gpu->buffer); 810 816 unmap_suballoc: 811 817 etnaviv_cmdbuf_suballoc_unmap(gpu->mmu, &gpu->cmdbuf_mapping); 812 - destroy_suballoc: 813 - etnaviv_cmdbuf_suballoc_destroy(gpu->cmdbuf_suballoc); 814 818 destroy_iommu: 815 819 etnaviv_iommu_destroy(gpu->mmu); 816 820 fail: ··· 1684 1692 if (gpu->initialized) { 1685 1693 etnaviv_cmdbuf_free(&gpu->buffer); 1686 1694 etnaviv_cmdbuf_suballoc_unmap(gpu->mmu, &gpu->cmdbuf_mapping); 1687 - etnaviv_cmdbuf_suballoc_destroy(gpu->cmdbuf_suballoc); 1688 1695 etnaviv_iommu_destroy(gpu->mmu); 1689 1696 gpu->initialized = false; 1690 1697 }
-1
drivers/gpu/drm/etnaviv/etnaviv_gpu.h
··· 137 137 int irq; 138 138 139 139 struct etnaviv_iommu *mmu; 140 - struct etnaviv_cmdbuf_suballoc *cmdbuf_suballoc; 141 140 142 141 /* Power Control: */ 143 142 struct clk *clk_bus;