@@ -1621,9 +1621,12 @@ struct nvmet_ctrl *nvmet_alloc_ctrl(struct nvmet_alloc_ctrl_args *args)
if (!ctrl->sqs)
goto out_free_changed_ns_list;
- ret = ida_alloc_range(&cntlid_ida,
- subsys->cntlid_min, subsys->cntlid_max,
- GFP_KERNEL);
+ if (args->cntlid == NVMET_MAX_CNTLID)
+ ret = ida_alloc_range(&cntlid_ida, subsys->cntlid_min,
+ subsys->cntlid_max, GFP_KERNEL);
+ else
+ ret = ida_alloc_range(&cntlid_ida, args->cntlid, args->cntlid,
+ GFP_KERNEL);
if (ret < 0) {
args->status = NVME_SC_CONNECT_CTRL_BUSY | NVME_STATUS_DNR;
goto out_free_sqs;
@@ -288,6 +288,7 @@ static void nvmet_execute_admin_connect(struct nvmet_req *req)
args.hostnqn = d->hostnqn;
args.hostid = &d->hostid;
args.kato = le32_to_cpu(c->kato);
+ args.cntlid = NVMET_MAX_CNTLID;
ctrl = nvmet_alloc_ctrl(&args);
if (!ctrl)
@@ -582,6 +582,8 @@ void nvmet_ctrl_fatal_error(struct nvmet_ctrl *ctrl);
void nvmet_update_cc(struct nvmet_ctrl *ctrl, u32 new);
+#define NVMET_MAX_CNTLID 0xFFF0
+
struct nvmet_alloc_ctrl_args {
struct nvmet_port *port;
char *subsysnqn;
@@ -590,6 +592,7 @@ struct nvmet_alloc_ctrl_args {
const struct nvmet_fabrics_ops *ops;
struct device *p2p_client;
u32 kato;
+ u16 cntlid;
__le32 result;
u16 error_loc;
u16 status;
@@ -2031,6 +2031,7 @@ static int nvmet_pci_epf_create_ctrl(struct nvmet_pci_epf *nvme_epf,
args.hostid = &id;
args.hostnqn = hostnqn;
args.ops = &nvmet_pci_epf_fabrics_ops;
+ args.cntlid = NVMET_MAX_CNTLID;
ctrl->tctrl = nvmet_alloc_ctrl(&args);
if (!ctrl->tctrl) {
For the configfs controller interface we will want to pass in the cntlid from userspace. This modifies nvmet_alloc_ctrl so the caller can pass in the cntlid or allow nvmet code to allocate it like it does today for dynamic controllers. Signed-off-by: Mike Christie <michael.christie@oracle.com> --- drivers/nvme/target/core.c | 9 ++++++--- drivers/nvme/target/fabrics-cmd.c | 1 + drivers/nvme/target/nvmet.h | 3 +++ drivers/nvme/target/pci-epf.c | 1 + 4 files changed, 11 insertions(+), 3 deletions(-)