diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2014-07-17 22:30:01 +0200 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-07-18 01:59:27 +0200 |
commit | 6f65126c76e38e671c64ec171acff8a99c4de749 (patch) | |
tree | 63d0952c526d3a839dc87ffe4bcc1082c63378f0 /drivers/usb/host/ohci-hcd.c | |
parent | USB: shutdown all URBs after controller death (diff) | |
download | linux-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.c | 38 |
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; |