aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--payloads/libpayload/drivers/usb/xhci.c19
-rw-r--r--payloads/libpayload/drivers/usb/xhci_private.h3
2 files changed, 13 insertions, 9 deletions
diff --git a/payloads/libpayload/drivers/usb/xhci.c b/payloads/libpayload/drivers/usb/xhci.c
index 2e9dd3b912..d31a8e2a8e 100644
--- a/payloads/libpayload/drivers/usb/xhci.c
+++ b/payloads/libpayload/drivers/usb/xhci.c
@@ -551,6 +551,7 @@ xhci_enqueue_td(transfer_ring_t *const tr, const int ep, const size_t mps,
trb->ptr_low = virt_to_phys(cur_start);
TRB_SET(TL, trb, cur_length);
TRB_SET(TDS, trb, packets);
+ TRB_SET(CH, trb, 1);
/* Check for first, data stage TRB */
if (!trb_count && ep == 1) {
@@ -560,17 +561,19 @@ xhci_enqueue_td(transfer_ring_t *const tr, const int ep, const size_t mps,
TRB_SET(TT, trb, TRB_NORMAL);
}
- /* Check for last TRB */
- if (!length)
- TRB_SET(IOC, trb, 1);
- else
- TRB_SET(CH, trb, 1);
-
xhci_enqueue_trb(tr);
cur_start += cur_length;
++trb_count;
}
+
+ trb = tr->cur;
+ xhci_clear_trb(trb, tr->pcs);
+ trb->ptr_low = virt_to_phys(trb); /* for easier debugging only */
+ TRB_SET(TT, trb, TRB_EVENT_DATA);
+ TRB_SET(IOC, trb, 1);
+
+ xhci_enqueue_trb(tr);
}
static int
@@ -583,7 +586,7 @@ xhci_control(usbdev_t *const dev, const direction_t dir,
transfer_ring_t *const tr = di->transfer_rings[1];
const size_t off = (size_t)data & 0xffff;
- if ((off + dalen) > ((TRANSFER_RING_SIZE - 3) << 16)) {
+ if ((off + dalen) > ((TRANSFER_RING_SIZE - 4) << 16)) {
xhci_debug("Unsupported transfer size\n");
return 1;
}
@@ -670,7 +673,7 @@ xhci_bulk(endpoint_t *const ep,
transfer_ring_t *const tr = di->transfer_rings[ep_id];
const size_t off = (size_t)data & 0xffff;
- if ((off + size) > ((TRANSFER_RING_SIZE - 1) << 16)) {
+ if ((off + size) > ((TRANSFER_RING_SIZE - 2) << 16)) {
xhci_debug("Unsupported transfer size\n");
return 1;
}
diff --git a/payloads/libpayload/drivers/usb/xhci_private.h b/payloads/libpayload/drivers/usb/xhci_private.h
index 945c7f1982..c7048f494e 100644
--- a/payloads/libpayload/drivers/usb/xhci_private.h
+++ b/payloads/libpayload/drivers/usb/xhci_private.h
@@ -65,7 +65,7 @@ enum { XHCI_FULL_SPEED = 1, XHCI_LOW_SPEED = 2, XHCI_HIGH_SPEED = 3, XHCI_SUPER_
enum {
TRB_NORMAL = 1,
TRB_SETUP_STAGE = 2, TRB_DATA_STAGE = 3, TRB_STATUS_STAGE = 4,
- TRB_LINK = 6,
+ TRB_LINK = 6, TRB_EVENT_DATA = 7,
TRB_CMD_ENABLE_SLOT = 9, TRB_CMD_DISABLE_SLOT = 10, TRB_CMD_ADDRESS_DEV = 11,
TRB_CMD_CONFIGURE_EP = 12, TRB_CMD_EVAL_CTX = 13, TRB_CMD_RESET_EP = 14,
TRB_CMD_STOP_EP = 15, TRB_CMD_SET_TR_DQ = 16, TRB_CMD_NOOP = 23,
@@ -150,6 +150,7 @@ typedef struct {
u8 adv;
} event_ring_t;
+/* Never raise this above 256 to prevent transfer event length overflow! */
#define TRANSFER_RING_SIZE 32
typedef struct {
trb_t *ring;