git: a21f12840f5f - main - nvme_sim: Connect to events broadcast with nvme_if
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 10 Dec 2025 22:53:53 UTC
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