diff options
author | Per Forlin <per.forlin@linaro.org> | 2011-08-19 23:21:27 +0400 |
---|---|---|
committer | Felipe Balbi <balbi@ti.com> | 2011-09-09 14:06:04 +0400 |
commit | 6532c7fdb2c3a2ec1b949ecd2ff5375069c1639a (patch) | |
tree | 26afd8fdff7923f818f49aa405bb4208d1da914e /drivers/usb/gadget/file_storage.c | |
parent | 04eee25b1d754a837360504b7af426d1f86ffeb7 (diff) | |
download | linux-6532c7fdb2c3a2ec1b949ecd2ff5375069c1639a.tar.xz |
usb: gadget: storage: make FSG_NUM_BUFFERS variable size
FSG_NUM_BUFFERS is set to 2 as default.
Usually 2 buffers are enough to establish a good buffering pipeline.
The number may be increased in order to compensate a for bursty VFS
behaviour.
Here follows a description of system that may require more than
2 buffers.
* CPU ondemand governor active
* latency cost for wake up and/or frequency change
* DMA for IO
Use case description.
* Data transfer from MMC via VFS to USB.
* DMA shuffles data from MMC and to USB.
* The CPU wakes up every now and then to pass data in and out from VFS,
which cause the bursty VFS behaviour.
Test set up
* Running dd on the host reading from the mass storage device
* cmdline: dd if=/dev/sdb of=/dev/null bs=4k count=$((256*100))
* Caches are dropped on the host and on the device before each run
Measurements on a Snowball board with ondemand_governor active.
FSG_NUM_BUFFERS 2
104857600 bytes (105 MB) copied, 5.62173 s, 18.7 MB/s
104857600 bytes (105 MB) copied, 5.61811 s, 18.7 MB/s
104857600 bytes (105 MB) copied, 5.57817 s, 18.8 MB/s
FSG_NUM_BUFFERS 4
104857600 bytes (105 MB) copied, 5.26839 s, 19.9 MB/s
104857600 bytes (105 MB) copied, 5.2691 s, 19.9 MB/s
104857600 bytes (105 MB) copied, 5.2711 s, 19.9 MB/s
There may not be one optimal number for all boards. This is why
the number is added to Kconfig. If selecting USB_GADGET_DEBUG_FILES
this value may be set by a module parameter as well.
Signed-off-by: Per Forlin <per.forlin@linaro.org>
Acked-by: Michal Nazarewicz <mina86@mina86.com>
Acked-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/gadget/file_storage.c')
-rw-r--r-- | drivers/usb/gadget/file_storage.c | 27 |
1 files changed, 17 insertions, 10 deletions
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index c6f96a2b3110..4b9797d07a67 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c @@ -460,7 +460,6 @@ struct fsg_dev { struct fsg_buffhd *next_buffhd_to_fill; struct fsg_buffhd *next_buffhd_to_drain; - struct fsg_buffhd buffhds[FSG_NUM_BUFFERS]; int thread_wakeup_needed; struct completion thread_notifier; @@ -487,6 +486,8 @@ struct fsg_dev { unsigned int nluns; struct fsg_lun *luns; struct fsg_lun *curlun; + /* Must be the last entry */ + struct fsg_buffhd buffhds[]; }; typedef void (*fsg_routine_t)(struct fsg_dev *); @@ -2737,7 +2738,7 @@ static int do_set_interface(struct fsg_dev *fsg, int altsetting) reset: /* Deallocate the requests */ - for (i = 0; i < FSG_NUM_BUFFERS; ++i) { + for (i = 0; i < fsg_num_buffers; ++i) { struct fsg_buffhd *bh = &fsg->buffhds[i]; if (bh->inreq) { @@ -2798,7 +2799,7 @@ reset: } /* Allocate the requests */ - for (i = 0; i < FSG_NUM_BUFFERS; ++i) { + for (i = 0; i < fsg_num_buffers; ++i) { struct fsg_buffhd *bh = &fsg->buffhds[i]; if ((rc = alloc_request(fsg, fsg->bulk_in, &bh->inreq)) != 0) @@ -2894,7 +2895,7 @@ static void handle_exception(struct fsg_dev *fsg) /* Cancel all the pending transfers */ if (fsg->intreq_busy) usb_ep_dequeue(fsg->intr_in, fsg->intreq); - for (i = 0; i < FSG_NUM_BUFFERS; ++i) { + for (i = 0; i < fsg_num_buffers; ++i) { bh = &fsg->buffhds[i]; if (bh->inreq_busy) usb_ep_dequeue(fsg->bulk_in, bh->inreq); @@ -2905,7 +2906,7 @@ static void handle_exception(struct fsg_dev *fsg) /* Wait until everything is idle */ for (;;) { num_active = fsg->intreq_busy; - for (i = 0; i < FSG_NUM_BUFFERS; ++i) { + for (i = 0; i < fsg_num_buffers; ++i) { bh = &fsg->buffhds[i]; num_active += bh->inreq_busy + bh->outreq_busy; } @@ -2927,7 +2928,7 @@ static void handle_exception(struct fsg_dev *fsg) * state, and the exception. Then invoke the handler. */ spin_lock_irq(&fsg->lock); - for (i = 0; i < FSG_NUM_BUFFERS; ++i) { + for (i = 0; i < fsg_num_buffers; ++i) { bh = &fsg->buffhds[i]; bh->state = BUF_STATE_EMPTY; } @@ -3157,7 +3158,7 @@ static void /* __init_or_exit */ fsg_unbind(struct usb_gadget *gadget) } /* Free the data buffers */ - for (i = 0; i < FSG_NUM_BUFFERS; ++i) + for (i = 0; i < fsg_num_buffers; ++i) kfree(fsg->buffhds[i].buf); /* Free the request and buffer for endpoint 0 */ @@ -3445,7 +3446,7 @@ static int __init fsg_bind(struct usb_gadget *gadget) req->complete = ep0_complete; /* Allocate the data buffers */ - for (i = 0; i < FSG_NUM_BUFFERS; ++i) { + for (i = 0; i < fsg_num_buffers; ++i) { struct fsg_buffhd *bh = &fsg->buffhds[i]; /* Allocate for the bulk-in endpoint. We assume that @@ -3456,7 +3457,7 @@ static int __init fsg_bind(struct usb_gadget *gadget) goto out; bh->next = bh + 1; } - fsg->buffhds[FSG_NUM_BUFFERS - 1].next = &fsg->buffhds[0]; + fsg->buffhds[fsg_num_buffers - 1].next = &fsg->buffhds[0]; /* This should reflect the actual gadget power source */ usb_gadget_set_selfpowered(gadget); @@ -3572,7 +3573,9 @@ static int __init fsg_alloc(void) { struct fsg_dev *fsg; - fsg = kzalloc(sizeof *fsg, GFP_KERNEL); + fsg = kzalloc(sizeof *fsg + + fsg_num_buffers * sizeof *(fsg->buffhds), GFP_KERNEL); + if (!fsg) return -ENOMEM; spin_lock_init(&fsg->lock); @@ -3590,6 +3593,10 @@ static int __init fsg_init(void) int rc; struct fsg_dev *fsg; + rc = fsg_num_buffers_validate(); + if (rc != 0) + return rc; + if ((rc = fsg_alloc()) != 0) return rc; fsg = the_fsg; |