All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2] nvme: Move block dev creation from uclass post probe to driver probe
@ 2021-06-21 14:56 Bin Meng
  2021-06-21 14:56 ` [PATCH 2/2] nvme: Skip block device creation for inactive namespaces Bin Meng
  0 siblings, 1 reply; 2+ messages in thread
From: Bin Meng @ 2021-06-21 14:56 UTC (permalink / raw)
  To: u-boot; +Cc: Bin Meng

At present the block device creation happens in the NVMe uclass driver
post probe phase. Move it to driver probe phase instead. A per-child
platdata is added to store the namespace id, so that we can obtain it
in the block driver probe phase, without the assumption that the ns id
is encoded in the block device name.

Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
---

 drivers/nvme/nvme-uclass.c | 30 ------------------------------
 drivers/nvme/nvme.c        | 30 +++++++++++++++++++++++++-----
 drivers/nvme/nvme.h        | 14 ++++++++++++++
 3 files changed, 39 insertions(+), 35 deletions(-)

diff --git a/drivers/nvme/nvme-uclass.c b/drivers/nvme/nvme-uclass.c
index 277e31e1f3..610166d76e 100644
--- a/drivers/nvme/nvme-uclass.c
+++ b/drivers/nvme/nvme-uclass.c
@@ -5,39 +5,9 @@
  */
 
 #include <common.h>
-#include <blk.h>
-#include <errno.h>
 #include <dm.h>
-#include <dm/device.h>
-#include "nvme.h"
-
-static int nvme_uclass_post_probe(struct udevice *udev)
-{
-	char name[20];
-	struct udevice *ns_udev;
-	int i, ret;
-	struct nvme_dev *ndev = dev_get_priv(udev);
-
-	/* Create a blk device for each namespace */
-	for (i = 0; i < ndev->nn; i++) {
-		/*
-		 * Encode the namespace id to the device name so that
-		 * we can extract it when doing the probe.
-		 */
-		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)
-			return ret;
-	}
-
-	return 0;
-}
 
 UCLASS_DRIVER(nvme) = {
 	.name	= "nvme",
 	.id	= UCLASS_NVME,
-	.post_probe = nvme_uclass_post_probe,
 };
diff --git a/drivers/nvme/nvme.c b/drivers/nvme/nvme.c
index c61dab20c5..0b4a73d170 100644
--- a/drivers/nvme/nvme.c
+++ b/drivers/nvme/nvme.c
@@ -696,10 +696,11 @@ int nvme_scan_namespace(void)
 static int nvme_blk_probe(struct udevice *udev)
 {
 	struct nvme_dev *ndev = dev_get_priv(udev->parent);
+	struct nvme_child_plat *nvme_pplat = dev_get_parent_plat(udev);
 	struct blk_desc *desc = dev_get_uclass_plat(udev);
 	struct nvme_ns *ns = dev_get_priv(udev);
 	u8 flbas;
-	struct pci_child_plat *pplat;
+	struct pci_child_plat *pci_pplat;
 	struct nvme_id_ns *id;
 
 	id = memalign(ndev->page_size, sizeof(struct nvme_id_ns));
@@ -708,8 +709,7 @@ static int nvme_blk_probe(struct udevice *udev)
 
 	memset(ns, 0, sizeof(*ns));
 	ns->dev = ndev;
-	/* extract the namespace id from the block device name */
-	ns->ns_id = trailing_strtol(udev->name) + 1;
+	ns->ns_id = nvme_pplat->ns_id;
 	if (nvme_identify(ndev, ns->ns_id, 0, (dma_addr_t)(long)id)) {
 		free(id);
 		return -EIO;
@@ -727,8 +727,8 @@ static int nvme_blk_probe(struct udevice *udev)
 	desc->log2blksz = ns->lba_shift;
 	desc->blksz = 1 << ns->lba_shift;
 	desc->bdev = udev;
-	pplat = dev_get_parent_plat(udev->parent);
-	sprintf(desc->vendor, "0x%.4x", pplat->vendor);
+	pci_pplat = dev_get_parent_plat(udev->parent);
+	sprintf(desc->vendor, "0x%.4x", pci_pplat->vendor);
 	memcpy(desc->product, ndev->serial, sizeof(ndev->serial));
 	memcpy(desc->revision, ndev->firmware_rev, sizeof(ndev->firmware_rev));
 
@@ -879,6 +879,25 @@ static int nvme_probe(struct udevice *udev)
 
 	nvme_get_info_from_identify(ndev);
 
+	/* Create a blk device for each namespace */
+	for (int i = 1; i <= ndev->nn; i++) {
+		struct udevice *ns_udev;
+		struct nvme_child_plat *pplat;
+		char name[20];
+
+		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;
+
+		/* Update the platform data */
+		pplat = dev_get_parent_plat(ns_udev);
+		pplat->ns_id = i;
+	}
+
 	return 0;
 
 free_queue:
@@ -893,6 +912,7 @@ U_BOOT_DRIVER(nvme) = {
 	.bind	= nvme_bind,
 	.probe	= nvme_probe,
 	.priv_auto	= sizeof(struct nvme_dev),
+	.per_child_plat_auto	= sizeof(struct nvme_child_plat),
 };
 
 struct pci_device_id nvme_supported[] = {
diff --git a/drivers/nvme/nvme.h b/drivers/nvme/nvme.h
index aa4b3bac67..11b3ab6872 100644
--- a/drivers/nvme/nvme.h
+++ b/drivers/nvme/nvme.h
@@ -637,4 +637,18 @@ struct nvme_ns {
 	u32 mode_select_block_len;
 };
 
+/**
+ * An NVM Express child (namespace) platdata
+ *
+ * Every blk device on a NVMe bus has this per-child data.
+ *
+ * It can be accessed using dev_get_parent_plat(dev) if dev->parent is a
+ * NVMe device (i.e. UCLASS_NVME)
+ *
+ * @ns_id:	namespace id
+ */
+struct nvme_child_plat {
+	unsigned ns_id;
+};
+
 #endif /* __DRIVER_NVME_H__ */
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* [PATCH 2/2] nvme: Skip block device creation for inactive namespaces
  2021-06-21 14:56 [PATCH 1/2] nvme: Move block dev creation from uclass post probe to driver probe Bin Meng
@ 2021-06-21 14:56 ` Bin Meng
  0 siblings, 0 replies; 2+ messages in thread
From: Bin Meng @ 2021-06-21 14:56 UTC (permalink / raw)
  To: u-boot; +Cc: Bin Meng, Heinrich Schuchardt

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:
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2021-06-21 14:57 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-06-21 14:56 [PATCH 1/2] nvme: Move block dev creation from uclass post probe to driver probe Bin Meng
2021-06-21 14:56 ` [PATCH 2/2] nvme: Skip block device creation for inactive namespaces Bin Meng

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.