diff options
Diffstat (limited to 'drivers/usb/host/xhci-ring.c')
| -rw-r--r-- | drivers/usb/host/xhci-ring.c | 61 | 
1 files changed, 35 insertions, 26 deletions
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 88287546530..1969c001b3f 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -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 "  |