summaryrefslogtreecommitdiffstats
path: root/payloads/libpayload/drivers/usb
diff options
context:
space:
mode:
authorYunzhi Li <lyz@rock-chips.com>2015-07-24 16:12:42 +0800
committerAaron Durbin <adurbin@chromium.org>2015-08-14 15:17:18 +0200
commit8b4988933c129028f97a7300800ff58afbb366d6 (patch)
tree1ea6f5ef8403c607a62230deae67a0c2c6b4d47b /payloads/libpayload/drivers/usb
parent6fd5bd20d389a85c360d473bd60e73441b71c306 (diff)
downloadcoreboot-8b4988933c129028f97a7300800ff58afbb366d6.tar.gz
coreboot-8b4988933c129028f97a7300800ff58afbb366d6.tar.bz2
coreboot-8b4988933c129028f97a7300800ff58afbb366d6.zip
libpayload: usb: dwc2: fix short packet transfer
If short packet detected, stop this transfer and return the actual transferred size BUG=chrome-os-partner:42817 TEST=Netboot could run well BRANCH=None Original-Change-Id: Icb4317f48aa04ac15bb1886b81d2e3c472d123d0 Original-Signed-off-by: Yunzhi Li <lyz@rock-chips.com> Original-Reviewed-on: https://chromium-review.googlesource.com/288215 Original-Reviewed-by: Julius Werner <jwerner@chromium.org> Original-Commit-Queue: Lin Huang <hl@rock-chips.com> Original-Tested-by: Lin Huang <hl@rock-chips.com> Original-(cherry picked from commit d372343b4e3d664ce2d76dbf55a5061b5d496bba) Original-Reviewed-on: https://chromium-review.googlesource.com/291064 Original-Commit-Queue: Julius Werner <jwerner@chromium.org> Original-Tested-by: Julius Werner <jwerner@chromium.org> Change-Id: I43d9edffe2074c037f2df203621863e54d2597fa Signed-off-by: Yunzhi Li <lyz@rock-chips.com> Reviewed-on: http://review.coreboot.org/11187 Tested-by: build bot (Jenkins) Reviewed-by: Patrick Georgi <pgeorgi@google.com>
Diffstat (limited to 'payloads/libpayload/drivers/usb')
-rw-r--r--payloads/libpayload/drivers/usb/dwc2.c29
1 files changed, 18 insertions, 11 deletions
diff --git a/payloads/libpayload/drivers/usb/dwc2.c b/payloads/libpayload/drivers/usb/dwc2.c
index a3979e51acdd..267dea7c71f6 100644
--- a/payloads/libpayload/drivers/usb/dwc2.c
+++ b/payloads/libpayload/drivers/usb/dwc2.c
@@ -174,8 +174,6 @@ wait_for_complete(endpoint_t *ep, uint32_t ch_num)
return -HCSTAT_BABBLE;
else if (hcint.stall)
return -HCSTAT_STALL;
- else if (hcint.ack)
- return -HCSTAT_ACK;
else if (hcint.nyet)
return -HCSTAT_NYET;
else
@@ -209,7 +207,7 @@ wait_for_complete(endpoint_t *ep, uint32_t ch_num)
static int
dwc2_do_xfer(endpoint_t *ep, int size, int pid, ep_dir_t dir,
- uint32_t ch_num, u8 *data_buf)
+ uint32_t ch_num, u8 *data_buf, int *short_pkt)
{
uint32_t do_copy;
int ret;
@@ -277,6 +275,10 @@ dwc2_do_xfer(endpoint_t *ep, int size, int pid, ep_dir_t dir,
if (do_copy && (dir == EPDIR_IN))
memcpy(data_buf, aligned_buf, transferred);
+
+ if ((short_pkt != NULL) && (dir == EPDIR_IN))
+ *short_pkt = (ret > 0) ? 1 : 0;
+
}
/* Save data toggle */
@@ -292,7 +294,8 @@ dwc2_do_xfer(endpoint_t *ep, int size, int pid, ep_dir_t dir,
static int
dwc2_split_transfer(endpoint_t *ep, int size, int pid, ep_dir_t dir,
- uint32_t ch_num, u8 *data_buf, split_info_t *split)
+ uint32_t ch_num, u8 *data_buf, split_info_t *split,
+ int *short_pkt)
{
dwc2_reg_t *reg = DWC2_REG(ep->dev->controller);
hfnum_t hfnum;
@@ -311,7 +314,7 @@ dwc2_split_transfer(endpoint_t *ep, int size, int pid, ep_dir_t dir,
/* Handle Start-Split */
ret = dwc2_do_xfer(ep, dir == EPDIR_IN ? 0 : size, pid, dir, ch_num,
- data_buf);
+ data_buf, NULL);
if (ret < 0)
goto out;
@@ -326,7 +329,7 @@ dwc2_split_transfer(endpoint_t *ep, int size, int pid, ep_dir_t dir,
/* Handle Complete-Split */
do {
ret = dwc2_do_xfer(ep, dir == EPDIR_OUT ? 0 : size, ep->toggle,
- dir, ch_num, data_buf);
+ dir, ch_num, data_buf, short_pkt);
} while (ret == -HCSTAT_NYET);
if (dir == EPDIR_IN)
@@ -360,15 +363,17 @@ dwc2_transfer(endpoint_t *ep, int size, int pid, ep_dir_t dir, uint32_t ch_num,
u8 *src, uint8_t skip_nak)
{
split_info_t split;
- int ret, transferred = 0, timeout = 3000;
+ int ret, short_pkt, transferred = 0, timeout = 3000;
ep->toggle = pid;
do {
+ short_pkt = 0;
if (dwc2_need_split(ep->dev, &split)) {
nak_retry:
- ret = dwc2_split_transfer(ep, size, ep->toggle, dir, 0,
- src, &split);
+ ret = dwc2_split_transfer(ep, MIN(ep->maxpacketsize,
+ size), ep->toggle, dir, 0, src, &split,
+ &short_pkt);
/*
* dwc2_split_transfer() waits for the next FullSpeed
@@ -380,7 +385,8 @@ nak_retry:
goto nak_retry;
}
} else {
- ret = dwc2_do_xfer(ep, size, pid, dir, 0, src);
+ ret = dwc2_do_xfer(ep, MIN(DMA_SIZE, size), pid, dir, 0,
+ src, &short_pkt);
}
if (ret < 0)
@@ -389,7 +395,8 @@ nak_retry:
size -= ret;
src += ret;
transferred += ret;
- } while (size > 0);
+
+ } while (size > 0 && !short_pkt);
return transferred;
}