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. 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 -- 1.7.1 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html