
At present for each namespace there is a block device created for it. There won't be any issue if the number of supported namespaces reported from the NVMe device is only 1.
Since QEMU commit 7f0f1acedf15 ("hw/block/nvme: support multiple namespaces"), the number of supported namespaces reported has been changed from 1 to 256, but the active namespace depends on the command line parameters passed to QEMU, with the most common case that namespace 1 being active and all other 255 inactive.
If a namespace is not active, the namespace identify command returns a zero filled data structure. We can use field NSZE (namespace size) to decide if a block device should be created.
Reported-by: Heinrich Schuchardt xypron.glpk@gmx.de Signed-off-by: Bin Meng bmeng.cn@gmail.com ---
drivers/nvme/nvme.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-)
diff --git a/drivers/nvme/nvme.c b/drivers/nvme/nvme.c index 0b4a73d170..5ec5eaca16 100644 --- a/drivers/nvme/nvme.c +++ b/drivers/nvme/nvme.c @@ -835,6 +835,7 @@ static int nvme_probe(struct udevice *udev) { int ret; struct nvme_dev *ndev = dev_get_priv(udev); + struct nvme_id_ns *id;
ndev->instance = trailing_strtol(udev->name);
@@ -880,26 +881,46 @@ static int nvme_probe(struct udevice *udev) nvme_get_info_from_identify(ndev);
/* Create a blk device for each namespace */ + + id = memalign(ndev->page_size, sizeof(struct nvme_id_ns)); + if (!id) { + ret = -ENOMEM; + goto free_queue; + } + for (int i = 1; i <= ndev->nn; i++) { struct udevice *ns_udev; struct nvme_child_plat *pplat; char name[20];
+ memset(id, 0, sizeof(*id)); + if (nvme_identify(ndev, i, 0, (dma_addr_t)(long)id)) { + ret = -EIO; + goto free_id; + } + + /* skip inactive namespace */ + if (!id->nsze) + continue; + sprintf(name, "blk#%d", i);
/* The real blksz and size will be set by nvme_blk_probe() */ ret = blk_create_devicef(udev, "nvme-blk", name, IF_TYPE_NVME, -1, 512, 0, &ns_udev); if (ret) - goto free_queue; + goto free_id;
/* Update the platform data */ pplat = dev_get_parent_plat(ns_udev); pplat->ns_id = i; }
+ free(id); return 0;
+free_id: + free(id); free_queue: free((void *)ndev->queues); free_nvme: