From 4ad99808f277033971091d8386d819da5fe19e6b Mon Sep 17 00:00:00 2001 From: Daniel Verkamp Date: Mon, 7 Mar 2016 10:36:17 -0700 Subject: [PATCH] nvme: allow user to override controller defaults Provide a new structure, spdk_nvme_ctrlr_opts, to let the user modify the default controller initialization options during probe/attach. Currently, only the number of queue pairs can be modified in this way; other options will be added later. Change-Id: Ie27b9429291d93a9353c0d820f0ad467d3b0e7cb Signed-off-by: Daniel Verkamp --- examples/nvme/identify/identify.c | 5 ++-- examples/nvme/nvme_manage/nvme_manage.c | 5 ++-- examples/nvme/perf/perf.c | 5 ++-- examples/nvme/reserve/reservation.c | 5 ++-- include/spdk/nvme.h | 27 +++++++++++++++++-- lib/nvme/nvme.c | 9 +++++-- lib/nvme/nvme_ctrlr.c | 24 ++++++++++------- lib/nvme/nvme_internal.h | 6 +++-- test/lib/nvme/aer/aer.c | 5 ++-- test/lib/nvme/reset/reset.c | 5 ++-- test/lib/nvme/sgl/nvme_sgl.c | 5 ++-- test/lib/nvme/unit/nvme_c/nvme_ut.c | 6 +++++ .../nvme/unit/nvme_ctrlr_c/nvme_ctrlr_ut.c | 4 +-- .../nvme/unit/nvme_ns_cmd_c/nvme_ns_cmd_ut.c | 6 +++++ 14 files changed, 85 insertions(+), 32 deletions(-) diff --git a/examples/nvme/identify/identify.c b/examples/nvme/identify/identify.c index 0f2218382..482185e9a 100644 --- a/examples/nvme/identify/identify.c +++ b/examples/nvme/identify/identify.c @@ -771,7 +771,7 @@ parse_args(int argc, char **argv) } static bool -probe_cb(void *cb_ctx, struct spdk_pci_device *dev) +probe_cb(void *cb_ctx, struct spdk_pci_device *dev, struct spdk_nvme_ctrlr_opts *opts) { if (spdk_pci_device_has_non_uio_driver(dev)) { fprintf(stderr, "non-uio kernel driver attached to NVMe\n"); @@ -788,7 +788,8 @@ probe_cb(void *cb_ctx, struct spdk_pci_device *dev) } static void -attach_cb(void *cb_ctx, struct spdk_pci_device *pci_dev, struct spdk_nvme_ctrlr *ctrlr) +attach_cb(void *cb_ctx, struct spdk_pci_device *pci_dev, struct spdk_nvme_ctrlr *ctrlr, + const struct spdk_nvme_ctrlr_opts *opts) { print_controller(ctrlr, pci_dev); spdk_nvme_detach(ctrlr); diff --git a/examples/nvme/nvme_manage/nvme_manage.c b/examples/nvme/nvme_manage/nvme_manage.c index 6aa745153..1ebb1f4a0 100644 --- a/examples/nvme/nvme_manage/nvme_manage.c +++ b/examples/nvme/nvme_manage/nvme_manage.c @@ -96,7 +96,7 @@ cmp_devs(const void *ap, const void *bp) } static bool -probe_cb(void *cb_ctx, struct spdk_pci_device *dev) +probe_cb(void *cb_ctx, struct spdk_pci_device *dev, struct spdk_nvme_ctrlr_opts *opts) { if (spdk_pci_device_has_non_uio_driver(dev)) { fprintf(stderr, "non-uio kernel driver attached to NVMe\n"); @@ -113,7 +113,8 @@ probe_cb(void *cb_ctx, struct spdk_pci_device *dev) } static void -attach_cb(void *cb_ctx, struct spdk_pci_device *pci_dev, struct spdk_nvme_ctrlr *ctrlr) +attach_cb(void *cb_ctx, struct spdk_pci_device *pci_dev, struct spdk_nvme_ctrlr *ctrlr, + const struct spdk_nvme_ctrlr_opts *opts) { struct dev *dev; diff --git a/examples/nvme/perf/perf.c b/examples/nvme/perf/perf.c index 3d09e30a9..5687eaf2a 100644 --- a/examples/nvme/perf/perf.c +++ b/examples/nvme/perf/perf.c @@ -884,7 +884,7 @@ register_workers(void) } static bool -probe_cb(void *cb_ctx, struct spdk_pci_device *dev) +probe_cb(void *cb_ctx, struct spdk_pci_device *dev, struct spdk_nvme_ctrlr_opts *opts) { if (spdk_pci_device_has_non_uio_driver(dev)) { fprintf(stderr, "non-uio kernel driver attached to NVMe\n"); @@ -907,7 +907,8 @@ probe_cb(void *cb_ctx, struct spdk_pci_device *dev) } static void -attach_cb(void *cb_ctx, struct spdk_pci_device *dev, struct spdk_nvme_ctrlr *ctrlr) +attach_cb(void *cb_ctx, struct spdk_pci_device *dev, struct spdk_nvme_ctrlr *ctrlr, + const struct spdk_nvme_ctrlr_opts *opts) { printf("Attached to %04x:%02x:%02x.%02x\n", spdk_pci_device_get_domain(dev), diff --git a/examples/nvme/reserve/reservation.c b/examples/nvme/reserve/reservation.c index bebe0e51b..102f84b40 100644 --- a/examples/nvme/reserve/reservation.c +++ b/examples/nvme/reserve/reservation.c @@ -382,7 +382,7 @@ reserve_controller(struct spdk_nvme_ctrlr *ctrlr, struct spdk_nvme_qpair *qpair, } static bool -probe_cb(void *cb_ctx, struct spdk_pci_device *dev) +probe_cb(void *cb_ctx, struct spdk_pci_device *dev, struct spdk_nvme_ctrlr_opts *opts) { if (spdk_pci_device_has_non_uio_driver(dev)) { fprintf(stderr, "non-uio kernel driver attached to NVMe\n"); @@ -399,7 +399,8 @@ probe_cb(void *cb_ctx, struct spdk_pci_device *dev) } static void -attach_cb(void *cb_ctx, struct spdk_pci_device *pci_dev, struct spdk_nvme_ctrlr *ctrlr) +attach_cb(void *cb_ctx, struct spdk_pci_device *pci_dev, struct spdk_nvme_ctrlr *ctrlr, + const struct spdk_nvme_ctrlr_opts *opts) { struct dev *dev; diff --git a/include/spdk/nvme.h b/include/spdk/nvme.h index 0206d13e9..b0d90012f 100644 --- a/include/spdk/nvme.h +++ b/include/spdk/nvme.h @@ -56,18 +56,41 @@ extern int32_t spdk_nvme_retry_count; /** \brief Opaque handle to a controller. Returned by \ref spdk_nvme_probe()'s attach_cb. */ struct spdk_nvme_ctrlr; +/** + * \brief NVMe controller initialization options. + * + * A pointer to this structure will be provided for each probe callback from spdk_nvme_probe() to + * allow the user to request non-default options, and the actual options enabled on the controller + * will be provided during the attach callback. + */ +struct spdk_nvme_ctrlr_opts { + /** + * Number of I/O queues to request (used to set Number of Queues feature) + */ + uint32_t num_io_queues; +}; + /** * Callback for spdk_nvme_probe() enumeration. * + * \param opts NVMe controller initialization options. This structure will be populated with the + * default values on entry, and the user callback may update any options to request a different + * value. The controller may not support all requested parameters, so the final values will be + * provided during the attach callback. * \return true to attach to this device. */ -typedef bool (*spdk_nvme_probe_cb)(void *cb_ctx, struct spdk_pci_device *pci_dev); +typedef bool (*spdk_nvme_probe_cb)(void *cb_ctx, struct spdk_pci_device *pci_dev, + struct spdk_nvme_ctrlr_opts *opts); /** * Callback for spdk_nvme_probe() to report a device that has been attached to the userspace NVMe driver. + * + * \param opts NVMe controller initialization options that were actually used. Options may differ + * from the requested options from the probe call depending on what the controller supports. */ typedef void (*spdk_nvme_attach_cb)(void *cb_ctx, struct spdk_pci_device *pci_dev, - struct spdk_nvme_ctrlr *ctrlr); + struct spdk_nvme_ctrlr *ctrlr, + const struct spdk_nvme_ctrlr_opts *opts); /** * \brief Enumerate the NVMe devices attached to the system and attach the userspace NVMe driver diff --git a/lib/nvme/nvme.c b/lib/nvme/nvme.c index 773366133..8fea59615 100644 --- a/lib/nvme/nvme.c +++ b/lib/nvme/nvme.c @@ -189,6 +189,7 @@ nvme_enum_cb(void *ctx, struct spdk_pci_device *pci_dev) { struct nvme_enum_ctx *enum_ctx = ctx; struct spdk_nvme_ctrlr *ctrlr; + struct spdk_nvme_ctrlr_opts opts; /* Verify that this controller is not already attached */ TAILQ_FOREACH(ctrlr, &g_nvme_driver.attached_ctrlrs, tailq) { @@ -200,13 +201,17 @@ nvme_enum_cb(void *ctx, struct spdk_pci_device *pci_dev) } } - if (enum_ctx->probe_cb(enum_ctx->cb_ctx, pci_dev)) { + spdk_nvme_ctrlr_opts_set_defaults(&opts); + + if (enum_ctx->probe_cb(enum_ctx->cb_ctx, pci_dev, &opts)) { ctrlr = nvme_attach(pci_dev); if (ctrlr == NULL) { nvme_printf(NULL, "nvme_attach() failed\n"); return -1; } + ctrlr->opts = opts; + TAILQ_INSERT_TAIL(&g_nvme_driver.init_ctrlrs, ctrlr, tailq); } @@ -268,7 +273,7 @@ spdk_nvme_probe(void *cb_ctx, spdk_nvme_probe_cb probe_cb, spdk_nvme_attach_cb a * that may take the driver lock, like nvme_detach(). */ nvme_mutex_unlock(&g_nvme_driver.lock); - attach_cb(cb_ctx, ctrlr->devhandle, ctrlr); + attach_cb(cb_ctx, ctrlr->devhandle, ctrlr, &ctrlr->opts); nvme_mutex_lock(&g_nvme_driver.lock); break; diff --git a/lib/nvme/nvme_ctrlr.c b/lib/nvme/nvme_ctrlr.c index a5adf14a5..878c97e29 100644 --- a/lib/nvme/nvme_ctrlr.c +++ b/lib/nvme/nvme_ctrlr.c @@ -42,6 +42,13 @@ static int nvme_ctrlr_construct_and_submit_aer(struct spdk_nvme_ctrlr *ctrlr, struct nvme_async_event_request *aer); + +void +spdk_nvme_ctrlr_opts_set_defaults(struct spdk_nvme_ctrlr_opts *opts) +{ + opts->num_io_queues = DEFAULT_MAX_IO_QUEUES; +} + static int spdk_nvme_ctrlr_create_qpair(struct spdk_nvme_ctrlr *ctrlr, struct spdk_nvme_qpair *qpair) { @@ -357,12 +364,12 @@ nvme_ctrlr_construct_io_qpairs(struct spdk_nvme_ctrlr *ctrlr) ctrlr->max_xfer_size = NVME_MAX_XFER_SIZE; - ctrlr->ioq = calloc(ctrlr->num_io_queues, sizeof(struct spdk_nvme_qpair)); + ctrlr->ioq = calloc(ctrlr->opts.num_io_queues, sizeof(struct spdk_nvme_qpair)); if (ctrlr->ioq == NULL) return -1; - for (i = 0; i < ctrlr->num_io_queues; i++) { + for (i = 0; i < ctrlr->opts.num_io_queues; i++) { qpair = &ctrlr->ioq[i]; /* @@ -390,7 +397,7 @@ nvme_ctrlr_fail(struct spdk_nvme_ctrlr *ctrlr) ctrlr->is_failed = true; nvme_qpair_fail(&ctrlr->adminq); - for (i = 0; i < ctrlr->num_io_queues; i++) { + for (i = 0; i < ctrlr->opts.num_io_queues; i++) { nvme_qpair_fail(&ctrlr->ioq[i]); } } @@ -544,7 +551,7 @@ spdk_nvme_ctrlr_reset(struct spdk_nvme_ctrlr *ctrlr) /* Disable all queues before disabling the controller hardware. */ nvme_qpair_disable(&ctrlr->adminq); - for (i = 0; i < ctrlr->num_io_queues; i++) { + for (i = 0; i < ctrlr->opts.num_io_queues; i++) { nvme_qpair_disable(&ctrlr->ioq[i]); } @@ -616,13 +623,10 @@ nvme_ctrlr_set_num_qpairs(struct spdk_nvme_ctrlr *ctrlr) struct nvme_completion_poll_status status; int cq_allocated, sq_allocated; int rc; - uint32_t max_io_queues; status.done = false; - max_io_queues = DEFAULT_MAX_IO_QUEUES; - - rc = nvme_ctrlr_cmd_set_num_queues(ctrlr, max_io_queues, + rc = nvme_ctrlr_cmd_set_num_queues(ctrlr, ctrlr->opts.num_io_queues, nvme_completion_poll_cb, &status); if (rc != 0) { return rc; @@ -644,7 +648,7 @@ nvme_ctrlr_set_num_qpairs(struct spdk_nvme_ctrlr *ctrlr) sq_allocated = (status.cpl.cdw0 & 0xFFFF) + 1; cq_allocated = (status.cpl.cdw0 >> 16) + 1; - ctrlr->num_io_queues = nvme_min(sq_allocated, cq_allocated); + ctrlr->opts.num_io_queues = nvme_min(sq_allocated, cq_allocated); return 0; } @@ -1028,7 +1032,7 @@ nvme_ctrlr_destruct(struct spdk_nvme_ctrlr *ctrlr) nvme_ctrlr_destruct_namespaces(ctrlr); - for (i = 0; i < ctrlr->num_io_queues; i++) { + for (i = 0; i < ctrlr->opts.num_io_queues; i++) { nvme_qpair_destroy(&ctrlr->ioq[i]); } diff --git a/lib/nvme/nvme_internal.h b/lib/nvme/nvme_internal.h index 1f1601648..dd2f6f044 100644 --- a/lib/nvme/nvme_internal.h +++ b/lib/nvme/nvme_internal.h @@ -397,8 +397,6 @@ struct spdk_nvme_ctrlr { /* Opaque handle to associated PCI device. */ struct spdk_pci_device *devhandle; - uint32_t num_io_queues; - /** maximum i/o size in bytes */ uint32_t max_xfer_size; @@ -433,6 +431,8 @@ struct spdk_nvme_ctrlr { TAILQ_HEAD(, spdk_nvme_qpair) free_io_qpairs; TAILQ_HEAD(, spdk_nvme_qpair) active_io_qpairs; + + struct spdk_nvme_ctrlr_opts opts; }; struct nvme_driver { @@ -548,4 +548,6 @@ struct nvme_request *nvme_allocate_request_contig(void *buffer, uint32_t payload void nvme_free_request(struct nvme_request *req); bool nvme_intel_has_quirk(struct pci_id *id, uint64_t quirk); +void spdk_nvme_ctrlr_opts_set_defaults(struct spdk_nvme_ctrlr_opts *opts); + #endif /* __NVME_INTERNAL_H__ */ diff --git a/test/lib/nvme/aer/aer.c b/test/lib/nvme/aer/aer.c index 1ab4c4754..da0bf3d2d 100644 --- a/test/lib/nvme/aer/aer.c +++ b/test/lib/nvme/aer/aer.c @@ -188,7 +188,7 @@ static void aer_cb(void *arg, const struct spdk_nvme_cpl *cpl) static bool -probe_cb(void *cb_ctx, struct spdk_pci_device *dev) +probe_cb(void *cb_ctx, struct spdk_pci_device *dev, struct spdk_nvme_ctrlr_opts *opts) { if (spdk_pci_device_has_non_uio_driver(dev)) { fprintf(stderr, "non-uio kernel driver attached to NVMe\n"); @@ -211,7 +211,8 @@ probe_cb(void *cb_ctx, struct spdk_pci_device *dev) } static void -attach_cb(void *cb_ctx, struct spdk_pci_device *pci_dev, struct spdk_nvme_ctrlr *ctrlr) +attach_cb(void *cb_ctx, struct spdk_pci_device *pci_dev, struct spdk_nvme_ctrlr *ctrlr, + const struct spdk_nvme_ctrlr_opts *opts) { struct dev *dev; diff --git a/test/lib/nvme/reset/reset.c b/test/lib/nvme/reset/reset.c index d41c24956..39d672853 100644 --- a/test/lib/nvme/reset/reset.c +++ b/test/lib/nvme/reset/reset.c @@ -512,7 +512,7 @@ register_workers(void) static bool -probe_cb(void *cb_ctx, struct spdk_pci_device *dev) +probe_cb(void *cb_ctx, struct spdk_pci_device *dev, struct spdk_nvme_ctrlr_opts *opts) { if (spdk_pci_device_has_non_uio_driver(dev)) { fprintf(stderr, "non-uio kernel driver attached to NVMe\n"); @@ -529,7 +529,8 @@ probe_cb(void *cb_ctx, struct spdk_pci_device *dev) } static void -attach_cb(void *cb_ctx, struct spdk_pci_device *pci_dev, struct spdk_nvme_ctrlr *ctrlr) +attach_cb(void *cb_ctx, struct spdk_pci_device *pci_dev, struct spdk_nvme_ctrlr *ctrlr, + const struct spdk_nvme_ctrlr_opts *opts) { register_ctrlr(ctrlr); } diff --git a/test/lib/nvme/sgl/nvme_sgl.c b/test/lib/nvme/sgl/nvme_sgl.c index 658153bd7..36f7f86e1 100644 --- a/test/lib/nvme/sgl/nvme_sgl.c +++ b/test/lib/nvme/sgl/nvme_sgl.c @@ -402,7 +402,7 @@ writev_readv_tests(struct dev *dev, nvme_build_io_req_fn_t build_io_fn) } static bool -probe_cb(void *cb_ctx, struct spdk_pci_device *dev) +probe_cb(void *cb_ctx, struct spdk_pci_device *dev, struct spdk_nvme_ctrlr_opts *opts) { if (spdk_pci_device_has_non_uio_driver(dev)) { fprintf(stderr, "non-uio kernel driver attached to NVMe\n"); @@ -425,7 +425,8 @@ probe_cb(void *cb_ctx, struct spdk_pci_device *dev) } static void -attach_cb(void *cb_ctx, struct spdk_pci_device *pci_dev, struct spdk_nvme_ctrlr *ctrlr) +attach_cb(void *cb_ctx, struct spdk_pci_device *pci_dev, struct spdk_nvme_ctrlr *ctrlr, + const struct spdk_nvme_ctrlr_opts *opts) { struct dev *dev; diff --git a/test/lib/nvme/unit/nvme_c/nvme_ut.c b/test/lib/nvme/unit/nvme_c/nvme_ut.c index 3417a439b..e11c125e7 100644 --- a/test/lib/nvme/unit/nvme_c/nvme_ut.c +++ b/test/lib/nvme/unit/nvme_c/nvme_ut.c @@ -65,6 +65,12 @@ nvme_ctrlr_start(struct spdk_nvme_ctrlr *ctrlr) return 0; } +void +spdk_nvme_ctrlr_opts_set_defaults(struct spdk_nvme_ctrlr_opts *opts) +{ + memset(opts, 0, sizeof(*opts)); +} + int main(int argc, char **argv) { CU_pSuite suite = NULL; diff --git a/test/lib/nvme/unit/nvme_ctrlr_c/nvme_ctrlr_ut.c b/test/lib/nvme/unit/nvme_ctrlr_c/nvme_ctrlr_ut.c index 6adcb20ff..1228fc2bb 100644 --- a/test/lib/nvme/unit/nvme_ctrlr_c/nvme_ctrlr_ut.c +++ b/test/lib/nvme/unit/nvme_ctrlr_c/nvme_ctrlr_ut.c @@ -422,7 +422,7 @@ setup_qpairs(struct spdk_nvme_ctrlr *ctrlr, uint32_t num_io_queues) SPDK_CU_ASSERT_FATAL(nvme_ctrlr_construct(ctrlr, NULL) == 0); /* Fake out the parts of ctrlr needed for I/O qpair allocation */ - ctrlr->num_io_queues = num_io_queues; + ctrlr->opts.num_io_queues = num_io_queues; SPDK_CU_ASSERT_FATAL(nvme_ctrlr_construct_io_qpairs(ctrlr) == 0); } @@ -500,7 +500,7 @@ test_nvme_ctrlr_fail(void) { struct spdk_nvme_ctrlr ctrlr = {}; - ctrlr.num_io_queues = 0; + ctrlr.opts.num_io_queues = 0; nvme_ctrlr_fail(&ctrlr); CU_ASSERT(ctrlr.is_failed == true); diff --git a/test/lib/nvme/unit/nvme_ns_cmd_c/nvme_ns_cmd_ut.c b/test/lib/nvme/unit/nvme_ns_cmd_c/nvme_ns_cmd_ut.c index 45134f8bf..98e2662c3 100644 --- a/test/lib/nvme/unit/nvme_ns_cmd_c/nvme_ns_cmd_ut.c +++ b/test/lib/nvme/unit/nvme_ns_cmd_c/nvme_ns_cmd_ut.c @@ -77,6 +77,12 @@ nvme_ctrlr_start(struct spdk_nvme_ctrlr *ctrlr) return 0; } +void +spdk_nvme_ctrlr_opts_set_defaults(struct spdk_nvme_ctrlr_opts *opts) +{ + memset(opts, 0, sizeof(*opts)); +} + uint32_t spdk_nvme_ns_get_sector_size(struct spdk_nvme_ns *ns) {