| 1 | |
| 2 | |
| 3 | * Copyright (C) 2013 Red Hat
|
| 4 | * Author: Rob Clark <[email protected]>
|
| 5 |
|
| 6 |
|
| 7 | #include "msm_ringbuffer.h"
|
| 8 | #include "msm_gpu.h"
|
| 9 |
|
| 10 | static uint num_hw_submissions = 8;
|
| 11 | MODULE_PARM_DESC(num_hw_submissions, "The max # of jobs to write into ringbuffer (default 8)");
|
| 12 | module_param(num_hw_submissions, uint, 0600);
|
| 13 |
|
| 14 | static struct dma_fence *msm_job_run(struct drm_sched_job *job)
|
| 15 | {
|
| 16 | struct msm_gem_submit *submit = to_msm_submit(job);
|
| 17 | struct msm_fence_context *fctx = submit->ring->fctx;
|
| 18 | struct msm_gpu *gpu = submit->gpu;
|
| 19 | struct drm_device *dev = gpu->dev;
|
| 20 | unsigned nr_cmds = submit->nr_cmds;
|
| 21 | int i;
|
| 22 |
|
| 23 | msm_fence_init(submit->hw_fence, fctx);
|
| 24 |
|
| 25 | mutex_lock(&dev->gem_lru_mutex);
|
| 26 |
|
| 27 | for (i = 0; i < submit->nr_bos; i++) {
|
| 28 | struct drm_gem_object *obj = submit->bos[i].obj;
|
| 29 |
|
| 30 | msm_gem_unpin_active(obj);
|
| 31 | }
|
| 32 |
|
| 33 | submit->bos_pinned = false;
|
| 34 |
|
| 35 | mutex_unlock(&dev->gem_lru_mutex);
|
| 36 |
|
| 37 |
|
| 38 | mutex_lock(&gpu->lock);
|
| 39 |
|
| 40 | if (submit->queue->ctx->closed)
|
| 41 | submit->nr_cmds = 0;
|
| 42 |
|
| 43 | msm_gpu_submit(gpu, submit);
|
| 44 |
|
| 45 | submit->nr_cmds = nr_cmds;
|
| 46 |
|
| 47 | mutex_unlock(&gpu->lock);
|
| 48 |
|
| 49 | return dma_fence_get(submit->hw_fence);
|
| 50 | }
|
| 51 |
|
| 52 | static void msm_job_free(struct drm_sched_job *job)
|
| 53 | {
|
| 54 | struct msm_gem_submit *submit = to_msm_submit(job);
|
| 55 |
|
| 56 | drm_sched_job_cleanup(job);
|
| 57 | msm_gem_submit_put(submit);
|
| 58 | }
|
| 59 |
|
| 60 | static const struct drm_sched_backend_ops msm_sched_ops = {
|
| 61 | .run_job = msm_job_run,
|
| 62 | .free_job = msm_job_free
|
| 63 | };
|
| 64 |
|
| 65 | struct msm_ringbuffer *msm_ringbuffer_new(struct msm_gpu *gpu, int id,
|
| 66 | void *memptrs, uint64_t memptrs_iova)
|
| 67 | {
|
| 68 | struct drm_sched_init_args args = {
|
| 69 | .ops = &msm_sched_ops,
|
| 70 | .num_rqs = DRM_SCHED_PRIORITY_COUNT,
|
| 71 | .credit_limit = num_hw_submissions,
|
| 72 | .timeout = MAX_SCHEDULE_TIMEOUT,
|
| 73 | .dev = gpu->dev->dev,
|
| 74 | };
|
| 75 | struct msm_ringbuffer *ring;
|
| 76 | char name[32];
|
| 77 | int ret;
|
| 78 |
|
| 79 |
|
| 80 | BUILD_BUG_ON(!is_power_of_2(MSM_GPU_RINGBUFFER_SZ));
|
| 81 |
|
| 82 | ring = kzalloc_obj(*ring);
|
| 83 | if (!ring) {
|
| 84 | ret = -ENOMEM;
|
| 85 | goto fail;
|
| 86 | }
|
| 87 |
|
| 88 | ring->gpu = gpu;
|
| 89 | ring->id = id;
|
| 90 |
|
| 91 | ring->start = msm_gem_kernel_new(gpu->dev, MSM_GPU_RINGBUFFER_SZ,
|
| 92 | check_apriv(gpu, MSM_BO_WC | MSM_BO_GPU_READONLY),
|
| 93 | gpu->vm, &ring->bo, &ring->iova);
|
| 94 |
|
| 95 | if (IS_ERR(ring->start)) {
|
| 96 | ret = PTR_ERR(ring->start);
|
| 97 | ring->start = NULL;
|
| 98 | goto fail;
|
| 99 | }
|
| 100 |
|
| 101 | msm_gem_object_set_name(ring->bo, "ring%d", id);
|
| 102 | args.name = to_msm_bo(ring->bo)->name;
|
| 103 |
|
| 104 | ring->end = ring->start + (MSM_GPU_RINGBUFFER_SZ >> 2);
|
| 105 | ring->next = ring->start;
|
| 106 | ring->cur = ring->start;
|
| 107 |
|
| 108 | ring->memptrs = memptrs;
|
| 109 | ring->memptrs_iova = memptrs_iova;
|
| 110 |
|
| 111 | ret = drm_sched_init(&ring->sched, &args);
|
| 112 | if (ret)
|
| 113 | goto fail;
|
| 114 | ring->sched_initialized = true;
|
| 115 |
|
| 116 | INIT_LIST_HEAD(&ring->submits);
|
| 117 | spin_lock_init(&ring->submit_lock);
|
| 118 | spin_lock_init(&ring->preempt_lock);
|
| 119 |
|
| 120 | snprintf(name, sizeof(name), "gpu-ring-%d", ring->id);
|
| 121 |
|
| 122 | ring->fctx = msm_fence_context_alloc(gpu->dev, &ring->memptrs->fence, name);
|
| 123 |
|
| 124 | return ring;
|
| 125 |
|
| 126 | fail:
|
| 127 | msm_ringbuffer_destroy(ring);
|
| 128 | return ERR_PTR(ret);
|
| 129 | }
|
| 130 |
|
| 131 | void msm_ringbuffer_destroy(struct msm_ringbuffer *ring)
|
| 132 | {
|
| 133 | if (IS_ERR_OR_NULL(ring))
|
| 134 | return;
|
| 135 |
|
| 136 | if (ring->sched_initialized)
|
| 137 | drm_sched_fini(&ring->sched);
|
| 138 |
|
| 139 | msm_fence_context_free(ring->fctx);
|
| 140 |
|
| 141 | msm_gem_kernel_put(ring->bo, ring->gpu->vm);
|
| 142 |
|
| 143 | kfree_rcu(ring, rcu);
|
| 144 | }
|