[PATCH] USB: UHCI: add native scatter-gather support(v1)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Ming Lei <tom.leiming@xxxxxxxxx>

This patch adds native scatter-gather support to uhci-hcd.

Reviewed-by:   Alan Stern <stern@xxxxxxxxxxxxxxxxxxx>
Signed-off-by: Ming Lei <tom.leiming@xxxxxxxxx>
---
v1: some trivial fix on Alan's comment.
---
 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 d3ade40..51031c2 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
-- 
1.7.3

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux