Author: jimharris
Date: Tue Mar 26 18:39:54 2013
New Revision: 248738
URL: http://svnweb.freebsd.org/changeset/base/248738

Log:
  Add an interface for nvme shim drivers (i.e. nvd) to register for
  notifications when new nvme controllers are added to the system.
  
  Sponsored by: Intel

Modified:
  head/sys/dev/nvd/nvd.c
  head/sys/dev/nvme/nvme.c
  head/sys/dev/nvme/nvme.h
  head/sys/dev/nvme/nvme_ctrlr.c
  head/sys/dev/nvme/nvme_private.h

Modified: head/sys/dev/nvd/nvd.c
==============================================================================
--- head/sys/dev/nvd/nvd.c      Tue Mar 26 18:37:36 2013        (r248737)
+++ head/sys/dev/nvd/nvd.c      Tue Mar 26 18:39:54 2013        (r248738)
@@ -45,7 +45,7 @@ struct nvd_disk;
 static disk_ioctl_t nvd_ioctl;
 static disk_strategy_t nvd_strategy;
 
-static void create_geom_disk(void *, struct nvme_namespace *ns);
+static void *create_geom_disk(struct nvme_namespace *ns, void *ctrlr);
 static void destroy_geom_disk(struct nvd_disk *ndisk);
 
 static int nvd_load(void);
@@ -105,7 +105,7 @@ nvd_load()
 {
 
        TAILQ_INIT(&nvd_head);
-       consumer_handle = nvme_register_consumer(create_geom_disk, NULL);
+       consumer_handle = nvme_register_consumer(create_geom_disk, NULL, NULL);
 
        return (consumer_handle != NULL ? 0 : -1);
 }
@@ -233,8 +233,8 @@ nvd_bioq_process(void *arg, int pending)
        }
 }
 
-static void
-create_geom_disk(void *arg, struct nvme_namespace *ns)
+static void *
+create_geom_disk(struct nvme_namespace *ns, void *ctrlr)
 {
        struct nvd_disk *ndisk;
        struct disk *disk;
@@ -287,6 +287,8 @@ create_geom_disk(void *arg, struct nvme_
        taskqueue_start_threads(&ndisk->tq, 1, PI_DISK, "nvd taskq");
 
        TAILQ_INSERT_HEAD(&nvd_head, ndisk, tailq);
+
+       return (NULL);
 }
 
 static void

Modified: head/sys/dev/nvme/nvme.c
==============================================================================
--- head/sys/dev/nvme/nvme.c    Tue Mar 26 18:37:36 2013        (r248737)
+++ head/sys/dev/nvme/nvme.c    Tue Mar 26 18:39:54 2013        (r248738)
@@ -40,11 +40,14 @@ __FBSDID("$FreeBSD$");
 #include "nvme_private.h"
 
 struct nvme_consumer {
-       nvme_consumer_cb_fn_t           cb_fn;
-       void                            *cb_arg;
+       uint32_t                id;
+       nvme_cons_ns_fn_t       ns_fn;
+       nvme_cons_ctrlr_fn_t    ctrlr_fn;
+       nvme_cons_async_fn_t    async_fn;
 };
 
 struct nvme_consumer nvme_consumer[NVME_MAX_CONSUMERS];
+#define        INVALID_CONSUMER_ID     0xFFFF
 
 uma_zone_t nvme_request_zone;
 
@@ -118,8 +121,13 @@ nvme_probe (device_t device)
 static void
 nvme_init(void)
 {
+       uint32_t        i;
+
        nvme_request_zone = uma_zcreate("nvme_request",
            sizeof(struct nvme_request), NULL, NULL, NULL, NULL, 0, 0);
+
+       for (i = 0; i < NVME_MAX_CONSUMERS; i++)
+               nvme_consumer[i].id = INVALID_CONSUMER_ID;
 }
 
 SYSINIT(nvme_register, SI_SUB_DRIVERS, SI_ORDER_SECOND, nvme_init, NULL);
@@ -292,26 +300,52 @@ nvme_detach (device_t dev)
 }
 
 static void
-nvme_notify_consumer(struct nvme_consumer *consumer)
+nvme_notify_consumer(struct nvme_consumer *cons)
 {
        device_t                *devlist;
        struct nvme_controller  *ctrlr;
-       int                     dev, ns, devcount;
+       struct nvme_namespace   *ns;
+       void                    *ctrlr_cookie;
+       int                     dev_idx, ns_idx, devcount;
 
        if (devclass_get_devices(nvme_devclass, &devlist, &devcount))
                return;
 
-       for (dev = 0; dev < devcount; dev++) {
-               ctrlr = DEVICE2SOFTC(devlist[dev]);
-               for (ns = 0; ns < ctrlr->cdata.nn; ns++)
-                       (*consumer->cb_fn)(consumer->cb_arg, &ctrlr->ns[ns]);
+       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;
+               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);
+               }
        }
 
        free(devlist, M_TEMP);
 }
 
+void
+nvme_notify_async_consumers(struct nvme_controller *ctrlr,
+                           const struct nvme_completion *async_cpl)
+{
+       struct nvme_consumer    *cons;
+       uint32_t                i;
+
+       for (i = 0; i < NVME_MAX_CONSUMERS; i++) {
+               cons = &nvme_consumer[i];
+               if (cons->id != INVALID_CONSUMER_ID && cons->async_fn != NULL)
+                       (*cons->async_fn)(ctrlr->cons_cookie[i], async_cpl);
+       }
+}
+
 struct nvme_consumer *
-nvme_register_consumer(nvme_consumer_cb_fn_t cb_fn, void *cb_arg)
+nvme_register_consumer(nvme_cons_ns_fn_t ns_fn, nvme_cons_ctrlr_fn_t ctrlr_fn,
+                      nvme_cons_async_fn_t async_fn)
 {
        int i;
 
@@ -320,9 +354,11 @@ nvme_register_consumer(nvme_consumer_cb_
         *  right now since we only have one nvme consumer - nvd(4).
         */
        for (i = 0; i < NVME_MAX_CONSUMERS; i++)
-               if (nvme_consumer[i].cb_fn == NULL) {
-                       nvme_consumer[i].cb_fn = cb_fn;
-                       nvme_consumer[i].cb_arg = cb_arg;
+               if (nvme_consumer[i].id == INVALID_CONSUMER_ID) {
+                       nvme_consumer[i].id = i;
+                       nvme_consumer[i].ns_fn = ns_fn;
+                       nvme_consumer[i].ctrlr_fn = ctrlr_fn;
+                       nvme_consumer[i].async_fn = async_fn;
 
                        nvme_notify_consumer(&nvme_consumer[i]);
                        return (&nvme_consumer[i]);
@@ -336,7 +372,6 @@ void
 nvme_unregister_consumer(struct nvme_consumer *consumer)
 {
 
-       consumer->cb_fn = NULL;
-       consumer->cb_arg = NULL;
+       consumer->id = INVALID_CONSUMER_ID;
 }
 

Modified: head/sys/dev/nvme/nvme.h
==============================================================================
--- head/sys/dev/nvme/nvme.h    Tue Mar 26 18:37:36 2013        (r248737)
+++ head/sys/dev/nvme/nvme.h    Tue Mar 26 18:39:54 2013        (r248738)
@@ -690,10 +690,14 @@ enum nvme_io_test_flags {
 struct bio;
 
 struct nvme_namespace;
+struct nvme_controller;
 struct nvme_consumer;
 
 typedef void (*nvme_cb_fn_t)(void *, const struct nvme_completion *);
-typedef void (*nvme_consumer_cb_fn_t)(void *, struct nvme_namespace *);
+
+typedef void *(*nvme_cons_ns_fn_t)(struct nvme_namespace *, void *);
+typedef void *(*nvme_cons_ctrlr_fn_t)(struct nvme_controller *);
+typedef void (*nvme_cons_async_fn_t)(void *, const struct nvme_completion *);
 
 enum nvme_namespace_flags {
        NVME_NS_DEALLOCATE_SUPPORTED    = 0x1,
@@ -714,10 +718,14 @@ int       nvme_ns_cmd_flush(struct nvme_namesp
                          void *cb_arg);
 
 /* Registration functions */
-struct nvme_consumer * nvme_register_consumer(nvme_consumer_cb_fn_t cb_fn,
-                                              void *cb_arg);
+struct nvme_consumer * nvme_register_consumer(nvme_cons_ns_fn_t    ns_fn,
+                                              nvme_cons_ctrlr_fn_t ctrlr_fn,
+                                              nvme_cons_async_fn_t async_fn);
 void           nvme_unregister_consumer(struct nvme_consumer *consumer);
 
+/* Controller helper functions */
+device_t       nvme_ctrlr_get_device(struct nvme_controller *ctrlr);
+
 /* Namespace helper functions */
 uint32_t       nvme_ns_get_max_io_xfer_size(struct nvme_namespace *ns);
 uint32_t       nvme_ns_get_sector_size(struct nvme_namespace *ns);

Modified: head/sys/dev/nvme/nvme_ctrlr.c
==============================================================================
--- head/sys/dev/nvme/nvme_ctrlr.c      Tue Mar 26 18:37:36 2013        
(r248737)
+++ head/sys/dev/nvme/nvme_ctrlr.c      Tue Mar 26 18:39:54 2013        
(r248738)
@@ -551,6 +551,8 @@ nvme_ctrlr_async_event_cb(void *arg, con
                return;
        }
 
+       nvme_notify_async_consumers(aer->ctrlr, cpl);
+
        /* TODO: decode async event type based on status */
 
        /*
@@ -909,3 +911,10 @@ nvme_ctrlr_submit_io_request(struct nvme
 
        nvme_qpair_submit_request(qpair, req);
 }
+
+device_t
+nvme_ctrlr_get_device(struct nvme_controller *ctrlr)
+{
+
+       return (ctrlr->dev);
+}

Modified: head/sys/dev/nvme/nvme_private.h
==============================================================================
--- head/sys/dev/nvme/nvme_private.h    Tue Mar 26 18:37:36 2013        
(r248737)
+++ head/sys/dev/nvme/nvme_private.h    Tue Mar 26 18:39:54 2013        
(r248738)
@@ -190,6 +190,7 @@ struct nvme_namespace {
        uint16_t                        id;
        uint16_t                        flags;
        struct cdev                     *cdev;
+       void                            *cons_cookie[NVME_MAX_CONSUMERS];
 };
 
 /*
@@ -264,6 +265,8 @@ struct nvme_controller {
        uint32_t                        num_aers;
        struct nvme_async_event_request aer[NVME_MAX_ASYNC_EVENTS];
 
+       void                            *cons_cookie[NVME_MAX_CONSUMERS];
+
 #ifdef CHATHAM2
        uint64_t                chatham_size;
        uint64_t                chatham_lbas;
@@ -446,4 +449,7 @@ nvme_allocate_request_uio(struct uio *ui
 
 #define nvme_free_request(req) uma_zfree(nvme_request_zone, req)
 
+void   nvme_notify_async_consumers(struct nvme_controller *ctrlr,
+                                   const struct nvme_completion *async_cpl);
+
 #endif /* __NVME_PRIVATE_H__ */
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to