ChangeSet 1.808.2.25, 2002/10/28 11:58:59-08:00, [EMAIL PROTECTED]
[PATCH] USB storage: use scatter-gather core primitives
This patch switches the usb-storage driver to using the new USB core
scatter-gather primitives. This _should_ create a significant performance
gain.
diff -Nru a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
--- a/drivers/usb/storage/transport.c Mon Oct 28 13:51:29 2002
+++ b/drivers/usb/storage/transport.c Mon Oct 28 13:51:29 2002
@@ -655,43 +655,107 @@
}
/*
+ * Transfer a scatter-gather list via bulk transfer
+ *
+ * This function does basically the same thing as usb_stor_bulk_transfer_buf()
+ * above, but it uses the usbcore scatter-gather primitives
+ */
+int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe,
+ struct scatterlist *sg, int num_sg, unsigned int length,
+ unsigned int *act_len)
+{
+ int result;
+ int partial;
+
+ /* initialize the scatter-gather request block */
+ US_DEBUGP("usb_stor_bulk_transfer_sglist(): xfer %d bytes, "
+ "%d entires\n", length, num_sg);
+ result = usb_sg_init(us->current_sg, us->pusb_dev, pipe, 0,
+ sg, num_sg, length, SLAB_NOIO);
+ if (result) {
+ US_DEBUGP("usb_sg_init returned %d\n", result);
+ return USB_STOR_XFER_ERROR;
+ }
+
+ /* since the block has been initialized successfully, it's now
+ * okay to cancel it */
+ set_bit(US_FLIDX_CANCEL_SG, &us->flags);
+
+ /* has the current command been aborted? */
+ if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
+
+ /* cancel the request, if it hasn't been cancelled already */
+ if (test_and_clear_bit(US_FLIDX_CANCEL_SG, &us->flags)) {
+ US_DEBUGP("-- cancelling sg request\n");
+ usb_sg_cancel(us->current_sg);
+ }
+ }
+
+ usb_sg_wait(us->current_sg);
+ clear_bit(US_FLIDX_CANCEL_SG, &us->flags);
+
+ result = us->current_sg->status;
+ partial = us->current_sg->bytes;
+ US_DEBUGP("usb_sg_wait() returned %d xferrerd %d/%d\n",
+ result, partial, length);
+ if (act_len)
+ *act_len = partial;
+
+ /* if we stall, we need to clear it before we go on */
+ if (result == -EPIPE) {
+ US_DEBUGP("clearing endpoint halt for pipe 0x%x,"
+ "stalled at %d bytes\n", pipe, partial);
+ if (usb_stor_clear_halt(us, pipe) < 0)
+ return USB_STOR_XFER_ERROR;
+ return USB_STOR_XFER_STALLED;
+ }
+
+ /* NAK - that means we've tried this a few times already */
+ if (result == -ETIMEDOUT) {
+ US_DEBUGP("-- device NAKed\n");
+ return USB_STOR_XFER_ERROR;
+ }
+
+ /* the catch-all error case */
+ if (result) {
+ US_DEBUGP("-- unknown error\n");
+ return USB_STOR_XFER_ERROR;
+ }
+
+ /* did we send all the data? */
+ if (partial == length) {
+ US_DEBUGP("-- transfer complete\n");
+ return USB_STOR_XFER_GOOD;
+ }
+
+ /* no error code, so we must have transferred some data,
+ * just not all of it */
+ US_DEBUGP("-- transferred only %d bytes\n", partial);
+ return USB_STOR_XFER_SHORT;
+}
+
+/*
* Transfer an entire SCSI command's worth of data payload over the bulk
* pipe.
*
- * Note that this uses usb_stor_bulk_transfer_buf to achieve its goals --
- * this function simply determines if we're going to use scatter-gather or not,
- * and acts appropriately.
+ * Nore that this uses the usb_stor_bulk_transfer_buf() and
+ * usb_stor_bulk_transfer_sglist() to achieve its goals --
+ * this function simply determines whether we're going to use
+ * scatter-gather or not, and acts apropriately.
*/
int usb_stor_bulk_transfer_sg(struct us_data* us, unsigned int pipe,
char *buf, unsigned int length_left, int use_sg, int *residual)
{
- int i;
- int result = USB_STOR_XFER_ERROR;
- struct scatterlist *sg;
- unsigned int amount;
+ int result;
unsigned int partial;
/* are we scatter-gathering? */
if (use_sg) {
-
- /* loop over all the scatter gather structures and
- * make the appropriate requests for each, until done
- */
- sg = (struct scatterlist *) buf;
- for (i = 0; (i < use_sg) && (length_left > 0); (i++, ++sg)) {
-
- /* transfer the lesser of the next buffer or the
- * remaining data */
- amount = sg->length < length_left ?
- sg->length : length_left;
- result = usb_stor_bulk_transfer_buf(us, pipe,
- sg_address(*sg), amount, &partial);
- length_left -= partial;
-
- /* if we get an error, end the loop here */
- if (result != USB_STOR_XFER_GOOD)
- break;
- }
+ /* use the usb core scatter-gather primitives */
+ result = usb_stor_bulk_transfer_sglist(us, pipe,
+ (struct scatterlist *) buf, use_sg,
+ length_left, &partial);
+ length_left -= partial;
} else {
/* no scatter-gather, just make the request */
result = usb_stor_bulk_transfer_buf(us, pipe, buf,
@@ -924,6 +988,12 @@
if (test_and_clear_bit(US_FLIDX_CAN_CANCEL, &us->flags)) {
US_DEBUGP("-- cancelling URB\n");
usb_unlink_urb(us->current_urb);
+ }
+
+ /* If we are waiting for a scatter-gather operation, cancel it. */
+ if (test_and_clear_bit(US_FLIDX_CANCEL_SG, &us->flags)) {
+ US_DEBUGP("-- cancelling sg request\n");
+ usb_sg_cancel(us->current_sg);
}
/* If we are waiting for an IRQ, simulate it */
diff -Nru a/drivers/usb/storage/transport.h b/drivers/usb/storage/transport.h
--- a/drivers/usb/storage/transport.h Mon Oct 28 13:51:29 2002
+++ b/drivers/usb/storage/transport.h Mon Oct 28 13:51:29 2002
@@ -164,6 +164,9 @@
void *data, u16 size);
extern int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe,
char *buf, unsigned int length, unsigned int *act_len);
+extern int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe,
+ struct scatterlist *sg, int num_sg, unsigned int length,
+ unsigned int *act_len);
extern int usb_stor_bulk_transfer_sg(struct us_data *us, unsigned int pipe,
char *buf, unsigned int length, int use_sg, int *residual);
diff -Nru a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
--- a/drivers/usb/storage/usb.c Mon Oct 28 13:51:29 2002
+++ b/drivers/usb/storage/usb.c Mon Oct 28 13:51:29 2002
@@ -547,6 +547,13 @@
return 2;
}
+ US_DEBUGP("Allocating scatter-gather request block\n");
+ ss->current_sg = kmalloc(sizeof(*ss->current_sg), GFP_KERNEL);
+ if (!ss->current_sg) {
+ US_DEBUGP("allocation failed\n");
+ return 5;
+ }
+
/* allocate the IRQ URB, if it is needed */
if (ss->protocol == US_PR_CBI) {
US_DEBUGP("Allocating IRQ for CBI transport\n");
@@ -606,6 +613,12 @@
ss->irq_urb = NULL;
}
up(&(ss->irq_urb_sem));
+
+ /* free the scatter-gather request block */
+ if (ss->current_sg) {
+ kfree(ss->current_sg);
+ ss->current_sg = NULL;
+ }
/* free up the main URB for this device */
if (ss->current_urb) {
diff -Nru a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
--- a/drivers/usb/storage/usb.h Mon Oct 28 13:51:29 2002
+++ b/drivers/usb/storage/usb.h Mon Oct 28 13:51:29 2002
@@ -107,6 +107,7 @@
#define US_FL_DEV_ATTACHED 0x00010000 /* is the device attached? */
#define US_FLIDX_IP_WANTED 17 /* 0x00020000 is an IRQ expected? */
#define US_FLIDX_CAN_CANCEL 18 /* 0x00040000 okay to cancel current_urb? */
+#define US_FLIDX_CANCEL_SG 19 /* 0x00080000 okay to cancel current_sg? */
/* processing state machine states */
@@ -184,6 +185,7 @@
/* control and bulk communications data */
struct urb *current_urb; /* non-int USB requests */
struct usb_ctrlrequest *dr; /* control requests */
+ struct usb_sg_request *current_sg; /* scatter-gather USB */
/* the semaphore for sleeping the control thread */
struct semaphore sema; /* to sleep thread on */
-------------------------------------------------------
This sf.net email is sponsored by:ThinkGeek
Welcome to geek heaven.
http://thinkgeek.com/sf
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel