|
@@ -1599,14 +1599,20 @@ static void handle_port_status(struct xhci_hcd *xhci,
|
|
|
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);
|
|
|
- bogus_port_status = true;
|
|
|
- goto cleanup;
|
|
|
+ inc_deq(xhci, xhci->event_ring);
|
|
|
+ return;
|
|
|
}
|
|
|
|
|
|
/* Figure out which usb_hcd this port is attached to:
|
|
|
* is it a USB 3.0 port or a USB 2.0/1.1 port?
|
|
|
*/
|
|
|
major_revision = xhci->port_array[port_id - 1];
|
|
|
+
|
|
|
+ /* Find the right roothub. */
|
|
|
+ hcd = xhci_to_hcd(xhci);
|
|
|
+ if ((major_revision == 0x03) != (hcd->speed == HCD_USB3))
|
|
|
+ hcd = xhci->shared_hcd;
|
|
|
+
|
|
|
if (major_revision == 0) {
|
|
|
xhci_warn(xhci, "Event for port %u not in "
|
|
|
"Extended Capabilities, ignoring.\n",
|
|
@@ -1629,10 +1635,6 @@ static void handle_port_status(struct xhci_hcd *xhci,
|
|
|
* into the index into the ports on the correct split roothub, and the
|
|
|
* correct bus_state structure.
|
|
|
*/
|
|
|
- /* Find the right roothub. */
|
|
|
- hcd = xhci_to_hcd(xhci);
|
|
|
- if ((major_revision == 0x03) != (hcd->speed == HCD_USB3))
|
|
|
- hcd = xhci->shared_hcd;
|
|
|
bus_state = &xhci->bus_state[hcd_index(hcd)];
|
|
|
if (hcd->speed == HCD_USB3)
|
|
|
port_array = xhci->usb3_ports;
|
|
@@ -2027,8 +2029,8 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td,
|
|
|
if (event_trb != ep_ring->dequeue &&
|
|
|
event_trb != td->last_trb)
|
|
|
td->urb->actual_length =
|
|
|
- td->urb->transfer_buffer_length
|
|
|
- - TRB_LEN(le32_to_cpu(event->transfer_len));
|
|
|
+ td->urb->transfer_buffer_length -
|
|
|
+ EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
|
|
|
else
|
|
|
td->urb->actual_length = 0;
|
|
|
|
|
@@ -2060,7 +2062,7 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td,
|
|
|
/* Maybe the event was for the data stage? */
|
|
|
td->urb->actual_length =
|
|
|
td->urb->transfer_buffer_length -
|
|
|
- TRB_LEN(le32_to_cpu(event->transfer_len));
|
|
|
+ EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
|
|
|
xhci_dbg(xhci, "Waiting for status "
|
|
|
"stage event\n");
|
|
|
return 0;
|
|
@@ -2096,7 +2098,7 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
|
|
|
/* handle completion code */
|
|
|
switch (trb_comp_code) {
|
|
|
case COMP_SUCCESS:
|
|
|
- if (TRB_LEN(le32_to_cpu(event->transfer_len)) == 0) {
|
|
|
+ if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) == 0) {
|
|
|
frame->status = 0;
|
|
|
break;
|
|
|
}
|
|
@@ -2141,7 +2143,7 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
|
|
|
len += TRB_LEN(le32_to_cpu(cur_trb->generic.field[2]));
|
|
|
}
|
|
|
len += TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])) -
|
|
|
- TRB_LEN(le32_to_cpu(event->transfer_len));
|
|
|
+ EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
|
|
|
|
|
|
if (trb_comp_code != COMP_STOP_INVAL) {
|
|
|
frame->actual_length = len;
|
|
@@ -2199,7 +2201,7 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
|
|
|
case COMP_SUCCESS:
|
|
|
/* Double check that the HW transferred everything. */
|
|
|
if (event_trb != td->last_trb ||
|
|
|
- TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) {
|
|
|
+ EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) {
|
|
|
xhci_warn(xhci, "WARN Successful completion "
|
|
|
"on short TX\n");
|
|
|
if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
|
|
@@ -2227,18 +2229,18 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
|
|
|
"%d bytes untransferred\n",
|
|
|
td->urb->ep->desc.bEndpointAddress,
|
|
|
td->urb->transfer_buffer_length,
|
|
|
- TRB_LEN(le32_to_cpu(event->transfer_len)));
|
|
|
+ EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)));
|
|
|
/* Fast path - was this the last TRB in the TD for this URB? */
|
|
|
if (event_trb == td->last_trb) {
|
|
|
- if (TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) {
|
|
|
+ if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) {
|
|
|
td->urb->actual_length =
|
|
|
td->urb->transfer_buffer_length -
|
|
|
- TRB_LEN(le32_to_cpu(event->transfer_len));
|
|
|
+ EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
|
|
|
if (td->urb->transfer_buffer_length <
|
|
|
td->urb->actual_length) {
|
|
|
xhci_warn(xhci, "HC gave bad length "
|
|
|
"of %d bytes left\n",
|
|
|
- TRB_LEN(le32_to_cpu(event->transfer_len)));
|
|
|
+ EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)));
|
|
|
td->urb->actual_length = 0;
|
|
|
if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
|
|
|
*status = -EREMOTEIO;
|
|
@@ -2280,7 +2282,7 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
|
|
|
if (trb_comp_code != COMP_STOP_INVAL)
|
|
|
td->urb->actual_length +=
|
|
|
TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])) -
|
|
|
- TRB_LEN(le32_to_cpu(event->transfer_len));
|
|
|
+ EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
|
|
|
}
|
|
|
|
|
|
return finish_td(xhci, td, event_trb, event, ep, status, false);
|
|
@@ -2368,7 +2370,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
|
|
|
* transfer type
|
|
|
*/
|
|
|
case COMP_SUCCESS:
|
|
|
- if (TRB_LEN(le32_to_cpu(event->transfer_len)) == 0)
|
|
|
+ if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) == 0)
|
|
|
break;
|
|
|
if (xhci->quirks & XHCI_TRUST_TX_LENGTH)
|
|
|
trb_comp_code = COMP_SHORT_TX;
|
|
@@ -2461,14 +2463,21 @@ static int handle_tx_event(struct xhci_hcd *xhci,
|
|
|
* TD list.
|
|
|
*/
|
|
|
if (list_empty(&ep_ring->td_list)) {
|
|
|
- xhci_warn(xhci, "WARN Event TRB for slot %d ep %d "
|
|
|
- "with no TDs queued?\n",
|
|
|
- TRB_TO_SLOT_ID(le32_to_cpu(event->flags)),
|
|
|
- ep_index);
|
|
|
- xhci_dbg(xhci, "Event TRB with TRB type ID %u\n",
|
|
|
- (le32_to_cpu(event->flags) &
|
|
|
- TRB_TYPE_BITMASK)>>10);
|
|
|
- xhci_print_trb_offsets(xhci, (union xhci_trb *) event);
|
|
|
+ /*
|
|
|
+ * A stopped endpoint may generate an extra completion
|
|
|
+ * event if the device was suspended. Don't print
|
|
|
+ * warnings.
|
|
|
+ */
|
|
|
+ if (!(trb_comp_code == COMP_STOP ||
|
|
|
+ trb_comp_code == COMP_STOP_INVAL)) {
|
|
|
+ xhci_warn(xhci, "WARN Event TRB for slot %d ep %d with no TDs queued?\n",
|
|
|
+ TRB_TO_SLOT_ID(le32_to_cpu(event->flags)),
|
|
|
+ ep_index);
|
|
|
+ xhci_dbg(xhci, "Event TRB with TRB type ID %u\n",
|
|
|
+ (le32_to_cpu(event->flags) &
|
|
|
+ TRB_TYPE_BITMASK)>>10);
|
|
|
+ xhci_print_trb_offsets(xhci, (union xhci_trb *) event);
|
|
|
+ }
|
|
|
if (ep->skip) {
|
|
|
ep->skip = false;
|
|
|
xhci_dbg(xhci, "td_list is empty while skip "
|