Date: Wed, 10 Dec 2025 22:53:51 +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: 1e39b5d4833e - main - nvme_sim: Attach as a child of nvme Message-ID: <6939f9ff.b819.65552ec6@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=1e39b5d4833e3be0261ff9cc2d360aa36698c3dc commit 1e39b5d4833e3be0261ff9cc2d360aa36698c3dc Author: Warner Losh <imp@FreeBSD.org> AuthorDate: 2025-12-10 22:52:23 +0000 Commit: Warner Losh <imp@FreeBSD.org> CommitDate: 2025-12-10 22:52:23 +0000 nvme_sim: Attach as a child of nvme Rather than registering as a consumer of the nvme controller, hook into the child device and use that. This is a small regression at the moment: we don't fail the device when that happens at runtime, and we don't handle new namespaces when they arrive (though that feature is currently fragile). Sponsored by: Netflix Differential Revision: https://reviews.freebsd.org/D51384 --- sys/dev/nvme/nvme_sim.c | 138 +++++++++++++++++++++++++++++------------------- 1 file changed, 85 insertions(+), 53 deletions(-) diff --git a/sys/dev/nvme/nvme_sim.c b/sys/dev/nvme/nvme_sim.c index e015fbe4d072..88d777f556ed 100644 --- a/sys/dev/nvme/nvme_sim.c +++ b/sys/dev/nvme/nvme_sim.c @@ -304,61 +304,101 @@ nvme_sim_poll(struct cam_sim *sim) nvme_ctrlr_poll(sim2ctrlr(sim)); } -static void * -nvme_sim_new_controller(struct nvme_controller *ctrlr) +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) +{ + if (nvme_use_nvd) + return (ENXIO); + + device_set_desc(dev, "nvme cam"); + return (BUS_PROBE_DEFAULT); +} + +static int +nvme_sim_attach(device_t dev) { - struct nvme_sim_softc *sc; struct cam_devq *devq; int max_trans; + int err = ENOMEM; + struct nvme_sim_softc *sc = device_get_softc(dev); + struct nvme_controller *ctrlr = device_get_ivars(dev); max_trans = ctrlr->max_hw_pend_io; devq = cam_simq_alloc(max_trans); if (devq == NULL) - return (NULL); + return (ENOMEM); - sc = malloc(sizeof(*sc), M_NVME, M_ZERO | M_WAITOK); sc->s_ctrlr = ctrlr; sc->s_sim = cam_sim_alloc(nvme_sim_action, nvme_sim_poll, - "nvme", sc, device_get_unit(ctrlr->dev), + "nvme", sc, device_get_unit(dev), NULL, max_trans, max_trans, devq); if (sc->s_sim == NULL) { - printf("Failed to allocate a sim\n"); + device_printf(dev, "Failed to allocate a sim\n"); cam_simq_free(devq); goto err1; } - if (xpt_bus_register(sc->s_sim, ctrlr->dev, 0) != CAM_SUCCESS) { - printf("Failed to create a bus\n"); + 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) { - printf("Failed to create a path\n"); + err = ENXIO; + device_printf(dev, "Failed to create a path\n"); goto err3; } - return (sc); + 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_sim_ns_change(ns, sc); + } + return (0); 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 (NULL); + return (err); } -static void * -nvme_sim_ns_change(struct nvme_namespace *ns, void *sc_arg) +static int +nvme_sim_fail(device_t dev, struct nvme_namespace *ns) { - struct nvme_sim_softc *sc = sc_arg; + struct nvme_sim_softc *sc = device_get_softc(dev); struct cam_path *tmppath; union ccb *ccb; 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 (NULL); + device_printf(dev, "unable to create path for rescan\n"); + return (ENOMEM); } /* * If it's gone, then signal that and leave. @@ -366,13 +406,13 @@ nvme_sim_ns_change(struct nvme_namespace *ns, void *sc_arg) if (ns->flags & NVME_NS_GONE) { xpt_async(AC_LOST_DEVICE, tmppath, NULL); xpt_free_path(tmppath); - return (sc_arg); + return (0); } ccb = xpt_alloc_ccb_nowait(); if (ccb == NULL) { - printf("unable to alloc CCB for rescan\n"); - return (NULL); + device_printf(dev, "unable to alloc CCB for rescan\n"); + return (ENOMEM); } ccb->ccb_h.path = tmppath; @@ -383,45 +423,37 @@ nvme_sim_ns_change(struct nvme_namespace *ns, void *sc_arg) */ xpt_rescan(ccb); - return (sc_arg); + return (0); } -static void -nvme_sim_controller_fail(void *ctrlr_arg) +static int +nvme_sim_detach(device_t dev) { - struct nvme_sim_softc *sc = ctrlr_arg; + struct nvme_controller *ctrlr = device_get_ivars(dev); - xpt_async(AC_LOST_DEVICE, sc->s_path, NULL); - xpt_free_path(sc->s_path); - xpt_bus_deregister(cam_sim_path(sc->s_sim)); - cam_sim_free(sc->s_sim, /*free_devq*/TRUE); - free(sc, M_NVME); -} + for (int i = 0; i < min(ctrlr->cdata.nn, NVME_MAX_NAMESPACES); i++) { + struct nvme_namespace *ns = &ctrlr->ns[i]; -struct nvme_consumer *consumer_cookie; - -static void -nvme_sim_init(void *dummy __unused) -{ - if (nvme_use_nvd) - return; - - consumer_cookie = nvme_register_consumer(nvme_sim_ns_change, - nvme_sim_new_controller, NULL, nvme_sim_controller_fail); + if (ns->data.nsze == 0) + continue; + nvme_sim_fail(dev, ns); + } + return (0); } -SYSINIT(nvme_sim_register, SI_SUB_DRIVERS, SI_ORDER_ANY, - nvme_sim_init, NULL); - -static void -nvme_sim_uninit(void *dummy __unused) -{ - if (nvme_use_nvd) - return; - /* XXX Cleanup */ +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), + { 0, 0 } +}; - nvme_unregister_consumer(consumer_cookie); -} +static driver_t nvme_sim_driver = { + "nvme_sim", + nvme_sim_methods, + sizeof(struct nvme_sim_softc), +}; -SYSUNINIT(nvme_sim_unregister, SI_SUB_DRIVERS, SI_ORDER_ANY, - nvme_sim_uninit, NULL); +DRIVER_MODULE(nvme_sim, nvme, nvme_sim_driver, NULL, NULL); +MODULE_VERSION(nvme_shim, 1);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?6939f9ff.b819.65552ec6>
