Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 10 Dec 2025 22:53:54 +0000
From:      Warner Losh <imp@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: aed44717a160 - main - nvd: Connect nvme_if methods
Message-ID:  <6939fa02.b2a3.323cdf4@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help

The branch main has been updated by imp:

URL: https://cgit.FreeBSD.org/src/commit/?id=aed44717a1606e4c5c79f7c8831de49cba64d7e6

commit aed44717a1606e4c5c79f7c8831de49cba64d7e6
Author:     Warner Losh <imp@FreeBSD.org>
AuthorDate: 2025-12-10 22:52:38 +0000
Commit:     Warner Losh <imp@FreeBSD.org>
CommitDate: 2025-12-10 22:52:38 +0000

    nvd: Connect nvme_if methods
    
    Conenct methods to manage namespaces explicitly to replace the old
    consumer interface.
    
    Sponsored by:           Netflix
    Differential Revision:  https://reviews.freebsd.org/D51388
---
 sys/dev/nvd/nvd.c           | 237 +++++++++++++++++++++++++-------------------
 sys/dev/nvme/nvme.c         |  36 -------
 sys/dev/nvme/nvme_ctrlr.c   |  45 ++++++---
 sys/dev/nvme/nvme_if.m      |   2 +-
 sys/dev/nvme/nvme_private.h |   2 -
 sys/modules/nvd/Makefile    |   2 +-
 6 files changed, 167 insertions(+), 157 deletions(-)

diff --git a/sys/dev/nvd/nvd.c b/sys/dev/nvd/nvd.c
index fef3d1a1bc92..d96a752a12d9 100644
--- a/sys/dev/nvd/nvd.c
+++ b/sys/dev/nvd/nvd.c
@@ -29,6 +29,7 @@
 
 #include <sys/param.h>
 #include <sys/bio.h>
+#include <sys/bus.h>
 #include <sys/devicestat.h>
 #include <sys/kernel.h>
 #include <sys/malloc.h>
@@ -47,6 +48,8 @@
 
 #include <dev/pci/pcivar.h>
 
+#include "nvme_if.h"
+
 #define NVD_STR		"nvd"
 
 struct nvd_disk;
@@ -385,17 +388,96 @@ nvd_bioq_process(void *arg, int pending)
 	}
 }
 
-static void
-nvd_new_disk(struct nvme_namespace *ns, struct nvd_controller *ctrlr)
+static int
+nvdc_controller_failed(device_t dev)
+{
+	struct nvd_controller	*nvd_ctrlr = device_get_softc(dev);
+	struct nvd_disk		*ndisk;
+
+	mtx_lock(&nvd_lock);
+	TAILQ_REMOVE(&ctrlr_head, nvd_ctrlr, tailq);
+	TAILQ_FOREACH(ndisk, &nvd_ctrlr->disk_head, ctrlr_tailq)
+		nvd_gone(ndisk);
+	while (!TAILQ_EMPTY(&nvd_ctrlr->disk_head))
+		msleep(&nvd_ctrlr->disk_head, &nvd_lock, 0, "nvd_fail", 0);
+	mtx_unlock(&nvd_lock);
+	return (0);
+}
+
+static int
+nvdc_probe(device_t dev)
+{
+	if (!nvme_use_nvd)
+		return (ENXIO);
+
+	device_set_desc(dev, "nvme storage namespace");
+	return (BUS_PROBE_DEFAULT);
+}
+
+static int
+nvdc_attach(device_t dev)
+{
+	struct nvd_controller	*nvd_ctrlr = device_get_softc(dev);
+	struct nvme_controller	*ctrlr = device_get_ivars(dev);
+
+	nvd_ctrlr->ctrlr = ctrlr;
+	TAILQ_INIT(&nvd_ctrlr->disk_head);
+	mtx_lock(&nvd_lock);
+	TAILQ_INSERT_TAIL(&ctrlr_head, nvd_ctrlr, tailq);
+	mtx_unlock(&nvd_lock);
+
+	return (0);
+}
+
+static int
+nvdc_detach(device_t dev)
+{
+	return (nvdc_controller_failed(dev));
+}
+
+static struct nvd_disk *
+nvd_nsid_to_disk(struct nvd_controller *nvd_ctrlr, uint32_t nsid)
+{
+	struct nvd_disk		*ndisk;
+
+	mtx_lock(&nvd_lock);
+	TAILQ_FOREACH(ndisk, &nvd_ctrlr->disk_head, ctrlr_tailq) {
+		if (ndisk->ns->id != nsid)
+			continue;
+		break;
+	}
+	mtx_unlock(&nvd_lock);
+	return ndisk;
+}
+
+static struct nvd_disk *
+nvd_ns_to_disk(struct nvd_controller *nvd_ctrlr, struct nvme_namespace *ns)
 {
+	struct nvd_disk		*ndisk;
+
+	mtx_lock(&nvd_lock);
+	TAILQ_FOREACH(ndisk, &nvd_ctrlr->disk_head, ctrlr_tailq) {
+		if (ndisk->ns != ns)
+			continue;
+		break;
+	}
+	mtx_unlock(&nvd_lock);
+	return ndisk;
+}
+
+static int
+nvdc_ns_added(device_t dev, struct nvme_namespace *ns)
+{
+	struct nvd_controller	*nvd_ctrlr = device_get_softc(dev);
+	struct nvd_disk		*ndisk;
 	uint8_t			descr[NVME_MODEL_NUMBER_LENGTH+1];
-	struct nvd_disk		*ndisk, *tnd;
+	struct nvd_disk		*tnd;
 	struct disk		*disk;
-	device_t		 dev = ctrlr->ctrlr->dev;
-	int unit;
+	device_t		 pdev = nvd_ctrlr->ctrlr->dev;
+	int			 unit;
 
 	ndisk = malloc(sizeof(struct nvd_disk), M_NVD, M_ZERO | M_WAITOK);
-	ndisk->ctrlr = ctrlr;
+	ndisk->ctrlr = nvd_ctrlr;
 	ndisk->ns = ns;
 	ndisk->cur_depth = 0;
 	ndisk->ordered_in_flight = 0;
@@ -415,7 +497,7 @@ nvd_new_disk(struct nvme_namespace *ns, struct nvd_controller *ctrlr)
 		TAILQ_INSERT_BEFORE(tnd, ndisk, global_tailq);
 	else
 		TAILQ_INSERT_TAIL(&disk_head, ndisk, global_tailq);
-	TAILQ_INSERT_TAIL(&ctrlr->disk_head, ndisk, ctrlr_tailq);
+	TAILQ_INSERT_TAIL(&nvd_ctrlr->disk_head, ndisk, ctrlr_tailq);
 	mtx_unlock(&nvd_lock);
 
 	ndisk->tq = taskqueue_create("nvd_taskq", M_WAITOK,
@@ -464,14 +546,14 @@ nvd_new_disk(struct nvme_namespace *ns, struct nvd_controller *ctrlr)
 	 * which has no access to the config space for this controller, report
 	 * the AHCI controller's data.
 	 */
-	if (ctrlr->ctrlr->quirks & QUIRK_AHCI)
-		dev = device_get_parent(dev);
-	disk->d_hba_vendor = pci_get_vendor(dev);
-	disk->d_hba_device = pci_get_device(dev);
-	disk->d_hba_subvendor = pci_get_subvendor(dev);
-	disk->d_hba_subdevice = pci_get_subdevice(dev);
+	if (nvd_ctrlr->ctrlr->quirks & QUIRK_AHCI)
+		pdev = device_get_parent(pdev);
+	disk->d_hba_vendor = pci_get_vendor(pdev);
+	disk->d_hba_device = pci_get_device(pdev);
+	disk->d_hba_subvendor = pci_get_subvendor(pdev);
+	disk->d_hba_subdevice = pci_get_subdevice(pdev);
 	disk->d_rotation_rate = DISK_RR_NON_ROTATING;
-	strlcpy(disk->d_attachment, device_get_nameunit(dev),
+	strlcpy(disk->d_attachment, device_get_nameunit(pdev),
 	    sizeof(disk->d_attachment));
 
 	disk_create(disk, DISK_VERSION);
@@ -481,14 +563,35 @@ nvd_new_disk(struct nvme_namespace *ns, struct nvd_controller *ctrlr)
 		(uintmax_t)disk->d_mediasize / (1024*1024),
 		(uintmax_t)disk->d_mediasize / disk->d_sectorsize,
 		disk->d_sectorsize);
+
+	return (0);
 }
 
-#if 0
-static void
-nvd_resize(struct nvd_disk *ndisk)
+static int
+nvdc_ns_removed(device_t dev, struct nvme_namespace *ns)
 {
-	struct disk		*disk = ndisk->disk;
-	struct nvme_namespace	*ns = ndisk->ns;
+	struct nvd_controller	*nvd_ctrlr = device_get_softc(dev);
+	struct nvd_disk		*ndisk = nvd_ns_to_disk(nvd_ctrlr, ns);
+
+	if (ndisk == NULL)
+		panic("nvdc: no namespace found for ns  %p", ns);
+	nvd_gone(ndisk);
+	/* gonecb removes it from the list -- no need to wait */
+	return (0);
+}
+
+static int
+nvdc_ns_changed(device_t dev, uint32_t nsid)
+{
+	struct nvd_controller	*nvd_ctrlr = device_get_softc(dev);
+	struct nvd_disk		*ndisk = nvd_nsid_to_disk(nvd_ctrlr, nsid);
+	struct disk		*disk;
+	struct nvme_namespace	*ns;
+
+	if (ndisk == NULL)
+		panic("nvdc: no namespace found for %d", nsid);
+	disk = ndisk->disk;
+	ns = ndisk->ns;
 
 	disk->d_sectorsize = nvme_ns_get_sector_size(ns);
 	disk->d_mediasize = (off_t)nvme_ns_get_size(ns);
@@ -504,98 +607,28 @@ nvd_resize(struct nvd_disk *ndisk)
 		(uintmax_t)disk->d_mediasize / (1024*1024),
 		(uintmax_t)disk->d_mediasize / disk->d_sectorsize,
 		disk->d_sectorsize);
-}
-#endif
-
-static int
-nvdc_fail(device_t dev)
-{
-	return ENXIO;
-}
-
-#if 0
-static void *
-nvd_ns_changed(struct nvme_namespace *ns, void *ctrlr_arg)
-{
-	struct nvd_disk		*ndisk;
-	struct nvd_controller	*ctrlr = ctrlr_arg;
-
-	if ((ns->flags & NVME_NS_DELTA) == 0) {
-		nvd_new_disk(ns, ctrlr_arg);
-		return (ctrlr_arg);
-	}
-
-	mtx_lock(&nvd_lock);
-	TAILQ_FOREACH(ndisk, &ctrlr->disk_head, ctrlr_tailq) {
-		if (ndisk->ns->id != ns->id)
-			continue;
-		nvd_resize(ndisk);
-		break;
-	}
-	mtx_unlock(&nvd_lock);
-	return (ctrlr_arg);
-}
-
-static void
-nvd_controller_fail(void *ctrlr_arg)
-{
-	struct nvd_controller	*ctrlr = ctrlr_arg;
-	struct nvd_disk		*ndisk;
-
-	mtx_lock(&nvd_lock);
-	TAILQ_REMOVE(&ctrlr_head, ctrlr, tailq);
-	TAILQ_FOREACH(ndisk, &ctrlr->disk_head, ctrlr_tailq)
-		nvd_gone(ndisk);
-	while (!TAILQ_EMPTY(&ctrlr->disk_head))
-		msleep(&ctrlr->disk_head, &nvd_lock, 0, "nvd_fail", 0);
-	mtx_unlock(&nvd_lock);
-}
-#endif
-
-static int
-nvdc_probe(device_t dev)
-{
-	if (!nvme_use_nvd)
-		return (ENXIO);
-
-	device_set_desc(dev, "nvme storage namespace");
-	return (BUS_PROBE_DEFAULT);
-}
-
-static int
-nvdc_attach(device_t dev)
-{
-	struct nvd_controller	*nvd_ctrlr = device_get_softc(dev);
-	struct nvme_controller	*ctrlr = device_get_ivars(dev);
-
-	nvd_ctrlr->ctrlr = ctrlr;
-	TAILQ_INIT(&nvd_ctrlr->disk_head);
-	mtx_lock(&nvd_lock);
-	TAILQ_INSERT_TAIL(&ctrlr_head, nvd_ctrlr, tailq);
-	mtx_unlock(&nvd_lock);
-
-	for (int i = 0; i < min(ctrlr->cdata.nn, NVME_MAX_NAMESPACES); i++) {
-		struct nvme_namespace	*ns = &ctrlr->ns[i];
-
-		if (ns->data.nsze == 0)
-			continue;
-		nvd_new_disk(ns, nvd_ctrlr);
-	}
-
 	return (0);
 }
 
 static int
-nvdc_detach(device_t dev)
+nvdc_handle_aen(device_t dev, const struct nvme_completion *cpl,
+    uint32_t pg_nr, void *page, uint32_t page_len)
 {
-	return (nvdc_fail(dev));
+	/* Do nothing */
+	return (0);
 }
 
 static device_method_t nvdc_methods[] = {
 	/* Device interface */
-	DEVMETHOD(device_probe,     nvdc_probe),
-	DEVMETHOD(device_attach,    nvdc_attach),
-	DEVMETHOD(device_detach,    nvdc_detach),
+	DEVMETHOD(device_probe,		nvdc_probe),
+	DEVMETHOD(device_attach,	nvdc_attach),
+	DEVMETHOD(device_detach,	nvdc_detach),
+	/* Nvme controller messages */
+	DEVMETHOD(nvme_ns_added,	nvdc_ns_added),
+	DEVMETHOD(nvme_ns_removed,	nvdc_ns_removed),
+	DEVMETHOD(nvme_ns_changed,	nvdc_ns_changed),
+	DEVMETHOD(nvme_controller_failed, nvdc_controller_failed),
+	DEVMETHOD(nvme_handle_aen,   	nvdc_handle_aen),
 	{ 0, 0 }
 };
 
diff --git a/sys/dev/nvme/nvme.c b/sys/dev/nvme/nvme.c
index 7788889ae591..3ff64c781884 100644
--- a/sys/dev/nvme/nvme.c
+++ b/sys/dev/nvme/nvme.c
@@ -170,18 +170,6 @@ nvme_notify(struct nvme_consumer *cons,
 	}
 }
 
-void
-nvme_notify_new_controller(struct nvme_controller *ctrlr)
-{
-	int i;
-
-	for (i = 0; i < NVME_MAX_CONSUMERS; i++) {
-		if (nvme_consumer[i].id != INVALID_CONSUMER_ID) {
-			nvme_notify(&nvme_consumer[i], ctrlr);
-		}
-	}
-}
-
 static void
 nvme_notify_new_consumer(struct nvme_consumer *cons)
 {
@@ -247,30 +235,6 @@ nvme_notify_fail_consumers(struct nvme_controller *ctrlr)
 	}
 }
 
-void
-nvme_notify_ns(struct nvme_controller *ctrlr, int nsid)
-{
-	struct nvme_consumer	*cons;
-	struct nvme_namespace	*ns;
-	void			*ctrlr_cookie;
-	uint32_t		i;
-
-	KASSERT(nsid <= NVME_MAX_NAMESPACES,
-	    ("%s: Namespace notification to nsid %d exceeds range\n",
-		device_get_nameunit(ctrlr->dev), nsid));
-
-	if (!ctrlr->is_initialized)
-		return;
-
-	ns = &ctrlr->ns[nsid - 1];
-	for (i = 0; i < NVME_MAX_CONSUMERS; i++) {
-		cons = &nvme_consumer[i];
-		if (cons->id != INVALID_CONSUMER_ID && cons->ns_fn != NULL &&
-		    (ctrlr_cookie = ctrlr->cons_cookie[i]) != NULL)
-			ns->cons_cookie[i] = (*cons->ns_fn)(ns, ctrlr_cookie);
-	}
-}
-
 struct nvme_consumer *
 nvme_register_consumer(nvme_cons_ns_fn_t ns_fn, nvme_cons_ctrlr_fn_t ctrlr_fn,
 		       nvme_cons_async_fn_t async_fn,
diff --git a/sys/dev/nvme/nvme_ctrlr.c b/sys/dev/nvme/nvme_ctrlr.c
index 50753f06c4e2..7a449fdc4727 100644
--- a/sys/dev/nvme/nvme_ctrlr.c
+++ b/sys/dev/nvme/nvme_ctrlr.c
@@ -48,6 +48,8 @@
 #include "nvme_private.h"
 #include "nvme_linux.h"
 
+#include "nvme_if.h"
+
 #define B4_CHK_RDY_DELAY_MS	2300		/* work around controller bug */
 
 static void nvme_ctrlr_construct_and_submit_aer(struct nvme_controller *ctrlr,
@@ -1082,10 +1084,20 @@ nvme_ctrlr_start_config_hook(void *arg)
 		device_t child;
 
 		ctrlr->is_initialized = true;
-		nvme_notify_new_controller(ctrlr);
 		child = device_add_child(ctrlr->dev, NULL, DEVICE_UNIT_ANY);
 		device_set_ivars(child, ctrlr);
 		bus_attach_children(ctrlr->dev);
+
+		/*
+		 * Now notify the child of all the known namepsaces
+		 */
+		for (int i = 0; i < min(ctrlr->cdata.nn, NVME_MAX_NAMESPACES); i++) {
+			struct nvme_namespace	*ns = &ctrlr->ns[i];
+
+			if (ns->data.nsze == 0)
+				continue;
+			NVME_NS_ADDED(child, ns);
+		}
 	}
 	TSEXIT();
 }
@@ -1223,23 +1235,26 @@ nvme_ctrlr_aer_task(void *arg, int pending)
 		nvme_ctrlr_cmd_set_async_event_config(aer->ctrlr,
 		    aer->ctrlr->async_event_config, NULL, NULL);
 	} else if (aer->log_page_id == NVME_LOG_CHANGED_NAMESPACE) {
-		struct nvme_ns_list *nsl =
-		    (struct nvme_ns_list *)aer->log_page_buffer;
-		struct nvme_controller *ctrlr = aer->ctrlr;
+		device_t *children;
+		int n_children;
+		struct nvme_ns_list *nsl;
 
+		if (device_get_children(aer->ctrlr->dev, &children, &n_children) != 0) {
+			children = NULL;
+			n_children = 0;
+		}
+		nsl = (struct nvme_ns_list *)aer->log_page_buffer;
 		for (int i = 0; i < nitems(nsl->ns) && nsl->ns[i] != 0; i++) {
-			struct nvme_namespace *ns;
-			uint32_t id = nsl->ns[i];
-
-			if (nsl->ns[i] > NVME_MAX_NAMESPACES)
-				break;
-
-			ns = &ctrlr->ns[id - 1];
-			ns->flags |= NVME_NS_DELTA;
-			nvme_ns_construct(ns, id, ctrlr);
-			nvme_notify_ns(ctrlr, id);
-			ns->flags &= ~NVME_NS_DELTA;
+			/*
+			 * I think we need to query the name space here and see
+			 * if it went away, arrived, or changed in size and call
+			 * the nuanced routine (after constructing or before
+			 * destructing the namespace). XXX needs more work XXX.
+			 */
+			for (int j = 0; j < n_children; j++)
+				NVME_NS_CHANGED(children[j], nsl->ns[i]);
 		}
+		free(children, M_TEMP);
 	}
 
 	/*
diff --git a/sys/dev/nvme/nvme_if.m b/sys/dev/nvme/nvme_if.m
index a89381d165f7..5a06ff112f4c 100644
--- a/sys/dev/nvme/nvme_if.m
+++ b/sys/dev/nvme/nvme_if.m
@@ -33,7 +33,7 @@ METHOD int ns_removed {
 #
 METHOD int ns_changed {
 	device_t	dev;		/* nvme device */
-	struct nvme_namespace *ns;	/* information about the namespace */
+	uint32_t	nsid;		/* nsid that just changed */
 };
 
 #
diff --git a/sys/dev/nvme/nvme_private.h b/sys/dev/nvme/nvme_private.h
index a425a6a5ad62..cd0ef444150f 100644
--- a/sys/dev/nvme/nvme_private.h
+++ b/sys/dev/nvme/nvme_private.h
@@ -561,8 +561,6 @@ void	nvme_notify_async_consumers(struct nvme_controller *ctrlr,
 				    uint32_t log_page_id, void *log_page_buffer,
 				    uint32_t log_page_size);
 void	nvme_notify_fail_consumers(struct nvme_controller *ctrlr);
-void	nvme_notify_new_controller(struct nvme_controller *ctrlr);
-void	nvme_notify_ns(struct nvme_controller *ctrlr, int nsid);
 
 void	nvme_ctrlr_shared_handler(void *arg);
 void	nvme_ctrlr_poll(struct nvme_controller *ctrlr);
diff --git a/sys/modules/nvd/Makefile b/sys/modules/nvd/Makefile
index 08b2d61859e9..84bffa71942e 100644
--- a/sys/modules/nvd/Makefile
+++ b/sys/modules/nvd/Makefile
@@ -1,6 +1,6 @@
 .PATH: ${SRCTOP}/sys/dev/nvd
 
 KMOD=	nvd
-SRCS=	nvd.c opt_geom.h device_if.h bus_if.h pci_if.h
+SRCS=	nvd.c opt_geom.h device_if.h bus_if.h nvme_if.h pci_if.h
 
 .include <bsd.kmod.mk>



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?6939fa02.b2a3.323cdf4>