restore large xfer workaround

sadly, it's not possible to gracefully switch from large to blocked
xfers, further xfer ioctls fail after the first large xfer fails.
This commit is contained in:
Jeff Epler 2025-03-17 10:29:45 -05:00
parent fc7295eb74
commit 89dd515ae5

View file

@ -12,6 +12,42 @@
namespace piomatter {
static int pio_sm_xfer_data_large(PIO pio, int sm, int direction, size_t size,
uint32_t *databuf) {
#if 0
// it would be NICE to gracefully fall back to blocked transfer, but sadly
// once the large xfer ioctl fails, future small xfers fail too.
static enum { UNKNOWN, OK, BAD } large_xfer_status = UNKNOWN;
printf("large_xfer_status=%d\n", large_xfer_status);
if (large_xfer_status != BAD) {
int r = pio_sm_xfer_data(pio, sm, direction, size, databuf);
if (large_xfer_status == UNKNOWN && r != 0) {
large_xfer_status = BAD;
fprintf(stderr,
"Transmission limit workaround engaged. May reduce quality of "
"output.\nSee https://github.com/raspberrypi/utils/issues/123 "
"for details.\n");
} else {
if (large_xfer_status == UNKNOWN && r == 0) {
large_xfer_status = OK;
}
return r;
}
}
#endif
constexpr size_t MAX_XFER = 65532;
while (size) {
size_t xfersize = std::min(size_t{MAX_XFER}, size);
int r = pio_sm_xfer_data(pio, sm, direction, xfersize, databuf);
if (r != 0) {
return r;
}
size -= xfersize;
databuf += xfersize / sizeof(*databuf);
}
return 0;
}
static uint64_t monotonicns64() {
struct timespec tp;
clock_gettime(CLOCK_MONOTONIC, &tp);
@ -181,12 +217,12 @@ struct piomatter : piomatter_base {
auto dataptr = const_cast<uint32_t *>(&data[0]);
// returns err = rp1_ioctl.... which seems to be a negative
// errno value
int r =
pio_sm_xfer_data(pio, sm, PIO_DIR_TO_SM, datasize, dataptr);
int r = pio_sm_xfer_data_large(pio, sm, PIO_DIR_TO_SM, datasize,
dataptr);
if (r != 0) {
pending_error_errno.store(-r);
printf("xfer_data() returned error %d (%s)\n", r,
strerror(-r));
pending_error_errno.store(errno);
printf("xfer_data() returned error %d (errno=%s)\n", r,
strerror(errno));
}
t1 = monotonicns64();
if (t0 != t1) {