diff options
| author | Ming Lei <tom.leiming@gmail.com> | 2010-09-30 20:32:44 +0800 | 
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-10-22 10:22:00 -0700 | 
| commit | 689d6eacd1b7c3677bfe6ee367766f21c3c80e26 (patch) | |
| tree | 2524c96c3e6dbd6244292a2a4d0ba769564d5ecf /drivers/usb/host/uhci-q.c | |
| parent | 00be545e49d83485d49a598d3b7e090088934be8 (diff) | |
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>
Diffstat (limited to 'drivers/usb/host/uhci-q.c')
| -rw-r--r-- | drivers/usb/host/uhci-q.c | 33 | 
1 files changed, 29 insertions, 4 deletions
| diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index d3ade4018487..2090b45eb606 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c @@ -917,10 +917,13 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb,  	unsigned long destination, status;  	int maxsze = le16_to_cpu(qh->hep->desc.wMaxPacketSize);  	int len = urb->transfer_buffer_length; -	dma_addr_t data = urb->transfer_dma; +	int this_sg_len; +	dma_addr_t data;  	__le32 *plink;  	struct urb_priv *urbp = urb->hcpriv;  	unsigned int toggle; +	struct scatterlist  *sg; +	int i;  	if (len < 0)  		return -EINVAL; @@ -937,12 +940,26 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb,  	if (usb_pipein(urb->pipe))  		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  	 */  	plink = NULL;  	td = qh->dummy_td; -	do {	/* Allow zero length packets */ +	for (;;) {	/* Allow zero length packets */  		int pktsze = maxsze;  		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;  		status |= TD_CTRL_ACTIVE; +		toggle ^= 1;  		data += pktsze; +		this_sg_len -= pktsze;  		len -= maxsze; -		toggle ^= 1; -	} while (len > 0); +		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 | 
