summaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/ohci-hcd.c
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2014-07-17 22:30:01 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-07-18 01:59:27 +0200
commit6f65126c76e38e671c64ec171acff8a99c4de749 (patch)
tree63d0952c526d3a839dc87ffe4bcc1082c63378f0 /drivers/usb/host/ohci-hcd.c
parentUSB: shutdown all URBs after controller death (diff)
downloadlinux-6f65126c76e38e671c64ec171acff8a99c4de749.tar.xz
linux-6f65126c76e38e671c64ec171acff8a99c4de749.zip
USB: OHCI: add SG support
Apparently nobody ever remembered to add Scatter-Gather support to ohci-hcd. This patch adds it. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/host/ohci-hcd.c')
-rw-r--r--drivers/usb/host/ohci-hcd.c38
1 files changed, 32 insertions, 6 deletions
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index 6f8ec52c7e0c..7f94c586c5dc 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -109,6 +109,33 @@ MODULE_PARM_DESC (no_handshake, "true (not default) disables BIOS handshake");
/*-------------------------------------------------------------------------*/
+static int number_of_tds(struct urb *urb)
+{
+ int len, i, num, this_sg_len;
+ struct scatterlist *sg;
+
+ len = urb->transfer_buffer_length;
+ i = urb->num_mapped_sgs;
+
+ if (len > 0 && i > 0) { /* Scatter-gather transfer */
+ num = 0;
+ sg = urb->sg;
+ for (;;) {
+ this_sg_len = min_t(int, sg_dma_len(sg), len);
+ num += DIV_ROUND_UP(this_sg_len, 4096);
+ len -= this_sg_len;
+ if (--i <= 0 || len <= 0)
+ break;
+ sg = sg_next(sg);
+ }
+
+ } else { /* Non-SG transfer */
+ /* one TD for every 4096 Bytes (could be up to 8K) */
+ num = DIV_ROUND_UP(len, 4096);
+ }
+ return num;
+}
+
/*
* queue up an urb for anything except the root hub
*/
@@ -142,12 +169,8 @@ static int ohci_urb_enqueue (
// case PIPE_INTERRUPT:
// case PIPE_BULK:
default:
- /* one TD for every 4096 Bytes (can be up to 8K) */
- size += urb->transfer_buffer_length / 4096;
- /* ... and for any remaining bytes ... */
- if ((urb->transfer_buffer_length % 4096) != 0)
- size++;
- /* ... and maybe a zero length packet to wrap it up */
+ size += number_of_tds(urb);
+ /* maybe a zero-length packet to wrap it up */
if (size == 0)
size++;
else if ((urb->transfer_flags & URB_ZERO_PACKET) != 0
@@ -506,6 +529,9 @@ static int ohci_init (struct ohci_hcd *ohci)
int ret;
struct usb_hcd *hcd = ohci_to_hcd(ohci);
+ /* Accept arbitrarily long scatter-gather lists */
+ hcd->self.sg_tablesize = ~0;
+
if (distrust_firmware)
ohci->flags |= OHCI_QUIRK_HUB_POWER;