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 <daniel.verkamp@intel.com>
This commit is contained in:
parent
23f95df80d
commit
4ad99808f2
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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),
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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]);
|
||||
}
|
||||
|
||||
|
@ -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__ */
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user