2021-08-26 21:16:45

by Adam Manzanares

[permalink] [raw]
Subject: [PATCH 2/2] nvmet: use passthru cntrl in nvmet_init_cap

For a passthru controller make cap initialization dependent on the cap of
the passthru controller.

Fixes: ab5d0b38c047 (nvmet: add Command Set Identifier support)
Signed-off-by: Adam Manzanares <[email protected]>
---
drivers/nvme/target/core.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/nvme/target/core.c b/drivers/nvme/target/core.c
index 66d05eecc2a9..220ba5ed5f3a 100644
--- a/drivers/nvme/target/core.c
+++ b/drivers/nvme/target/core.c
@@ -9,6 +9,7 @@
#include <linux/rculist.h>
#include <linux/pci-p2pdma.h>
#include <linux/scatterlist.h>
+#include "../host/nvme.h"

#define CREATE_TRACE_POINTS
#include "trace.h"
@@ -1198,10 +1199,13 @@ void nvmet_update_cc(struct nvmet_ctrl *ctrl, u32 new)

static void nvmet_init_cap(struct nvmet_ctrl *ctrl)
{
+ struct nvme_ctrl *ptctrl = nvmet_passthru_ctrl(ctrl->subsys);
+
/* command sets supported: NVMe command set: */
ctrl->cap = (1ULL << 37);
/* Controller supports one or more I/O Command Sets */
- ctrl->cap |= (1ULL << 43);
+ if ((ptctrl && nvme_multi_css(ptctrl)) || !ptctrl)
+ ctrl->cap |= (1ULL << 43);
/* CC.EN timeout in 500msec units: */
ctrl->cap |= (15ULL << 24);
/* maximum queue entries supported: */
@@ -1363,8 +1367,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 +1380,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,
--
2.25.1


2021-08-27 06:18:34

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [PATCH 2/2] nvmet: use passthru cntrl in nvmet_init_cap

Technically this looks good, but the core target code should not have
to poke into the host side data structures. Does this version still look
good to you?

---
From c5777caf1562df35150a71e5c91c5b272956beee Mon Sep 17 00:00:00 2001
From: Adam Manzanares <[email protected]>
Date: Thu, 26 Aug 2021 21:15:45 +0000
Subject: nvmet: looks at the passthrough controller when initializing CAP

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 <[email protected]>
Reviewed-by: Keith Busch <[email protected]>
[hch: refactored the code a bit to keep it more contained in passthru.c]
Signed-off-by: Christoph Hellwig <[email protected]>
---
drivers/nvme/target/core.c | 6 ++++--
drivers/nvme/target/nvmet.h | 2 ++
drivers/nvme/target/passthru.c | 10 ++++++++++
3 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/drivers/nvme/target/core.c b/drivers/nvme/target/core.c
index 66d05eecc2a9..11c44706dc2d 100644
--- a/drivers/nvme/target/core.c
+++ b/drivers/nvme/target/core.c
@@ -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,
diff --git a/drivers/nvme/target/nvmet.h b/drivers/nvme/target/nvmet.h
index 06dd3d537f07..183119607968 100644
--- a/drivers/nvme/target/nvmet.h
+++ b/drivers/nvme/target/nvmet.h
@@ -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);

diff --git a/drivers/nvme/target/passthru.c b/drivers/nvme/target/passthru.c
index 225cd1ffbe45..8784c487e462 100644
--- a/drivers/nvme/target/passthru.c
+++ b/drivers/nvme/target/passthru.c
@@ -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;
--
2.30.2

2021-08-27 16:21:24

by Adam Manzanares

[permalink] [raw]
Subject: Re: [PATCH 2/2] nvmet: use passthru cntrl in nvmet_init_cap

On Fri, Aug 27, 2021 at 08:17:37AM +0200, [email protected] wrote:
> Technically this looks good, but the core target code should not have
> to poke into the host side data structures. Does this version still look
> good to you?

Yup looks good, thanks for the help cleaning it up.

>
> ---
> From c5777caf1562df35150a71e5c91c5b272956beee Mon Sep 17 00:00:00 2001
> From: Adam Manzanares <[email protected]>
> Date: Thu, 26 Aug 2021 21:15:45 +0000
> Subject: nvmet: looks at the passthrough controller when initializing CAP
>
> 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 <[email protected]>
> Reviewed-by: Keith Busch <[email protected]>
> [hch: refactored the code a bit to keep it more contained in passthru.c]
> Signed-off-by: Christoph Hellwig <[email protected]>
> ---
> drivers/nvme/target/core.c | 6 ++++--
> drivers/nvme/target/nvmet.h | 2 ++
> drivers/nvme/target/passthru.c | 10 ++++++++++
> 3 files changed, 16 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/nvme/target/core.c b/drivers/nvme/target/core.c
> index 66d05eecc2a9..11c44706dc2d 100644
> --- a/drivers/nvme/target/core.c
> +++ b/drivers/nvme/target/core.c
> @@ -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,
> diff --git a/drivers/nvme/target/nvmet.h b/drivers/nvme/target/nvmet.h
> index 06dd3d537f07..183119607968 100644
> --- a/drivers/nvme/target/nvmet.h
> +++ b/drivers/nvme/target/nvmet.h
> @@ -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);
>
> diff --git a/drivers/nvme/target/passthru.c b/drivers/nvme/target/passthru.c
> index 225cd1ffbe45..8784c487e462 100644
> --- a/drivers/nvme/target/passthru.c
> +++ b/drivers/nvme/target/passthru.c
> @@ -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;
> --
> 2.30.2
>