Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (C) 2013 Red Hat
0004  * Author: Rob Clark <robdclark@gmail.com>
0005  */
0006 
0007 #include "msm_ringbuffer.h"
0008 #include "msm_gpu.h"
0009 
0010 static uint num_hw_submissions = 8;
0011 MODULE_PARM_DESC(num_hw_submissions, "The max # of jobs to write into ringbuffer (default 8)");
0012 module_param(num_hw_submissions, uint, 0600);
0013 
0014 static struct dma_fence *msm_job_run(struct drm_sched_job *job)
0015 {
0016     struct msm_gem_submit *submit = to_msm_submit(job);
0017     struct msm_fence_context *fctx = submit->ring->fctx;
0018     struct msm_gpu *gpu = submit->gpu;
0019     int i;
0020 
0021     submit->hw_fence = msm_fence_alloc(fctx);
0022 
0023     for (i = 0; i < submit->nr_bos; i++) {
0024         struct drm_gem_object *obj = &submit->bos[i].obj->base;
0025 
0026         msm_gem_lock(obj);
0027         msm_gem_unpin_vma_fenced(submit->bos[i].vma, fctx);
0028         submit->bos[i].flags &= ~BO_VMA_PINNED;
0029         msm_gem_unlock(obj);
0030     }
0031 
0032     pm_runtime_get_sync(&gpu->pdev->dev);
0033 
0034     /* TODO move submit path over to using a per-ring lock.. */
0035     mutex_lock(&gpu->lock);
0036 
0037     msm_gpu_submit(gpu, submit);
0038 
0039     mutex_unlock(&gpu->lock);
0040 
0041     pm_runtime_put(&gpu->pdev->dev);
0042 
0043     return dma_fence_get(submit->hw_fence);
0044 }
0045 
0046 static void msm_job_free(struct drm_sched_job *job)
0047 {
0048     struct msm_gem_submit *submit = to_msm_submit(job);
0049 
0050     drm_sched_job_cleanup(job);
0051     msm_gem_submit_put(submit);
0052 }
0053 
0054 static const struct drm_sched_backend_ops msm_sched_ops = {
0055     .run_job = msm_job_run,
0056     .free_job = msm_job_free
0057 };
0058 
0059 struct msm_ringbuffer *msm_ringbuffer_new(struct msm_gpu *gpu, int id,
0060         void *memptrs, uint64_t memptrs_iova)
0061 {
0062     struct msm_ringbuffer *ring;
0063     long sched_timeout;
0064     char name[32];
0065     int ret;
0066 
0067     /* We assume everwhere that MSM_GPU_RINGBUFFER_SZ is a power of 2 */
0068     BUILD_BUG_ON(!is_power_of_2(MSM_GPU_RINGBUFFER_SZ));
0069 
0070     ring = kzalloc(sizeof(*ring), GFP_KERNEL);
0071     if (!ring) {
0072         ret = -ENOMEM;
0073         goto fail;
0074     }
0075 
0076     ring->gpu = gpu;
0077     ring->id = id;
0078 
0079     ring->start = msm_gem_kernel_new(gpu->dev, MSM_GPU_RINGBUFFER_SZ,
0080         check_apriv(gpu, MSM_BO_WC | MSM_BO_GPU_READONLY),
0081         gpu->aspace, &ring->bo, &ring->iova);
0082 
0083     if (IS_ERR(ring->start)) {
0084         ret = PTR_ERR(ring->start);
0085         ring->start = NULL;
0086         goto fail;
0087     }
0088 
0089     msm_gem_object_set_name(ring->bo, "ring%d", id);
0090 
0091     ring->end   = ring->start + (MSM_GPU_RINGBUFFER_SZ >> 2);
0092     ring->next  = ring->start;
0093     ring->cur   = ring->start;
0094 
0095     ring->memptrs = memptrs;
0096     ring->memptrs_iova = memptrs_iova;
0097 
0098      /* currently managing hangcheck ourselves: */
0099     sched_timeout = MAX_SCHEDULE_TIMEOUT;
0100 
0101     ret = drm_sched_init(&ring->sched, &msm_sched_ops,
0102             num_hw_submissions, 0, sched_timeout,
0103             NULL, NULL, to_msm_bo(ring->bo)->name, gpu->dev->dev);
0104     if (ret) {
0105         goto fail;
0106     }
0107 
0108     INIT_LIST_HEAD(&ring->submits);
0109     spin_lock_init(&ring->submit_lock);
0110     spin_lock_init(&ring->preempt_lock);
0111 
0112     snprintf(name, sizeof(name), "gpu-ring-%d", ring->id);
0113 
0114     ring->fctx = msm_fence_context_alloc(gpu->dev, &ring->memptrs->fence, name);
0115 
0116     return ring;
0117 
0118 fail:
0119     msm_ringbuffer_destroy(ring);
0120     return ERR_PTR(ret);
0121 }
0122 
0123 void msm_ringbuffer_destroy(struct msm_ringbuffer *ring)
0124 {
0125     if (IS_ERR_OR_NULL(ring))
0126         return;
0127 
0128     drm_sched_fini(&ring->sched);
0129 
0130     msm_fence_context_free(ring->fctx);
0131 
0132     msm_gem_kernel_put(ring->bo, ring->gpu->aspace);
0133 
0134     kfree(ring);
0135 }