aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget/f_mass_storage.c
diff options
context:
space:
mode:
authorPer Forlin <per.forlin@linaro.org>2011-08-19 15:21:27 -0400
committerFelipe Balbi <balbi@ti.com>2011-09-09 06:06:04 -0400
commit6532c7fdb2c3a2ec1b949ecd2ff5375069c1639a (patch)
tree26afd8fdff7923f818f49aa405bb4208d1da914e /drivers/usb/gadget/f_mass_storage.c
parent04eee25b1d754a837360504b7af426d1f86ffeb7 (diff)
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/f_mass_storage.c')
-rw-r--r--drivers/usb/gadget/f_mass_storage.c29
1 files changed, 21 insertions, 8 deletions
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c
index 4306a8339487..756941473148 100644
--- a/drivers/usb/gadget/f_mass_storage.c
+++ b/drivers/usb/gadget/f_mass_storage.c
@@ -362,7 +362,7 @@ struct fsg_common {
362 362
363 struct fsg_buffhd *next_buffhd_to_fill; 363 struct fsg_buffhd *next_buffhd_to_fill;
364 struct fsg_buffhd *next_buffhd_to_drain; 364 struct fsg_buffhd *next_buffhd_to_drain;
365 struct fsg_buffhd buffhds[FSG_NUM_BUFFERS]; 365 struct fsg_buffhd *buffhds;
366 366
367 int cmnd_size; 367 int cmnd_size;
368 u8 cmnd[MAX_COMMAND_SIZE]; 368 u8 cmnd[MAX_COMMAND_SIZE];
@@ -2340,7 +2340,7 @@ reset:
2340 if (common->fsg) { 2340 if (common->fsg) {
2341 fsg = common->fsg; 2341 fsg = common->fsg;
2342 2342
2343 for (i = 0; i < FSG_NUM_BUFFERS; ++i) { 2343 for (i = 0; i < fsg_num_buffers; ++i) {
2344 struct fsg_buffhd *bh = &common->buffhds[i]; 2344 struct fsg_buffhd *bh = &common->buffhds[i];
2345 2345
2346 if (bh->inreq) { 2346 if (bh->inreq) {
@@ -2397,7 +2397,7 @@ reset:
2397 clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags); 2397 clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags);
2398 2398
2399 /* Allocate the requests */ 2399 /* Allocate the requests */
2400 for (i = 0; i < FSG_NUM_BUFFERS; ++i) { 2400 for (i = 0; i < fsg_num_buffers; ++i) {
2401 struct fsg_buffhd *bh = &common->buffhds[i]; 2401 struct fsg_buffhd *bh = &common->buffhds[i];
2402 2402
2403 rc = alloc_request(common, fsg->bulk_in, &bh->inreq); 2403 rc = alloc_request(common, fsg->bulk_in, &bh->inreq);
@@ -2466,7 +2466,7 @@ static void handle_exception(struct fsg_common *common)
2466 2466
2467 /* Cancel all the pending transfers */ 2467 /* Cancel all the pending transfers */
2468 if (likely(common->fsg)) { 2468 if (likely(common->fsg)) {
2469 for (i = 0; i < FSG_NUM_BUFFERS; ++i) { 2469 for (i = 0; i < fsg_num_buffers; ++i) {
2470 bh = &common->buffhds[i]; 2470 bh = &common->buffhds[i];
2471 if (bh->inreq_busy) 2471 if (bh->inreq_busy)
2472 usb_ep_dequeue(common->fsg->bulk_in, bh->inreq); 2472 usb_ep_dequeue(common->fsg->bulk_in, bh->inreq);
@@ -2478,7 +2478,7 @@ static void handle_exception(struct fsg_common *common)
2478 /* Wait until everything is idle */ 2478 /* Wait until everything is idle */
2479 for (;;) { 2479 for (;;) {
2480 int num_active = 0; 2480 int num_active = 0;
2481 for (i = 0; i < FSG_NUM_BUFFERS; ++i) { 2481 for (i = 0; i < fsg_num_buffers; ++i) {
2482 bh = &common->buffhds[i]; 2482 bh = &common->buffhds[i];
2483 num_active += bh->inreq_busy + bh->outreq_busy; 2483 num_active += bh->inreq_busy + bh->outreq_busy;
2484 } 2484 }
@@ -2501,7 +2501,7 @@ static void handle_exception(struct fsg_common *common)
2501 */ 2501 */
2502 spin_lock_irq(&common->lock); 2502 spin_lock_irq(&common->lock);
2503 2503
2504 for (i = 0; i < FSG_NUM_BUFFERS; ++i) { 2504 for (i = 0; i < fsg_num_buffers; ++i) {
2505 bh = &common->buffhds[i]; 2505 bh = &common->buffhds[i];
2506 bh->state = BUF_STATE_EMPTY; 2506 bh->state = BUF_STATE_EMPTY;
2507 } 2507 }
@@ -2710,6 +2710,10 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common,
2710 int nluns, i, rc; 2710 int nluns, i, rc;
2711 char *pathbuf; 2711 char *pathbuf;
2712 2712
2713 rc = fsg_num_buffers_validate();
2714 if (rc != 0)
2715 return ERR_PTR(rc);
2716
2713 /* Find out how many LUNs there should be */ 2717 /* Find out how many LUNs there should be */
2714 nluns = cfg->nluns; 2718 nluns = cfg->nluns;
2715 if (nluns < 1 || nluns > FSG_MAX_LUNS) { 2719 if (nluns < 1 || nluns > FSG_MAX_LUNS) {
@@ -2728,6 +2732,14 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common,
2728 common->free_storage_on_release = 0; 2732 common->free_storage_on_release = 0;
2729 } 2733 }
2730 2734
2735 common->buffhds = kcalloc(fsg_num_buffers,
2736 sizeof *(common->buffhds), GFP_KERNEL);
2737 if (!common->buffhds) {
2738 if (common->free_storage_on_release)
2739 kfree(common);
2740 return ERR_PTR(-ENOMEM);
2741 }
2742
2731 common->ops = cfg->ops; 2743 common->ops = cfg->ops;
2732 common->private_data = cfg->private_data; 2744 common->private_data = cfg->private_data;
2733 2745
@@ -2805,7 +2817,7 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common,
2805 2817
2806 /* Data buffers cyclic list */ 2818 /* Data buffers cyclic list */
2807 bh = common->buffhds; 2819 bh = common->buffhds;
2808 i = FSG_NUM_BUFFERS; 2820 i = fsg_num_buffers;
2809 goto buffhds_first_it; 2821 goto buffhds_first_it;
2810 do { 2822 do {
2811 bh->next = bh + 1; 2823 bh->next = bh + 1;
@@ -2931,12 +2943,13 @@ static void fsg_common_release(struct kref *ref)
2931 2943
2932 { 2944 {
2933 struct fsg_buffhd *bh = common->buffhds; 2945 struct fsg_buffhd *bh = common->buffhds;
2934 unsigned i = FSG_NUM_BUFFERS; 2946 unsigned i = fsg_num_buffers;
2935 do { 2947 do {
2936 kfree(bh->buf); 2948 kfree(bh->buf);
2937 } while (++bh, --i); 2949 } while (++bh, --i);
2938 } 2950 }
2939 2951
2952 kfree(common->buffhds);
2940 if (common->free_storage_on_release) 2953 if (common->free_storage_on_release)
2941 kfree(common); 2954 kfree(common);
2942} 2955}