Re: [PATCH 31/44] drm/nouveau/nvkm: support loading fws into sg_table

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]<

 



On Tue, 2023-09-19 at 06:21 +1000, Ben Skeggs wrote:
> From: Ben Skeggs <bskeggs@xxxxxxxxxx>
> 
> - preparation for GSP-RM, which has massive FW images
> - based on a patch by Dave Airlie

Probably more canonical to use one of the standard phrases such as
Suggested-by


> 
> Signed-off-by: Ben Skeggs <bskeggs@xxxxxxxxxx>
> ---
>  .../drm/nouveau/include/nvkm/core/firmware.h  |  6 +-
>  drivers/gpu/drm/nouveau/nvkm/core/firmware.c  | 74
> ++++++++++++++++++-
>  2 files changed, 76 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/firmware.h
> b/drivers/gpu/drm/nouveau/include/nvkm/core/firmware.h
> index d4e507e252b1..20839be72644 100644
> --- a/drivers/gpu/drm/nouveau/include/nvkm/core/firmware.h
> +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/firmware.h
> @@ -10,6 +10,7 @@ struct nvkm_firmware {
>                 enum nvkm_firmware_type {
>                         NVKM_FIRMWARE_IMG_RAM,
>                         NVKM_FIRMWARE_IMG_DMA,
> +                       NVKM_FIRMWARE_IMG_SGT,
>                 } type;
>         } *func;
>         const char *name;
> @@ -21,7 +22,10 @@ struct nvkm_firmware {
>  
>         struct nvkm_firmware_mem {
>                 struct nvkm_memory memory;
> -               struct scatterlist sgl;
> +               union {
> +                       struct scatterlist sgl; /* DMA */
> +                       struct sg_table sgt;    /* SGT */
> +               };
>         } mem;
>  };
>  
> diff --git a/drivers/gpu/drm/nouveau/nvkm/core/firmware.c
> b/drivers/gpu/drm/nouveau/nvkm/core/firmware.c
> index 91fb494d4009..4641e7eebe56 100644
> --- a/drivers/gpu/drm/nouveau/nvkm/core/firmware.c
> +++ b/drivers/gpu/drm/nouveau/nvkm/core/firmware.c
> @@ -113,6 +113,22 @@ nvkm_firmware_put(const struct firmware *fw)
>  
>  #define nvkm_firmware_mem(p) container_of((p), struct nvkm_firmware,
> mem.memory)
>  
> +static struct scatterlist *
> +nvkm_firmware_mem_sgl(struct nvkm_memory *memory)
> +{
> +       struct nvkm_firmware *fw = nvkm_firmware_mem(memory);
> +
> +       switch (fw->func->type) {
> +       case NVKM_FIRMWARE_IMG_DMA: return &fw->mem.sgl;
> +       case NVKM_FIRMWARE_IMG_SGT: return  fw->mem.sgt.sgl;
> +       default:
> +               WARN_ON(1);
> +               break;
> +       }
> +
> +       return NULL;
> +}
> +
>  static int
>  nvkm_firmware_mem_map(struct nvkm_memory *memory, u64 offset, struct
> nvkm_vmm *vmm,
>                       struct nvkm_vma *vma, void *argv, u32 argc)
> @@ -121,10 +137,10 @@ nvkm_firmware_mem_map(struct nvkm_memory
> *memory, u64 offset, struct nvkm_vmm *v
>         struct nvkm_vmm_map map = {
>                 .memory = &fw->mem.memory,
>                 .offset = offset,
> -               .sgl = &fw->mem.sgl,
> +               .sgl = nvkm_firmware_mem_sgl(memory),
>         };
>  
> -       if (WARN_ON(fw->func->type != NVKM_FIRMWARE_IMG_DMA))
> +       if (!map.sgl)
>                 return -ENOSYS;
>  
>         return nvkm_vmm_map(vmm, vma, argv, argc, &map);
> @@ -133,12 +149,15 @@ nvkm_firmware_mem_map(struct nvkm_memory
> *memory, u64 offset, struct nvkm_vmm *v
>  static u64
>  nvkm_firmware_mem_size(struct nvkm_memory *memory)
>  {
> -       return sg_dma_len(&nvkm_firmware_mem(memory)->mem.sgl);
> +       struct scatterlist *sgl = nvkm_firmware_mem_sgl(memory);
> +
> +       return sgl ? sg_dma_len(sgl) : 0;
>  }
>  
>  static u64
>  nvkm_firmware_mem_addr(struct nvkm_memory *memory)
>  {
> +       BUG_ON(nvkm_firmware_mem(memory)->func->type !=
> NVKM_FIRMWARE_IMG_DMA);
>         return nvkm_firmware_mem(memory)->phys;
>  }
>  
> @@ -189,6 +208,12 @@ nvkm_firmware_dtor(struct nvkm_firmware *fw)
>                 nvkm_memory_unref(&memory);
>                 dma_free_coherent(fw->device->dev, sg_dma_len(&fw-
> >mem.sgl), fw->img, fw->phys);
>                 break;
> +       case NVKM_FIRMWARE_IMG_SGT:
> +               nvkm_memory_unref(&memory);
> +               dma_unmap_sgtable(fw->device->dev, &fw->mem.sgt,
> DMA_TO_DEVICE, 0);
> +               sg_free_table(&fw->mem.sgt);
> +               vfree(fw->img);
> +               break;
>         default:
>                 WARN_ON(1);
>                 break;
> @@ -226,6 +251,49 @@ nvkm_firmware_ctor(const struct
> nvkm_firmware_func *func, const char *name,
>                 sg_dma_len(&fw->mem.sgl) = len;
>         }
>                 break;
> +       case NVKM_FIRMWARE_IMG_SGT:
> +               len = ALIGN(fw->len, PAGE_SIZE);
> +
> +               fw->img = vmalloc(len);
> +               if (fw->img) {
> +                       int pages = len >> PAGE_SHIFT;
> +                       int ret = 0;
> +
> +                       memcpy(fw->img, src, fw->len);
> +
> +                       ret = sg_alloc_table(&fw->mem.sgt, pages,
> GFP_KERNEL);
> +                       if (ret == 0) {
> +                               struct scatterlist *sgl;
> +                               u8 *data = fw->img;
> +                               int i;
> +
> +                               for_each_sgtable_sg(&fw->mem.sgt,
> sgl, i) {
> +                                       struct page *page =
> vmalloc_to_page(data);
> +
> +                                       if (!page) {
> +                                               ret = -EFAULT;
> +                                               break;
> +                                       }
> +
> +                                       sg_set_page(sgl, page,
> PAGE_SIZE, 0);
> +                                       data += PAGE_SIZE;
> +                               }
> +
> +                               if (ret == 0) {
> +                                       ret = dma_map_sgtable(fw-
> >device->dev, &fw->mem.sgt,
> +                                                            
> DMA_TO_DEVICE, 0);
> +                               }
> +
> +                               if (ret)
> +                                       sg_free_table(&fw->mem.sgt);
> +                       }
> +
> +                       if (ret) {
> +                               vfree(fw->img);
> +                               fw->img = NULL;
> +                       }
> +               }
> +               break;
>         default:
>                 WARN_ON(1);
>                 return -EINVAL;





[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [eCos]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux