Linux Audio

Check our new training course

Loading...
v4.6
 
 1/*
 2 * Copyright (C) 2013 Red Hat
 3 * Author: Rob Clark <robdclark@gmail.com>
 4 *
 5 * This program is free software; you can redistribute it and/or modify it
 6 * under the terms of the GNU General Public License version 2 as published by
 7 * the Free Software Foundation.
 8 *
 9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program.  If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "msm_ringbuffer.h"
19#include "msm_gpu.h"
20
21struct msm_ringbuffer *msm_ringbuffer_new(struct msm_gpu *gpu, int size)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22{
23	struct msm_ringbuffer *ring;
 
 
24	int ret;
25
26	size = ALIGN(size, 4);   /* size should be dword aligned */
 
27
28	ring = kzalloc(sizeof(*ring), GFP_KERNEL);
29	if (!ring) {
30		ret = -ENOMEM;
31		goto fail;
32	}
33
34	ring->gpu = gpu;
35	ring->bo = msm_gem_new(gpu->dev, size, MSM_BO_WC);
36	if (IS_ERR(ring->bo)) {
37		ret = PTR_ERR(ring->bo);
38		ring->bo = NULL;
 
 
 
 
 
39		goto fail;
40	}
41
42	ring->start = msm_gem_vaddr_locked(ring->bo);
43	ring->end   = ring->start + (size / 4);
 
 
44	ring->cur   = ring->start;
45
46	ring->size = size;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
48	return ring;
49
50fail:
51	if (ring)
52		msm_ringbuffer_destroy(ring);
53	return ERR_PTR(ret);
54}
55
56void msm_ringbuffer_destroy(struct msm_ringbuffer *ring)
57{
58	if (ring->bo)
59		drm_gem_object_unreference_unlocked(ring->bo);
 
 
 
 
 
 
 
60	kfree(ring);
61}
v6.2
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Copyright (C) 2013 Red Hat
  4 * Author: Rob Clark <robdclark@gmail.com>
 
 
 
 
 
 
 
 
 
 
 
 
  5 */
  6
  7#include "msm_ringbuffer.h"
  8#include "msm_gpu.h"
  9
 10static uint num_hw_submissions = 8;
 11MODULE_PARM_DESC(num_hw_submissions, "The max # of jobs to write into ringbuffer (default 8)");
 12module_param(num_hw_submissions, uint, 0600);
 13
 14static 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	int i;
 20
 21	submit->hw_fence = msm_fence_alloc(fctx);
 22
 23	for (i = 0; i < submit->nr_bos; i++) {
 24		struct drm_gem_object *obj = &submit->bos[i].obj->base;
 25
 26		msm_gem_lock(obj);
 27		msm_gem_unpin_vma_fenced(submit->bos[i].vma, fctx);
 28		msm_gem_unpin_locked(obj);
 29		submit->bos[i].flags &= ~(BO_VMA_PINNED | BO_OBJ_PINNED);
 30		msm_gem_unlock(obj);
 31	}
 32
 33	/* TODO move submit path over to using a per-ring lock.. */
 34	mutex_lock(&gpu->lock);
 35
 36	msm_gpu_submit(gpu, submit);
 37
 38	mutex_unlock(&gpu->lock);
 39
 40	return dma_fence_get(submit->hw_fence);
 41}
 42
 43static void msm_job_free(struct drm_sched_job *job)
 44{
 45	struct msm_gem_submit *submit = to_msm_submit(job);
 46
 47	drm_sched_job_cleanup(job);
 48	msm_gem_submit_put(submit);
 49}
 50
 51static const struct drm_sched_backend_ops msm_sched_ops = {
 52	.run_job = msm_job_run,
 53	.free_job = msm_job_free
 54};
 55
 56struct msm_ringbuffer *msm_ringbuffer_new(struct msm_gpu *gpu, int id,
 57		void *memptrs, uint64_t memptrs_iova)
 58{
 59	struct msm_ringbuffer *ring;
 60	long sched_timeout;
 61	char name[32];
 62	int ret;
 63
 64	/* We assume everwhere that MSM_GPU_RINGBUFFER_SZ is a power of 2 */
 65	BUILD_BUG_ON(!is_power_of_2(MSM_GPU_RINGBUFFER_SZ));
 66
 67	ring = kzalloc(sizeof(*ring), GFP_KERNEL);
 68	if (!ring) {
 69		ret = -ENOMEM;
 70		goto fail;
 71	}
 72
 73	ring->gpu = gpu;
 74	ring->id = id;
 75
 76	ring->start = msm_gem_kernel_new(gpu->dev, MSM_GPU_RINGBUFFER_SZ,
 77		check_apriv(gpu, MSM_BO_WC | MSM_BO_GPU_READONLY),
 78		gpu->aspace, &ring->bo, &ring->iova);
 79
 80	if (IS_ERR(ring->start)) {
 81		ret = PTR_ERR(ring->start);
 82		ring->start = NULL;
 83		goto fail;
 84	}
 85
 86	msm_gem_object_set_name(ring->bo, "ring%d", id);
 87
 88	ring->end   = ring->start + (MSM_GPU_RINGBUFFER_SZ >> 2);
 89	ring->next  = ring->start;
 90	ring->cur   = ring->start;
 91
 92	ring->memptrs = memptrs;
 93	ring->memptrs_iova = memptrs_iova;
 94
 95	 /* currently managing hangcheck ourselves: */
 96	sched_timeout = MAX_SCHEDULE_TIMEOUT;
 97
 98	ret = drm_sched_init(&ring->sched, &msm_sched_ops,
 99			num_hw_submissions, 0, sched_timeout,
100			NULL, NULL, to_msm_bo(ring->bo)->name, gpu->dev->dev);
101	if (ret) {
102		goto fail;
103	}
104
105	INIT_LIST_HEAD(&ring->submits);
106	spin_lock_init(&ring->submit_lock);
107	spin_lock_init(&ring->preempt_lock);
108
109	snprintf(name, sizeof(name), "gpu-ring-%d", ring->id);
110
111	ring->fctx = msm_fence_context_alloc(gpu->dev, &ring->memptrs->fence, name);
112
113	return ring;
114
115fail:
116	msm_ringbuffer_destroy(ring);
 
117	return ERR_PTR(ret);
118}
119
120void msm_ringbuffer_destroy(struct msm_ringbuffer *ring)
121{
122	if (IS_ERR_OR_NULL(ring))
123		return;
124
125	drm_sched_fini(&ring->sched);
126
127	msm_fence_context_free(ring->fctx);
128
129	msm_gem_kernel_put(ring->bo, ring->gpu->aspace);
130
131	kfree(ring);
132}