Skip to content

Commit

Permalink
firmware: fix race conditions in control out transfers (-2 bytes XRAM).
Browse files Browse the repository at this point in the history
Before this change, the EP0BUF buffer used by control out transfers
could be overwritten by new control transfers before the firmware is
finished processing the previous control transfer.

The easiest way to illustrate this problem would be to run in a
different terminal the following:

```bash
while true; do lsusb -v -d 20b7:9db1 > /dev/null; done
```

While this is running, glasglow is completely unusable.
Presumably even a single lsusb run could cause corruption, if it
happens to be issued at the wrong time.

With this change glasgow is now usable, even if the above loop is
running.

Please see whitequark/libfx2#18 for more
details.
  • Loading branch information
purdeaandrei committed Sep 27, 2024
1 parent 586f049 commit b1e7539
Showing 1 changed file with 8 additions and 4 deletions.
12 changes: 8 additions & 4 deletions firmware/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -476,12 +476,13 @@ void handle_pending_usb_setup() {
}
SETUP_EP0_BUF(chunk_len);
} else {
SETUP_EP0_BUF(0);
SETUP_EP0_OUT_BUF();
while(EP0CS & _BUSY);
if(!eeprom_write(arg_chip, arg_addr, EP0BUF, chunk_len, /*double_byte=*/true,
page_size, timeout)) {
goto stall_ep0_return;
}
ACK_EP0();
}

arg_len -= chunk_len;
Expand All @@ -505,9 +506,10 @@ void handle_pending_usb_setup() {
return;
}
} else {
SETUP_EP0_BUF(0);
SETUP_EP0_OUT_BUF();
while(EP0CS & _BUSY);
fpga_reg_write(EP0BUF, arg_len);
ACK_EP0();
return;
}
}
Expand Down Expand Up @@ -547,12 +549,13 @@ void handle_pending_usb_setup() {
while(arg_len > 0) {
uint8_t chunk_len = arg_len < 64 ? arg_len : 64;

SETUP_EP0_BUF(0);
SETUP_EP0_OUT_BUF();
while(EP0CS & _BUSY);
fpga_load(EP0BUF, chunk_len);

arg_len -= chunk_len;
}
ACK_EP0();

bitstream_idx = arg_idx;
return;
Expand All @@ -569,9 +572,10 @@ void handle_pending_usb_setup() {
SETUP_EP0_BUF(CONFIG_SIZE_BITSTREAM_ID);
} else {
if(fpga_start()) {
SETUP_EP0_BUF(0);
SETUP_EP0_OUT_BUF();
while(EP0CS & _BUSY);
xmemcpy(glasgow_config.bitstream_id, EP0BUF, CONFIG_SIZE_BITSTREAM_ID);
ACK_EP0();
} else {
goto stall_ep0_return;
}
Expand Down

0 comments on commit b1e7539

Please sign in to comment.