aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget/file_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/file_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/file_storage.c')
-rw-r--r--drivers/usb/gadget/file_storage.c50
1 files changed, 24 insertions, 26 deletions
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index 39ece40a045f..59d97750cecd 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -69,8 +69,7 @@
69 * each LUN would be settable independently as a disk drive or a CD-ROM 69 * each LUN would be settable independently as a disk drive or a CD-ROM
70 * drive, but currently all LUNs have to be the same type. The CD-ROM 70 * drive, but currently all LUNs have to be the same type. The CD-ROM
71 * emulation includes a single data track and no audio tracks; hence there 71 * emulation includes a single data track and no audio tracks; hence there
72 * need be only one backing file per LUN. Note also that the CD-ROM block 72 * need be only one backing file per LUN.
73 * length is set to 512 rather than the more common value 2048.
74 * 73 *
75 * Requirements are modest; only a bulk-in and a bulk-out endpoint are 74 * Requirements are modest; only a bulk-in and a bulk-out endpoint are
76 * needed (an interrupt-out endpoint is also needed for CBI). The memory 75 * needed (an interrupt-out endpoint is also needed for CBI). The memory
@@ -1158,7 +1157,7 @@ static int do_read(struct fsg_dev *fsg)
1158 curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; 1157 curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
1159 return -EINVAL; 1158 return -EINVAL;
1160 } 1159 }
1161 file_offset = ((loff_t) lba) << 9; 1160 file_offset = ((loff_t) lba) << curlun->blkbits;
1162 1161
1163 /* Carry out the file reads */ 1162 /* Carry out the file reads */
1164 amount_left = fsg->data_size_from_cmnd; 1163 amount_left = fsg->data_size_from_cmnd;
@@ -1196,7 +1195,7 @@ static int do_read(struct fsg_dev *fsg)
1196 if (amount == 0) { 1195 if (amount == 0) {
1197 curlun->sense_data = 1196 curlun->sense_data =
1198 SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; 1197 SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
1199 curlun->sense_data_info = file_offset >> 9; 1198 curlun->sense_data_info = file_offset >> curlun->blkbits;
1200 curlun->info_valid = 1; 1199 curlun->info_valid = 1;
1201 bh->inreq->length = 0; 1200 bh->inreq->length = 0;
1202 bh->state = BUF_STATE_FULL; 1201 bh->state = BUF_STATE_FULL;
@@ -1221,7 +1220,7 @@ static int do_read(struct fsg_dev *fsg)
1221 } else if (nread < amount) { 1220 } else if (nread < amount) {
1222 LDBG(curlun, "partial file read: %d/%u\n", 1221 LDBG(curlun, "partial file read: %d/%u\n",
1223 (int) nread, amount); 1222 (int) nread, amount);
1224 nread -= (nread & 511); // Round down to a block 1223 nread = round_down(nread, curlun->blksize);
1225 } 1224 }
1226 file_offset += nread; 1225 file_offset += nread;
1227 amount_left -= nread; 1226 amount_left -= nread;
@@ -1232,7 +1231,7 @@ static int do_read(struct fsg_dev *fsg)
1232 /* If an error occurred, report it and its position */ 1231 /* If an error occurred, report it and its position */
1233 if (nread < amount) { 1232 if (nread < amount) {
1234 curlun->sense_data = SS_UNRECOVERED_READ_ERROR; 1233 curlun->sense_data = SS_UNRECOVERED_READ_ERROR;
1235 curlun->sense_data_info = file_offset >> 9; 1234 curlun->sense_data_info = file_offset >> curlun->blkbits;
1236 curlun->info_valid = 1; 1235 curlun->info_valid = 1;
1237 break; 1236 break;
1238 } 1237 }
@@ -1303,7 +1302,7 @@ static int do_write(struct fsg_dev *fsg)
1303 1302
1304 /* Carry out the file writes */ 1303 /* Carry out the file writes */
1305 get_some_more = 1; 1304 get_some_more = 1;
1306 file_offset = usb_offset = ((loff_t) lba) << 9; 1305 file_offset = usb_offset = ((loff_t) lba) << curlun->blkbits;
1307 amount_left_to_req = amount_left_to_write = fsg->data_size_from_cmnd; 1306 amount_left_to_req = amount_left_to_write = fsg->data_size_from_cmnd;
1308 1307
1309 while (amount_left_to_write > 0) { 1308 while (amount_left_to_write > 0) {
@@ -1333,11 +1332,11 @@ static int do_write(struct fsg_dev *fsg)
1333 get_some_more = 0; 1332 get_some_more = 0;
1334 curlun->sense_data = 1333 curlun->sense_data =
1335 SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; 1334 SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
1336 curlun->sense_data_info = usb_offset >> 9; 1335 curlun->sense_data_info = usb_offset >> curlun->blkbits;
1337 curlun->info_valid = 1; 1336 curlun->info_valid = 1;
1338 continue; 1337 continue;
1339 } 1338 }
1340 amount -= (amount & 511); 1339 amount = round_down(amount, curlun->blksize);
1341 if (amount == 0) { 1340 if (amount == 0) {
1342 1341
1343 /* Why were we were asked to transfer a 1342 /* Why were we were asked to transfer a
@@ -1376,7 +1375,7 @@ static int do_write(struct fsg_dev *fsg)
1376 /* Did something go wrong with the transfer? */ 1375 /* Did something go wrong with the transfer? */
1377 if (bh->outreq->status != 0) { 1376 if (bh->outreq->status != 0) {
1378 curlun->sense_data = SS_COMMUNICATION_FAILURE; 1377 curlun->sense_data = SS_COMMUNICATION_FAILURE;
1379 curlun->sense_data_info = file_offset >> 9; 1378 curlun->sense_data_info = file_offset >> curlun->blkbits;
1380 curlun->info_valid = 1; 1379 curlun->info_valid = 1;
1381 break; 1380 break;
1382 } 1381 }
@@ -1408,8 +1407,7 @@ static int do_write(struct fsg_dev *fsg)
1408 } else if (nwritten < amount) { 1407 } else if (nwritten < amount) {
1409 LDBG(curlun, "partial file write: %d/%u\n", 1408 LDBG(curlun, "partial file write: %d/%u\n",
1410 (int) nwritten, amount); 1409 (int) nwritten, amount);
1411 nwritten -= (nwritten & 511); 1410 nwritten = round_down(nwritten, curlun->blksize);
1412 // Round down to a block
1413 } 1411 }
1414 file_offset += nwritten; 1412 file_offset += nwritten;
1415 amount_left_to_write -= nwritten; 1413 amount_left_to_write -= nwritten;
@@ -1418,7 +1416,7 @@ static int do_write(struct fsg_dev *fsg)
1418 /* If an error occurred, report it and its position */ 1416 /* If an error occurred, report it and its position */
1419 if (nwritten < amount) { 1417 if (nwritten < amount) {
1420 curlun->sense_data = SS_WRITE_ERROR; 1418 curlun->sense_data = SS_WRITE_ERROR;
1421 curlun->sense_data_info = file_offset >> 9; 1419 curlun->sense_data_info = file_offset >> curlun->blkbits;
1422 curlun->info_valid = 1; 1420 curlun->info_valid = 1;
1423 break; 1421 break;
1424 } 1422 }
@@ -1500,8 +1498,8 @@ static int do_verify(struct fsg_dev *fsg)
1500 return -EIO; // No default reply 1498 return -EIO; // No default reply
1501 1499
1502 /* Prepare to carry out the file verify */ 1500 /* Prepare to carry out the file verify */
1503 amount_left = verification_length << 9; 1501 amount_left = verification_length << curlun->blkbits;
1504 file_offset = ((loff_t) lba) << 9; 1502 file_offset = ((loff_t) lba) << curlun->blkbits;
1505 1503
1506 /* Write out all the dirty buffers before invalidating them */ 1504 /* Write out all the dirty buffers before invalidating them */
1507 fsg_lun_fsync_sub(curlun); 1505 fsg_lun_fsync_sub(curlun);
@@ -1527,7 +1525,7 @@ static int do_verify(struct fsg_dev *fsg)
1527 if (amount == 0) { 1525 if (amount == 0) {
1528 curlun->sense_data = 1526 curlun->sense_data =
1529 SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; 1527 SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
1530 curlun->sense_data_info = file_offset >> 9; 1528 curlun->sense_data_info = file_offset >> curlun->blkbits;
1531 curlun->info_valid = 1; 1529 curlun->info_valid = 1;
1532 break; 1530 break;
1533 } 1531 }
@@ -1550,11 +1548,11 @@ static int do_verify(struct fsg_dev *fsg)
1550 } else if (nread < amount) { 1548 } else if (nread < amount) {
1551 LDBG(curlun, "partial file verify: %d/%u\n", 1549 LDBG(curlun, "partial file verify: %d/%u\n",
1552 (int) nread, amount); 1550 (int) nread, amount);
1553 nread -= (nread & 511); // Round down to a sector 1551 nread = round_down(nread, curlun->blksize);
1554 } 1552 }
1555 if (nread == 0) { 1553 if (nread == 0) {
1556 curlun->sense_data = SS_UNRECOVERED_READ_ERROR; 1554 curlun->sense_data = SS_UNRECOVERED_READ_ERROR;
1557 curlun->sense_data_info = file_offset >> 9; 1555 curlun->sense_data_info = file_offset >> curlun->blkbits;
1558 curlun->info_valid = 1; 1556 curlun->info_valid = 1;
1559 break; 1557 break;
1560 } 1558 }
@@ -1668,7 +1666,7 @@ static int do_read_capacity(struct fsg_dev *fsg, struct fsg_buffhd *bh)
1668 1666
1669 put_unaligned_be32(curlun->num_sectors - 1, &buf[0]); 1667 put_unaligned_be32(curlun->num_sectors - 1, &buf[0]);
1670 /* Max logical block */ 1668 /* Max logical block */
1671 put_unaligned_be32(512, &buf[4]); /* Block length */ 1669 put_unaligned_be32(curlun->blksize, &buf[4]); /* Block length */
1672 return 8; 1670 return 8;
1673} 1671}
1674 1672
@@ -1890,7 +1888,7 @@ static int do_read_format_capacities(struct fsg_dev *fsg,
1890 1888
1891 put_unaligned_be32(curlun->num_sectors, &buf[0]); 1889 put_unaligned_be32(curlun->num_sectors, &buf[0]);
1892 /* Number of blocks */ 1890 /* Number of blocks */
1893 put_unaligned_be32(512, &buf[4]); /* Block length */ 1891 put_unaligned_be32(curlun->blksize, &buf[4]); /* Block length */
1894 buf[4] = 0x02; /* Current capacity */ 1892 buf[4] = 0x02; /* Current capacity */
1895 return 12; 1893 return 12;
1896} 1894}
@@ -2415,7 +2413,7 @@ static int do_scsi_command(struct fsg_dev *fsg)
2415 2413
2416 case READ_6: 2414 case READ_6:
2417 i = fsg->cmnd[4]; 2415 i = fsg->cmnd[4];
2418 fsg->data_size_from_cmnd = (i == 0 ? 256 : i) << 9; 2416 fsg->data_size_from_cmnd = (i == 0 ? 256 : i) << fsg->curlun->blkbits;
2419 if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST, 2417 if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST,
2420 (7<<1) | (1<<4), 1, 2418 (7<<1) | (1<<4), 1,
2421 "READ(6)")) == 0) 2419 "READ(6)")) == 0)
@@ -2424,7 +2422,7 @@ static int do_scsi_command(struct fsg_dev *fsg)
2424 2422
2425 case READ_10: 2423 case READ_10:
2426 fsg->data_size_from_cmnd = 2424 fsg->data_size_from_cmnd =
2427 get_unaligned_be16(&fsg->cmnd[7]) << 9; 2425 get_unaligned_be16(&fsg->cmnd[7]) << fsg->curlun->blkbits;
2428 if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST, 2426 if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
2429 (1<<1) | (0xf<<2) | (3<<7), 1, 2427 (1<<1) | (0xf<<2) | (3<<7), 1,
2430 "READ(10)")) == 0) 2428 "READ(10)")) == 0)
@@ -2433,7 +2431,7 @@ static int do_scsi_command(struct fsg_dev *fsg)
2433 2431
2434 case READ_12: 2432 case READ_12:
2435 fsg->data_size_from_cmnd = 2433 fsg->data_size_from_cmnd =
2436 get_unaligned_be32(&fsg->cmnd[6]) << 9; 2434 get_unaligned_be32(&fsg->cmnd[6]) << fsg->curlun->blkbits;
2437 if ((reply = check_command(fsg, 12, DATA_DIR_TO_HOST, 2435 if ((reply = check_command(fsg, 12, DATA_DIR_TO_HOST,
2438 (1<<1) | (0xf<<2) | (0xf<<6), 1, 2436 (1<<1) | (0xf<<2) | (0xf<<6), 1,
2439 "READ(12)")) == 0) 2437 "READ(12)")) == 0)
@@ -2519,7 +2517,7 @@ static int do_scsi_command(struct fsg_dev *fsg)
2519 2517
2520 case WRITE_6: 2518 case WRITE_6:
2521 i = fsg->cmnd[4]; 2519 i = fsg->cmnd[4];
2522 fsg->data_size_from_cmnd = (i == 0 ? 256 : i) << 9; 2520 fsg->data_size_from_cmnd = (i == 0 ? 256 : i) << fsg->curlun->blkbits;
2523 if ((reply = check_command(fsg, 6, DATA_DIR_FROM_HOST, 2521 if ((reply = check_command(fsg, 6, DATA_DIR_FROM_HOST,
2524 (7<<1) | (1<<4), 1, 2522 (7<<1) | (1<<4), 1,
2525 "WRITE(6)")) == 0) 2523 "WRITE(6)")) == 0)
@@ -2528,7 +2526,7 @@ static int do_scsi_command(struct fsg_dev *fsg)
2528 2526
2529 case WRITE_10: 2527 case WRITE_10:
2530 fsg->data_size_from_cmnd = 2528 fsg->data_size_from_cmnd =
2531 get_unaligned_be16(&fsg->cmnd[7]) << 9; 2529 get_unaligned_be16(&fsg->cmnd[7]) << fsg->curlun->blkbits;
2532 if ((reply = check_command(fsg, 10, DATA_DIR_FROM_HOST, 2530 if ((reply = check_command(fsg, 10, DATA_DIR_FROM_HOST,
2533 (1<<1) | (0xf<<2) | (3<<7), 1, 2531 (1<<1) | (0xf<<2) | (3<<7), 1,
2534 "WRITE(10)")) == 0) 2532 "WRITE(10)")) == 0)
@@ -2537,7 +2535,7 @@ static int do_scsi_command(struct fsg_dev *fsg)
2537 2535
2538 case WRITE_12: 2536 case WRITE_12:
2539 fsg->data_size_from_cmnd = 2537 fsg->data_size_from_cmnd =
2540 get_unaligned_be32(&fsg->cmnd[6]) << 9; 2538 get_unaligned_be32(&fsg->cmnd[6]) << fsg->curlun->blkbits;
2541 if ((reply = check_command(fsg, 12, DATA_DIR_FROM_HOST, 2539 if ((reply = check_command(fsg, 12, DATA_DIR_FROM_HOST,
2542 (1<<1) | (0xf<<2) | (0xf<<6), 1, 2540 (1<<1) | (0xf<<2) | (0xf<<6), 1,
2543 "WRITE(12)")) == 0) 2541 "WRITE(12)")) == 0)