[PATCH 100/122] USB: whci-hcd: correctly handle sg lists longer than QTD_MAX_XFER_SIZE.

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

 



From: David Vrabel <david.vrabel@xxxxxxx>

When building qTDs (sTDs) from a scatter-gather list, the length of the
qTD must be a multiple of wMaxPacketSize if the transfer continues into
another qTD.

This also fixes a link failure on configurations for 32 bit processors
with 64 bit dma_addr_t (e.g., CONFIG_HIGHMEM_64G).

Signed-off-by: David Vrabel <david.vrabel@xxxxxxx>
Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxx>
---
 drivers/usb/host/whci/qset.c |   22 +++++++++++-----------
 1 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/drivers/usb/host/whci/qset.c b/drivers/usb/host/whci/qset.c
index 39e855a..7d4204d 100644
--- a/drivers/usb/host/whci/qset.c
+++ b/drivers/usb/host/whci/qset.c
@@ -465,16 +465,16 @@ static int qset_add_urb_sg(struct whc *whc, struct whc_qset *qset, struct urb *u
 			 * - the previous one isn't full.
 			 *
 			 * If a new std is needed but the previous one
-			 * did not end on a wMaxPacketSize boundary
-			 * then this sg list cannot be mapped onto
-			 * multiple qTDs.  Return an error and let the
-			 * caller sort it out.
+			 * was not a whole number of packets then this
+			 * sg list cannot be mapped onto multiple
+			 * qTDs.  Return an error and let the caller
+			 * sort it out.
 			 */
 			if (!std
 			    || (prev_end & (WHCI_PAGE_SIZE-1))
 			    || (dma_addr & (WHCI_PAGE_SIZE-1))
 			    || std->len + WHCI_PAGE_SIZE > QTD_MAX_XFER_SIZE) {
-				if (prev_end % qset->max_packet != 0)
+				if (std->len % qset->max_packet != 0)
 					return -EINVAL;
 				std = qset_new_std(whc, qset, urb, mem_flags);
 				if (std == NULL) {
@@ -487,14 +487,14 @@ static int qset_add_urb_sg(struct whc *whc, struct whc_qset *qset, struct urb *u
 			dma_len = dma_remaining;
 
 			/*
-			 * If the remainder in this element doesn't
-			 * fit in a single qTD, end the qTD on a
-			 * wMaxPacketSize boundary.
+			 * If the remainder of this element doesn't
+			 * fit in a single qTD, limit the qTD to a
+			 * whole number of packets.  This allows the
+			 * remainder to go into the next qTD.
 			 */
 			if (std->len + dma_len > QTD_MAX_XFER_SIZE) {
-				dma_len = QTD_MAX_XFER_SIZE - std->len;
-				ep = ((dma_addr + dma_len) / qset->max_packet) * qset->max_packet;
-				dma_len = ep - dma_addr;
+				dma_len = (QTD_MAX_XFER_SIZE / qset->max_packet)
+					* qset->max_packet - std->len;
 			}
 
 			std->len += dma_len;
-- 
1.6.5.5

--
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