diff options
author | Nico Huber <nico.huber@secunet.com> | 2023-05-31 12:49:42 +0000 |
---|---|---|
committer | Martin L Roth <gaumless@gmail.com> | 2023-06-04 18:49:35 +0000 |
commit | 2a976f0d072c334de5b6a615745d40cdb577df81 (patch) | |
tree | c907bddd642242231199b8e0034b449afca1e443 | |
parent | f397bec457aeb780ba9f15a0559eeff708144c49 (diff) |
libpayload/uhci: Return expected length for control/bulk transfers
Libpayload's USB API was changed in commit e9738dbe2b (libpayload: Make
USB transfer functions return amount of bytes). However, the UHCI driver
was never adapted. Instead of returning 0 for success, we can return the
expected data length as a best effort. We won't be able to catch short
transfers this way, but previously working cases will work again.
Change-Id: I31d7de495a46af401e2cbe5a3b8f6349facad8ff
Signed-off-by: Nico Huber <nico.huber@secunet.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/75349
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Paul Menzel <paulepanter@mailbox.org>
Reviewed-by: Julius Werner <jwerner@chromium.org>
-rw-r--r-- | payloads/libpayload/drivers/usb/uhci.c | 24 |
1 files changed, 13 insertions, 11 deletions
diff --git a/payloads/libpayload/drivers/usb/uhci.c b/payloads/libpayload/drivers/usb/uhci.c index 538107eca3..eb252cd8ad 100644 --- a/payloads/libpayload/drivers/usb/uhci.c +++ b/payloads/libpayload/drivers/usb/uhci.c @@ -310,7 +310,7 @@ min(int a, int b) } static int -uhci_control(usbdev_t *dev, direction_t dir, int drlen, void *devreq, int dalen, +uhci_control(usbdev_t *dev, direction_t dir, int drlen, void *devreq, const int dalen, unsigned char *data) { int endp = 0; /* this is control: always 0 */ @@ -339,6 +339,7 @@ uhci_control(usbdev_t *dev, direction_t dir, int drlen, void *devreq, int dalen, TD_STATUS_ACTIVE; int toggle = 1; + int len_left = dalen; for (i = 1; i < count; i++) { switch (dir) { case SETUP: tds[i].token = UHCI_SETUP; break; @@ -347,14 +348,14 @@ uhci_control(usbdev_t *dev, direction_t dir, int drlen, void *devreq, int dalen, } tds[i].token |= dev->address << TD_DEVADDR_SHIFT | endp << TD_EP_SHIFT | - maxlen(min(mlen, dalen)) << TD_MAXLEN_SHIFT | + maxlen(min(mlen, len_left)) << TD_MAXLEN_SHIFT | toggle << TD_TOGGLE_SHIFT; tds[i].bufptr = virt_to_phys(data); tds[i].ctrlsts = (3 << TD_COUNTER_SHIFT) | (dev->speed?TD_LOWSPEED:0) | TD_STATUS_ACTIVE; toggle ^= 1; - dalen -= mlen; + len_left -= mlen; data += mlen; } @@ -374,7 +375,7 @@ uhci_control(usbdev_t *dev, direction_t dir, int drlen, void *devreq, int dalen, qh_data); int result; if (td == 0) { - result = 0; + result = dalen; /* TODO: We should return the actually transferred length. */ } else { usb_debug("control packet, req %x\n", req); td_dump(td); @@ -438,25 +439,26 @@ run_schedule(usbdev_t *dev, td_t *td) /* finalize == 1: if data is of packet aligned size, add a zero length packet */ static int -uhci_bulk(endpoint_t *ep, int size, u8 *data, int finalize) +uhci_bulk(endpoint_t *ep, const int dalen, u8 *data, int finalize) { int maxpsize = ep->maxpacketsize; if (maxpsize == 0) fatal("MaxPacketSize == 0!!!"); - int numpackets = (size + maxpsize - 1) / maxpsize; - if (finalize && ((size % maxpsize) == 0)) { + int numpackets = (dalen + maxpsize - 1) / maxpsize; + if (finalize && ((dalen % maxpsize) == 0)) { numpackets++; } if (numpackets == 0) return 0; td_t *tds = create_schedule(numpackets); int i = 0, toggle = ep->toggle; - while ((size > 0) || ((size == 0) && (finalize != 0))) { - fill_schedule(&tds[i], ep, min(size, maxpsize), data, + int len_left = dalen; + while ((len_left > 0) || ((len_left == 0) && (finalize != 0))) { + fill_schedule(&tds[i], ep, min(len_left, maxpsize), data, &toggle); i++; data += maxpsize; - size -= maxpsize; + len_left -= maxpsize; } if (run_schedule(ep->dev, tds) == 1) { free(tds); @@ -464,7 +466,7 @@ uhci_bulk(endpoint_t *ep, int size, u8 *data, int finalize) } ep->toggle = toggle; free(tds); - return 0; + return dalen; /* TODO: We should return the actually transferred length. */ } typedef struct { |