aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--Documentation/ABI/testing/sysfs-devices-platform-_UDC_-gadget12
-rw-r--r--drivers/usb/gadget/file_storage.c31
-rw-r--r--drivers/usb/gadget/storage_common.c28
3 files changed, 64 insertions, 7 deletions
diff --git a/Documentation/ABI/testing/sysfs-devices-platform-_UDC_-gadget b/Documentation/ABI/testing/sysfs-devices-platform-_UDC_-gadget
index 34034027b13c..d548eaac230a 100644
--- a/Documentation/ABI/testing/sysfs-devices-platform-_UDC_-gadget
+++ b/Documentation/ABI/testing/sysfs-devices-platform-_UDC_-gadget
@@ -7,3 +7,15 @@ Description:
7 0 -> resumed 7 0 -> resumed
8 8
9 (_UDC_ is the name of the USB Device Controller driver) 9 (_UDC_ is the name of the USB Device Controller driver)
10
11What: /sys/devices/platform/_UDC_/gadget/gadget-lunX/nofua
12Date: July 2010
13Contact: Andy Shevchenko <andy.shevchenko@gmail.com>
14Description:
15 Show or set the reaction on the FUA (Force Unit Access) bit in
16 the SCSI WRITE(10,12) commands when a gadget in USB Mass
17 Storage mode.
18
19 Possible values are:
20 1 -> ignore the FUA flag
21 0 -> obey the FUA flag
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);
diff --git a/drivers/usb/gadget/storage_common.c b/drivers/usb/gadget/storage_common.c
index 3bbddab72e57..484acfb1a7c5 100644
--- a/drivers/usb/gadget/storage_common.c
+++ b/drivers/usb/gadget/storage_common.c
@@ -284,6 +284,7 @@ struct fsg_lun {
284 unsigned int prevent_medium_removal:1; 284 unsigned int prevent_medium_removal:1;
285 unsigned int registered:1; 285 unsigned int registered:1;
286 unsigned int info_valid:1; 286 unsigned int info_valid:1;
287 unsigned int nofua:1;
287 288
288 u32 sense_data; 289 u32 sense_data;
289 u32 sense_data_info; 290 u32 sense_data_info;
@@ -714,6 +715,14 @@ static ssize_t fsg_show_ro(struct device *dev, struct device_attribute *attr,
714 : curlun->initially_ro); 715 : curlun->initially_ro);
715} 716}
716 717
718static ssize_t fsg_show_nofua(struct device *dev, struct device_attribute *attr,
719 char *buf)
720{
721 struct fsg_lun *curlun = fsg_lun_from_dev(dev);
722
723 return sprintf(buf, "%u\n", curlun->nofua);
724}
725
717static ssize_t fsg_show_file(struct device *dev, struct device_attribute *attr, 726static ssize_t fsg_show_file(struct device *dev, struct device_attribute *attr,
718 char *buf) 727 char *buf)
719{ 728{
@@ -770,6 +779,25 @@ static ssize_t fsg_store_ro(struct device *dev, struct device_attribute *attr,
770 return rc; 779 return rc;
771} 780}
772 781
782static ssize_t fsg_store_nofua(struct device *dev,
783 struct device_attribute *attr,
784 const char *buf, size_t count)
785{
786 struct fsg_lun *curlun = fsg_lun_from_dev(dev);
787 unsigned long nofua;
788
789 if (strict_strtoul(buf, 2, &nofua))
790 return -EINVAL;
791
792 /* Sync data when switching from async mode to sync */
793 if (!nofua && curlun->nofua)
794 fsg_lun_fsync_sub(curlun);
795
796 curlun->nofua = nofua;
797
798 return count;
799}
800
773static ssize_t fsg_store_file(struct device *dev, struct device_attribute *attr, 801static ssize_t fsg_store_file(struct device *dev, struct device_attribute *attr,
774 const char *buf, size_t count) 802 const char *buf, size_t count)
775{ 803{