Author: jimharris
Date: Wed May  7 16:47:58 2014
New Revision: 265565
URL: http://svnweb.freebsd.org/changeset/base/265565

Log:
  MFC r263310:
  
  nvme: Close hole where nvd(4) would not be notified of all nvme(4)
  instances if modules loaded during boot.

Modified:
  stable/9/sys/dev/nvme/nvme.c
  stable/9/sys/dev/nvme/nvme_ctrlr.c
  stable/9/sys/dev/nvme/nvme_private.h
Directory Properties:
  stable/9/sys/   (props changed)
  stable/9/sys/dev/   (props changed)

Modified: stable/9/sys/dev/nvme/nvme.c
==============================================================================
--- stable/9/sys/dev/nvme/nvme.c        Wed May  7 16:46:56 2014        
(r265564)
+++ stable/9/sys/dev/nvme/nvme.c        Wed May  7 16:47:58 2014        
(r265565)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (C) 2012-2013 Intel Corporation
+ * Copyright (C) 2012-2014 Intel Corporation
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -266,39 +266,75 @@ nvme_detach (device_t dev)
 }
 
 static void
-nvme_notify_consumer(struct nvme_consumer *cons)
+nvme_notify(struct nvme_consumer *cons,
+           struct nvme_controller *ctrlr)
 {
-       device_t                *devlist;
-       struct nvme_controller  *ctrlr;
        struct nvme_namespace   *ns;
        void                    *ctrlr_cookie;
-       int                     dev_idx, ns_idx, devcount;
+       int                     cmpset, ns_idx;
+
+       /*
+        * The consumer may register itself after the nvme devices
+        *  have registered with the kernel, but before the
+        *  driver has completed initialization.  In that case,
+        *  return here, and when initialization completes, the
+        *  controller will make sure the consumer gets notified.
+        */
+       if (!ctrlr->is_initialized)
+               return;
+
+       cmpset = atomic_cmpset_32(&ctrlr->notification_sent, 0, 1);
+
+       if (cmpset == 0)
+               return;
+
+       if (cons->ctrlr_fn != NULL)
+               ctrlr_cookie = (*cons->ctrlr_fn)(ctrlr);
+       else
+               ctrlr_cookie = NULL;
+       ctrlr->cons_cookie[cons->id] = ctrlr_cookie;
+       if (ctrlr->is_failed) {
+               if (cons->fail_fn != NULL)
+                       (*cons->fail_fn)(ctrlr_cookie);
+               /*
+                * Do not notify consumers about the namespaces of a
+                *  failed controller.
+                */
+               return;
+       }
+       for (ns_idx = 0; ns_idx < ctrlr->cdata.nn; ns_idx++) {
+               ns = &ctrlr->ns[ns_idx];
+               if (cons->ns_fn != NULL)
+                       ns->cons_cookie[cons->id] =
+                           (*cons->ns_fn)(ns, ctrlr_cookie);
+       }
+}
+
+void
+nvme_notify_new_controller(struct nvme_controller *ctrlr)
+{
+       int i;
+
+       for (i = 0; i < NVME_MAX_CONSUMERS; i++) {
+               if (nvme_consumer[i].id != INVALID_CONSUMER_ID) {
+                       nvme_notify(&nvme_consumer[i], ctrlr);
+               }
+       }
+}
+
+static void
+nvme_notify_new_consumer(struct nvme_consumer *cons)
+{
+       device_t                *devlist;
+       struct nvme_controller  *ctrlr;
+       int                     dev_idx, devcount;
 
        if (devclass_get_devices(nvme_devclass, &devlist, &devcount))
                return;
 
        for (dev_idx = 0; dev_idx < devcount; dev_idx++) {
                ctrlr = DEVICE2SOFTC(devlist[dev_idx]);
-               if (cons->ctrlr_fn != NULL)
-                       ctrlr_cookie = (*cons->ctrlr_fn)(ctrlr);
-               else
-                       ctrlr_cookie = NULL;
-               ctrlr->cons_cookie[cons->id] = ctrlr_cookie;
-               if (ctrlr->is_failed) {
-                       if (cons->fail_fn != NULL)
-                               (*cons->fail_fn)(ctrlr_cookie);
-                       /*
-                        * Do not notify consumers about the namespaces of a
-                        *  failed controller.
-                        */
-                       continue;
-               }
-               for (ns_idx = 0; ns_idx < ctrlr->cdata.nn; ns_idx++) {
-                       ns = &ctrlr->ns[ns_idx];
-                       if (cons->ns_fn != NULL)
-                               ns->cons_cookie[cons->id] =
-                                   (*cons->ns_fn)(ns, ctrlr_cookie);
-               }
+               nvme_notify(cons, ctrlr);
        }
 
        free(devlist, M_TEMP);
@@ -353,7 +389,7 @@ nvme_register_consumer(nvme_cons_ns_fn_t
                        nvme_consumer[i].async_fn = async_fn;
                        nvme_consumer[i].fail_fn = fail_fn;
 
-                       nvme_notify_consumer(&nvme_consumer[i]);
+                       nvme_notify_new_consumer(&nvme_consumer[i]);
                        return (&nvme_consumer[i]);
                }
 

Modified: stable/9/sys/dev/nvme/nvme_ctrlr.c
==============================================================================
--- stable/9/sys/dev/nvme/nvme_ctrlr.c  Wed May  7 16:46:56 2014        
(r265564)
+++ stable/9/sys/dev/nvme/nvme_ctrlr.c  Wed May  7 16:47:58 2014        
(r265565)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (C) 2012-2013 Intel Corporation
+ * Copyright (C) 2012-2014 Intel Corporation
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -851,6 +851,9 @@ nvme_ctrlr_start_config_hook(void *arg)
 
        nvme_ctrlr_start(ctrlr);
        config_intrhook_disestablish(&ctrlr->config_hook);
+
+       ctrlr->is_initialized = 1;
+       nvme_notify_new_controller(ctrlr);
 }
 
 static void
@@ -1174,6 +1177,8 @@ intx:
        taskqueue_start_threads(&ctrlr->taskqueue, 1, PI_DISK, "nvme taskq");
 
        ctrlr->is_resetting = 0;
+       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);

Modified: stable/9/sys/dev/nvme/nvme_private.h
==============================================================================
--- stable/9/sys/dev/nvme/nvme_private.h        Wed May  7 16:46:56 2014        
(r265564)
+++ stable/9/sys/dev/nvme/nvme_private.h        Wed May  7 16:47:58 2014        
(r265565)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (C) 2012-2013 Intel Corporation
+ * Copyright (C) 2012-2014 Intel Corporation
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -330,7 +330,9 @@ struct nvme_controller {
 
        void                            *cons_cookie[NVME_MAX_CONSUMERS];
 
-       uint32_t                is_resetting;
+       uint32_t                        is_resetting;
+       uint32_t                        is_initialized;
+       uint32_t                        notification_sent;
 
        boolean_t                       is_failed;
        STAILQ_HEAD(, nvme_request)     fail_req;
@@ -556,5 +558,6 @@ void        nvme_notify_async_consumers(struct 
                                    uint32_t log_page_id, void *log_page_buffer,
                                    uint32_t log_page_size);
 void   nvme_notify_fail_consumers(struct nvme_controller *ctrlr);
+void   nvme_notify_new_controller(struct nvme_controller *ctrlr);
 
 #endif /* __NVME_PRIVATE_H__ */
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to