Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 10 Dec 2025 22:53:53 +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: a21f12840f5f - main - nvme_sim: Connect to events broadcast with nvme_if
Message-ID:  <6939fa01.b117.36a8aca3@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=a21f12840f5f25d777920957ed8ba7362052eaa7

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

    nvme_sim: Connect to events broadcast with nvme_if
    
    Connect up the nvme_ns_* events. Copy code from old ways, as needed, and
    refactor a little.
    
    Sponsored by:           Netflix
    Reviewed by:            dab
    Differential Revision:  https://reviews.freebsd.org/D51387
---
 sys/dev/nvme/nvme_sim.c   | 145 +++++++++++++++++++++++++++-------------------
 sys/modules/nvme/Makefile |   1 +
 2 files changed, 85 insertions(+), 61 deletions(-)

diff --git a/sys/dev/nvme/nvme_sim.c b/sys/dev/nvme/nvme_sim.c
index 88d777f556ed..d134d1daafc3 100644
--- a/sys/dev/nvme/nvme_sim.c
+++ b/sys/dev/nvme/nvme_sim.c
@@ -44,10 +44,15 @@
 
 #include "nvme_private.h"
 
+#include "nvme_if.h"
+
 #define ccb_accb_ptr spriv_ptr0
 #define ccb_ctrlr_ptr spriv_ptr1
 static void	nvme_sim_action(struct cam_sim *sim, union ccb *ccb);
 static void	nvme_sim_poll(struct cam_sim *sim);
+static int	nvme_sim_ns_added(device_t dev, struct nvme_namespace *ns);
+static int	nvme_sim_ns_changed(device_t dev, uint32_t nsid);
+static int	nvme_sim_ns_removed(device_t dev, struct nvme_namespace *ns);
 
 #define sim2softc(sim)	((struct nvme_sim_softc *)cam_sim_softc(sim))
 #define sim2ctrlr(sim)	(sim2softc(sim)->s_ctrlr)
@@ -304,26 +309,6 @@ nvme_sim_poll(struct cam_sim *sim)
 	nvme_ctrlr_poll(sim2ctrlr(sim));
 }
 
-static void
-nvme_sim_ns_change(struct nvme_namespace *ns, struct nvme_sim_softc *sc)
-{
-	union ccb *ccb;
-
-	/*
-	 * We map the NVMe namespace idea onto the CAM unit LUN. For each new
-	 * namespace, we create a new CAM path for it. We then rescan the path
-	 * to get it to enumerate.
-	 */
-	ccb = xpt_alloc_ccb();
-	if (xpt_create_path(&ccb->ccb_h.path, /*periph*/NULL,
-	    cam_sim_path(sc->s_sim), 0, ns->id) != CAM_REQ_CMP) {
-		printf("unable to create path for rescan\n");
-		xpt_free_ccb(ccb);
-		return;
-	}
-	xpt_rescan(ccb);
-}
-
 static int
 nvme_sim_probe(device_t dev)
 {
@@ -339,7 +324,7 @@ nvme_sim_attach(device_t dev)
 {
 	struct cam_devq *devq;
 	int max_trans;
-	int err = ENOMEM;
+	int err = ENXIO;
 	struct nvme_sim_softc *sc = device_get_softc(dev);
 	struct nvme_controller	*ctrlr = device_get_ivars(dev);
 
@@ -356,16 +341,14 @@ nvme_sim_attach(device_t dev)
 	if (sc->s_sim == NULL) {
 		device_printf(dev, "Failed to allocate a sim\n");
 		cam_simq_free(devq);
-		goto err1;
+		return (ENOMEM);
 	}
 	if (xpt_bus_register(sc->s_sim, dev, 0) != CAM_SUCCESS) {
-		err = ENXIO;
 		device_printf(dev, "Failed to create a bus\n");
 		goto err2;
 	}
 	if (xpt_create_path(&sc->s_path, /*periph*/NULL, cam_sim_path(sc->s_sim),
 	    CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
-		err = ENXIO;
 		device_printf(dev, "Failed to create a path\n");
 		goto err3;
 	}
@@ -375,7 +358,7 @@ nvme_sim_attach(device_t dev)
 
 		if (ns->data.nsze == 0)
 			continue;
-		nvme_sim_ns_change(ns, sc);
+		nvme_sim_ns_added(dev, ns);
 	}
 
 	return (0);
@@ -383,69 +366,109 @@ err3:
 	xpt_bus_deregister(cam_sim_path(sc->s_sim));
 err2:
 	cam_sim_free(sc->s_sim, /*free_devq*/TRUE);
-err1:
-	free(sc, M_NVME);
 	return (err);
 }
 
+
 static int
-nvme_sim_fail(device_t dev, struct nvme_namespace *ns)
+nvme_sim_fail_all_ns(device_t dev)
 {
 	struct nvme_sim_softc *sc = device_get_softc(dev);
-	struct cam_path *tmppath;
-	union ccb *ccb;
+	struct nvme_controller *ctrlr = sc->s_ctrlr;
 
-	if (xpt_create_path(&tmppath, /*periph*/NULL,
-	    cam_sim_path(sc->s_sim), 0, ns->id) != CAM_REQ_CMP) {
-		device_printf(dev, "unable to create path for rescan\n");
-		return (ENOMEM);
-	}
-	/*
-	 * If it's gone, then signal that and leave.
-	 */
-	if (ns->flags & NVME_NS_GONE) {
-		xpt_async(AC_LOST_DEVICE, tmppath, NULL);
-		xpt_free_path(tmppath);
-		return (0);
-	}
+	for (int i = 0; i < min(ctrlr->cdata.nn, NVME_MAX_NAMESPACES); i++) {
+		struct nvme_namespace	*ns = &ctrlr->ns[i];
 
-	ccb = xpt_alloc_ccb_nowait();
-	if (ccb == NULL) {
-		device_printf(dev, "unable to alloc CCB for rescan\n");
-		return (ENOMEM);
+		if (ns->data.nsze == 0)
+			continue;
+		nvme_sim_ns_removed(dev, ns);
 	}
-	ccb->ccb_h.path = tmppath;
+	return (0);
+}
+
+static int
+nvme_sim_detach(device_t dev)
+{
+	return (nvme_sim_fail_all_ns(dev));
+}
+
+static int
+nvme_sim_ns_added(device_t dev, struct nvme_namespace *ns)
+{
+	struct nvme_sim_softc *sc = device_get_softc(dev);
+	union ccb *ccb;
 
 	/*
 	 * We map the NVMe namespace idea onto the CAM unit LUN. For each new
-	 * namespace, scan or rescan the path to enumerate it. tmppath freed at
-	 * end of scan.
+	 * namespace, scan or rescan the path to enumerate it.
 	 */
+	ccb = xpt_alloc_ccb();
+	if (xpt_create_path(&ccb->ccb_h.path, /*periph*/NULL,
+	    cam_sim_path(sc->s_sim), 0, ns->id) != CAM_REQ_CMP) {
+		printf("unable to create path for rescan\n");
+		return (ENOMEM);
+	}
 	xpt_rescan(ccb);
 
 	return (0);
 }
 
 static int
-nvme_sim_detach(device_t dev)
+nvme_sim_ns_removed(device_t dev, struct nvme_namespace *ns)
 {
-	struct nvme_controller	*ctrlr = device_get_ivars(dev);
-
-	for (int i = 0; i < min(ctrlr->cdata.nn, NVME_MAX_NAMESPACES); i++) {
-		struct nvme_namespace	*ns = &ctrlr->ns[i];
+	struct nvme_sim_softc *sc = device_get_softc(dev);
+	struct cam_path *tmppath;
 
-		if (ns->data.nsze == 0)
-			continue;
-		nvme_sim_fail(dev, ns);
+	if (xpt_create_path(&tmppath, /*periph*/NULL,
+	    cam_sim_path(sc->s_sim), 0, ns->id) != CAM_REQ_CMP) {
+		printf("unable to create path for rescan\n");
+		return (ENOMEM);
 	}
+	xpt_async(AC_LOST_DEVICE, tmppath, NULL);
+	xpt_free_path(tmppath);
+
+	return (0);
+}
+
+static int
+nvme_sim_ns_changed(device_t dev, uint32_t nsid)
+{
+	struct nvme_sim_softc *sc = device_get_softc(dev);
+	struct nvme_namespace *ns = &sc->s_ctrlr->ns[nsid - 1];
+
+	/*
+	 * These wind up being the same. For a configured cam_ed, we generate
+	 * AC_GETDEV_CHANGED, but for new one we do AC_FOUND_DEVICE, but the
+	 * scan is the same.
+	 */
+	return (nvme_sim_ns_added(dev, ns));
+}
+
+static int
+nvme_sim_controller_failed(device_t dev)
+{
+	return (nvme_sim_fail_all_ns(dev));
+}
+
+static int
+nvme_sim_handle_aen(device_t dev, const struct nvme_completion *cpl,
+    uint32_t pg_nr, void *page, uint32_t page_len)
+{
+	/* Do nothing */
 	return (0);
 }
 
 static device_method_t nvme_sim_methods[] = {
 	/* Device interface */
-	DEVMETHOD(device_probe,     nvme_sim_probe),
-	DEVMETHOD(device_attach,    nvme_sim_attach),
-	DEVMETHOD(device_detach,    nvme_sim_detach),
+	DEVMETHOD(device_probe,		nvme_sim_probe),
+	DEVMETHOD(device_attach,	nvme_sim_attach),
+	DEVMETHOD(device_detach,	nvme_sim_detach),
+	/* Nvme controller messages */
+	DEVMETHOD(nvme_ns_added,   	nvme_sim_ns_added),
+	DEVMETHOD(nvme_ns_removed,   	nvme_sim_ns_removed),
+	DEVMETHOD(nvme_ns_changed,   	nvme_sim_ns_changed),
+	DEVMETHOD(nvme_controller_failed, nvme_sim_controller_failed),
+	DEVMETHOD(nvme_handle_aen,   	nvme_sim_handle_aen),
 	{ 0, 0 }
 };
 
diff --git a/sys/modules/nvme/Makefile b/sys/modules/nvme/Makefile
index 936a28fa5de9..b10f5dd190bf 100644
--- a/sys/modules/nvme/Makefile
+++ b/sys/modules/nvme/Makefile
@@ -16,6 +16,7 @@ SRCS =	nvme.c			\
 				\
 	bus_if.h		\
 	device_if.h		\
+	nvme_if.h		\
 	opt_cam.h		\
 	opt_nvme.h		\
 	pci_if.h



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?6939fa01.b117.36a8aca3>