]> Git Repo - linux.git/blobdiff - drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c
Merge tag 'amd-drm-next-6.5-2023-06-09' of https://gitlab.freedesktop.org/agd5f/linux...
[linux.git] / drivers / gpu / drm / amd / amdgpu / amdgpu_gart.c
index 01cb89ffbd566a5128dff3780c3f0017376571da..73b8cca35bab8780d1938a45d035d19648bdd081 100644 (file)
@@ -35,6 +35,7 @@
 #endif
 #include "amdgpu.h"
 #include <drm/drm_drv.h>
+#include <drm/ttm/ttm_tt.h>
 
 /*
  * GART
@@ -102,6 +103,142 @@ void amdgpu_gart_dummy_page_fini(struct amdgpu_device *adev)
        adev->dummy_page_addr = 0;
 }
 
+/**
+ * amdgpu_gart_table_ram_alloc - allocate system ram for gart page table
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Allocate system memory for GART page table for ASICs that don't have
+ * dedicated VRAM.
+ * Returns 0 for success, error for failure.
+ */
+int amdgpu_gart_table_ram_alloc(struct amdgpu_device *adev)
+{
+       unsigned int order = get_order(adev->gart.table_size);
+       gfp_t gfp_flags = GFP_KERNEL | __GFP_ZERO;
+       struct amdgpu_bo *bo = NULL;
+       struct sg_table *sg = NULL;
+       struct amdgpu_bo_param bp;
+       dma_addr_t dma_addr;
+       struct page *p;
+       int ret;
+
+       if (adev->gart.bo != NULL)
+               return 0;
+
+       p = alloc_pages(gfp_flags, order);
+       if (!p)
+               return -ENOMEM;
+
+       /* If the hardware does not support UTCL2 snooping of the CPU caches
+        * then set_memory_wc() could be used as a workaround to mark the pages
+        * as write combine memory.
+        */
+       dma_addr = dma_map_page(&adev->pdev->dev, p, 0, adev->gart.table_size,
+                               DMA_BIDIRECTIONAL);
+       if (dma_mapping_error(&adev->pdev->dev, dma_addr)) {
+               dev_err(&adev->pdev->dev, "Failed to DMA MAP the GART BO page\n");
+               __free_pages(p, order);
+               p = NULL;
+               return -EFAULT;
+       }
+
+       dev_info(adev->dev, "%s dma_addr:%pad\n", __func__, &dma_addr);
+       /* Create SG table */
+       sg = kmalloc(sizeof(*sg), GFP_KERNEL);
+       if (!sg) {
+               ret = -ENOMEM;
+               goto error;
+       }
+       ret = sg_alloc_table(sg, 1, GFP_KERNEL);
+       if (ret)
+               goto error;
+
+       sg_dma_address(sg->sgl) = dma_addr;
+       sg->sgl->length = adev->gart.table_size;
+#ifdef CONFIG_NEED_SG_DMA_LENGTH
+       sg->sgl->dma_length = adev->gart.table_size;
+#endif
+       /* Create SG BO */
+       memset(&bp, 0, sizeof(bp));
+       bp.size = adev->gart.table_size;
+       bp.byte_align = PAGE_SIZE;
+       bp.domain = AMDGPU_GEM_DOMAIN_CPU;
+       bp.type = ttm_bo_type_sg;
+       bp.resv = NULL;
+       bp.bo_ptr_size = sizeof(struct amdgpu_bo);
+       bp.flags = 0;
+       ret = amdgpu_bo_create(adev, &bp, &bo);
+       if (ret)
+               goto error;
+
+       bo->tbo.sg = sg;
+       bo->tbo.ttm->sg = sg;
+       bo->allowed_domains = AMDGPU_GEM_DOMAIN_GTT;
+       bo->preferred_domains = AMDGPU_GEM_DOMAIN_GTT;
+
+       ret = amdgpu_bo_reserve(bo, true);
+       if (ret) {
+               dev_err(adev->dev, "(%d) failed to reserve bo for GART system bo\n", ret);
+               goto error;
+       }
+
+       ret = amdgpu_bo_pin(bo, AMDGPU_GEM_DOMAIN_GTT);
+       WARN(ret, "Pinning the GART table failed");
+       if (ret)
+               goto error_resv;
+
+       adev->gart.bo = bo;
+       adev->gart.ptr = page_to_virt(p);
+       /* Make GART table accessible in VMID0 */
+       ret = amdgpu_ttm_alloc_gart(&adev->gart.bo->tbo);
+       if (ret)
+               amdgpu_gart_table_ram_free(adev);
+       amdgpu_bo_unreserve(bo);
+
+       return 0;
+
+error_resv:
+       amdgpu_bo_unreserve(bo);
+error:
+       amdgpu_bo_unref(&bo);
+       if (sg) {
+               sg_free_table(sg);
+               kfree(sg);
+       }
+       __free_pages(p, order);
+       return ret;
+}
+
+/**
+ * amdgpu_gart_table_ram_free - free gart page table system ram
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Free the system memory used for the GART page tableon ASICs that don't
+ * have dedicated VRAM.
+ */
+void amdgpu_gart_table_ram_free(struct amdgpu_device *adev)
+{
+       unsigned int order = get_order(adev->gart.table_size);
+       struct sg_table *sg = adev->gart.bo->tbo.sg;
+       struct page *p;
+       int ret;
+
+       ret = amdgpu_bo_reserve(adev->gart.bo, false);
+       if (!ret) {
+               amdgpu_bo_unpin(adev->gart.bo);
+               amdgpu_bo_unreserve(adev->gart.bo);
+       }
+       amdgpu_bo_unref(&adev->gart.bo);
+       sg_free_table(sg);
+       kfree(sg);
+       p = virt_to_page(adev->gart.ptr);
+       __free_pages(p, order);
+
+       adev->gart.ptr = NULL;
+}
+
 /**
  * amdgpu_gart_table_vram_alloc - allocate vram for gart page table
  *
@@ -182,7 +319,7 @@ void amdgpu_gart_unbind(struct amdgpu_device *adev, uint64_t offset,
        }
        mb();
        amdgpu_device_flush_hdp(adev, NULL);
-       for (i = 0; i < adev->num_vmhubs; i++)
+       for_each_set_bit(i, adev->vmhubs_mask, AMDGPU_MAX_VMHUBS)
                amdgpu_gmc_flush_gpu_tlb(adev, 0, i, 0);
 
        drm_dev_exit(idx);
@@ -264,7 +401,7 @@ void amdgpu_gart_invalidate_tlb(struct amdgpu_device *adev)
 
        mb();
        amdgpu_device_flush_hdp(adev, NULL);
-       for (i = 0; i < adev->num_vmhubs; i++)
+       for_each_set_bit(i, adev->vmhubs_mask, AMDGPU_MAX_VMHUBS)
                amdgpu_gmc_flush_gpu_tlb(adev, 0, i, 0);
 }
 
This page took 0.039696 seconds and 4 git commands to generate.