Author: mav
Date: Mon Apr 30 23:05:57 2018
New Revision: 333130
URL: https://svnweb.freebsd.org/changeset/base/333130

Log:
  Improve nvme(4) attach/detach sequences.
  
  This change allows clean device detach on attach failures and driver unload,
  while previous code tried to talk to already shut down controller, or even
  accessed resources failed to allocate.
  
  Sponsored by: iXsystems, Inc.

Modified:
  head/sys/dev/nvme/nvme_ctrlr.c

Modified: head/sys/dev/nvme/nvme_ctrlr.c
==============================================================================
--- head/sys/dev/nvme/nvme_ctrlr.c      Mon Apr 30 21:56:08 2018        
(r333129)
+++ head/sys/dev/nvme/nvme_ctrlr.c      Mon Apr 30 23:05:57 2018        
(r333130)
@@ -1203,6 +1203,7 @@ nvme_ctrlr_setup_interrupts(struct nvme_controller *ct
 int
 nvme_ctrlr_construct(struct nvme_controller *ctrlr, device_t dev)
 {
+       struct make_dev_args    md_args;
        uint32_t        cap_lo;
        uint32_t        cap_hi;
        uint8_t         to;
@@ -1254,14 +1255,6 @@ nvme_ctrlr_construct(struct nvme_controller *ctrlr, de
        if (nvme_ctrlr_construct_admin_qpair(ctrlr) != 0)
                return (ENXIO);
 
-       ctrlr->cdev = make_dev(&nvme_ctrlr_cdevsw, device_get_unit(dev),
-           UID_ROOT, GID_WHEEL, 0600, "nvme%d", device_get_unit(dev));
-
-       if (ctrlr->cdev == NULL)
-               return (ENXIO);
-
-       ctrlr->cdev->si_drv1 = (void *)ctrlr;
-
        ctrlr->taskqueue = taskqueue_create("nvme_taskq", M_WAITOK,
            taskqueue_thread_enqueue, &ctrlr->taskqueue);
        taskqueue_start_threads(&ctrlr->taskqueue, 1, PI_DISK, "nvme taskq");
@@ -1270,11 +1263,22 @@ nvme_ctrlr_construct(struct nvme_controller *ctrlr, de
        ctrlr->is_initialized = 0;
        ctrlr->notification_sent = 0;
        TASK_INIT(&ctrlr->reset_task, 0, nvme_ctrlr_reset_task, ctrlr);
-
        TASK_INIT(&ctrlr->fail_req_task, 0, nvme_ctrlr_fail_req_task, ctrlr);
        STAILQ_INIT(&ctrlr->fail_req);
        ctrlr->is_failed = FALSE;
 
+       make_dev_args_init(&md_args);
+       md_args.mda_devsw = &nvme_ctrlr_cdevsw;
+       md_args.mda_uid = UID_ROOT;
+       md_args.mda_gid = GID_WHEEL;
+       md_args.mda_mode = 0600;
+       md_args.mda_unit = device_get_unit(dev);
+       md_args.mda_si_drv1 = (void *)ctrlr;
+       status = make_dev_s(&md_args, &ctrlr->cdev, "nvme%d",
+           device_get_unit(dev));
+       if (status != 0)
+               return (ENXIO);
+
        return (0);
 }
 
@@ -1283,18 +1287,9 @@ nvme_ctrlr_destruct(struct nvme_controller *ctrlr, dev
 {
        int                             i;
 
-       /*
-        *  Notify the controller of a shutdown, even though this is due to
-        *   a driver unload, not a system shutdown (this path is not invoked
-        *   during shutdown).  This ensures the controller receives a
-        *   shutdown notification in case the system is shutdown before
-        *   reloading the driver.
-        */
-       nvme_ctrlr_shutdown(ctrlr);
+       if (ctrlr->resource == NULL)
+               goto nores;
 
-       nvme_ctrlr_disable(ctrlr);
-       taskqueue_free(ctrlr->taskqueue);
-
        for (i = 0; i < NVME_MAX_NAMESPACES; i++)
                nvme_ns_destruct(&ctrlr->ns[i]);
 
@@ -1305,21 +1300,24 @@ nvme_ctrlr_destruct(struct nvme_controller *ctrlr, dev
                nvme_ctrlr_destroy_qpair(ctrlr, &ctrlr->ioq[i]);
                nvme_io_qpair_destroy(&ctrlr->ioq[i]);
        }
-
        free(ctrlr->ioq, M_NVME);
 
        nvme_admin_qpair_destroy(&ctrlr->adminq);
 
-       if (ctrlr->resource != NULL) {
-               bus_release_resource(dev, SYS_RES_MEMORY,
-                   ctrlr->resource_id, ctrlr->resource);
-       }
+       /*
+        *  Notify the controller of a shutdown, even though this is due to
+        *   a driver unload, not a system shutdown (this path is not invoked
+        *   during shutdown).  This ensures the controller receives a
+        *   shutdown notification in case the system is shutdown before
+        *   reloading the driver.
+        */
+       nvme_ctrlr_shutdown(ctrlr);
 
-       if (ctrlr->bar4_resource != NULL) {
-               bus_release_resource(dev, SYS_RES_MEMORY,
-                   ctrlr->bar4_resource_id, ctrlr->bar4_resource);
-       }
+       nvme_ctrlr_disable(ctrlr);
 
+       if (ctrlr->taskqueue)
+               taskqueue_free(ctrlr->taskqueue);
+
        if (ctrlr->tag)
                bus_teardown_intr(ctrlr->dev, ctrlr->res, ctrlr->tag);
 
@@ -1329,6 +1327,17 @@ nvme_ctrlr_destruct(struct nvme_controller *ctrlr, dev
 
        if (ctrlr->msix_enabled)
                pci_release_msi(dev);
+
+       if (ctrlr->bar4_resource != NULL) {
+               bus_release_resource(dev, SYS_RES_MEMORY,
+                   ctrlr->bar4_resource_id, ctrlr->bar4_resource);
+       }
+
+       bus_release_resource(dev, SYS_RES_MEMORY,
+           ctrlr->resource_id, ctrlr->resource);
+
+nores:
+       mtx_destroy(&ctrlr->lock);
 }
 
 void
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to