USB: UHCI: add native scatter-gather support(v1)
This patch adds native scatter-gather support to uhci-hcd. Reviewed-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Ming Lei <tom.leiming@gmail.com> Acked-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
		
					parent
					
						
							
								00be545e49
							
						
					
				
			
			
				commit
				
					
						689d6eacd1
					
				
			
		
					 1 changed files with 30 additions and 5 deletions
				
			
		| 
						 | 
					@ -917,10 +917,13 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb,
 | 
				
			||||||
	unsigned long destination, status;
 | 
						unsigned long destination, status;
 | 
				
			||||||
	int maxsze = le16_to_cpu(qh->hep->desc.wMaxPacketSize);
 | 
						int maxsze = le16_to_cpu(qh->hep->desc.wMaxPacketSize);
 | 
				
			||||||
	int len = urb->transfer_buffer_length;
 | 
						int len = urb->transfer_buffer_length;
 | 
				
			||||||
	dma_addr_t data = urb->transfer_dma;
 | 
						int this_sg_len;
 | 
				
			||||||
 | 
						dma_addr_t data;
 | 
				
			||||||
	__le32 *plink;
 | 
						__le32 *plink;
 | 
				
			||||||
	struct urb_priv *urbp = urb->hcpriv;
 | 
						struct urb_priv *urbp = urb->hcpriv;
 | 
				
			||||||
	unsigned int toggle;
 | 
						unsigned int toggle;
 | 
				
			||||||
 | 
						struct scatterlist  *sg;
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (len < 0)
 | 
						if (len < 0)
 | 
				
			||||||
		return -EINVAL;
 | 
							return -EINVAL;
 | 
				
			||||||
| 
						 | 
					@ -937,12 +940,26 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb,
 | 
				
			||||||
	if (usb_pipein(urb->pipe))
 | 
						if (usb_pipein(urb->pipe))
 | 
				
			||||||
		status |= TD_CTRL_SPD;
 | 
							status |= TD_CTRL_SPD;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						i = urb->num_sgs;
 | 
				
			||||||
 | 
						if (len > 0 && i > 0) {
 | 
				
			||||||
 | 
							sg = urb->sg;
 | 
				
			||||||
 | 
							data = sg_dma_address(sg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* urb->transfer_buffer_length may be smaller than the
 | 
				
			||||||
 | 
							 * size of the scatterlist (or vice versa)
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							this_sg_len = min_t(int, sg_dma_len(sg), len);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							sg = NULL;
 | 
				
			||||||
 | 
							data = urb->transfer_dma;
 | 
				
			||||||
 | 
							this_sg_len = len;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * Build the DATA TDs
 | 
						 * Build the DATA TDs
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	plink = NULL;
 | 
						plink = NULL;
 | 
				
			||||||
	td = qh->dummy_td;
 | 
						td = qh->dummy_td;
 | 
				
			||||||
	do {	/* Allow zero length packets */
 | 
						for (;;) {	/* Allow zero length packets */
 | 
				
			||||||
		int pktsze = maxsze;
 | 
							int pktsze = maxsze;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (len <= pktsze) {		/* The last packet */
 | 
							if (len <= pktsze) {		/* The last packet */
 | 
				
			||||||
| 
						 | 
					@ -965,10 +982,18 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb,
 | 
				
			||||||
		plink = &td->link;
 | 
							plink = &td->link;
 | 
				
			||||||
		status |= TD_CTRL_ACTIVE;
 | 
							status |= TD_CTRL_ACTIVE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		data += pktsze;
 | 
					 | 
				
			||||||
		len -= maxsze;
 | 
					 | 
				
			||||||
		toggle ^= 1;
 | 
							toggle ^= 1;
 | 
				
			||||||
	} while (len > 0);
 | 
							data += pktsze;
 | 
				
			||||||
 | 
							this_sg_len -= pktsze;
 | 
				
			||||||
 | 
							len -= maxsze;
 | 
				
			||||||
 | 
							if (this_sg_len <= 0) {
 | 
				
			||||||
 | 
								if (--i <= 0 || len <= 0)
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								sg = sg_next(sg);
 | 
				
			||||||
 | 
								data = sg_dma_address(sg);
 | 
				
			||||||
 | 
								this_sg_len = min_t(int, sg_dma_len(sg), len);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * URB_ZERO_PACKET means adding a 0-length packet, if direction
 | 
						 * URB_ZERO_PACKET means adding a 0-length packet, if direction
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue