xref: /aosp_15_r20/external/mesa3d/src/virtio/vdrm/vdrm.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright © 2023 Google, Inc.
3*61046927SAndroid Build Coastguard Worker  * SPDX-License-Identifier: MIT
4*61046927SAndroid Build Coastguard Worker  */
5*61046927SAndroid Build Coastguard Worker 
6*61046927SAndroid Build Coastguard Worker #include "util/u_math.h"
7*61046927SAndroid Build Coastguard Worker #include "util/perf/cpu_trace.h"
8*61046927SAndroid Build Coastguard Worker 
9*61046927SAndroid Build Coastguard Worker #include "vdrm.h"
10*61046927SAndroid Build Coastguard Worker 
11*61046927SAndroid Build Coastguard Worker struct vdrm_device * vdrm_virtgpu_connect(int fd, uint32_t context_type);
12*61046927SAndroid Build Coastguard Worker 
13*61046927SAndroid Build Coastguard Worker struct vdrm_device *
vdrm_device_connect(int fd,uint32_t context_type)14*61046927SAndroid Build Coastguard Worker vdrm_device_connect(int fd, uint32_t context_type)
15*61046927SAndroid Build Coastguard Worker {
16*61046927SAndroid Build Coastguard Worker    struct vdrm_device *vdev;
17*61046927SAndroid Build Coastguard Worker 
18*61046927SAndroid Build Coastguard Worker    // TODO vtest vs virtio..
19*61046927SAndroid Build Coastguard Worker    vdev = vdrm_virtgpu_connect(fd, context_type);
20*61046927SAndroid Build Coastguard Worker    if (!vdev)
21*61046927SAndroid Build Coastguard Worker       return NULL;
22*61046927SAndroid Build Coastguard Worker 
23*61046927SAndroid Build Coastguard Worker    simple_mtx_init(&vdev->rsp_lock, mtx_plain);
24*61046927SAndroid Build Coastguard Worker    simple_mtx_init(&vdev->eb_lock, mtx_plain);
25*61046927SAndroid Build Coastguard Worker 
26*61046927SAndroid Build Coastguard Worker    return vdev;
27*61046927SAndroid Build Coastguard Worker }
28*61046927SAndroid Build Coastguard Worker 
29*61046927SAndroid Build Coastguard Worker void
vdrm_device_close(struct vdrm_device * vdev)30*61046927SAndroid Build Coastguard Worker vdrm_device_close(struct vdrm_device *vdev)
31*61046927SAndroid Build Coastguard Worker {
32*61046927SAndroid Build Coastguard Worker    vdev->funcs->close(vdev);
33*61046927SAndroid Build Coastguard Worker    free(vdev);
34*61046927SAndroid Build Coastguard Worker }
35*61046927SAndroid Build Coastguard Worker 
36*61046927SAndroid Build Coastguard Worker uint32_t
vdrm_bo_create(struct vdrm_device * vdev,size_t size,uint32_t blob_flags,uint64_t blob_id,struct vdrm_ccmd_req * req)37*61046927SAndroid Build Coastguard Worker vdrm_bo_create(struct vdrm_device *vdev, size_t size, uint32_t blob_flags,
38*61046927SAndroid Build Coastguard Worker                uint64_t blob_id, struct vdrm_ccmd_req *req)
39*61046927SAndroid Build Coastguard Worker {
40*61046927SAndroid Build Coastguard Worker    uint32_t handle;
41*61046927SAndroid Build Coastguard Worker 
42*61046927SAndroid Build Coastguard Worker    simple_mtx_lock(&vdev->eb_lock);
43*61046927SAndroid Build Coastguard Worker 
44*61046927SAndroid Build Coastguard Worker    /* flush any buffered cmds so they are seen by the host *prior* to
45*61046927SAndroid Build Coastguard Worker     * the cmds associated with bo creation.
46*61046927SAndroid Build Coastguard Worker     */
47*61046927SAndroid Build Coastguard Worker    vdev->funcs->flush_locked(vdev, NULL);
48*61046927SAndroid Build Coastguard Worker 
49*61046927SAndroid Build Coastguard Worker    req->seqno = ++vdev->next_seqno;
50*61046927SAndroid Build Coastguard Worker 
51*61046927SAndroid Build Coastguard Worker    handle = vdev->funcs->bo_create(vdev, size, blob_flags, blob_id, req);
52*61046927SAndroid Build Coastguard Worker 
53*61046927SAndroid Build Coastguard Worker    simple_mtx_unlock(&vdev->eb_lock);
54*61046927SAndroid Build Coastguard Worker 
55*61046927SAndroid Build Coastguard Worker    return handle;
56*61046927SAndroid Build Coastguard Worker }
57*61046927SAndroid Build Coastguard Worker 
58*61046927SAndroid Build Coastguard Worker void *
vdrm_alloc_rsp(struct vdrm_device * vdev,struct vdrm_ccmd_req * req,uint32_t sz)59*61046927SAndroid Build Coastguard Worker vdrm_alloc_rsp(struct vdrm_device *vdev, struct vdrm_ccmd_req *req, uint32_t sz)
60*61046927SAndroid Build Coastguard Worker {
61*61046927SAndroid Build Coastguard Worker    unsigned off;
62*61046927SAndroid Build Coastguard Worker 
63*61046927SAndroid Build Coastguard Worker    simple_mtx_lock(&vdev->rsp_lock);
64*61046927SAndroid Build Coastguard Worker 
65*61046927SAndroid Build Coastguard Worker    sz = align(sz, 8);
66*61046927SAndroid Build Coastguard Worker 
67*61046927SAndroid Build Coastguard Worker    if ((vdev->next_rsp_off + sz) >= vdev->rsp_mem_len)
68*61046927SAndroid Build Coastguard Worker       vdev->next_rsp_off = 0;
69*61046927SAndroid Build Coastguard Worker 
70*61046927SAndroid Build Coastguard Worker    off = vdev->next_rsp_off;
71*61046927SAndroid Build Coastguard Worker    vdev->next_rsp_off += sz;
72*61046927SAndroid Build Coastguard Worker 
73*61046927SAndroid Build Coastguard Worker    simple_mtx_unlock(&vdev->rsp_lock);
74*61046927SAndroid Build Coastguard Worker 
75*61046927SAndroid Build Coastguard Worker    req->rsp_off = off;
76*61046927SAndroid Build Coastguard Worker 
77*61046927SAndroid Build Coastguard Worker    struct vdrm_ccmd_rsp *rsp = (void *)&vdev->rsp_mem[off];
78*61046927SAndroid Build Coastguard Worker    rsp->len = sz;
79*61046927SAndroid Build Coastguard Worker 
80*61046927SAndroid Build Coastguard Worker    return rsp;
81*61046927SAndroid Build Coastguard Worker }
82*61046927SAndroid Build Coastguard Worker 
83*61046927SAndroid Build Coastguard Worker static int
enqueue_req(struct vdrm_device * vdev,struct vdrm_ccmd_req * req)84*61046927SAndroid Build Coastguard Worker enqueue_req(struct vdrm_device *vdev, struct vdrm_ccmd_req *req)
85*61046927SAndroid Build Coastguard Worker {
86*61046927SAndroid Build Coastguard Worker    simple_mtx_assert_locked(&vdev->eb_lock);
87*61046927SAndroid Build Coastguard Worker 
88*61046927SAndroid Build Coastguard Worker    req->seqno = ++vdev->next_seqno;
89*61046927SAndroid Build Coastguard Worker 
90*61046927SAndroid Build Coastguard Worker    if ((vdev->reqbuf_len + req->len) > sizeof(vdev->reqbuf)) {
91*61046927SAndroid Build Coastguard Worker       int ret = vdev->funcs->flush_locked(vdev, NULL);
92*61046927SAndroid Build Coastguard Worker       if (ret)
93*61046927SAndroid Build Coastguard Worker          return ret;
94*61046927SAndroid Build Coastguard Worker    }
95*61046927SAndroid Build Coastguard Worker 
96*61046927SAndroid Build Coastguard Worker    memcpy(&vdev->reqbuf[vdev->reqbuf_len], req, req->len);
97*61046927SAndroid Build Coastguard Worker    vdev->reqbuf_len += req->len;
98*61046927SAndroid Build Coastguard Worker    vdev->reqbuf_cnt++;
99*61046927SAndroid Build Coastguard Worker 
100*61046927SAndroid Build Coastguard Worker    return 0;
101*61046927SAndroid Build Coastguard Worker }
102*61046927SAndroid Build Coastguard Worker 
103*61046927SAndroid Build Coastguard Worker int
vdrm_execbuf(struct vdrm_device * vdev,struct vdrm_execbuf_params * p)104*61046927SAndroid Build Coastguard Worker vdrm_execbuf(struct vdrm_device *vdev, struct vdrm_execbuf_params *p)
105*61046927SAndroid Build Coastguard Worker {
106*61046927SAndroid Build Coastguard Worker    int ret = 0;
107*61046927SAndroid Build Coastguard Worker 
108*61046927SAndroid Build Coastguard Worker    MESA_TRACE_FUNC();
109*61046927SAndroid Build Coastguard Worker 
110*61046927SAndroid Build Coastguard Worker    simple_mtx_lock(&vdev->eb_lock);
111*61046927SAndroid Build Coastguard Worker 
112*61046927SAndroid Build Coastguard Worker    p->req->seqno = ++vdev->next_seqno;
113*61046927SAndroid Build Coastguard Worker 
114*61046927SAndroid Build Coastguard Worker    ret = vdev->funcs->flush_locked(vdev, NULL);
115*61046927SAndroid Build Coastguard Worker    if (ret)
116*61046927SAndroid Build Coastguard Worker       goto out_unlock;
117*61046927SAndroid Build Coastguard Worker 
118*61046927SAndroid Build Coastguard Worker    ret = vdev->funcs->execbuf_locked(vdev, p, p->req, p->req->len);
119*61046927SAndroid Build Coastguard Worker 
120*61046927SAndroid Build Coastguard Worker out_unlock:
121*61046927SAndroid Build Coastguard Worker    simple_mtx_unlock(&vdev->eb_lock);
122*61046927SAndroid Build Coastguard Worker 
123*61046927SAndroid Build Coastguard Worker    return ret;
124*61046927SAndroid Build Coastguard Worker }
125*61046927SAndroid Build Coastguard Worker 
126*61046927SAndroid Build Coastguard Worker /**
127*61046927SAndroid Build Coastguard Worker  * Buffer/send a request cmd to host
128*61046927SAndroid Build Coastguard Worker  */
129*61046927SAndroid Build Coastguard Worker int
vdrm_send_req(struct vdrm_device * vdev,struct vdrm_ccmd_req * req,bool sync)130*61046927SAndroid Build Coastguard Worker vdrm_send_req(struct vdrm_device *vdev, struct vdrm_ccmd_req *req, bool sync)
131*61046927SAndroid Build Coastguard Worker {
132*61046927SAndroid Build Coastguard Worker    MESA_TRACE_FUNC();
133*61046927SAndroid Build Coastguard Worker 
134*61046927SAndroid Build Coastguard Worker    uintptr_t fence = 0;
135*61046927SAndroid Build Coastguard Worker    int ret = 0;
136*61046927SAndroid Build Coastguard Worker 
137*61046927SAndroid Build Coastguard Worker    simple_mtx_lock(&vdev->eb_lock);
138*61046927SAndroid Build Coastguard Worker    ret = enqueue_req(vdev, req);
139*61046927SAndroid Build Coastguard Worker 
140*61046927SAndroid Build Coastguard Worker    if (ret || !sync)
141*61046927SAndroid Build Coastguard Worker       goto out_unlock;
142*61046927SAndroid Build Coastguard Worker 
143*61046927SAndroid Build Coastguard Worker    ret = vdev->funcs->flush_locked(vdev, &fence);
144*61046927SAndroid Build Coastguard Worker 
145*61046927SAndroid Build Coastguard Worker out_unlock:
146*61046927SAndroid Build Coastguard Worker    simple_mtx_unlock(&vdev->eb_lock);
147*61046927SAndroid Build Coastguard Worker 
148*61046927SAndroid Build Coastguard Worker    if (ret)
149*61046927SAndroid Build Coastguard Worker       return ret;
150*61046927SAndroid Build Coastguard Worker 
151*61046927SAndroid Build Coastguard Worker    if (sync) {
152*61046927SAndroid Build Coastguard Worker       MESA_TRACE_SCOPE("vdrm_execbuf sync");
153*61046927SAndroid Build Coastguard Worker       vdev->funcs->wait_fence(vdev, fence);
154*61046927SAndroid Build Coastguard Worker       vdrm_host_sync(vdev, req);
155*61046927SAndroid Build Coastguard Worker    }
156*61046927SAndroid Build Coastguard Worker 
157*61046927SAndroid Build Coastguard Worker    return 0;
158*61046927SAndroid Build Coastguard Worker }
159*61046927SAndroid Build Coastguard Worker 
160*61046927SAndroid Build Coastguard Worker int
vdrm_flush(struct vdrm_device * vdev)161*61046927SAndroid Build Coastguard Worker vdrm_flush(struct vdrm_device *vdev)
162*61046927SAndroid Build Coastguard Worker {
163*61046927SAndroid Build Coastguard Worker    int ret = 0;
164*61046927SAndroid Build Coastguard Worker 
165*61046927SAndroid Build Coastguard Worker    MESA_TRACE_FUNC();
166*61046927SAndroid Build Coastguard Worker 
167*61046927SAndroid Build Coastguard Worker    simple_mtx_lock(&vdev->eb_lock);
168*61046927SAndroid Build Coastguard Worker    ret = vdev->funcs->flush_locked(vdev, NULL);
169*61046927SAndroid Build Coastguard Worker    simple_mtx_unlock(&vdev->eb_lock);
170*61046927SAndroid Build Coastguard Worker 
171*61046927SAndroid Build Coastguard Worker    return ret;
172*61046927SAndroid Build Coastguard Worker }
173*61046927SAndroid Build Coastguard Worker 
174*61046927SAndroid Build Coastguard Worker /**
175*61046927SAndroid Build Coastguard Worker  * Helper for fence/seqno comparisions which deals properly with rollover.
176*61046927SAndroid Build Coastguard Worker  * Returns true if fence 'a' is before fence 'b'
177*61046927SAndroid Build Coastguard Worker  */
178*61046927SAndroid Build Coastguard Worker static bool
fence_before(uint32_t a,uint32_t b)179*61046927SAndroid Build Coastguard Worker fence_before(uint32_t a, uint32_t b)
180*61046927SAndroid Build Coastguard Worker {
181*61046927SAndroid Build Coastguard Worker    return (int32_t)(a - b) < 0;
182*61046927SAndroid Build Coastguard Worker }
183*61046927SAndroid Build Coastguard Worker 
184*61046927SAndroid Build Coastguard Worker /**
185*61046927SAndroid Build Coastguard Worker  * Wait until host has processed the specified request.
186*61046927SAndroid Build Coastguard Worker  */
187*61046927SAndroid Build Coastguard Worker void
vdrm_host_sync(struct vdrm_device * vdev,const struct vdrm_ccmd_req * req)188*61046927SAndroid Build Coastguard Worker vdrm_host_sync(struct vdrm_device *vdev, const struct vdrm_ccmd_req *req)
189*61046927SAndroid Build Coastguard Worker {
190*61046927SAndroid Build Coastguard Worker    while (fence_before(vdev->shmem->seqno, req->seqno))
191*61046927SAndroid Build Coastguard Worker       sched_yield();
192*61046927SAndroid Build Coastguard Worker }
193