nvmet: looks at the passthrough controller when initializing CAP
authorAdam Manzanares <a.manzanares@samsung.com>
Thu, 26 Aug 2021 21:15:45 +0000 (21:15 +0000)
committerChristoph Hellwig <hch@lst.de>
Mon, 6 Sep 2021 07:59:03 +0000 (09:59 +0200)
For a passthru controller make cap initialization dependent on the cap of
the passthru controller, given that multiple Command Set support needs
to be supported by the underlying controller.  For that move the
initialization of CAP later so that it can use the fully initialized
nvmet_ctrl structure.

Fixes: ab5d0b38c047 (nvmet: add Command Set Identifier support)
Signed-off-by: Adam Manzanares <a.manzanares@samsung.com>
Reviewed-by: Keith Busch <kbusch@kernel.org>
[hch: refactored the code a bit to keep it more contained in passthru.c]
Signed-off-by: Christoph Hellwig <hch@lst.de>
drivers/nvme/target/core.c
drivers/nvme/target/nvmet.h
drivers/nvme/target/passthru.c

index 66d05eecc2a9cbbd8415eabd799efb981babfcf4..11c44706dc2da2ec3f713a2893c5871bd08b173e 100644 (file)
@@ -1206,6 +1206,9 @@ static void nvmet_init_cap(struct nvmet_ctrl *ctrl)
        ctrl->cap |= (15ULL << 24);
        /* maximum queue entries supported: */
        ctrl->cap |= NVMET_QUEUE_SIZE - 1;
+
+       if (nvmet_passthru_ctrl(ctrl->subsys))
+               nvmet_passthrough_override_cap(ctrl);
 }
 
 struct nvmet_ctrl *nvmet_ctrl_find_get(const char *subsysnqn,
@@ -1363,8 +1366,6 @@ u16 nvmet_alloc_ctrl(const char *subsysnqn, const char *hostnqn,
                goto out_put_subsystem;
        mutex_init(&ctrl->lock);
 
-       nvmet_init_cap(ctrl);
-
        ctrl->port = req->port;
 
        INIT_WORK(&ctrl->async_event_work, nvmet_async_event_work);
@@ -1378,6 +1379,7 @@ u16 nvmet_alloc_ctrl(const char *subsysnqn, const char *hostnqn,
 
        kref_init(&ctrl->ref);
        ctrl->subsys = subsys;
+       nvmet_init_cap(ctrl);
        WRITE_ONCE(ctrl->aen_enabled, NVMET_AEN_CFG_OPTIONAL);
 
        ctrl->changed_ns_list = kmalloc_array(NVME_MAX_CHANGED_NAMESPACES,
index 06dd3d537f073238279e88d8821d2eeeb7044a6d..18311960796816ec13b0fa69962d90c2961089c1 100644 (file)
@@ -613,6 +613,8 @@ nvmet_req_passthru_ctrl(struct nvmet_req *req)
        return nvmet_passthru_ctrl(nvmet_req_subsys(req));
 }
 
+void nvmet_passthrough_override_cap(struct nvmet_ctrl *ctrl);
+
 u16 errno_to_nvme_status(struct nvmet_req *req, int errno);
 u16 nvmet_report_invalid_opcode(struct nvmet_req *req);
 
index 225cd1ffbe45881fd133f9af9f4fb45ec620cf1d..8784c487e46213e35e5805a3b6fd1f4def518442 100644 (file)
@@ -20,6 +20,16 @@ MODULE_IMPORT_NS(NVME_TARGET_PASSTHRU);
  */
 static DEFINE_XARRAY(passthru_subsystems);
 
+void nvmet_passthrough_override_cap(struct nvmet_ctrl *ctrl)
+{
+       /*
+        * Multiple command set support can only be declared if the underlying
+        * controller actually supports it.
+        */
+       if (!nvme_multi_css(ctrl->subsys->passthru_ctrl))
+               ctrl->cap &= ~(1ULL << 43);
+}
+
 static u16 nvmet_passthru_override_id_ctrl(struct nvmet_req *req)
 {
        struct nvmet_ctrl *ctrl = req->sq->ctrl;