diff options
Diffstat (limited to 'drivers/usb/host/xhci-ring.c')
| -rw-r--r-- | drivers/usb/host/xhci-ring.c | 34 | 
1 files changed, 20 insertions, 14 deletions
| diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 4e1a8946b8d1..cbb44b7b9d65 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -318,7 +318,7 @@ static int xhci_abort_cmd_ring(struct xhci_hcd *xhci)  	 * seconds), then it should assume that the there are  	 * larger problems with the xHC and assert HCRST.  	 */ -	ret = handshake(xhci, &xhci->op_regs->cmd_ring, +	ret = xhci_handshake(xhci, &xhci->op_regs->cmd_ring,  			CMD_RING_RUNNING, 0, 5 * 1000 * 1000);  	if (ret < 0) {  		xhci_err(xhci, "Stopped the command ring failed, " @@ -3071,11 +3071,11 @@ static u32 xhci_td_remainder(unsigned int remainder)  }  /* - * For xHCI 1.0 host controllers, TD size is the number of packets remaining in - * the TD (*not* including this TRB). + * For xHCI 1.0 host controllers, TD size is the number of max packet sized + * packets remaining in the TD (*not* including this TRB).   *   * Total TD packet count = total_packet_count = - *     roundup(TD size in bytes / wMaxPacketSize) + *     DIV_ROUND_UP(TD size in bytes / wMaxPacketSize)   *   * Packets transferred up to and including this TRB = packets_transferred =   *     rounddown(total bytes transferred including this TRB / wMaxPacketSize) @@ -3083,15 +3083,16 @@ static u32 xhci_td_remainder(unsigned int remainder)   * TD size = total_packet_count - packets_transferred   *   * It must fit in bits 21:17, so it can't be bigger than 31. + * The last TRB in a TD must have the TD size set to zero.   */ -  static u32 xhci_v1_0_td_remainder(int running_total, int trb_buff_len, -		unsigned int total_packet_count, struct urb *urb) +		unsigned int total_packet_count, struct urb *urb, +		unsigned int num_trbs_left)  {  	int packets_transferred;  	/* One TRB with a zero-length data packet. */ -	if (running_total == 0 && trb_buff_len == 0) +	if (num_trbs_left == 0 || (running_total == 0 && trb_buff_len == 0))  		return 0;  	/* All the TRB queueing functions don't count the current TRB in @@ -3100,7 +3101,9 @@ static u32 xhci_v1_0_td_remainder(int running_total, int trb_buff_len,  	packets_transferred = (running_total + trb_buff_len) /  		usb_endpoint_maxp(&urb->ep->desc); -	return xhci_td_remainder(total_packet_count - packets_transferred); +	if ((total_packet_count - packets_transferred) > 31) +		return 31 << 17; +	return (total_packet_count - packets_transferred) << 17;  }  static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, @@ -3127,7 +3130,7 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,  	num_trbs = count_sg_trbs_needed(xhci, urb);  	num_sgs = urb->num_mapped_sgs; -	total_packet_count = roundup(urb->transfer_buffer_length, +	total_packet_count = DIV_ROUND_UP(urb->transfer_buffer_length,  			usb_endpoint_maxp(&urb->ep->desc));  	trb_buff_len = prepare_transfer(xhci, xhci->devs[slot_id], @@ -3210,7 +3213,8 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,  					running_total);  		} else {  			remainder = xhci_v1_0_td_remainder(running_total, -					trb_buff_len, total_packet_count, urb); +					trb_buff_len, total_packet_count, urb, +					num_trbs - 1);  		}  		length_field = TRB_LEN(trb_buff_len) |  			remainder | @@ -3318,7 +3322,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,  	start_cycle = ep_ring->cycle_state;  	running_total = 0; -	total_packet_count = roundup(urb->transfer_buffer_length, +	total_packet_count = DIV_ROUND_UP(urb->transfer_buffer_length,  			usb_endpoint_maxp(&urb->ep->desc));  	/* How much data is in the first TRB? */  	addr = (u64) urb->transfer_dma; @@ -3364,7 +3368,8 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,  					running_total);  		} else {  			remainder = xhci_v1_0_td_remainder(running_total, -					trb_buff_len, total_packet_count, urb); +					trb_buff_len, total_packet_count, urb, +					num_trbs - 1);  		}  		length_field = TRB_LEN(trb_buff_len) |  			remainder | @@ -3627,7 +3632,7 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,  		addr = start_addr + urb->iso_frame_desc[i].offset;  		td_len = urb->iso_frame_desc[i].length;  		td_remain_len = td_len; -		total_packet_count = roundup(td_len, +		total_packet_count = DIV_ROUND_UP(td_len,  				usb_endpoint_maxp(&urb->ep->desc));  		/* A zero-length transfer still involves at least one packet. */  		if (total_packet_count == 0) @@ -3706,7 +3711,8 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,  			} else {  				remainder = xhci_v1_0_td_remainder(  						running_total, trb_buff_len, -						total_packet_count, urb); +						total_packet_count, urb, +						(trbs_per_td - j - 1));  			}  			length_field = TRB_LEN(trb_buff_len) |  				remainder | |