From: Ana Bobillo <[email protected]> nvme_blk_probe() takes the LBA data size (log2 of the block size) of the namespace's current LBA format as the device reports it, and shifts by it: 1 << ns->lba_shift is undefined for a value of 31 or more, and nvme_blk_rw() sizes each transfer with 1 << (dev->max_transfer_shift - ns->lba_shift), a negative shift for a block larger than the maximum transfer size of the controller.
Check it, through a new nvme_lba_shift(), against the block sizes blk_valid_blksz() accepts and the maximum transfer size. nvme_init() skips a namespace with an unsupported LBA data size, as it skips an inactive one, rather than create a block device for it that then fails to probe, failing nvme_init() and leaving the namespaces it has already probed on a controller that failed to probe. nvme_blk_probe() checks the value it uses again. Signed-off-by: Ana Bobillo <[email protected]> Reviewed-by: Simon Glass <[email protected]> --- (no changes since v1) drivers/nvme/nvme.c | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/drivers/nvme/nvme.c b/drivers/nvme/nvme.c index c815a967137..3df9b531bfd 100644 --- a/drivers/nvme/nvme.c +++ b/drivers/nvme/nvme.c @@ -15,6 +15,7 @@ #include <time.h> #include <dm/device-internal.h> #include <linux/compat.h> +#include <linux/log2.h> #include "nvme.h" #define NVME_Q_DEPTH 2 @@ -701,6 +702,26 @@ int nvme_scan_namespace(void) return 0; } +/** + * nvme_lba_shift() - Get the LBA data size of a namespace + * + * @dev: NVMe controller + * @id: Identify Namespace data of the namespace + * Return: log2 of its block size, or -EINVAL if that size is not supported + */ +static int nvme_lba_shift(struct nvme_dev *dev, struct nvme_id_ns *id) +{ + u8 ds = id->lbaf[id->flbas & NVME_NS_FLBAS_LBA_MASK].ds; + + if (ds < ilog2(DEFAULT_BLKSZ) || ds > ilog2(BLK_MAX_BLKSZ) || + ds > dev->max_transfer_shift) { + log_err("Unsupported LBA data size 2^%d\n", ds); + return -EINVAL; + } + + return ds; +} + static int nvme_blk_probe(struct udevice *udev) { struct nvme_dev *ndev = dev_get_priv(udev->parent); @@ -708,6 +729,7 @@ static int nvme_blk_probe(struct udevice *udev) struct nvme_ns *ns = dev_get_priv(udev); u8 flbas; struct nvme_id_ns *id; + int ret; id = memalign(ndev->page_size, sizeof(struct nvme_id_ns)); if (!id) @@ -724,7 +746,12 @@ static int nvme_blk_probe(struct udevice *udev) memcpy(&ns->eui64, &id->eui64, sizeof(id->eui64)); flbas = id->flbas & NVME_NS_FLBAS_LBA_MASK; ns->flbas = flbas; - ns->lba_shift = id->lbaf[flbas].ds; + ret = nvme_lba_shift(ndev, id); + if (ret < 0) { + free(id); + return ret; + } + ns->lba_shift = ret; list_add(&ns->list, &ndev->namespaces); desc->lba = le64_to_cpu(id->nsze); @@ -899,6 +926,10 @@ int nvme_init(struct udevice *udev) if (!id->nsze) continue; + /* skip a namespace whose block size is not supported */ + if (nvme_lba_shift(ndev, id) < 0) + continue; + /* * Encode the namespace id to the device name so that * we can extract it when doing the probe.
