From: Ana Bobillo <[email protected]> usb_stor_get_info() takes the block size from the READ CAPACITY reply of the device as it is. Once blk_post_probe() refuses a block size that blk_valid_blksz() rejects, at the end of this series, such a device would fail to probe there, and usb_stor_probe_device() would stop, skipping the other LUNs of the device.
Check the block size where it is read, and treat a LUN reporting one that blk_valid_blksz() rejects as unusable, as for a LUN that is not ready, saying which LUN is skipped. This also covers the legacy (non-BLK) path, which calls part_init() itself. Add a test where the sandbox flash stick reports an unsupported block size. Signed-off-by: Ana Bobillo <[email protected]> Reviewed-by: Simon Glass <[email protected]> --- (no changes since v2) Changes in v2: - Move the READ CAPACITY fallback fix to a patch of its own (Simon) - Name the LUN in the message (Simon) - Check for that message in the test, with UTF_CONSOLE (Simon) arch/sandbox/include/asm/test.h | 10 +++++++ common/usb_storage.c | 5 ++++ drivers/usb/emul/sandbox_flash.c | 8 +++++ test/dm/usb.c | 51 ++++++++++++++++++++++++++++++++ 4 files changed, 74 insertions(+) diff --git a/arch/sandbox/include/asm/test.h b/arch/sandbox/include/asm/test.h index 0438790028b..e5590d01a92 100644 --- a/arch/sandbox/include/asm/test.h +++ b/arch/sandbox/include/asm/test.h @@ -123,6 +123,16 @@ long sandbox_i2c_rtc_get_set_base_time(struct udevice *dev, long base_time); int sandbox_usb_keyb_add_string(struct udevice *dev, const char *str); +/** + * sandbox_flash_set_block_size() - Set the block size a flash stick reports + * + * @dev: USB flash-stick emulator + * @block_size: Block size in bytes + * + * The host reads it when it next probes the stick's mass-storage device. + */ +void sandbox_flash_set_block_size(struct udevice *dev, int block_size); + /** * sandbox_osd_get_mem() - get the internal memory of a sandbox OSD * diff --git a/common/usb_storage.c b/common/usb_storage.c index f7c96195b59..6bada2b309b 100644 --- a/common/usb_storage.c +++ b/common/usb_storage.c @@ -1513,6 +1513,11 @@ int usb_stor_get_info(struct usb_device *dev, struct us_data *ss, blksz = be32_to_cpu(cap[1]); debug("Capacity = 0x%08x, blocksz = 0x%08x\n", capacity, blksz); + if (!blk_valid_blksz(blksz)) { + printf("LUN %d: unsupported block size %u, skipping\n", + dev_desc->lun, blksz); + return 0; + } dev_desc->lba = capacity; dev_desc->blksz = blksz; dev_desc->log2blksz = LOG2(dev_desc->blksz); diff --git a/drivers/usb/emul/sandbox_flash.c b/drivers/usb/emul/sandbox_flash.c index b5176bb30ce..02e0901050f 100644 --- a/drivers/usb/emul/sandbox_flash.c +++ b/drivers/usb/emul/sandbox_flash.c @@ -13,6 +13,7 @@ #include <scsi.h> #include <scsi_emul.h> #include <usb.h> +#include <asm/test.h> /* * This driver emulates a flash stick using the UFI command specification and @@ -357,6 +358,13 @@ static int sandbox_flash_probe(struct udevice *dev) return 0; } +void sandbox_flash_set_block_size(struct udevice *dev, int block_size) +{ + struct sandbox_flash_priv *priv = dev_get_priv(dev); + + priv->eminfo.block_size = block_size; +} + static int sandbox_flash_remove(struct udevice *dev) { struct sandbox_flash_priv *priv = dev_get_priv(dev); diff --git a/test/dm/usb.c b/test/dm/usb.c index fa894c1096e..79a85b11910 100644 --- a/test/dm/usb.c +++ b/test/dm/usb.c @@ -84,6 +84,57 @@ static int dm_test_usb_flash(struct unit_test_state *uts) } DM_TEST(dm_test_usb_flash, UTF_SCAN_PDATA | UTF_SCAN_FDT); +/* Test that a flash stick reporting an unsupported block size is refused */ +static int dm_test_usb_flash_blksz(struct unit_test_state *uts) +{ + static const struct { + int blksz; + bool ok; + } cases[] = { + { 256, false }, + { 520, false }, + { 2 * BLK_MAX_BLKSZ, false }, + { SZ_4K, true }, + }; + struct udevice *dev, *emul, *blk; + struct blk_desc *desc; + int i, ret; + + state_set_skip_delays(true); + ut_assertok(usb_init()); + ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 0, &dev)); + ut_assertok(uclass_get_device_by_name(UCLASS_USB_EMUL, "flash-stick@0", + &emul)); + + for (i = 0; i < ARRAY_SIZE(cases); i++) { + /* Probe the stick again, so that it reads the block size */ + console_record_reset(); + sandbox_flash_set_block_size(emul, cases[i].blksz); + ut_assertok(device_remove(dev, DM_REMOVE_NORMAL)); + ut_assertok(device_chld_unbind(dev, NULL)); + ut_assertok(device_probe(dev)); + + ret = device_find_first_child_by_uclass(dev, UCLASS_BLK, &blk); + if (!cases[i].ok) { + /* usb_stor_get_info() refuses the LUN */ + ut_assert_nextline("LUN 0: unsupported block size %d, skipping", + cases[i].blksz); + ut_assert_console_end(); + ut_asserteq(-ENODEV, ret); + continue; + } + ut_assert_console_end(); + ut_assertok(ret); + desc = dev_get_uclass_plat(blk); + ut_asserteq(cases[i].blksz, desc->blksz); + } + + ut_assertok(usb_stop()); + + return 0; +} +DM_TEST(dm_test_usb_flash_blksz, UTF_SCAN_PDATA | UTF_SCAN_FDT | UTF_CONSOLE); + /* test that we can handle multiple storage devices */ static int dm_test_usb_multi(struct unit_test_state *uts) {
