[PATCH 2/2] nvme: Skip block device creation for inactive namespaces

Bin Meng bmeng.cn at gmail.com
Mon Jun 21 16:56:29 CEST 2021


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 at gmx.de>
Signed-off-by: Bin Meng <bmeng.cn at 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:
-- 
2.25.1



More information about the U-Boot mailing list