diff --git a/drivers/nvme/host/fabrics.c b/drivers/nvme/host/fabrics.c index 571de549fbaf..27a8ce51d2b3 100644 --- a/drivers/nvme/host/fabrics.c +++ b/drivers/nvme/host/fabrics.c @@ -1125,18 +1125,27 @@ static int nvmf_parse_options(struct nvmf_ctrl_options *opts, void nvmf_set_io_queues(struct nvmf_ctrl_options *opts, u32 nr_io_queues, u32 io_queues[HCTX_MAX_TYPES]) { + /* + * Each queue type is mapped to the CPUs separately, so a type with + * more queues than online CPUs has hardware contexts without an online + * CPU. Use the same limits as nvmf_nr_io_queues. + */ + u32 nr_io = min(opts->nr_io_queues, num_online_cpus()); + u32 nr_write = min(opts->nr_write_queues, num_online_cpus()); + u32 nr_poll = min(opts->nr_poll_queues, num_online_cpus()); + memset(io_queues, 0, sizeof(*io_queues) * HCTX_MAX_TYPES); - if (opts->nr_write_queues && opts->nr_io_queues < nr_io_queues) { + if (nr_write && nr_io < nr_io_queues) { /* * separate read/write queues * hand out dedicated default queues only after we have * sufficient read queues. */ - io_queues[HCTX_TYPE_READ] = opts->nr_io_queues; + io_queues[HCTX_TYPE_READ] = nr_io; nr_io_queues -= io_queues[HCTX_TYPE_READ]; io_queues[HCTX_TYPE_DEFAULT] = - min(opts->nr_write_queues, nr_io_queues); + min(nr_write, nr_io_queues); nr_io_queues -= io_queues[HCTX_TYPE_DEFAULT]; } else { /* @@ -1145,14 +1154,14 @@ void nvmf_set_io_queues(struct nvmf_ctrl_options *opts, u32 nr_io_queues, * sufficient queue count to have dedicated default queues. */ io_queues[HCTX_TYPE_DEFAULT] = - min(opts->nr_io_queues, nr_io_queues); + min(nr_io, nr_io_queues); nr_io_queues -= io_queues[HCTX_TYPE_DEFAULT]; } - if (opts->nr_poll_queues && nr_io_queues) { + if (nr_poll && nr_io_queues) { /* map dedicated poll queues only if we have queues left */ io_queues[HCTX_TYPE_POLL] = - min(opts->nr_poll_queues, nr_io_queues); + min(nr_poll, nr_io_queues); } } EXPORT_SYMBOL_GPL(nvmf_set_io_queues);