aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget/file_storage.c
diff options
context:
space:
mode:
authorAndy Shevchenko <andy.shevchenko@gmail.com>2010-07-22 10:53:56 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2010-08-10 17:35:42 -0400
commita93917d39fc388c4761d2530af82513e2d3bf9f6 (patch)
tree0e2f7bed30b16c70a2f71951adfadeab7a29a4a8 /drivers/usb/gadget/file_storage.c
parent8156d158efa6370a8183f47327f122edbb4f2cb6 (diff)
USB: gadget: storage: optional SCSI WRITE FUA bit
MS Windows mounts removable storage in "Removal optimized mode" by default. All the writes to the media are synchronous which is achieved by setting FUA (Force Unit Access) bit in SCSI WRITE(10,12) commands. This prevents I/O requests aggregation in block layer dramatically decreasing performance. This patch brings an option to accept or ignore mentioned bit a) via specifying module parameter "nofua", or b) through sysfs entry /sys/devices/platform/_UDC_/gadget/gadget-lunX/nofua (_UDC_ is the name of the USB Device Controller driver) Patch is based on the work that was done by Denis Karpov for Maemo 5 platform. Signed-off-by: Andy Shevchenko <ext-andriy.shevchenko@nokia.com> Acked-by: Alan Stern <stern@rowland.harvard.edu> Cc: Denis Karpov <ext-denis.2.karpov@nokia.com> Cc: Adrian Hunter <adrian.hunter@nokia.com> Cc: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/gadget/file_storage.c')
-rw-r--r--drivers/usb/gadget/file_storage.c31
1 files changed, 24 insertions, 7 deletions
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index d57c09f764d6..88e5ad2bc710 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -93,6 +93,8 @@
93 * removable Default false, boolean for removable media 93 * removable Default false, boolean for removable media
94 * luns=N Default N = number of filenames, number of 94 * luns=N Default N = number of filenames, number of
95 * LUNs to support 95 * LUNs to support
96 * nofua=b[,b...] Default false, booleans for ignore FUA flag
97 * in SCSI WRITE(10,12) commands
96 * stall Default determined according to the type of 98 * stall Default determined according to the type of
97 * USB device controller (usually true), 99 * USB device controller (usually true),
98 * boolean to permit the driver to halt 100 * boolean to permit the driver to halt
@@ -112,12 +114,12 @@
112 * PAGE_CACHE_SIZE) 114 * PAGE_CACHE_SIZE)
113 * 115 *
114 * If CONFIG_USB_FILE_STORAGE_TEST is not set, only the "file", "ro", 116 * If CONFIG_USB_FILE_STORAGE_TEST is not set, only the "file", "ro",
115 * "removable", "luns", "stall", and "cdrom" options are available; default 117 * "removable", "luns", "nofua", "stall", and "cdrom" options are available;
116 * values are used for everything else. 118 * default values are used for everything else.
117 * 119 *
118 * The pathnames of the backing files and the ro settings are available in 120 * The pathnames of the backing files and the ro settings are available in
119 * the attribute files "file" and "ro" in the lun<n> subdirectory of the 121 * the attribute files "file", "nofua", and "ro" in the lun<n> subdirectory of
120 * gadget's sysfs directory. If the "removable" option is set, writing to 122 * the gadget's sysfs directory. If the "removable" option is set, writing to
121 * these files will simulate ejecting/loading the medium (writing an empty 123 * these files will simulate ejecting/loading the medium (writing an empty
122 * line means eject) and adjusting a write-enable tab. Changes to the ro 124 * line means eject) and adjusting a write-enable tab. Changes to the ro
123 * setting are not allowed when the medium is loaded or if CD-ROM emulation 125 * setting are not allowed when the medium is loaded or if CD-ROM emulation
@@ -304,8 +306,10 @@ MODULE_LICENSE("Dual BSD/GPL");
304static struct { 306static struct {
305 char *file[FSG_MAX_LUNS]; 307 char *file[FSG_MAX_LUNS];
306 int ro[FSG_MAX_LUNS]; 308 int ro[FSG_MAX_LUNS];
309 int nofua[FSG_MAX_LUNS];
307 unsigned int num_filenames; 310 unsigned int num_filenames;
308 unsigned int num_ros; 311 unsigned int num_ros;
312 unsigned int num_nofuas;
309 unsigned int nluns; 313 unsigned int nluns;
310 314
311 int removable; 315 int removable;
@@ -345,6 +349,10 @@ MODULE_PARM_DESC(file, "names of backing files or devices");
345module_param_array_named(ro, mod_data.ro, bool, &mod_data.num_ros, S_IRUGO); 349module_param_array_named(ro, mod_data.ro, bool, &mod_data.num_ros, S_IRUGO);
346MODULE_PARM_DESC(ro, "true to force read-only"); 350MODULE_PARM_DESC(ro, "true to force read-only");
347 351
352module_param_array_named(nofua, mod_data.nofua, bool, &mod_data.num_nofuas,
353 S_IRUGO);
354MODULE_PARM_DESC(nofua, "true to ignore SCSI WRITE(10,12) FUA bit");
355
348module_param_named(luns, mod_data.nluns, uint, S_IRUGO); 356module_param_named(luns, mod_data.nluns, uint, S_IRUGO);
349MODULE_PARM_DESC(luns, "number of LUNs"); 357MODULE_PARM_DESC(luns, "number of LUNs");
350 358
@@ -1279,7 +1287,8 @@ static int do_write(struct fsg_dev *fsg)
1279 curlun->sense_data = SS_INVALID_FIELD_IN_CDB; 1287 curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
1280 return -EINVAL; 1288 return -EINVAL;
1281 } 1289 }
1282 if (fsg->cmnd[1] & 0x08) { // FUA 1290 /* FUA */
1291 if (!curlun->nofua && (fsg->cmnd[1] & 0x08)) {
1283 spin_lock(&curlun->filp->f_lock); 1292 spin_lock(&curlun->filp->f_lock);
1284 curlun->filp->f_flags |= O_DSYNC; 1293 curlun->filp->f_flags |= O_DSYNC;
1285 spin_unlock(&curlun->filp->f_lock); 1294 spin_unlock(&curlun->filp->f_lock);
@@ -3133,6 +3142,7 @@ static int fsg_main_thread(void *fsg_)
3133 3142
3134/* The write permissions and store_xxx pointers are set in fsg_bind() */ 3143/* The write permissions and store_xxx pointers are set in fsg_bind() */
3135static DEVICE_ATTR(ro, 0444, fsg_show_ro, NULL); 3144static DEVICE_ATTR(ro, 0444, fsg_show_ro, NULL);
3145static DEVICE_ATTR(nofua, 0644, fsg_show_nofua, NULL);
3136static DEVICE_ATTR(file, 0444, fsg_show_file, NULL); 3146static DEVICE_ATTR(file, 0444, fsg_show_file, NULL);
3137 3147
3138 3148
@@ -3362,6 +3372,10 @@ static int __ref fsg_bind(struct usb_gadget *gadget)
3362 } 3372 }
3363 } 3373 }
3364 3374
3375 /* Only for removable media? */
3376 dev_attr_nofua.attr.mode = 0644;
3377 dev_attr_nofua.store = fsg_store_nofua;
3378
3365 /* Find out how many LUNs there should be */ 3379 /* Find out how many LUNs there should be */
3366 i = mod_data.nluns; 3380 i = mod_data.nluns;
3367 if (i == 0) 3381 if (i == 0)
@@ -3387,6 +3401,7 @@ static int __ref fsg_bind(struct usb_gadget *gadget)
3387 curlun->ro = mod_data.cdrom || mod_data.ro[i]; 3401 curlun->ro = mod_data.cdrom || mod_data.ro[i];
3388 curlun->initially_ro = curlun->ro; 3402 curlun->initially_ro = curlun->ro;
3389 curlun->removable = mod_data.removable; 3403 curlun->removable = mod_data.removable;
3404 curlun->nofua = mod_data.nofua[i];
3390 curlun->dev.release = lun_release; 3405 curlun->dev.release = lun_release;
3391 curlun->dev.parent = &gadget->dev; 3406 curlun->dev.parent = &gadget->dev;
3392 curlun->dev.driver = &fsg_driver.driver; 3407 curlun->dev.driver = &fsg_driver.driver;
@@ -3401,6 +3416,8 @@ static int __ref fsg_bind(struct usb_gadget *gadget)
3401 if ((rc = device_create_file(&curlun->dev, 3416 if ((rc = device_create_file(&curlun->dev,
3402 &dev_attr_ro)) != 0 || 3417 &dev_attr_ro)) != 0 ||
3403 (rc = device_create_file(&curlun->dev, 3418 (rc = device_create_file(&curlun->dev,
3419 &dev_attr_nofua)) != 0 ||
3420 (rc = device_create_file(&curlun->dev,
3404 &dev_attr_file)) != 0) { 3421 &dev_attr_file)) != 0) {
3405 device_unregister(&curlun->dev); 3422 device_unregister(&curlun->dev);
3406 goto out; 3423 goto out;
@@ -3525,8 +3542,8 @@ static int __ref fsg_bind(struct usb_gadget *gadget)
3525 if (IS_ERR(p)) 3542 if (IS_ERR(p))
3526 p = NULL; 3543 p = NULL;
3527 } 3544 }
3528 LINFO(curlun, "ro=%d, file: %s\n", 3545 LINFO(curlun, "ro=%d, nofua=%d, file: %s\n",
3529 curlun->ro, (p ? p : "(error)")); 3546 curlun->ro, curlun->nofua, (p ? p : "(error)"));
3530 } 3547 }
3531 } 3548 }
3532 kfree(pathbuf); 3549 kfree(pathbuf);