diff --git a/sys/dev/nvme/nvme_sim.c b/sys/dev/nvme/nvme_sim.c --- a/sys/dev/nvme/nvme_sim.c +++ b/sys/dev/nvme/nvme_sim.c @@ -305,114 +305,128 @@ 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) +/* + * XXX need to connect this when we add failure notification back + */ +static int +nvme_sim_fail(device_t dev) { - struct nvme_sim_softc *sc = sc_arg; - union ccb *ccb; + struct nvme_sim_softc *sc = device_get_softc(dev); - ccb = xpt_alloc_ccb_nowait(); - if (ccb == NULL) { - printf("unable to alloc CCB for rescan\n"); - return (NULL); - } - - /* - * 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. - */ - 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 (NULL); - } - xpt_rescan(ccb); - - return (sc_arg); -} - -static void -nvme_sim_controller_fail(void *ctrlr_arg) -{ - struct nvme_sim_softc *sc = ctrlr_arg; + if (sc->s_sim == NULL) + return (0); 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); + sc->s_sim = NULL; + return (0); } -struct nvme_consumer *consumer_cookie; - -static void -nvme_sim_init(void) +static int +nvme_sim_detach(device_t dev) { - if (nvme_use_nvd) - return; - - consumer_cookie = nvme_register_consumer(nvme_sim_ns_change, - nvme_sim_new_controller, NULL, nvme_sim_controller_fail); + return (nvme_sim_fail(dev)); } -SYSINIT(nvme_sim_register, SI_SUB_DRIVERS, SI_ORDER_ANY, - nvme_sim_init, NULL); - -static void -nvme_sim_uninit(void) -{ - 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);