[PATCH] usb: wire adapter: add scatter gather support
This patch adds support for scatter gather DMA to the wire adapter and updates the HWA to advertise support for SG transfers. This allows the block layer to submit transfer requests to the HWA HC without first breaking them up into PAGE_SIZE requests. Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com diff --git a/drivers/usb/host/hwa-hc.c b/drivers/usb/host/hwa-hc.c index c0df599..4af750e 100644 --- a/drivers/usb/host/hwa-hc.c +++ b/drivers/usb/host/hwa-hc.c @@ -774,6 +774,7 @@ static int hwahc_probe(struct usb_interface *usb_iface, goto error_alloc; } usb_hcd-wireless = 1; + usb_hcd-self.sg_tablesize = ~0; wusbhc = usb_hcd_to_wusbhc(usb_hcd); hwahc = container_of(wusbhc, struct hwahc, wusbhc); hwahc_init(hwahc); diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c index 6ef94bc..16968c8 100644 --- a/drivers/usb/wusbcore/wa-xfer.c +++ b/drivers/usb/wusbcore/wa-xfer.c @@ -85,6 +85,7 @@ #include linux/hash.h #include linux/ratelimit.h #include linux/export.h +#include linux/scatterlist.h #include wa-hc.h #include wusbhc.h @@ -442,8 +443,7 @@ static ssize_t __wa_xfer_setup_sizes(struct wa_xfer *xfer, goto error; } xfer-seg_size = (xfer-seg_size / maxpktsize) * maxpktsize; - xfer-segs = (urb-transfer_buffer_length + xfer-seg_size - 1) - / xfer-seg_size; + xfer-segs = DIV_ROUND_UP(urb-transfer_buffer_length, xfer-seg_size); if (xfer-segs = WA_SEGS_MAX) { dev_err(dev, BUG? ops, number of segments %d bigger than %d\n, (int)(urb-transfer_buffer_length / xfer-seg_size), @@ -627,6 +627,86 @@ static void wa_seg_cb(struct urb *urb) } } +/* allocate an SG list to store bytes_to_transfer bytes and copy the + * subset of the in_sg that matches the buffer subset + * we are about to transfer. */ +static struct scatterlist *wa_xfer_create_subset_sg(struct scatterlist *in_sg, + const unsigned int bytes_transferred, + const unsigned int bytes_to_transfer, unsigned int *out_num_sgs) +{ + struct scatterlist *out_sg; + unsigned int bytes_processed = 0, offset_into_current_page_data = 0, + nents; + struct scatterlist *current_xfer_sg = in_sg; + struct scatterlist *current_seg_sg, *last_seg_sg; + + /* skip previously transferred pages. */ + while ((current_xfer_sg) + (bytes_processed bytes_transferred)) { + bytes_processed += current_xfer_sg-length; + + /* advance the sg if current segment starts on or past the + next page. */ + if (bytes_processed = bytes_transferred) + current_xfer_sg = sg_next(current_xfer_sg); + } + + /* the data for the current segment starts in current_xfer_sg. + calculate the offset. */ + if (bytes_processed bytes_transferred) { + offset_into_current_page_data = current_xfer_sg-length - + (bytes_processed - bytes_transferred); + } + + /* calculate the number of pages needed by this segment. */ + nents = DIV_ROUND_UP((bytes_to_transfer + + offset_into_current_page_data + + current_xfer_sg-offset), + PAGE_SIZE); + + out_sg = kmalloc((sizeof(struct scatterlist) * nents), GFP_ATOMIC); + if (out_sg) { + sg_init_table(out_sg, nents); + + /* copy the portion of the incoming SG that correlates to the +* data to be transferred by this segment to the segment SG. */ + last_seg_sg = current_seg_sg = out_sg; + bytes_processed = 0; + + /* reset nents and calculate the actual number of sg entries + needed. */ + nents = 0; + while ((bytes_processed bytes_to_transfer) + current_seg_sg current_xfer_sg) { + unsigned int page_len = min((current_xfer_sg-length - + offset_into_current_page_data), + (bytes_to_transfer - bytes_processed)); + + sg_set_page(current_seg_sg, sg_page(current_xfer_sg), + page_len, + current_xfer_sg-offset + + offset_into_current_page_data); + + bytes_processed += page_len; + + last_seg_sg = current_seg_sg; + current_seg_sg = sg_next(current_seg_sg); + current_xfer_sg = sg_next(current_xfer_sg); + + /* only the first page may require additional offset. */ + offset_into_current_page_data = 0; + nents++; + } + + /* update num_sgs and terminate
Re: [PATCH] usb: wire adapter: add scatter gather support
On Tue, Jun 11, 2013 at 10:39:31AM -0500, Thomas Pugliese wrote: This patch adds support for scatter gather DMA to the wire adapter and Don't you mean wireless adapter? updates the HWA to advertise support for SG transfers. This allows the block layer to submit transfer requests to the HWA HC without first breaking them up into PAGE_SIZE requests. Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com Please cc: me on patches you want applied, so I don't loose them in the mailing list archives accidentally. thanks, greg k-h -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] usb: wire adapter: add scatter gather support
On Tue, 11 Jun 2013, Greg KH wrote: On Tue, Jun 11, 2013 at 10:39:31AM -0500, Thomas Pugliese wrote: This patch adds support for scatter gather DMA to the wire adapter and Don't you mean wireless adapter? The Wireless USB spec uses the term wire adapter to specify the means by which the USB protocol is tunnelled over Wireless USB. The wireless host controller is a host wire adapter (HWA) and the device-side of the link is a device wire adapter (DWA) if it allows wired USB devices to be plugged into it. updates the HWA to advertise support for SG transfers. This allows the block layer to submit transfer requests to the HWA HC without first breaking them up into PAGE_SIZE requests. Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com Please cc: me on patches you want applied, so I don't loose them in the mailing list archives accidentally. Will do. Thanks. thanks, greg k-h -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] usb: wire adapter: add scatter gather support
On Tue, 11 Jun 2013, Thomas Pugliese wrote: This patch adds support for scatter gather DMA to the wire adapter and updates the HWA to advertise support for SG transfers. This allows the block layer to submit transfer requests to the HWA HC without first breaking them up into PAGE_SIZE requests. While I do not really understand what is going on here, it nevertheless seems very peculiar. To begin with, whether or not the block layer breaks up transfers into PAGE_SIZE requests has no connection with SG. For another thing, the patch has the HCD creating an SG list. That's not how things work -- the HCD _receives_ the SG list attached to an URB. I'm not sure what problem this patch is intended to solve. Can you explain in more detail? Alan Stern -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] usb: wire adapter: add scatter gather support
On Tue, 11 Jun 2013, Alan Stern wrote: On Tue, 11 Jun 2013, Thomas Pugliese wrote: This patch adds support for scatter gather DMA to the wire adapter and updates the HWA to advertise support for SG transfers. This allows the block layer to submit transfer requests to the HWA HC without first breaking them up into PAGE_SIZE requests. While I do not really understand what is going on here, it nevertheless seems very peculiar. To begin with, whether or not the block layer breaks up transfers into PAGE_SIZE requests has no connection with SG. For another thing, the patch has the HCD creating an SG list. That's not how things work -- the HCD _receives_ the SG list attached to an URB. I'm not sure what problem this patch is intended to solve. Can you explain in more detail? Alan Stern Sure. The HWA is a USB connected wireless HCD so the HWA driver communicates with the hardware by sending URBs instead of using mapped memory regions like *HCI devices. There is not necessarily a 1 to 1 correlation between the URBs that come in to the driver and URBs that get forwarded down the stack as HCD commands since there is some encapsulation and segmentation that may be done. Once SG support is enabled in the HWA, the driver now needs to create SGs for the URBs it sends down the stack. In the case of a buffer read URB, it looks like this: 1. The HWA HCD receives a read URB addressed to a device connected wirelessly downstream of the HWA. 2. The HWA driver creates an internal URB to send a Transfer Request command to the HWA on its bulk out endpoint that requests some or all of the data associated with the user's URB. This is analagous to filling in a qTD in EHCI. 3. The HWA driver creates another interal URB to read the Transfer Results back from the HWA's bulk in endpoint. 4. Based on the contents of the Transfer Result. The HWA driver submits a bulk in URB to read the actual data received from the device into the user's buffer. Depending on the amount of data associated with the user's URB, steps 2-4 may be iterated over multiple times due to the limited internal memory of the HWA. My patch updates step 4 to handle URBs that have SGs associated with them. The URB submitted in step 4 will need to include an SG that represents the portion of the origial URB buffer that it is currently reading from the HWA. Tom -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] usb: wire adapter: add scatter gather support
On Tue, 11 Jun 2013, Thomas Pugliese wrote: On Tue, 11 Jun 2013, Alan Stern wrote: On Tue, 11 Jun 2013, Thomas Pugliese wrote: This patch adds support for scatter gather DMA to the wire adapter and updates the HWA to advertise support for SG transfers. This allows the block layer to submit transfer requests to the HWA HC without first breaking them up into PAGE_SIZE requests. While I do not really understand what is going on here, it nevertheless seems very peculiar. To begin with, whether or not the block layer breaks up transfers into PAGE_SIZE requests has no connection with SG. For another thing, the patch has the HCD creating an SG list. That's not how things work -- the HCD _receives_ the SG list attached to an URB. I'm not sure what problem this patch is intended to solve. Can you explain in more detail? Alan Stern Sure. The HWA is a USB connected wireless HCD so the HWA driver communicates with the hardware by sending URBs instead of using mapped memory regions like *HCI devices. There is not necessarily a 1 to 1 correlation between the URBs that come in to the driver and URBs that get forwarded down the stack as HCD commands since there is some encapsulation and segmentation that may be done. Once SG support is enabled in the HWA, the driver now needs to create SGs for the URBs it sends down the stack. In the case of a buffer read URB, it looks like this: 1. The HWA HCD receives a read URB addressed to a device connected wirelessly downstream of the HWA. 2. The HWA driver creates an internal URB to send a Transfer Request command to the HWA on its bulk out endpoint that requests some or all of the data associated with the user's URB. This is analagous to filling in a qTD in EHCI. 3. The HWA driver creates another interal URB to read the Transfer Results back from the HWA's bulk in endpoint. 4. Based on the contents of the Transfer Result. The HWA driver submits a bulk in URB to read the actual data received from the device into the user's buffer. Depending on the amount of data associated with the user's URB, steps 2-4 may be iterated over multiple times due to the limited internal memory of the HWA. My patch updates step 4 to handle URBs that have SGs associated with them. The URB submitted in step 4 will need to include an SG that represents the portion of the origial URB buffer that it is currently reading from the HWA. I see. Thanks for the explanation. Things do get confusing when you have a USB-connected host controller! Alan Stern -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html