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>
This commit is contained in:
parent
f397bec457
commit
2a976f0d07
|
@ -310,7 +310,7 @@ min(int a, int b)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
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)
|
unsigned char *data)
|
||||||
{
|
{
|
||||||
int endp = 0; /* this is control: always 0 */
|
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;
|
TD_STATUS_ACTIVE;
|
||||||
|
|
||||||
int toggle = 1;
|
int toggle = 1;
|
||||||
|
int len_left = dalen;
|
||||||
for (i = 1; i < count; i++) {
|
for (i = 1; i < count; i++) {
|
||||||
switch (dir) {
|
switch (dir) {
|
||||||
case SETUP: tds[i].token = UHCI_SETUP; break;
|
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 |
|
tds[i].token |= dev->address << TD_DEVADDR_SHIFT |
|
||||||
endp << TD_EP_SHIFT |
|
endp << TD_EP_SHIFT |
|
||||||
maxlen(min(mlen, dalen)) << TD_MAXLEN_SHIFT |
|
maxlen(min(mlen, len_left)) << TD_MAXLEN_SHIFT |
|
||||||
toggle << TD_TOGGLE_SHIFT;
|
toggle << TD_TOGGLE_SHIFT;
|
||||||
tds[i].bufptr = virt_to_phys(data);
|
tds[i].bufptr = virt_to_phys(data);
|
||||||
tds[i].ctrlsts = (3 << TD_COUNTER_SHIFT) |
|
tds[i].ctrlsts = (3 << TD_COUNTER_SHIFT) |
|
||||||
(dev->speed?TD_LOWSPEED:0) |
|
(dev->speed?TD_LOWSPEED:0) |
|
||||||
TD_STATUS_ACTIVE;
|
TD_STATUS_ACTIVE;
|
||||||
toggle ^= 1;
|
toggle ^= 1;
|
||||||
dalen -= mlen;
|
len_left -= mlen;
|
||||||
data += mlen;
|
data += mlen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -374,7 +375,7 @@ uhci_control(usbdev_t *dev, direction_t dir, int drlen, void *devreq, int dalen,
|
||||||
qh_data);
|
qh_data);
|
||||||
int result;
|
int result;
|
||||||
if (td == 0) {
|
if (td == 0) {
|
||||||
result = 0;
|
result = dalen; /* TODO: We should return the actually transferred length. */
|
||||||
} else {
|
} else {
|
||||||
usb_debug("control packet, req %x\n", req);
|
usb_debug("control packet, req %x\n", req);
|
||||||
td_dump(td);
|
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 */
|
/* finalize == 1: if data is of packet aligned size, add a zero length packet */
|
||||||
static int
|
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;
|
int maxpsize = ep->maxpacketsize;
|
||||||
if (maxpsize == 0)
|
if (maxpsize == 0)
|
||||||
fatal("MaxPacketSize == 0!!!");
|
fatal("MaxPacketSize == 0!!!");
|
||||||
int numpackets = (size + maxpsize - 1) / maxpsize;
|
int numpackets = (dalen + maxpsize - 1) / maxpsize;
|
||||||
if (finalize && ((size % maxpsize) == 0)) {
|
if (finalize && ((dalen % maxpsize) == 0)) {
|
||||||
numpackets++;
|
numpackets++;
|
||||||
}
|
}
|
||||||
if (numpackets == 0)
|
if (numpackets == 0)
|
||||||
return 0;
|
return 0;
|
||||||
td_t *tds = create_schedule(numpackets);
|
td_t *tds = create_schedule(numpackets);
|
||||||
int i = 0, toggle = ep->toggle;
|
int i = 0, toggle = ep->toggle;
|
||||||
while ((size > 0) || ((size == 0) && (finalize != 0))) {
|
int len_left = dalen;
|
||||||
fill_schedule(&tds[i], ep, min(size, maxpsize), data,
|
while ((len_left > 0) || ((len_left == 0) && (finalize != 0))) {
|
||||||
|
fill_schedule(&tds[i], ep, min(len_left, maxpsize), data,
|
||||||
&toggle);
|
&toggle);
|
||||||
i++;
|
i++;
|
||||||
data += maxpsize;
|
data += maxpsize;
|
||||||
size -= maxpsize;
|
len_left -= maxpsize;
|
||||||
}
|
}
|
||||||
if (run_schedule(ep->dev, tds) == 1) {
|
if (run_schedule(ep->dev, tds) == 1) {
|
||||||
free(tds);
|
free(tds);
|
||||||
|
@ -464,7 +466,7 @@ uhci_bulk(endpoint_t *ep, int size, u8 *data, int finalize)
|
||||||
}
|
}
|
||||||
ep->toggle = toggle;
|
ep->toggle = toggle;
|
||||||
free(tds);
|
free(tds);
|
||||||
return 0;
|
return dalen; /* TODO: We should return the actually transferred length. */
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
Loading…
Reference in New Issue