On Fri, Sep 21 2012, Leo Song wrote: > If connect an UMS device (for example, an Android phone) to Linux PC and > Windows PC, then copy a big file (~500MB) to the device, you will find that > Linux PC's write speed is much faster than Windows PC. This issue can be fixed > by hiding the "caching mode page" on UMS device. > > Previously in f_mass_storage.c: do_mode_sense(), caching mode page was the > only mode page, and it was configured as: > Write cache enabled (WCE=1) > Read cache not disabled > No cache retention priorities > > The "Write cache enable"(WCE) bit has different influence for Linux PC and > Windows PC. > > For Linux PC, whether WCE is 0 or 1, the write speed from Linux PC to UMS > device has no difference. Linux PC just ignores this flag. > > For Windows PC, if > 1. the UMS devices has a valid "caching mode page" > 2. the WCE bit in "caching mode page" is set to 1 > 3. the "write-cache buffer flushing" on Windows PC is not turned off > > With these three conditions together, Windows PC will send SCSI WRITE COMMAND > with FUA=1 (FUA, force unit access), and FUA=1 will cause UMS device to wait > until the blocks have been written onto the medium, which will drag down write > speed a lot. Unluckily, this is Windows PC's default behavior. > > On Windows, the FUA=1 flag can be changed by turning off "write-cache buffer > flushing" under UMS device's properties, but if we do so, Windows will pop up > error message as following: > > Windows could not change the write-caching setting for the device. > Your device might not support this feature or changing the setting. > [ OK ] > > Windows need to change UMS device's caching mode page, but this page is hard > coded and can't be changed, so there will be error pop up. > > To fix this issue, we can just hide the "caching mode page". With this patch, > there will be no influence for Linux PC, because Linux PC does not handle UMS > device's caching mode page; for Windows PC, if it does see the "caching mode > page", it will not send SCSI WRITE COMMAND with FUA=1, and write speed will > become as fast as Linux PC. How does it interact with the nofua attribute? With f_mass_storage, you can write 1 to nofua file in sysfs's directory for given lun to make it ignore the FUA bit. > Signed-off-by: Leo Song <liangs@xxxxxxxxxxx> > --- > drivers/usb/gadget/f_mass_storage.c | 27 +++------------------------ > 1 files changed, 3 insertions(+), 24 deletions(-) > > diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c > index 4f1142e..70f3047 100644 > --- a/drivers/usb/gadget/f_mass_storage.c > +++ b/drivers/usb/gadget/f_mass_storage.c > @@ -1296,30 +1296,9 @@ static int do_mode_sense(struct fsg_common *common, struct fsg_buffhd *bh) > > /* No block descriptors */ > > - /* > - * The mode pages, in numerical order. The only page we support > - * is the Caching page. > - */ > - if (page_code == 0x08 || all_pages) { > - valid_page = 1; > - buf[0] = 0x08; /* Page code */ > - buf[1] = 10; /* Page length */ > - memset(buf+2, 0, 10); /* None of the fields are changeable */ > - > - if (!changeable_values) { > - buf[2] = 0x04; /* Write cache enable, */ > - /* Read cache not disabled */ > - /* No cache retention priorities */ > - put_unaligned_be16(0xffff, &buf[4]); > - /* Don't disable prefetch */ > - /* Minimum prefetch = 0 */ > - put_unaligned_be16(0xffff, &buf[8]); > - /* Maximum prefetch */ > - put_unaligned_be16(0xffff, &buf[10]); > - /* Maximum prefetch ceiling */ > - } > - buf += 12; > - } > + /* No mode pages */ > + > + valid_page = 1; > > /* > * Check that a valid page was requested and the mode data length -- Best regards, _ _ .o. | Liege of Serenely Enlightened Majesty of o' \,=./ `o ..o | Computer Science, Michał “mina86” Nazarewicz (o o) ooo +----<email/xmpp: mpn@xxxxxxxxxx>--------------ooO--(_)--Ooo--
Attachment:
pgp3rfqi6YZAA.pgp
Description: PGP signature