diff options
author | Andy Shevchenko <andy.shevchenko@gmail.com> | 2010-07-22 17:53:56 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-08-10 14:35:42 -0700 |
commit | a93917d39fc388c4761d2530af82513e2d3bf9f6 (patch) | |
tree | 0e2f7bed30b16c70a2f71951adfadeab7a29a4a8 /drivers/usb/gadget/storage_common.c | |
parent | 8156d158efa6370a8183f47327f122edbb4f2cb6 (diff) | |
download | op-kernel-dev-a93917d39fc388c4761d2530af82513e2d3bf9f6.zip op-kernel-dev-a93917d39fc388c4761d2530af82513e2d3bf9f6.tar.gz |
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/storage_common.c')
-rw-r--r-- | drivers/usb/gadget/storage_common.c | 28 |
1 files changed, 28 insertions, 0 deletions
diff --git a/drivers/usb/gadget/storage_common.c b/drivers/usb/gadget/storage_common.c index 3bbddab..484acfb 100644 --- a/drivers/usb/gadget/storage_common.c +++ b/drivers/usb/gadget/storage_common.c @@ -284,6 +284,7 @@ struct fsg_lun { unsigned int prevent_medium_removal:1; unsigned int registered:1; unsigned int info_valid:1; + unsigned int nofua:1; u32 sense_data; u32 sense_data_info; @@ -714,6 +715,14 @@ static ssize_t fsg_show_ro(struct device *dev, struct device_attribute *attr, : curlun->initially_ro); } +static ssize_t fsg_show_nofua(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct fsg_lun *curlun = fsg_lun_from_dev(dev); + + return sprintf(buf, "%u\n", curlun->nofua); +} + static ssize_t fsg_show_file(struct device *dev, struct device_attribute *attr, char *buf) { @@ -770,6 +779,25 @@ static ssize_t fsg_store_ro(struct device *dev, struct device_attribute *attr, return rc; } +static ssize_t fsg_store_nofua(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct fsg_lun *curlun = fsg_lun_from_dev(dev); + unsigned long nofua; + + if (strict_strtoul(buf, 2, &nofua)) + return -EINVAL; + + /* Sync data when switching from async mode to sync */ + if (!nofua && curlun->nofua) + fsg_lun_fsync_sub(curlun); + + curlun->nofua = nofua; + + return count; +} + static ssize_t fsg_store_file(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { |