1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker * Copyright 2020 Google
3*61046927SAndroid Build Coastguard Worker * SPDX-License-Identifier: MIT
4*61046927SAndroid Build Coastguard Worker */
5*61046927SAndroid Build Coastguard Worker #include "AddressSpaceStream.h"
6*61046927SAndroid Build Coastguard Worker
7*61046927SAndroid Build Coastguard Worker #include <errno.h>
8*61046927SAndroid Build Coastguard Worker #include <stdio.h>
9*61046927SAndroid Build Coastguard Worker #include <stdlib.h>
10*61046927SAndroid Build Coastguard Worker #include <string.h>
11*61046927SAndroid Build Coastguard Worker #include <unistd.h>
12*61046927SAndroid Build Coastguard Worker
13*61046927SAndroid Build Coastguard Worker #include "VirtGpu.h"
14*61046927SAndroid Build Coastguard Worker #include "util/log.h"
15*61046927SAndroid Build Coastguard Worker #include "util/perf/cpu_trace.h"
16*61046927SAndroid Build Coastguard Worker #include "virtgpu_gfxstream_protocol.h"
17*61046927SAndroid Build Coastguard Worker
18*61046927SAndroid Build Coastguard Worker static const size_t kReadSize = 512 * 1024;
19*61046927SAndroid Build Coastguard Worker static const size_t kWriteOffset = kReadSize;
20*61046927SAndroid Build Coastguard Worker
AddressSpaceStream(address_space_handle_t handle,uint32_t version,struct asg_context context,uint64_t ringOffset,uint64_t writeBufferOffset,struct address_space_ops ops)21*61046927SAndroid Build Coastguard Worker AddressSpaceStream::AddressSpaceStream(address_space_handle_t handle, uint32_t version,
22*61046927SAndroid Build Coastguard Worker struct asg_context context, uint64_t ringOffset,
23*61046927SAndroid Build Coastguard Worker uint64_t writeBufferOffset, struct address_space_ops ops)
24*61046927SAndroid Build Coastguard Worker : IOStream(context.ring_config->flush_interval),
25*61046927SAndroid Build Coastguard Worker m_ops(ops),
26*61046927SAndroid Build Coastguard Worker m_tmpBuf(0),
27*61046927SAndroid Build Coastguard Worker m_tmpBufSize(0),
28*61046927SAndroid Build Coastguard Worker m_tmpBufXferSize(0),
29*61046927SAndroid Build Coastguard Worker m_usingTmpBuf(0),
30*61046927SAndroid Build Coastguard Worker m_readBuf(0),
31*61046927SAndroid Build Coastguard Worker m_read(0),
32*61046927SAndroid Build Coastguard Worker m_readLeft(0),
33*61046927SAndroid Build Coastguard Worker m_handle(handle),
34*61046927SAndroid Build Coastguard Worker m_version(version),
35*61046927SAndroid Build Coastguard Worker m_context(context),
36*61046927SAndroid Build Coastguard Worker m_ringOffset(ringOffset),
37*61046927SAndroid Build Coastguard Worker m_writeBufferOffset(writeBufferOffset),
38*61046927SAndroid Build Coastguard Worker m_writeBufferSize(context.ring_config->buffer_size),
39*61046927SAndroid Build Coastguard Worker m_writeBufferMask(m_writeBufferSize - 1),
40*61046927SAndroid Build Coastguard Worker m_buf((unsigned char*)context.buffer),
41*61046927SAndroid Build Coastguard Worker m_writeStart(m_buf),
42*61046927SAndroid Build Coastguard Worker m_writeStep(context.ring_config->flush_interval),
43*61046927SAndroid Build Coastguard Worker m_notifs(0),
44*61046927SAndroid Build Coastguard Worker m_written(0),
45*61046927SAndroid Build Coastguard Worker m_backoffIters(0),
46*61046927SAndroid Build Coastguard Worker m_backoffFactor(1),
47*61046927SAndroid Build Coastguard Worker m_ringStorageSize(sizeof(struct asg_ring_storage) + m_writeBufferSize) {
48*61046927SAndroid Build Coastguard Worker // We'll use this in the future, but at the moment,
49*61046927SAndroid Build Coastguard Worker // it's a potential compile Werror.
50*61046927SAndroid Build Coastguard Worker (void)m_ringStorageSize;
51*61046927SAndroid Build Coastguard Worker (void)m_version;
52*61046927SAndroid Build Coastguard Worker }
53*61046927SAndroid Build Coastguard Worker
~AddressSpaceStream()54*61046927SAndroid Build Coastguard Worker AddressSpaceStream::~AddressSpaceStream() {
55*61046927SAndroid Build Coastguard Worker flush();
56*61046927SAndroid Build Coastguard Worker ensureType3Finished();
57*61046927SAndroid Build Coastguard Worker ensureType1Finished();
58*61046927SAndroid Build Coastguard Worker
59*61046927SAndroid Build Coastguard Worker if (!m_mapping) {
60*61046927SAndroid Build Coastguard Worker m_ops.unmap(m_context.to_host, sizeof(struct asg_ring_storage));
61*61046927SAndroid Build Coastguard Worker m_ops.unmap(m_context.buffer, m_writeBufferSize);
62*61046927SAndroid Build Coastguard Worker m_ops.unclaim_shared(m_handle, m_ringOffset);
63*61046927SAndroid Build Coastguard Worker m_ops.unclaim_shared(m_handle, m_writeBufferOffset);
64*61046927SAndroid Build Coastguard Worker }
65*61046927SAndroid Build Coastguard Worker
66*61046927SAndroid Build Coastguard Worker m_ops.close(m_handle);
67*61046927SAndroid Build Coastguard Worker if (m_readBuf) free(m_readBuf);
68*61046927SAndroid Build Coastguard Worker if (m_tmpBuf) free(m_tmpBuf);
69*61046927SAndroid Build Coastguard Worker }
70*61046927SAndroid Build Coastguard Worker
idealAllocSize(size_t len)71*61046927SAndroid Build Coastguard Worker size_t AddressSpaceStream::idealAllocSize(size_t len) {
72*61046927SAndroid Build Coastguard Worker if (len > m_writeStep) return len;
73*61046927SAndroid Build Coastguard Worker return m_writeStep;
74*61046927SAndroid Build Coastguard Worker }
75*61046927SAndroid Build Coastguard Worker
allocBuffer(size_t minSize)76*61046927SAndroid Build Coastguard Worker void* AddressSpaceStream::allocBuffer(size_t minSize) {
77*61046927SAndroid Build Coastguard Worker MESA_TRACE_SCOPE("allocBuffer");
78*61046927SAndroid Build Coastguard Worker ensureType3Finished();
79*61046927SAndroid Build Coastguard Worker
80*61046927SAndroid Build Coastguard Worker if (!m_readBuf) {
81*61046927SAndroid Build Coastguard Worker m_readBuf = (unsigned char*)malloc(kReadSize);
82*61046927SAndroid Build Coastguard Worker }
83*61046927SAndroid Build Coastguard Worker
84*61046927SAndroid Build Coastguard Worker size_t allocSize =
85*61046927SAndroid Build Coastguard Worker (m_writeStep < minSize ? minSize : m_writeStep);
86*61046927SAndroid Build Coastguard Worker
87*61046927SAndroid Build Coastguard Worker if (m_writeStep < allocSize) {
88*61046927SAndroid Build Coastguard Worker if (!m_tmpBuf) {
89*61046927SAndroid Build Coastguard Worker m_tmpBufSize = allocSize * 2;
90*61046927SAndroid Build Coastguard Worker m_tmpBuf = (unsigned char*)malloc(m_tmpBufSize);
91*61046927SAndroid Build Coastguard Worker }
92*61046927SAndroid Build Coastguard Worker
93*61046927SAndroid Build Coastguard Worker if (m_tmpBufSize < allocSize) {
94*61046927SAndroid Build Coastguard Worker m_tmpBufSize = allocSize * 2;
95*61046927SAndroid Build Coastguard Worker m_tmpBuf = (unsigned char*)realloc(m_tmpBuf, m_tmpBufSize);
96*61046927SAndroid Build Coastguard Worker }
97*61046927SAndroid Build Coastguard Worker
98*61046927SAndroid Build Coastguard Worker if (!m_usingTmpBuf) {
99*61046927SAndroid Build Coastguard Worker flush();
100*61046927SAndroid Build Coastguard Worker }
101*61046927SAndroid Build Coastguard Worker
102*61046927SAndroid Build Coastguard Worker m_usingTmpBuf = true;
103*61046927SAndroid Build Coastguard Worker m_tmpBufXferSize = allocSize;
104*61046927SAndroid Build Coastguard Worker return m_tmpBuf;
105*61046927SAndroid Build Coastguard Worker } else {
106*61046927SAndroid Build Coastguard Worker if (m_usingTmpBuf) {
107*61046927SAndroid Build Coastguard Worker writeFully(m_tmpBuf, m_tmpBufXferSize);
108*61046927SAndroid Build Coastguard Worker m_usingTmpBuf = false;
109*61046927SAndroid Build Coastguard Worker m_tmpBufXferSize = 0;
110*61046927SAndroid Build Coastguard Worker }
111*61046927SAndroid Build Coastguard Worker
112*61046927SAndroid Build Coastguard Worker return m_writeStart;
113*61046927SAndroid Build Coastguard Worker }
114*61046927SAndroid Build Coastguard Worker }
115*61046927SAndroid Build Coastguard Worker
commitBuffer(size_t size)116*61046927SAndroid Build Coastguard Worker int AddressSpaceStream::commitBuffer(size_t size)
117*61046927SAndroid Build Coastguard Worker {
118*61046927SAndroid Build Coastguard Worker if (size == 0) return 0;
119*61046927SAndroid Build Coastguard Worker
120*61046927SAndroid Build Coastguard Worker if (m_usingTmpBuf) {
121*61046927SAndroid Build Coastguard Worker writeFully(m_tmpBuf, size);
122*61046927SAndroid Build Coastguard Worker m_tmpBufXferSize = 0;
123*61046927SAndroid Build Coastguard Worker m_usingTmpBuf = false;
124*61046927SAndroid Build Coastguard Worker return 0;
125*61046927SAndroid Build Coastguard Worker } else {
126*61046927SAndroid Build Coastguard Worker int res = type1Write(m_writeStart - m_buf, size);
127*61046927SAndroid Build Coastguard Worker advanceWrite();
128*61046927SAndroid Build Coastguard Worker return res;
129*61046927SAndroid Build Coastguard Worker }
130*61046927SAndroid Build Coastguard Worker }
131*61046927SAndroid Build Coastguard Worker
readFully(void * ptr,size_t totalReadSize)132*61046927SAndroid Build Coastguard Worker const unsigned char *AddressSpaceStream::readFully(void *ptr, size_t totalReadSize)
133*61046927SAndroid Build Coastguard Worker {
134*61046927SAndroid Build Coastguard Worker
135*61046927SAndroid Build Coastguard Worker unsigned char* userReadBuf = static_cast<unsigned char*>(ptr);
136*61046927SAndroid Build Coastguard Worker
137*61046927SAndroid Build Coastguard Worker if (!userReadBuf) {
138*61046927SAndroid Build Coastguard Worker if (totalReadSize > 0) {
139*61046927SAndroid Build Coastguard Worker mesa_loge(
140*61046927SAndroid Build Coastguard Worker "AddressSpaceStream::commitBufferAndReadFully failed, userReadBuf=NULL, "
141*61046927SAndroid Build Coastguard Worker "totalReadSize %zu, lethal"
142*61046927SAndroid Build Coastguard Worker " error, exiting.",
143*61046927SAndroid Build Coastguard Worker totalReadSize);
144*61046927SAndroid Build Coastguard Worker abort();
145*61046927SAndroid Build Coastguard Worker }
146*61046927SAndroid Build Coastguard Worker return nullptr;
147*61046927SAndroid Build Coastguard Worker }
148*61046927SAndroid Build Coastguard Worker
149*61046927SAndroid Build Coastguard Worker // Advance buffered read if not yet consumed.
150*61046927SAndroid Build Coastguard Worker size_t remaining = totalReadSize;
151*61046927SAndroid Build Coastguard Worker size_t bufferedReadSize =
152*61046927SAndroid Build Coastguard Worker m_readLeft < remaining ? m_readLeft : remaining;
153*61046927SAndroid Build Coastguard Worker
154*61046927SAndroid Build Coastguard Worker if (bufferedReadSize) {
155*61046927SAndroid Build Coastguard Worker memcpy(userReadBuf,
156*61046927SAndroid Build Coastguard Worker m_readBuf + (m_read - m_readLeft),
157*61046927SAndroid Build Coastguard Worker bufferedReadSize);
158*61046927SAndroid Build Coastguard Worker remaining -= bufferedReadSize;
159*61046927SAndroid Build Coastguard Worker m_readLeft -= bufferedReadSize;
160*61046927SAndroid Build Coastguard Worker }
161*61046927SAndroid Build Coastguard Worker
162*61046927SAndroid Build Coastguard Worker if (!remaining) return userReadBuf;
163*61046927SAndroid Build Coastguard Worker
164*61046927SAndroid Build Coastguard Worker // Read up to kReadSize bytes if all buffered read has been consumed.
165*61046927SAndroid Build Coastguard Worker size_t maxRead = m_readLeft ? 0 : kReadSize;
166*61046927SAndroid Build Coastguard Worker ssize_t actual = 0;
167*61046927SAndroid Build Coastguard Worker
168*61046927SAndroid Build Coastguard Worker if (maxRead) {
169*61046927SAndroid Build Coastguard Worker actual = speculativeRead(m_readBuf, maxRead);
170*61046927SAndroid Build Coastguard Worker
171*61046927SAndroid Build Coastguard Worker // Updated buffered read size.
172*61046927SAndroid Build Coastguard Worker if (actual > 0) {
173*61046927SAndroid Build Coastguard Worker m_read = m_readLeft = actual;
174*61046927SAndroid Build Coastguard Worker }
175*61046927SAndroid Build Coastguard Worker
176*61046927SAndroid Build Coastguard Worker if (actual == 0) {
177*61046927SAndroid Build Coastguard Worker mesa_logd("%s: end of pipe", __FUNCTION__);
178*61046927SAndroid Build Coastguard Worker return NULL;
179*61046927SAndroid Build Coastguard Worker }
180*61046927SAndroid Build Coastguard Worker }
181*61046927SAndroid Build Coastguard Worker
182*61046927SAndroid Build Coastguard Worker // Consume buffered read and read more if necessary.
183*61046927SAndroid Build Coastguard Worker while (remaining) {
184*61046927SAndroid Build Coastguard Worker bufferedReadSize = m_readLeft < remaining ? m_readLeft : remaining;
185*61046927SAndroid Build Coastguard Worker if (bufferedReadSize) {
186*61046927SAndroid Build Coastguard Worker memcpy(userReadBuf + (totalReadSize - remaining),
187*61046927SAndroid Build Coastguard Worker m_readBuf + (m_read - m_readLeft),
188*61046927SAndroid Build Coastguard Worker bufferedReadSize);
189*61046927SAndroid Build Coastguard Worker remaining -= bufferedReadSize;
190*61046927SAndroid Build Coastguard Worker m_readLeft -= bufferedReadSize;
191*61046927SAndroid Build Coastguard Worker continue;
192*61046927SAndroid Build Coastguard Worker }
193*61046927SAndroid Build Coastguard Worker
194*61046927SAndroid Build Coastguard Worker actual = speculativeRead(m_readBuf, kReadSize);
195*61046927SAndroid Build Coastguard Worker
196*61046927SAndroid Build Coastguard Worker if (actual == 0) {
197*61046927SAndroid Build Coastguard Worker mesa_logd("%s: Failed reading from pipe: %d", __FUNCTION__, errno);
198*61046927SAndroid Build Coastguard Worker return NULL;
199*61046927SAndroid Build Coastguard Worker }
200*61046927SAndroid Build Coastguard Worker
201*61046927SAndroid Build Coastguard Worker if (actual > 0) {
202*61046927SAndroid Build Coastguard Worker m_read = m_readLeft = actual;
203*61046927SAndroid Build Coastguard Worker continue;
204*61046927SAndroid Build Coastguard Worker }
205*61046927SAndroid Build Coastguard Worker }
206*61046927SAndroid Build Coastguard Worker
207*61046927SAndroid Build Coastguard Worker resetBackoff();
208*61046927SAndroid Build Coastguard Worker return userReadBuf;
209*61046927SAndroid Build Coastguard Worker }
210*61046927SAndroid Build Coastguard Worker
read(void * buf,size_t * inout_len)211*61046927SAndroid Build Coastguard Worker const unsigned char *AddressSpaceStream::read(void *buf, size_t *inout_len) {
212*61046927SAndroid Build Coastguard Worker unsigned char* dst = (unsigned char*)buf;
213*61046927SAndroid Build Coastguard Worker size_t wanted = *inout_len;
214*61046927SAndroid Build Coastguard Worker ssize_t actual = speculativeRead(dst, wanted);
215*61046927SAndroid Build Coastguard Worker
216*61046927SAndroid Build Coastguard Worker if (actual >= 0) {
217*61046927SAndroid Build Coastguard Worker *inout_len = actual;
218*61046927SAndroid Build Coastguard Worker } else {
219*61046927SAndroid Build Coastguard Worker return nullptr;
220*61046927SAndroid Build Coastguard Worker }
221*61046927SAndroid Build Coastguard Worker
222*61046927SAndroid Build Coastguard Worker return (const unsigned char*)dst;
223*61046927SAndroid Build Coastguard Worker }
224*61046927SAndroid Build Coastguard Worker
writeFully(const void * buf,size_t size)225*61046927SAndroid Build Coastguard Worker int AddressSpaceStream::writeFully(const void* buf, size_t size) {
226*61046927SAndroid Build Coastguard Worker MESA_TRACE_SCOPE("writeFully");
227*61046927SAndroid Build Coastguard Worker ensureType3Finished();
228*61046927SAndroid Build Coastguard Worker ensureType1Finished();
229*61046927SAndroid Build Coastguard Worker
230*61046927SAndroid Build Coastguard Worker m_context.ring_config->transfer_size = size;
231*61046927SAndroid Build Coastguard Worker m_context.ring_config->transfer_mode = 3;
232*61046927SAndroid Build Coastguard Worker
233*61046927SAndroid Build Coastguard Worker size_t sent = 0;
234*61046927SAndroid Build Coastguard Worker size_t preferredChunkSize = m_writeBufferSize / 4;
235*61046927SAndroid Build Coastguard Worker size_t chunkSize = size < preferredChunkSize ? size : preferredChunkSize;
236*61046927SAndroid Build Coastguard Worker const uint8_t* bufferBytes = (const uint8_t*)buf;
237*61046927SAndroid Build Coastguard Worker
238*61046927SAndroid Build Coastguard Worker bool hostPinged = false;
239*61046927SAndroid Build Coastguard Worker while (sent < size) {
240*61046927SAndroid Build Coastguard Worker size_t remaining = size - sent;
241*61046927SAndroid Build Coastguard Worker size_t sendThisTime = remaining < chunkSize ? remaining : chunkSize;
242*61046927SAndroid Build Coastguard Worker
243*61046927SAndroid Build Coastguard Worker long sentChunks =
244*61046927SAndroid Build Coastguard Worker ring_buffer_view_write(
245*61046927SAndroid Build Coastguard Worker m_context.to_host_large_xfer.ring,
246*61046927SAndroid Build Coastguard Worker &m_context.to_host_large_xfer.view,
247*61046927SAndroid Build Coastguard Worker bufferBytes + sent, sendThisTime, 1);
248*61046927SAndroid Build Coastguard Worker
249*61046927SAndroid Build Coastguard Worker if (!hostPinged && *(m_context.host_state) != ASG_HOST_STATE_CAN_CONSUME &&
250*61046927SAndroid Build Coastguard Worker *(m_context.host_state) != ASG_HOST_STATE_RENDERING) {
251*61046927SAndroid Build Coastguard Worker notifyAvailable();
252*61046927SAndroid Build Coastguard Worker hostPinged = true;
253*61046927SAndroid Build Coastguard Worker }
254*61046927SAndroid Build Coastguard Worker
255*61046927SAndroid Build Coastguard Worker if (sentChunks == 0) {
256*61046927SAndroid Build Coastguard Worker ring_buffer_yield();
257*61046927SAndroid Build Coastguard Worker backoff();
258*61046927SAndroid Build Coastguard Worker }
259*61046927SAndroid Build Coastguard Worker
260*61046927SAndroid Build Coastguard Worker sent += sentChunks * sendThisTime;
261*61046927SAndroid Build Coastguard Worker
262*61046927SAndroid Build Coastguard Worker if (isInError()) {
263*61046927SAndroid Build Coastguard Worker return -1;
264*61046927SAndroid Build Coastguard Worker }
265*61046927SAndroid Build Coastguard Worker }
266*61046927SAndroid Build Coastguard Worker
267*61046927SAndroid Build Coastguard Worker bool isRenderingAfter = ASG_HOST_STATE_RENDERING == __atomic_load_n(m_context.host_state, __ATOMIC_ACQUIRE);
268*61046927SAndroid Build Coastguard Worker
269*61046927SAndroid Build Coastguard Worker if (!isRenderingAfter) {
270*61046927SAndroid Build Coastguard Worker notifyAvailable();
271*61046927SAndroid Build Coastguard Worker }
272*61046927SAndroid Build Coastguard Worker
273*61046927SAndroid Build Coastguard Worker ensureType3Finished();
274*61046927SAndroid Build Coastguard Worker
275*61046927SAndroid Build Coastguard Worker resetBackoff();
276*61046927SAndroid Build Coastguard Worker m_context.ring_config->transfer_mode = 1;
277*61046927SAndroid Build Coastguard Worker m_written += size;
278*61046927SAndroid Build Coastguard Worker
279*61046927SAndroid Build Coastguard Worker float mb = (float)m_written / 1048576.0f;
280*61046927SAndroid Build Coastguard Worker if (mb > 100.0f) {
281*61046927SAndroid Build Coastguard Worker mesa_logd("%s: %f mb in %d notifs. %f mb/notif\n", __func__, mb, m_notifs,
282*61046927SAndroid Build Coastguard Worker m_notifs ? mb / (float)m_notifs : 0.0f);
283*61046927SAndroid Build Coastguard Worker m_notifs = 0;
284*61046927SAndroid Build Coastguard Worker m_written = 0;
285*61046927SAndroid Build Coastguard Worker }
286*61046927SAndroid Build Coastguard Worker return 0;
287*61046927SAndroid Build Coastguard Worker }
288*61046927SAndroid Build Coastguard Worker
writeFullyAsync(const void * buf,size_t size)289*61046927SAndroid Build Coastguard Worker int AddressSpaceStream::writeFullyAsync(const void* buf, size_t size) {
290*61046927SAndroid Build Coastguard Worker MESA_TRACE_SCOPE("writeFullyAsync");
291*61046927SAndroid Build Coastguard Worker ensureType3Finished();
292*61046927SAndroid Build Coastguard Worker ensureType1Finished();
293*61046927SAndroid Build Coastguard Worker
294*61046927SAndroid Build Coastguard Worker __atomic_store_n(&m_context.ring_config->transfer_size, size, __ATOMIC_RELEASE);
295*61046927SAndroid Build Coastguard Worker m_context.ring_config->transfer_mode = 3;
296*61046927SAndroid Build Coastguard Worker
297*61046927SAndroid Build Coastguard Worker size_t sent = 0;
298*61046927SAndroid Build Coastguard Worker size_t preferredChunkSize = m_writeBufferSize / 2;
299*61046927SAndroid Build Coastguard Worker size_t chunkSize = size < preferredChunkSize ? size : preferredChunkSize;
300*61046927SAndroid Build Coastguard Worker const uint8_t* bufferBytes = (const uint8_t*)buf;
301*61046927SAndroid Build Coastguard Worker
302*61046927SAndroid Build Coastguard Worker bool pingedHost = false;
303*61046927SAndroid Build Coastguard Worker
304*61046927SAndroid Build Coastguard Worker while (sent < size) {
305*61046927SAndroid Build Coastguard Worker size_t remaining = size - sent;
306*61046927SAndroid Build Coastguard Worker size_t sendThisTime = remaining < chunkSize ? remaining : chunkSize;
307*61046927SAndroid Build Coastguard Worker
308*61046927SAndroid Build Coastguard Worker long sentChunks =
309*61046927SAndroid Build Coastguard Worker ring_buffer_view_write(
310*61046927SAndroid Build Coastguard Worker m_context.to_host_large_xfer.ring,
311*61046927SAndroid Build Coastguard Worker &m_context.to_host_large_xfer.view,
312*61046927SAndroid Build Coastguard Worker bufferBytes + sent, sendThisTime, 1);
313*61046927SAndroid Build Coastguard Worker
314*61046927SAndroid Build Coastguard Worker uint32_t hostState = __atomic_load_n(m_context.host_state, __ATOMIC_ACQUIRE);
315*61046927SAndroid Build Coastguard Worker
316*61046927SAndroid Build Coastguard Worker if (!pingedHost &&
317*61046927SAndroid Build Coastguard Worker hostState != ASG_HOST_STATE_CAN_CONSUME &&
318*61046927SAndroid Build Coastguard Worker hostState != ASG_HOST_STATE_RENDERING) {
319*61046927SAndroid Build Coastguard Worker pingedHost = true;
320*61046927SAndroid Build Coastguard Worker notifyAvailable();
321*61046927SAndroid Build Coastguard Worker }
322*61046927SAndroid Build Coastguard Worker
323*61046927SAndroid Build Coastguard Worker if (sentChunks == 0) {
324*61046927SAndroid Build Coastguard Worker ring_buffer_yield();
325*61046927SAndroid Build Coastguard Worker backoff();
326*61046927SAndroid Build Coastguard Worker }
327*61046927SAndroid Build Coastguard Worker
328*61046927SAndroid Build Coastguard Worker sent += sentChunks * sendThisTime;
329*61046927SAndroid Build Coastguard Worker
330*61046927SAndroid Build Coastguard Worker if (isInError()) {
331*61046927SAndroid Build Coastguard Worker return -1;
332*61046927SAndroid Build Coastguard Worker }
333*61046927SAndroid Build Coastguard Worker }
334*61046927SAndroid Build Coastguard Worker
335*61046927SAndroid Build Coastguard Worker
336*61046927SAndroid Build Coastguard Worker bool isRenderingAfter = ASG_HOST_STATE_RENDERING == __atomic_load_n(m_context.host_state, __ATOMIC_ACQUIRE);
337*61046927SAndroid Build Coastguard Worker
338*61046927SAndroid Build Coastguard Worker if (!isRenderingAfter) {
339*61046927SAndroid Build Coastguard Worker notifyAvailable();
340*61046927SAndroid Build Coastguard Worker }
341*61046927SAndroid Build Coastguard Worker
342*61046927SAndroid Build Coastguard Worker resetBackoff();
343*61046927SAndroid Build Coastguard Worker m_context.ring_config->transfer_mode = 1;
344*61046927SAndroid Build Coastguard Worker m_written += size;
345*61046927SAndroid Build Coastguard Worker
346*61046927SAndroid Build Coastguard Worker float mb = (float)m_written / 1048576.0f;
347*61046927SAndroid Build Coastguard Worker if (mb > 100.0f) {
348*61046927SAndroid Build Coastguard Worker mesa_logd("%s: %f mb in %d notifs. %f mb/notif\n", __func__, mb, m_notifs,
349*61046927SAndroid Build Coastguard Worker m_notifs ? mb / (float)m_notifs : 0.0f);
350*61046927SAndroid Build Coastguard Worker m_notifs = 0;
351*61046927SAndroid Build Coastguard Worker m_written = 0;
352*61046927SAndroid Build Coastguard Worker }
353*61046927SAndroid Build Coastguard Worker return 0;
354*61046927SAndroid Build Coastguard Worker }
355*61046927SAndroid Build Coastguard Worker
commitBufferAndReadFully(size_t writeSize,void * userReadBufPtr,size_t totalReadSize)356*61046927SAndroid Build Coastguard Worker const unsigned char *AddressSpaceStream::commitBufferAndReadFully(
357*61046927SAndroid Build Coastguard Worker size_t writeSize, void *userReadBufPtr, size_t totalReadSize) {
358*61046927SAndroid Build Coastguard Worker
359*61046927SAndroid Build Coastguard Worker if (m_usingTmpBuf) {
360*61046927SAndroid Build Coastguard Worker writeFully(m_tmpBuf, writeSize);
361*61046927SAndroid Build Coastguard Worker m_usingTmpBuf = false;
362*61046927SAndroid Build Coastguard Worker m_tmpBufXferSize = 0;
363*61046927SAndroid Build Coastguard Worker return readFully(userReadBufPtr, totalReadSize);
364*61046927SAndroid Build Coastguard Worker } else {
365*61046927SAndroid Build Coastguard Worker commitBuffer(writeSize);
366*61046927SAndroid Build Coastguard Worker return readFully(userReadBufPtr, totalReadSize);
367*61046927SAndroid Build Coastguard Worker }
368*61046927SAndroid Build Coastguard Worker }
369*61046927SAndroid Build Coastguard Worker
isInError() const370*61046927SAndroid Build Coastguard Worker bool AddressSpaceStream::isInError() const {
371*61046927SAndroid Build Coastguard Worker return 1 == m_context.ring_config->in_error;
372*61046927SAndroid Build Coastguard Worker }
373*61046927SAndroid Build Coastguard Worker
speculativeRead(unsigned char * readBuffer,size_t trySize)374*61046927SAndroid Build Coastguard Worker ssize_t AddressSpaceStream::speculativeRead(unsigned char* readBuffer, size_t trySize) {
375*61046927SAndroid Build Coastguard Worker ensureType3Finished();
376*61046927SAndroid Build Coastguard Worker ensureType1Finished();
377*61046927SAndroid Build Coastguard Worker
378*61046927SAndroid Build Coastguard Worker size_t actuallyRead = 0;
379*61046927SAndroid Build Coastguard Worker
380*61046927SAndroid Build Coastguard Worker while (!actuallyRead) {
381*61046927SAndroid Build Coastguard Worker
382*61046927SAndroid Build Coastguard Worker uint32_t readAvail =
383*61046927SAndroid Build Coastguard Worker ring_buffer_available_read(
384*61046927SAndroid Build Coastguard Worker m_context.from_host_large_xfer.ring,
385*61046927SAndroid Build Coastguard Worker &m_context.from_host_large_xfer.view);
386*61046927SAndroid Build Coastguard Worker
387*61046927SAndroid Build Coastguard Worker if (!readAvail) {
388*61046927SAndroid Build Coastguard Worker ring_buffer_yield();
389*61046927SAndroid Build Coastguard Worker backoff();
390*61046927SAndroid Build Coastguard Worker continue;
391*61046927SAndroid Build Coastguard Worker }
392*61046927SAndroid Build Coastguard Worker
393*61046927SAndroid Build Coastguard Worker uint32_t toRead = readAvail > trySize ? trySize : readAvail;
394*61046927SAndroid Build Coastguard Worker
395*61046927SAndroid Build Coastguard Worker long stepsRead = ring_buffer_view_read(
396*61046927SAndroid Build Coastguard Worker m_context.from_host_large_xfer.ring,
397*61046927SAndroid Build Coastguard Worker &m_context.from_host_large_xfer.view,
398*61046927SAndroid Build Coastguard Worker readBuffer, toRead, 1);
399*61046927SAndroid Build Coastguard Worker
400*61046927SAndroid Build Coastguard Worker actuallyRead += stepsRead * toRead;
401*61046927SAndroid Build Coastguard Worker
402*61046927SAndroid Build Coastguard Worker if (isInError()) {
403*61046927SAndroid Build Coastguard Worker return -1;
404*61046927SAndroid Build Coastguard Worker }
405*61046927SAndroid Build Coastguard Worker }
406*61046927SAndroid Build Coastguard Worker
407*61046927SAndroid Build Coastguard Worker return actuallyRead;
408*61046927SAndroid Build Coastguard Worker }
409*61046927SAndroid Build Coastguard Worker
notifyAvailable()410*61046927SAndroid Build Coastguard Worker void AddressSpaceStream::notifyAvailable() {
411*61046927SAndroid Build Coastguard Worker MESA_TRACE_SCOPE("PING");
412*61046927SAndroid Build Coastguard Worker struct address_space_ping request;
413*61046927SAndroid Build Coastguard Worker request.metadata = ASG_NOTIFY_AVAILABLE;
414*61046927SAndroid Build Coastguard Worker request.resourceId = m_resourceId;
415*61046927SAndroid Build Coastguard Worker m_ops.ping(m_handle, &request);
416*61046927SAndroid Build Coastguard Worker ++m_notifs;
417*61046927SAndroid Build Coastguard Worker }
418*61046927SAndroid Build Coastguard Worker
getRelativeBufferPos(uint32_t pos)419*61046927SAndroid Build Coastguard Worker uint32_t AddressSpaceStream::getRelativeBufferPos(uint32_t pos) {
420*61046927SAndroid Build Coastguard Worker return pos & m_writeBufferMask;
421*61046927SAndroid Build Coastguard Worker }
422*61046927SAndroid Build Coastguard Worker
advanceWrite()423*61046927SAndroid Build Coastguard Worker void AddressSpaceStream::advanceWrite() {
424*61046927SAndroid Build Coastguard Worker m_writeStart += m_context.ring_config->flush_interval;
425*61046927SAndroid Build Coastguard Worker
426*61046927SAndroid Build Coastguard Worker if (m_writeStart == m_buf + m_context.ring_config->buffer_size) {
427*61046927SAndroid Build Coastguard Worker m_writeStart = m_buf;
428*61046927SAndroid Build Coastguard Worker }
429*61046927SAndroid Build Coastguard Worker }
430*61046927SAndroid Build Coastguard Worker
ensureConsumerFinishing()431*61046927SAndroid Build Coastguard Worker void AddressSpaceStream::ensureConsumerFinishing() {
432*61046927SAndroid Build Coastguard Worker uint32_t currAvailRead = ring_buffer_available_read(m_context.to_host, 0);
433*61046927SAndroid Build Coastguard Worker
434*61046927SAndroid Build Coastguard Worker while (currAvailRead) {
435*61046927SAndroid Build Coastguard Worker ring_buffer_yield();
436*61046927SAndroid Build Coastguard Worker uint32_t nextAvailRead = ring_buffer_available_read(m_context.to_host, 0);
437*61046927SAndroid Build Coastguard Worker
438*61046927SAndroid Build Coastguard Worker if (nextAvailRead != currAvailRead) {
439*61046927SAndroid Build Coastguard Worker break;
440*61046927SAndroid Build Coastguard Worker }
441*61046927SAndroid Build Coastguard Worker
442*61046927SAndroid Build Coastguard Worker if (*(m_context.host_state) != ASG_HOST_STATE_CAN_CONSUME &&
443*61046927SAndroid Build Coastguard Worker *(m_context.host_state) != ASG_HOST_STATE_RENDERING) {
444*61046927SAndroid Build Coastguard Worker notifyAvailable();
445*61046927SAndroid Build Coastguard Worker break;
446*61046927SAndroid Build Coastguard Worker }
447*61046927SAndroid Build Coastguard Worker
448*61046927SAndroid Build Coastguard Worker backoff();
449*61046927SAndroid Build Coastguard Worker }
450*61046927SAndroid Build Coastguard Worker }
451*61046927SAndroid Build Coastguard Worker
ensureType1Finished()452*61046927SAndroid Build Coastguard Worker void AddressSpaceStream::ensureType1Finished() {
453*61046927SAndroid Build Coastguard Worker MESA_TRACE_SCOPE("ensureType1Finished");
454*61046927SAndroid Build Coastguard Worker
455*61046927SAndroid Build Coastguard Worker uint32_t currAvailRead =
456*61046927SAndroid Build Coastguard Worker ring_buffer_available_read(m_context.to_host, 0);
457*61046927SAndroid Build Coastguard Worker
458*61046927SAndroid Build Coastguard Worker while (currAvailRead) {
459*61046927SAndroid Build Coastguard Worker backoff();
460*61046927SAndroid Build Coastguard Worker ring_buffer_yield();
461*61046927SAndroid Build Coastguard Worker currAvailRead = ring_buffer_available_read(m_context.to_host, 0);
462*61046927SAndroid Build Coastguard Worker if (isInError()) {
463*61046927SAndroid Build Coastguard Worker return;
464*61046927SAndroid Build Coastguard Worker }
465*61046927SAndroid Build Coastguard Worker }
466*61046927SAndroid Build Coastguard Worker }
467*61046927SAndroid Build Coastguard Worker
ensureType3Finished()468*61046927SAndroid Build Coastguard Worker void AddressSpaceStream::ensureType3Finished() {
469*61046927SAndroid Build Coastguard Worker MESA_TRACE_SCOPE("ensureType3Finished");
470*61046927SAndroid Build Coastguard Worker uint32_t availReadLarge =
471*61046927SAndroid Build Coastguard Worker ring_buffer_available_read(
472*61046927SAndroid Build Coastguard Worker m_context.to_host_large_xfer.ring,
473*61046927SAndroid Build Coastguard Worker &m_context.to_host_large_xfer.view);
474*61046927SAndroid Build Coastguard Worker while (availReadLarge) {
475*61046927SAndroid Build Coastguard Worker ring_buffer_yield();
476*61046927SAndroid Build Coastguard Worker backoff();
477*61046927SAndroid Build Coastguard Worker availReadLarge =
478*61046927SAndroid Build Coastguard Worker ring_buffer_available_read(
479*61046927SAndroid Build Coastguard Worker m_context.to_host_large_xfer.ring,
480*61046927SAndroid Build Coastguard Worker &m_context.to_host_large_xfer.view);
481*61046927SAndroid Build Coastguard Worker if (*(m_context.host_state) != ASG_HOST_STATE_CAN_CONSUME &&
482*61046927SAndroid Build Coastguard Worker *(m_context.host_state) != ASG_HOST_STATE_RENDERING) {
483*61046927SAndroid Build Coastguard Worker notifyAvailable();
484*61046927SAndroid Build Coastguard Worker }
485*61046927SAndroid Build Coastguard Worker if (isInError()) {
486*61046927SAndroid Build Coastguard Worker return;
487*61046927SAndroid Build Coastguard Worker }
488*61046927SAndroid Build Coastguard Worker }
489*61046927SAndroid Build Coastguard Worker }
490*61046927SAndroid Build Coastguard Worker
type1Write(uint32_t bufferOffset,size_t size)491*61046927SAndroid Build Coastguard Worker int AddressSpaceStream::type1Write(uint32_t bufferOffset, size_t size) {
492*61046927SAndroid Build Coastguard Worker MESA_TRACE_SCOPE("type1Write");
493*61046927SAndroid Build Coastguard Worker
494*61046927SAndroid Build Coastguard Worker ensureType3Finished();
495*61046927SAndroid Build Coastguard Worker
496*61046927SAndroid Build Coastguard Worker size_t sent = 0;
497*61046927SAndroid Build Coastguard Worker size_t sizeForRing = sizeof(struct asg_type1_xfer);
498*61046927SAndroid Build Coastguard Worker
499*61046927SAndroid Build Coastguard Worker struct asg_type1_xfer xfer = {
500*61046927SAndroid Build Coastguard Worker bufferOffset,
501*61046927SAndroid Build Coastguard Worker (uint32_t)size,
502*61046927SAndroid Build Coastguard Worker };
503*61046927SAndroid Build Coastguard Worker
504*61046927SAndroid Build Coastguard Worker uint8_t* writeBufferBytes = (uint8_t*)(&xfer);
505*61046927SAndroid Build Coastguard Worker
506*61046927SAndroid Build Coastguard Worker uint32_t maxOutstanding = 1;
507*61046927SAndroid Build Coastguard Worker uint32_t maxSteps = m_context.ring_config->buffer_size /
508*61046927SAndroid Build Coastguard Worker m_context.ring_config->flush_interval;
509*61046927SAndroid Build Coastguard Worker
510*61046927SAndroid Build Coastguard Worker if (maxSteps > 1) maxOutstanding = maxSteps - 1;
511*61046927SAndroid Build Coastguard Worker
512*61046927SAndroid Build Coastguard Worker uint32_t ringAvailReadNow = ring_buffer_available_read(m_context.to_host, 0);
513*61046927SAndroid Build Coastguard Worker
514*61046927SAndroid Build Coastguard Worker while (ringAvailReadNow >= maxOutstanding * sizeForRing) {
515*61046927SAndroid Build Coastguard Worker ringAvailReadNow = ring_buffer_available_read(m_context.to_host, 0);
516*61046927SAndroid Build Coastguard Worker }
517*61046927SAndroid Build Coastguard Worker
518*61046927SAndroid Build Coastguard Worker bool hostPinged = false;
519*61046927SAndroid Build Coastguard Worker while (sent < sizeForRing) {
520*61046927SAndroid Build Coastguard Worker
521*61046927SAndroid Build Coastguard Worker long sentChunks = ring_buffer_write(
522*61046927SAndroid Build Coastguard Worker m_context.to_host,
523*61046927SAndroid Build Coastguard Worker writeBufferBytes + sent,
524*61046927SAndroid Build Coastguard Worker sizeForRing - sent, 1);
525*61046927SAndroid Build Coastguard Worker
526*61046927SAndroid Build Coastguard Worker if (!hostPinged &&
527*61046927SAndroid Build Coastguard Worker *(m_context.host_state) != ASG_HOST_STATE_CAN_CONSUME &&
528*61046927SAndroid Build Coastguard Worker *(m_context.host_state) != ASG_HOST_STATE_RENDERING) {
529*61046927SAndroid Build Coastguard Worker notifyAvailable();
530*61046927SAndroid Build Coastguard Worker hostPinged = true;
531*61046927SAndroid Build Coastguard Worker }
532*61046927SAndroid Build Coastguard Worker
533*61046927SAndroid Build Coastguard Worker if (sentChunks == 0) {
534*61046927SAndroid Build Coastguard Worker ring_buffer_yield();
535*61046927SAndroid Build Coastguard Worker backoff();
536*61046927SAndroid Build Coastguard Worker }
537*61046927SAndroid Build Coastguard Worker
538*61046927SAndroid Build Coastguard Worker sent += sentChunks * (sizeForRing - sent);
539*61046927SAndroid Build Coastguard Worker
540*61046927SAndroid Build Coastguard Worker if (isInError()) {
541*61046927SAndroid Build Coastguard Worker return -1;
542*61046927SAndroid Build Coastguard Worker }
543*61046927SAndroid Build Coastguard Worker }
544*61046927SAndroid Build Coastguard Worker
545*61046927SAndroid Build Coastguard Worker bool isRenderingAfter = ASG_HOST_STATE_RENDERING == __atomic_load_n(m_context.host_state, __ATOMIC_ACQUIRE);
546*61046927SAndroid Build Coastguard Worker
547*61046927SAndroid Build Coastguard Worker if (!isRenderingAfter) {
548*61046927SAndroid Build Coastguard Worker notifyAvailable();
549*61046927SAndroid Build Coastguard Worker }
550*61046927SAndroid Build Coastguard Worker
551*61046927SAndroid Build Coastguard Worker m_written += size;
552*61046927SAndroid Build Coastguard Worker
553*61046927SAndroid Build Coastguard Worker float mb = (float)m_written / 1048576.0f;
554*61046927SAndroid Build Coastguard Worker if (mb > 100.0f) {
555*61046927SAndroid Build Coastguard Worker mesa_logd("%s: %f mb in %d notifs. %f mb/notif\n", __func__, mb, m_notifs,
556*61046927SAndroid Build Coastguard Worker m_notifs ? mb / (float)m_notifs : 0.0f);
557*61046927SAndroid Build Coastguard Worker m_notifs = 0;
558*61046927SAndroid Build Coastguard Worker m_written = 0;
559*61046927SAndroid Build Coastguard Worker }
560*61046927SAndroid Build Coastguard Worker
561*61046927SAndroid Build Coastguard Worker resetBackoff();
562*61046927SAndroid Build Coastguard Worker return 0;
563*61046927SAndroid Build Coastguard Worker }
564*61046927SAndroid Build Coastguard Worker
backoff()565*61046927SAndroid Build Coastguard Worker void AddressSpaceStream::backoff() {
566*61046927SAndroid Build Coastguard Worker static const uint32_t kBackoffItersThreshold = 50000000;
567*61046927SAndroid Build Coastguard Worker static const uint32_t kBackoffFactorDoublingIncrement = 50000000;
568*61046927SAndroid Build Coastguard Worker ++m_backoffIters;
569*61046927SAndroid Build Coastguard Worker
570*61046927SAndroid Build Coastguard Worker if (m_backoffIters > kBackoffItersThreshold) {
571*61046927SAndroid Build Coastguard Worker usleep(m_backoffFactor);
572*61046927SAndroid Build Coastguard Worker uint32_t itersSoFarAfterThreshold = m_backoffIters - kBackoffItersThreshold;
573*61046927SAndroid Build Coastguard Worker if (itersSoFarAfterThreshold > kBackoffFactorDoublingIncrement) {
574*61046927SAndroid Build Coastguard Worker m_backoffFactor = m_backoffFactor << 1;
575*61046927SAndroid Build Coastguard Worker if (m_backoffFactor > 1000) m_backoffFactor = 1000;
576*61046927SAndroid Build Coastguard Worker m_backoffIters = kBackoffItersThreshold;
577*61046927SAndroid Build Coastguard Worker }
578*61046927SAndroid Build Coastguard Worker }
579*61046927SAndroid Build Coastguard Worker }
580*61046927SAndroid Build Coastguard Worker
resetBackoff()581*61046927SAndroid Build Coastguard Worker void AddressSpaceStream::resetBackoff() {
582*61046927SAndroid Build Coastguard Worker m_backoffIters = 0;
583*61046927SAndroid Build Coastguard Worker m_backoffFactor = 1;
584*61046927SAndroid Build Coastguard Worker }
585