summaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/xhci-ring.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host/xhci-ring.c')
-rw-r--r--drivers/usb/host/xhci-ring.c24
1 files changed, 20 insertions, 4 deletions
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 9215a28dad40..fed3385aeac0 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -1569,18 +1569,19 @@ static void handle_port_status(struct xhci_hcd *xhci,
"WARN: xHC returned failed port status event\n");
port_id = GET_PORT_ID(le32_to_cpu(event->generic.field[0]));
- xhci_dbg(xhci, "Port Status Change Event for port %d\n", port_id);
-
max_ports = HCS_MAX_PORTS(xhci->hcs_params1);
+
if ((port_id <= 0) || (port_id > max_ports)) {
- xhci_warn(xhci, "Invalid port id %d\n", port_id);
+ xhci_warn(xhci, "Port change event with invalid port ID %d\n",
+ port_id);
inc_deq(xhci, xhci->event_ring);
return;
}
port = &xhci->hw_ports[port_id - 1];
if (!port || !port->rhub || port->hcd_portnum == DUPLICATE_ENTRY) {
- xhci_warn(xhci, "Event for invalid port %u\n", port_id);
+ xhci_warn(xhci, "Port change event, no port for port ID %u\n",
+ port_id);
bogus_port_status = true;
goto cleanup;
}
@@ -1597,6 +1598,9 @@ static void handle_port_status(struct xhci_hcd *xhci,
hcd_portnum = port->hcd_portnum;
portsc = readl(port->addr);
+ xhci_dbg(xhci, "Port change event, %d-%d, id %d, portsc: 0x%x\n",
+ hcd->self.busnum, hcd_portnum + 1, port_id, portsc);
+
trace_xhci_handle_port_status(hcd_portnum, portsc);
if (hcd->state == HC_STATE_SUSPENDED) {
@@ -3275,6 +3279,12 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
field |= TRB_IOC;
more_trbs_coming = false;
td->last_trb = ring->enqueue;
+
+ if (xhci_urb_suitable_for_idt(urb)) {
+ memcpy(&send_addr, urb->transfer_buffer,
+ trb_buff_len);
+ field |= TRB_IDT;
+ }
}
/* Only set interrupt on short packet for IN endpoints */
@@ -3414,6 +3424,12 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
if (urb->transfer_buffer_length > 0) {
u32 length_field, remainder;
+ if (xhci_urb_suitable_for_idt(urb)) {
+ memcpy(&urb->transfer_dma, urb->transfer_buffer,
+ urb->transfer_buffer_length);
+ field |= TRB_IDT;
+ }
+
remainder = xhci_td_remainder(xhci, 0,
urb->transfer_buffer_length,
urb->transfer_buffer_length,