xref: /aosp_15_r20/external/libdrm/tegra/job.c (revision 7688df22e49036ff52a766b7101da3a49edadb8c)
1*7688df22SAndroid Build Coastguard Worker /*
2*7688df22SAndroid Build Coastguard Worker  * Copyright © 2012, 2013 Thierry Reding
3*7688df22SAndroid Build Coastguard Worker  * Copyright © 2013 Erik Faye-Lund
4*7688df22SAndroid Build Coastguard Worker  * Copyright © 2014 NVIDIA Corporation
5*7688df22SAndroid Build Coastguard Worker  *
6*7688df22SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
7*7688df22SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the "Software"),
8*7688df22SAndroid Build Coastguard Worker  * to deal in the Software without restriction, including without limitation
9*7688df22SAndroid Build Coastguard Worker  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10*7688df22SAndroid Build Coastguard Worker  * and/or sell copies of the Software, and to permit persons to whom the
11*7688df22SAndroid Build Coastguard Worker  * Software is furnished to do so, subject to the following conditions:
12*7688df22SAndroid Build Coastguard Worker  *
13*7688df22SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice shall be included in
14*7688df22SAndroid Build Coastguard Worker  * all copies or substantial portions of the Software.
15*7688df22SAndroid Build Coastguard Worker  *
16*7688df22SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17*7688df22SAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18*7688df22SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19*7688df22SAndroid Build Coastguard Worker  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20*7688df22SAndroid Build Coastguard Worker  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21*7688df22SAndroid Build Coastguard Worker  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22*7688df22SAndroid Build Coastguard Worker  * OTHER DEALINGS IN THE SOFTWARE.
23*7688df22SAndroid Build Coastguard Worker  */
24*7688df22SAndroid Build Coastguard Worker 
25*7688df22SAndroid Build Coastguard Worker #ifdef HAVE_CONFIG_H
26*7688df22SAndroid Build Coastguard Worker #  include "config.h"
27*7688df22SAndroid Build Coastguard Worker #endif
28*7688df22SAndroid Build Coastguard Worker 
29*7688df22SAndroid Build Coastguard Worker #include <errno.h>
30*7688df22SAndroid Build Coastguard Worker #include <stdlib.h>
31*7688df22SAndroid Build Coastguard Worker #include <string.h>
32*7688df22SAndroid Build Coastguard Worker #include <time.h>
33*7688df22SAndroid Build Coastguard Worker #include <unistd.h>
34*7688df22SAndroid Build Coastguard Worker 
35*7688df22SAndroid Build Coastguard Worker #include <sys/ioctl.h>
36*7688df22SAndroid Build Coastguard Worker #include <poll.h>
37*7688df22SAndroid Build Coastguard Worker 
38*7688df22SAndroid Build Coastguard Worker #include "private.h"
39*7688df22SAndroid Build Coastguard Worker 
40*7688df22SAndroid Build Coastguard Worker struct drm_tegra_submit_cmd *
drm_tegra_job_add_command(struct drm_tegra_job * job,uint32_t type,uint32_t flags)41*7688df22SAndroid Build Coastguard Worker drm_tegra_job_add_command(struct drm_tegra_job *job, uint32_t type,
42*7688df22SAndroid Build Coastguard Worker                           uint32_t flags)
43*7688df22SAndroid Build Coastguard Worker {
44*7688df22SAndroid Build Coastguard Worker     struct drm_tegra_submit_cmd *commands, *command;
45*7688df22SAndroid Build Coastguard Worker     size_t size;
46*7688df22SAndroid Build Coastguard Worker 
47*7688df22SAndroid Build Coastguard Worker     size = (job->num_commands + 1) * sizeof(*commands);
48*7688df22SAndroid Build Coastguard Worker 
49*7688df22SAndroid Build Coastguard Worker     commands = realloc(job->commands, size);
50*7688df22SAndroid Build Coastguard Worker     if (!commands)
51*7688df22SAndroid Build Coastguard Worker         return NULL;
52*7688df22SAndroid Build Coastguard Worker 
53*7688df22SAndroid Build Coastguard Worker     command = &commands[job->num_commands];
54*7688df22SAndroid Build Coastguard Worker     memset(command, 0, sizeof(*command));
55*7688df22SAndroid Build Coastguard Worker     command->type = type;
56*7688df22SAndroid Build Coastguard Worker     command->flags = flags;
57*7688df22SAndroid Build Coastguard Worker 
58*7688df22SAndroid Build Coastguard Worker     job->commands = commands;
59*7688df22SAndroid Build Coastguard Worker     job->num_commands++;
60*7688df22SAndroid Build Coastguard Worker 
61*7688df22SAndroid Build Coastguard Worker     return command;
62*7688df22SAndroid Build Coastguard Worker }
63*7688df22SAndroid Build Coastguard Worker 
64*7688df22SAndroid Build Coastguard Worker drm_public int
drm_tegra_job_new(struct drm_tegra_channel * channel,struct drm_tegra_job ** jobp)65*7688df22SAndroid Build Coastguard Worker drm_tegra_job_new(struct drm_tegra_channel *channel,
66*7688df22SAndroid Build Coastguard Worker                   struct drm_tegra_job **jobp)
67*7688df22SAndroid Build Coastguard Worker {
68*7688df22SAndroid Build Coastguard Worker     struct drm_tegra_job *job;
69*7688df22SAndroid Build Coastguard Worker 
70*7688df22SAndroid Build Coastguard Worker     job = calloc(1, sizeof(*job));
71*7688df22SAndroid Build Coastguard Worker     if (!job)
72*7688df22SAndroid Build Coastguard Worker         return -ENOMEM;
73*7688df22SAndroid Build Coastguard Worker 
74*7688df22SAndroid Build Coastguard Worker     job->page_size = sysconf(_SC_PAGESIZE);
75*7688df22SAndroid Build Coastguard Worker     job->channel = channel;
76*7688df22SAndroid Build Coastguard Worker 
77*7688df22SAndroid Build Coastguard Worker     *jobp = job;
78*7688df22SAndroid Build Coastguard Worker 
79*7688df22SAndroid Build Coastguard Worker     return 0;
80*7688df22SAndroid Build Coastguard Worker }
81*7688df22SAndroid Build Coastguard Worker 
drm_tegra_job_free(struct drm_tegra_job * job)82*7688df22SAndroid Build Coastguard Worker drm_public int drm_tegra_job_free(struct drm_tegra_job *job)
83*7688df22SAndroid Build Coastguard Worker {
84*7688df22SAndroid Build Coastguard Worker     if (!job)
85*7688df22SAndroid Build Coastguard Worker         return -EINVAL;
86*7688df22SAndroid Build Coastguard Worker 
87*7688df22SAndroid Build Coastguard Worker     if (job->pushbuf)
88*7688df22SAndroid Build Coastguard Worker         drm_tegra_pushbuf_free(job->pushbuf);
89*7688df22SAndroid Build Coastguard Worker 
90*7688df22SAndroid Build Coastguard Worker     if (job->commands)
91*7688df22SAndroid Build Coastguard Worker         free(job->commands);
92*7688df22SAndroid Build Coastguard Worker 
93*7688df22SAndroid Build Coastguard Worker     if (job->buffers)
94*7688df22SAndroid Build Coastguard Worker         free(job->buffers);
95*7688df22SAndroid Build Coastguard Worker 
96*7688df22SAndroid Build Coastguard Worker     free(job);
97*7688df22SAndroid Build Coastguard Worker 
98*7688df22SAndroid Build Coastguard Worker     return 0;
99*7688df22SAndroid Build Coastguard Worker }
100*7688df22SAndroid Build Coastguard Worker 
101*7688df22SAndroid Build Coastguard Worker drm_public int
drm_tegra_job_get_pushbuf(struct drm_tegra_job * job,struct drm_tegra_pushbuf ** pushbufp)102*7688df22SAndroid Build Coastguard Worker drm_tegra_job_get_pushbuf(struct drm_tegra_job *job,
103*7688df22SAndroid Build Coastguard Worker                           struct drm_tegra_pushbuf **pushbufp)
104*7688df22SAndroid Build Coastguard Worker {
105*7688df22SAndroid Build Coastguard Worker     struct drm_tegra_pushbuf *pushbuf;
106*7688df22SAndroid Build Coastguard Worker 
107*7688df22SAndroid Build Coastguard Worker     if (!job->pushbuf) {
108*7688df22SAndroid Build Coastguard Worker         pushbuf = calloc(1, sizeof(*pushbuf));
109*7688df22SAndroid Build Coastguard Worker         if (!pushbuf)
110*7688df22SAndroid Build Coastguard Worker             return -ENOMEM;
111*7688df22SAndroid Build Coastguard Worker 
112*7688df22SAndroid Build Coastguard Worker         pushbuf->job = job;
113*7688df22SAndroid Build Coastguard Worker 
114*7688df22SAndroid Build Coastguard Worker         pushbuf->start = calloc(1, job->page_size);
115*7688df22SAndroid Build Coastguard Worker         if (!pushbuf->start) {
116*7688df22SAndroid Build Coastguard Worker             free(pushbuf);
117*7688df22SAndroid Build Coastguard Worker             return -ENOMEM;
118*7688df22SAndroid Build Coastguard Worker         }
119*7688df22SAndroid Build Coastguard Worker 
120*7688df22SAndroid Build Coastguard Worker         pushbuf->end = pushbuf->start + job->page_size / 4;
121*7688df22SAndroid Build Coastguard Worker         pushbuf->ptr = pushbuf->start;
122*7688df22SAndroid Build Coastguard Worker 
123*7688df22SAndroid Build Coastguard Worker         job->pushbuf = pushbuf;
124*7688df22SAndroid Build Coastguard Worker     }
125*7688df22SAndroid Build Coastguard Worker 
126*7688df22SAndroid Build Coastguard Worker     *pushbufp = job->pushbuf;
127*7688df22SAndroid Build Coastguard Worker 
128*7688df22SAndroid Build Coastguard Worker     return 0;
129*7688df22SAndroid Build Coastguard Worker }
130*7688df22SAndroid Build Coastguard Worker 
131*7688df22SAndroid Build Coastguard Worker drm_public int
drm_tegra_job_submit(struct drm_tegra_job * job,struct drm_tegra_fence * fence)132*7688df22SAndroid Build Coastguard Worker drm_tegra_job_submit(struct drm_tegra_job *job, struct drm_tegra_fence *fence)
133*7688df22SAndroid Build Coastguard Worker {
134*7688df22SAndroid Build Coastguard Worker     struct drm_tegra_channel *channel = job->channel;
135*7688df22SAndroid Build Coastguard Worker     struct drm_tegra *drm = channel->drm;
136*7688df22SAndroid Build Coastguard Worker     struct drm_tegra_channel_submit args;
137*7688df22SAndroid Build Coastguard Worker     int err;
138*7688df22SAndroid Build Coastguard Worker 
139*7688df22SAndroid Build Coastguard Worker     memset(&args, 0, sizeof(args));
140*7688df22SAndroid Build Coastguard Worker     args.context = channel->context;
141*7688df22SAndroid Build Coastguard Worker     args.num_bufs = job->num_buffers;
142*7688df22SAndroid Build Coastguard Worker     args.num_cmds = job->num_commands;
143*7688df22SAndroid Build Coastguard Worker     args.gather_data_words = job->pushbuf->ptr - job->pushbuf->start;
144*7688df22SAndroid Build Coastguard Worker     args.syncpt.id = job->syncpt.id;
145*7688df22SAndroid Build Coastguard Worker     args.syncpt.increments = job->syncpt.increments;
146*7688df22SAndroid Build Coastguard Worker 
147*7688df22SAndroid Build Coastguard Worker     args.bufs_ptr = (uintptr_t)job->buffers;
148*7688df22SAndroid Build Coastguard Worker     args.cmds_ptr = (uintptr_t)job->commands;
149*7688df22SAndroid Build Coastguard Worker     args.gather_data_ptr = (uintptr_t)job->pushbuf->start;
150*7688df22SAndroid Build Coastguard Worker 
151*7688df22SAndroid Build Coastguard Worker     err = ioctl(drm->fd, DRM_IOCTL_TEGRA_CHANNEL_SUBMIT, &args);
152*7688df22SAndroid Build Coastguard Worker     if (err < 0)
153*7688df22SAndroid Build Coastguard Worker         return -errno;
154*7688df22SAndroid Build Coastguard Worker 
155*7688df22SAndroid Build Coastguard Worker     job->syncpt.fence = args.syncpt.value;
156*7688df22SAndroid Build Coastguard Worker 
157*7688df22SAndroid Build Coastguard Worker     if (fence) {
158*7688df22SAndroid Build Coastguard Worker         fence->drm = drm;
159*7688df22SAndroid Build Coastguard Worker         fence->syncpt = job->syncpt.id;
160*7688df22SAndroid Build Coastguard Worker         fence->value = job->syncpt.fence;
161*7688df22SAndroid Build Coastguard Worker     }
162*7688df22SAndroid Build Coastguard Worker 
163*7688df22SAndroid Build Coastguard Worker     return 0;
164*7688df22SAndroid Build Coastguard Worker }
165*7688df22SAndroid Build Coastguard Worker 
166*7688df22SAndroid Build Coastguard Worker drm_public int
drm_tegra_job_wait(struct drm_tegra_job * job,unsigned long timeout)167*7688df22SAndroid Build Coastguard Worker drm_tegra_job_wait(struct drm_tegra_job *job, unsigned long timeout)
168*7688df22SAndroid Build Coastguard Worker {
169*7688df22SAndroid Build Coastguard Worker     struct drm_tegra_channel *channel = job->channel;
170*7688df22SAndroid Build Coastguard Worker     struct drm_tegra *drm = channel->drm;
171*7688df22SAndroid Build Coastguard Worker     struct drm_tegra_syncpoint_wait args;
172*7688df22SAndroid Build Coastguard Worker     struct timespec ts;
173*7688df22SAndroid Build Coastguard Worker     int err;
174*7688df22SAndroid Build Coastguard Worker 
175*7688df22SAndroid Build Coastguard Worker     clock_gettime(CLOCK_MONOTONIC, &ts);
176*7688df22SAndroid Build Coastguard Worker 
177*7688df22SAndroid Build Coastguard Worker     memset(&args, 0, sizeof(args));
178*7688df22SAndroid Build Coastguard Worker     args.timeout_ns = ts.tv_sec * 1000000000 + ts.tv_nsec + timeout;
179*7688df22SAndroid Build Coastguard Worker     args.id = job->syncpt.id;
180*7688df22SAndroid Build Coastguard Worker     args.threshold = job->syncpt.fence;
181*7688df22SAndroid Build Coastguard Worker 
182*7688df22SAndroid Build Coastguard Worker     err = ioctl(drm->fd, DRM_IOCTL_TEGRA_SYNCPOINT_WAIT, &args);
183*7688df22SAndroid Build Coastguard Worker     if (err < 0)
184*7688df22SAndroid Build Coastguard Worker         return -errno;
185*7688df22SAndroid Build Coastguard Worker 
186*7688df22SAndroid Build Coastguard Worker     return 0;
187*7688df22SAndroid Build Coastguard Worker }
188