aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget/f_mass_storage.c
diff options
context:
space:
mode:
authorPeiyu Li <peiyu.li@csr.com>2011-08-18 01:52:59 -0400
committerFelipe Balbi <balbi@ti.com>2011-09-09 06:06:02 -0400
commit3f565a363cee14d2ed281823196d455bfc7c4170 (patch)
tree57e75064f7f153a3d5069b26d8b4fe9acf0a510a /drivers/usb/gadget/f_mass_storage.c
parent019ac83252dc2b356cb0ca81c25a077ec90309e7 (diff)
usb: gadget: storage: adapt logic block size to bound block devices
Now the mass storage driver has fixed logic block size of 512 bytes. The mass storage gadget read/write bound devices only through VFS, so the bottom level devices actually are just RAW devices to the driver and connected PC. As a RAW, hosts can always format, read and write it right in 512 bytes logic block and don't care about the actual logic block size of devices bound to the gadget. But if we want to share the bound block device partition between target board and PC, in case the logic block size of the bound block device is 4KB, we execute the following steps: 1. connect a board with mass storage gadget to PC(the board has set one partition of on-board block device as file name of the mass storage) 2. PC format the mass storage to VFAT by default logic block size and read/write it 3. disconnect boards from PC 4. target board mount the partition as VFAT Step 4 will fail since kernel on target thinks the logic block size of the bound partition as 4KB. A typical error is "FAT: logical sector size too small for device (logical sector size = 512)" If we execute opposite steps: 1. format the partition to VFAT on target board and read/write this partition 2. connect the board to Windows PC as usb mass storage gadget, windows will think the disk is not formatted So the conclusion is that only as a gadget, the mass storage driver has no any problem. But being shared VFAT or other filesystem on PC and target board, it will fail. This patch adapts logic block size to bound block devices and fix the issue. Cc: Michal Nazarewicz <mina86@mina86.com> Acked-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Peiyu Li <peiyu.li@csr.com> Signed-off-by: Xianglong Du <xianglong.du@csr.com> Signed-off-by: Huayi Li <huayi.li@csr.com> Signed-off-by: Barry Song <Baohua.Song@csr.com> Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/gadget/f_mass_storage.c')
-rw-r--r--drivers/usb/gadget/f_mass_storage.c63
1 files changed, 37 insertions, 26 deletions
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c
index 4ce3decda1db..1cdb1fa1b158 100644
--- a/drivers/usb/gadget/f_mass_storage.c
+++ b/drivers/usb/gadget/f_mass_storage.c
@@ -112,8 +112,7 @@
112 * is not loaded (an empty string as "filename" in the fsg_config 112 * is not loaded (an empty string as "filename" in the fsg_config
113 * structure causes error). The CD-ROM emulation includes a single 113 * structure causes error). The CD-ROM emulation includes a single
114 * data track and no audio tracks; hence there need be only one 114 * data track and no audio tracks; hence there need be only one
115 * backing file per LUN. Note also that the CD-ROM block length is 115 * backing file per LUN.
116 * set to 512 rather than the more common value 2048.
117 * 116 *
118 * 117 *
119 * MSF includes support for module parameters. If gadget using it 118 * MSF includes support for module parameters. If gadget using it
@@ -771,7 +770,7 @@ static int do_read(struct fsg_common *common)
771 curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; 770 curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
772 return -EINVAL; 771 return -EINVAL;
773 } 772 }
774 file_offset = ((loff_t) lba) << 9; 773 file_offset = ((loff_t) lba) << curlun->blkbits;
775 774
776 /* Carry out the file reads */ 775 /* Carry out the file reads */
777 amount_left = common->data_size_from_cmnd; 776 amount_left = common->data_size_from_cmnd;
@@ -812,7 +811,8 @@ static int do_read(struct fsg_common *common)
812 if (amount == 0) { 811 if (amount == 0) {
813 curlun->sense_data = 812 curlun->sense_data =
814 SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; 813 SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
815 curlun->sense_data_info = file_offset >> 9; 814 curlun->sense_data_info =
815 file_offset >> curlun->blkbits;
816 curlun->info_valid = 1; 816 curlun->info_valid = 1;
817 bh->inreq->length = 0; 817 bh->inreq->length = 0;
818 bh->state = BUF_STATE_FULL; 818 bh->state = BUF_STATE_FULL;
@@ -835,7 +835,7 @@ static int do_read(struct fsg_common *common)
835 } else if (nread < amount) { 835 } else if (nread < amount) {
836 LDBG(curlun, "partial file read: %d/%u\n", 836 LDBG(curlun, "partial file read: %d/%u\n",
837 (int)nread, amount); 837 (int)nread, amount);
838 nread -= (nread & 511); /* Round down to a block */ 838 nread = round_down(nread, curlun->blksize);
839 } 839 }
840 file_offset += nread; 840 file_offset += nread;
841 amount_left -= nread; 841 amount_left -= nread;
@@ -846,7 +846,8 @@ static int do_read(struct fsg_common *common)
846 /* If an error occurred, report it and its position */ 846 /* If an error occurred, report it and its position */
847 if (nread < amount) { 847 if (nread < amount) {
848 curlun->sense_data = SS_UNRECOVERED_READ_ERROR; 848 curlun->sense_data = SS_UNRECOVERED_READ_ERROR;
849 curlun->sense_data_info = file_offset >> 9; 849 curlun->sense_data_info =
850 file_offset >> curlun->blkbits;
850 curlun->info_valid = 1; 851 curlun->info_valid = 1;
851 break; 852 break;
852 } 853 }
@@ -921,7 +922,7 @@ static int do_write(struct fsg_common *common)
921 922
922 /* Carry out the file writes */ 923 /* Carry out the file writes */
923 get_some_more = 1; 924 get_some_more = 1;
924 file_offset = usb_offset = ((loff_t) lba) << 9; 925 file_offset = usb_offset = ((loff_t) lba) << curlun->blkbits;
925 amount_left_to_req = common->data_size_from_cmnd; 926 amount_left_to_req = common->data_size_from_cmnd;
926 amount_left_to_write = common->data_size_from_cmnd; 927 amount_left_to_write = common->data_size_from_cmnd;
927 928
@@ -954,11 +955,12 @@ static int do_write(struct fsg_common *common)
954 get_some_more = 0; 955 get_some_more = 0;
955 curlun->sense_data = 956 curlun->sense_data =
956 SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; 957 SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
957 curlun->sense_data_info = usb_offset >> 9; 958 curlun->sense_data_info =
959 usb_offset >> curlun->blkbits;
958 curlun->info_valid = 1; 960 curlun->info_valid = 1;
959 continue; 961 continue;
960 } 962 }
961 amount -= amount & 511; 963 amount = round_down(amount, curlun->blksize);
962 if (amount == 0) { 964 if (amount == 0) {
963 965
964 /* 966 /*
@@ -1002,7 +1004,8 @@ static int do_write(struct fsg_common *common)
1002 /* Did something go wrong with the transfer? */ 1004 /* Did something go wrong with the transfer? */
1003 if (bh->outreq->status != 0) { 1005 if (bh->outreq->status != 0) {
1004 curlun->sense_data = SS_COMMUNICATION_FAILURE; 1006 curlun->sense_data = SS_COMMUNICATION_FAILURE;
1005 curlun->sense_data_info = file_offset >> 9; 1007 curlun->sense_data_info =
1008 file_offset >> curlun->blkbits;
1006 curlun->info_valid = 1; 1009 curlun->info_valid = 1;
1007 break; 1010 break;
1008 } 1011 }
@@ -1033,8 +1036,7 @@ static int do_write(struct fsg_common *common)
1033 } else if (nwritten < amount) { 1036 } else if (nwritten < amount) {
1034 LDBG(curlun, "partial file write: %d/%u\n", 1037 LDBG(curlun, "partial file write: %d/%u\n",
1035 (int)nwritten, amount); 1038 (int)nwritten, amount);
1036 nwritten -= (nwritten & 511); 1039 nwritten = round_down(nwritten, curlun->blksize);
1037 /* Round down to a block */
1038 } 1040 }
1039 file_offset += nwritten; 1041 file_offset += nwritten;
1040 amount_left_to_write -= nwritten; 1042 amount_left_to_write -= nwritten;
@@ -1043,7 +1045,8 @@ static int do_write(struct fsg_common *common)
1043 /* If an error occurred, report it and its position */ 1045 /* If an error occurred, report it and its position */
1044 if (nwritten < amount) { 1046 if (nwritten < amount) {
1045 curlun->sense_data = SS_WRITE_ERROR; 1047 curlun->sense_data = SS_WRITE_ERROR;
1046 curlun->sense_data_info = file_offset >> 9; 1048 curlun->sense_data_info =
1049 file_offset >> curlun->blkbits;
1047 curlun->info_valid = 1; 1050 curlun->info_valid = 1;
1048 break; 1051 break;
1049 } 1052 }
@@ -1129,8 +1132,8 @@ static int do_verify(struct fsg_common *common)
1129 return -EIO; /* No default reply */ 1132 return -EIO; /* No default reply */
1130 1133
1131 /* Prepare to carry out the file verify */ 1134 /* Prepare to carry out the file verify */
1132 amount_left = verification_length << 9; 1135 amount_left = verification_length << curlun->blkbits;
1133 file_offset = ((loff_t) lba) << 9; 1136 file_offset = ((loff_t) lba) << curlun->blkbits;
1134 1137
1135 /* Write out all the dirty buffers before invalidating them */ 1138 /* Write out all the dirty buffers before invalidating them */
1136 fsg_lun_fsync_sub(curlun); 1139 fsg_lun_fsync_sub(curlun);
@@ -1157,7 +1160,8 @@ static int do_verify(struct fsg_common *common)
1157 if (amount == 0) { 1160 if (amount == 0) {
1158 curlun->sense_data = 1161 curlun->sense_data =
1159 SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; 1162 SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
1160 curlun->sense_data_info = file_offset >> 9; 1163 curlun->sense_data_info =
1164 file_offset >> curlun->blkbits;
1161 curlun->info_valid = 1; 1165 curlun->info_valid = 1;
1162 break; 1166 break;
1163 } 1167 }
@@ -1179,11 +1183,12 @@ static int do_verify(struct fsg_common *common)
1179 } else if (nread < amount) { 1183 } else if (nread < amount) {
1180 LDBG(curlun, "partial file verify: %d/%u\n", 1184 LDBG(curlun, "partial file verify: %d/%u\n",
1181 (int)nread, amount); 1185 (int)nread, amount);
1182 nread -= nread & 511; /* Round down to a sector */ 1186 nread = round_down(nread, curlun->blksize);
1183 } 1187 }
1184 if (nread == 0) { 1188 if (nread == 0) {
1185 curlun->sense_data = SS_UNRECOVERED_READ_ERROR; 1189 curlun->sense_data = SS_UNRECOVERED_READ_ERROR;
1186 curlun->sense_data_info = file_offset >> 9; 1190 curlun->sense_data_info =
1191 file_offset >> curlun->blkbits;
1187 curlun->info_valid = 1; 1192 curlun->info_valid = 1;
1188 break; 1193 break;
1189 } 1194 }
@@ -1289,7 +1294,7 @@ static int do_read_capacity(struct fsg_common *common, struct fsg_buffhd *bh)
1289 1294
1290 put_unaligned_be32(curlun->num_sectors - 1, &buf[0]); 1295 put_unaligned_be32(curlun->num_sectors - 1, &buf[0]);
1291 /* Max logical block */ 1296 /* Max logical block */
1292 put_unaligned_be32(512, &buf[4]); /* Block length */ 1297 put_unaligned_be32(curlun->blksize, &buf[4]);/* Block length */
1293 return 8; 1298 return 8;
1294} 1299}
1295 1300
@@ -1527,7 +1532,7 @@ static int do_read_format_capacities(struct fsg_common *common,
1527 1532
1528 put_unaligned_be32(curlun->num_sectors, &buf[0]); 1533 put_unaligned_be32(curlun->num_sectors, &buf[0]);
1529 /* Number of blocks */ 1534 /* Number of blocks */
1530 put_unaligned_be32(512, &buf[4]); /* Block length */ 1535 put_unaligned_be32(curlun->blksize, &buf[4]);/* Block length */
1531 buf[4] = 0x02; /* Current capacity */ 1536 buf[4] = 0x02; /* Current capacity */
1532 return 12; 1537 return 12;
1533} 1538}
@@ -2022,7 +2027,8 @@ static int do_scsi_command(struct fsg_common *common)
2022 2027
2023 case READ_6: 2028 case READ_6:
2024 i = common->cmnd[4]; 2029 i = common->cmnd[4];
2025 common->data_size_from_cmnd = (i == 0 ? 256 : i) << 9; 2030 common->data_size_from_cmnd = (i == 0 ? 256 : i) <<
2031 common->curlun->blkbits;
2026 reply = check_command(common, 6, DATA_DIR_TO_HOST, 2032 reply = check_command(common, 6, DATA_DIR_TO_HOST,
2027 (7<<1) | (1<<4), 1, 2033 (7<<1) | (1<<4), 1,
2028 "READ(6)"); 2034 "READ(6)");
@@ -2032,7 +2038,8 @@ static int do_scsi_command(struct fsg_common *common)
2032 2038
2033 case READ_10: 2039 case READ_10:
2034 common->data_size_from_cmnd = 2040 common->data_size_from_cmnd =
2035 get_unaligned_be16(&common->cmnd[7]) << 9; 2041 get_unaligned_be16(&common->cmnd[7]) <<
2042 common->curlun->blkbits;
2036 reply = check_command(common, 10, DATA_DIR_TO_HOST, 2043 reply = check_command(common, 10, DATA_DIR_TO_HOST,
2037 (1<<1) | (0xf<<2) | (3<<7), 1, 2044 (1<<1) | (0xf<<2) | (3<<7), 1,
2038 "READ(10)"); 2045 "READ(10)");
@@ -2042,7 +2049,8 @@ static int do_scsi_command(struct fsg_common *common)
2042 2049
2043 case READ_12: 2050 case READ_12:
2044 common->data_size_from_cmnd = 2051 common->data_size_from_cmnd =
2045 get_unaligned_be32(&common->cmnd[6]) << 9; 2052 get_unaligned_be32(&common->cmnd[6]) <<
2053 common->curlun->blkbits;
2046 reply = check_command(common, 12, DATA_DIR_TO_HOST, 2054 reply = check_command(common, 12, DATA_DIR_TO_HOST,
2047 (1<<1) | (0xf<<2) | (0xf<<6), 1, 2055 (1<<1) | (0xf<<2) | (0xf<<6), 1,
2048 "READ(12)"); 2056 "READ(12)");
@@ -2142,7 +2150,8 @@ static int do_scsi_command(struct fsg_common *common)
2142 2150
2143 case WRITE_6: 2151 case WRITE_6:
2144 i = common->cmnd[4]; 2152 i = common->cmnd[4];
2145 common->data_size_from_cmnd = (i == 0 ? 256 : i) << 9; 2153 common->data_size_from_cmnd = (i == 0 ? 256 : i) <<
2154 common->curlun->blkbits;
2146 reply = check_command(common, 6, DATA_DIR_FROM_HOST, 2155 reply = check_command(common, 6, DATA_DIR_FROM_HOST,
2147 (7<<1) | (1<<4), 1, 2156 (7<<1) | (1<<4), 1,
2148 "WRITE(6)"); 2157 "WRITE(6)");
@@ -2152,7 +2161,8 @@ static int do_scsi_command(struct fsg_common *common)
2152 2161
2153 case WRITE_10: 2162 case WRITE_10:
2154 common->data_size_from_cmnd = 2163 common->data_size_from_cmnd =
2155 get_unaligned_be16(&common->cmnd[7]) << 9; 2164 get_unaligned_be16(&common->cmnd[7]) <<
2165 common->curlun->blkbits;
2156 reply = check_command(common, 10, DATA_DIR_FROM_HOST, 2166 reply = check_command(common, 10, DATA_DIR_FROM_HOST,
2157 (1<<1) | (0xf<<2) | (3<<7), 1, 2167 (1<<1) | (0xf<<2) | (3<<7), 1,
2158 "WRITE(10)"); 2168 "WRITE(10)");
@@ -2162,7 +2172,8 @@ static int do_scsi_command(struct fsg_common *common)
2162 2172
2163 case WRITE_12: 2173 case WRITE_12:
2164 common->data_size_from_cmnd = 2174 common->data_size_from_cmnd =
2165 get_unaligned_be32(&common->cmnd[6]) << 9; 2175 get_unaligned_be32(&common->cmnd[6]) <<
2176 common->curlun->blkbits;
2166 reply = check_command(common, 12, DATA_DIR_FROM_HOST, 2177 reply = check_command(common, 12, DATA_DIR_FROM_HOST,
2167 (1<<1) | (0xf<<2) | (0xf<<6), 1, 2178 (1<<1) | (0xf<<2) | (0xf<<6), 1,
2168 "WRITE(12)"); 2179 "WRITE(12)");