From: Simon Glass <sjg@chromium.org> blk_get_devnum_by_uclass_idname() returns a struct blk_desc pointer, discarding the error code from device_probe(). When probe fails due to out-of-memory or other errors, callers see NULL and report a generic 'device not found' instead of the actual cause. Change the function to return int and pass back the block device via a struct udevice ** parameter. This propagates the actual error from device_probe() through to callers. Rename the legacy version to blk_get_desc_by_uclass_idname() since it has no struct udevice to return, and use CONFIG_IS_ENABLED(BLK) in disk/part.c to select the right function. Signed-off-by: Simon Glass <sjg@chromium.org> --- cmd/blkmap.c | 8 ++++---- disk/part.c | 23 ++++++++++++++++++----- drivers/block/blk-uclass.c | 19 +++++++++++-------- drivers/block/blk_legacy.c | 3 ++- include/blk.h | 24 +++++++++++++++++++----- test/boot/luks.c | 15 +++++++++------ 6 files changed, 63 insertions(+), 29 deletions(-) diff --git a/cmd/blkmap.c b/cmd/blkmap.c index 65edec899e2..2dc516e2ca4 100644 --- a/cmd/blkmap.c +++ b/cmd/blkmap.c @@ -28,7 +28,7 @@ struct map_handler { static int do_blkmap_map_linear(struct map_ctx *ctx, int argc, char *const argv[]) { - struct blk_desc *lbd; + struct udevice *ldev; int err, ldevnum; lbaint_t lblknr; @@ -38,15 +38,15 @@ static int do_blkmap_map_linear(struct map_ctx *ctx, int argc, ldevnum = dectoul(argv[2], NULL); lblknr = dectoul(argv[3], NULL); - lbd = blk_get_devnum_by_uclass_idname(argv[1], ldevnum); - if (!lbd) { + err = blk_get_devnum_by_uclass_idname(argv[1], ldevnum, &ldev); + if (err) { printf("Found no device matching \"%s %d\"\n", argv[1], ldevnum); return CMD_RET_FAILURE; } err = blkmap_map_linear(ctx->dev, ctx->blknr, ctx->blkcnt, - lbd->bdev, lblknr); + ldev, lblknr); if (err) { printf("Unable to map \"%s %d\" at block 0x" LBAF ": %d\n", argv[1], ldevnum, ctx->blknr, err); diff --git a/disk/part.c b/disk/part.c index b6dd3598c0f..d5ebdb037a6 100644 --- a/disk/part.c +++ b/disk/part.c @@ -8,6 +8,7 @@ #include <blk.h> #include <command.h> +#include <dm.h> #include <env.h> #include <errno.h> #include <log.h> @@ -124,11 +125,23 @@ static struct blk_desc *get_dev_hwpart(const char *ifname, int dev, int hwpart) if (!blk_enabled()) return NULL; - desc = blk_get_devnum_by_uclass_idname(ifname, dev); - if (!desc) { - debug("%s: No device for iface '%s', dev %d\n", __func__, - ifname, dev); - return NULL; + if (CONFIG_IS_ENABLED(BLK)) { + struct udevice *blk; + + ret = blk_get_devnum_by_uclass_idname(ifname, dev, &blk); + if (ret) { + log_debug("No device for iface '%s', dev %d: err=%d\n", + ifname, dev, ret); + return NULL; + } + desc = dev_get_uclass_plat(blk); + } else { + desc = blk_get_desc_by_uclass_idname(ifname, dev); + if (!desc) { + log_debug("No device for iface '%s', dev %d\n", + ifname, dev); + return NULL; + } } ret = blk_dselect_hwpart(desc, hwpart); if (ret) { diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c index a6ef34c2d5f..9c9169d6ac8 100644 --- a/drivers/block/blk-uclass.c +++ b/drivers/block/blk-uclass.c @@ -107,7 +107,8 @@ struct blk_desc *blk_get_devnum_by_uclass_id(enum uclass_id uclass_id, int devnu * name in a local table. This gives us an interface type which we can match * against the uclass of the block device's parent. */ -struct blk_desc *blk_get_devnum_by_uclass_idname(const char *uclass_idname, int devnum) +int blk_get_devnum_by_uclass_idname(const char *uclass_idname, int devnum, + struct udevice **blkp) { enum uclass_id uclass_id; enum uclass_id type; @@ -119,18 +120,18 @@ struct blk_desc *blk_get_devnum_by_uclass_idname(const char *uclass_idname, int if (type == UCLASS_INVALID) { debug("%s: Unknown interface type '%s'\n", __func__, uclass_idname); - return NULL; + return -ENODEV; } uclass_id = conv_uclass_id(type); if (uclass_id == UCLASS_INVALID) { debug("%s: Unknown uclass for interface type'\n", blk_get_uclass_name(type)); - return NULL; + return -ENODEV; } ret = uclass_get(UCLASS_BLK, &uc); if (ret) - return NULL; + return ret; uclass_foreach_dev(dev, uc) { struct blk_desc *desc = dev_get_uclass_plat(dev); @@ -146,15 +147,17 @@ struct blk_desc *blk_get_devnum_by_uclass_idname(const char *uclass_idname, int continue; } - if (device_probe(dev)) - return NULL; + ret = device_probe(dev); + if (ret) + return ret; debug("%s: Device desc %p\n", __func__, desc); - return desc; + *blkp = dev; + return 0; } debug("%s: No device found\n", __func__); - return NULL; + return -ENXIO; } /** diff --git a/drivers/block/blk_legacy.c b/drivers/block/blk_legacy.c index f36932183d1..28e40d23c71 100644 --- a/drivers/block/blk_legacy.c +++ b/drivers/block/blk_legacy.c @@ -199,7 +199,8 @@ int blk_dselect_hwpart(struct blk_desc *desc, int hwpart) return 0; } -struct blk_desc *blk_get_devnum_by_uclass_idname(const char *uclass_idname, int devnum) +struct blk_desc *blk_get_desc_by_uclass_idname(const char *uclass_idname, + int devnum) { struct blk_driver *drv = blk_driver_lookup_typename(uclass_idname); struct blk_desc *desc; diff --git a/include/blk.h b/include/blk.h index 877876cb622..14ab77f7c51 100644 --- a/include/blk.h +++ b/include/blk.h @@ -642,15 +642,29 @@ struct blk_desc *blk_get_devnum_by_uclass_id(enum uclass_id uclass_id, int devnu /** * blk_get_devnum_by_uclass_idname() - Get block device by type name and number * - * This looks up the block device type based on @uclass_idname, then calls - * blk_get_devnum_by_uclass_id(). + * This looks up the block device type based on @uclass_idname, then probes + * the device. + * + * @uclass_idname: Block device type name (e.g. "mmc") + * @devnum: Device number + * @blkp: Returns the block device + * Return: 0 if OK, -ENODEV if the uclass is not known, -ENXIO if the + * device is not found, or other -ve on probe error + */ +int blk_get_devnum_by_uclass_idname(const char *uclass_idname, int devnum, + struct udevice **blkp); + +/** + * blk_get_desc_by_uclass_idname() - Get block descriptor by type name/number + * + * Legacy version for non-DM block devices. * * @uclass_idname: Block device type name * @devnum: Device number - * Return: point to block device descriptor, or NULL if not found + * Return: pointer to block device descriptor, or NULL if not found */ -struct blk_desc *blk_get_devnum_by_uclass_idname(const char *uclass_idname, - int devnum); +struct blk_desc *blk_get_desc_by_uclass_idname(const char *uclass_idname, + int devnum); /** * blk_dselect_hwpart() - select a hardware partition diff --git a/test/boot/luks.c b/test/boot/luks.c index 339c7d7fc94..f6d0d951fee 100644 --- a/test/boot/luks.c +++ b/test/boot/luks.c @@ -220,6 +220,7 @@ BOOTSTD_TEST(bootstd_test_luks2_info, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE); static int bootstd_test_luks_unlock(struct unit_test_state *uts) { struct blk_desc *desc; + struct udevice *blk; struct udevice *mmc; loff_t file_size; @@ -242,8 +243,8 @@ static int bootstd_test_luks_unlock(struct unit_test_state *uts) ut_assert_console_end(); /* Verify that a file can be read from the decrypted filesystem */ - desc = blk_get_devnum_by_uclass_idname("blkmap", 0); - ut_assertnonnull(desc); + ut_assertok(blk_get_devnum_by_uclass_idname("blkmap", 0, &blk)); + desc = dev_get_uclass_plat(blk); ut_assertok(fs_set_blk_dev_with_part(desc, 0)); ut_assertok(fs_size("/bin/bash", &file_size)); @@ -262,6 +263,7 @@ static int bootstd_test_luks2_unlock(struct unit_test_state *uts) { struct disk_partition info; struct blk_desc *desc; + struct udevice *blk; struct udevice *mmc; u8 master_key[512]; loff_t file_size; @@ -284,8 +286,8 @@ static int bootstd_test_luks2_unlock(struct unit_test_state *uts) ut_assert_console_end(); /* Verify that a file can be read from the decrypted filesystem */ - desc = blk_get_devnum_by_uclass_idname("blkmap", 0); - ut_assertnonnull(desc); + ut_assertok(blk_get_devnum_by_uclass_idname("blkmap", 0, &blk)); + desc = dev_get_uclass_plat(blk); ut_assertok(fs_set_blk_dev_with_part(desc, 0)); ut_assertok(fs_size("/bin/bash", &file_size)); @@ -312,6 +314,7 @@ static int setup_mmc14(struct unit_test_state *uts, struct udevice **mmcp) static int bootstd_test_luks2_unlock_prederived(struct unit_test_state *uts) { struct blk_desc *desc; + struct udevice *blk; struct udevice *mmc; loff_t file_size; @@ -333,8 +336,8 @@ static int bootstd_test_luks2_unlock_prederived(struct unit_test_state *uts) ut_assert_console_end(); /* Verify that a file can be read from the decrypted filesystem */ - desc = blk_get_devnum_by_uclass_idname("blkmap", 0); - ut_assertnonnull(desc); + ut_assertok(blk_get_devnum_by_uclass_idname("blkmap", 0, &blk)); + desc = dev_get_uclass_plat(blk); ut_assertok(fs_set_blk_dev_with_part(desc, 0)); ut_assertok(fs_size("/bin/bash", &file_size)); -- 2.43.0