[PATCH] usb: wire adapter: add scatter gather support

2013-06-11 Thread Thomas Pugliese
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

2013-06-11 Thread Greg KH
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

2013-06-11 Thread Thomas Pugliese


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

2013-06-11 Thread Alan Stern
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

2013-06-11 Thread Thomas Pugliese


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

2013-06-11 Thread Alan Stern
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