[PATCH 1/3] nvme-core: make cid gencounter configurable
Chaitanya Kulkarni
chaitanyak at nvidia.com
Fri Dec 10 03:21:14 PST 2021
From: Chaitanya Kulkarni <kch at nvidia.com>
The recent commit uses a combination of command id and a gencounter
to calculate the command id so that we can call out buggy controllers
for spurious completions and that also avoids use after free.
This commit adds various if statements and bitwise operations
such as &, <<, >>, & along with comparison operations to validate the Â
gencounter and print out the errors.
Â
This feature is required to catch the buggy controller, but in the Â
production environment where controller is validated and known to be
stable this achieves nothing but adds additional code and runtime CPU Â
instructions for the PCIe controller.
Worst case scenario when NVMeOF setup is using passthru backend then
these instructions get duplicated on the host and on the target side
for each controller.
Â
This patch makes the gencounter feature configurable by Â
using new macro CONFIG_NVME_DEBUG_USE_CID_GENCTR. We move the current
tag + gencounter code when CONFIG_NVME_DEBUG_USE_CID_GENCTR is defined
and keep the original code where we use tag-based command id where
NVME_DEBUG_USE_CID_GENCTR is not defined.
Signed-off-by: Chaitanya Kulkarni <kch at nvidia.com>
---
drivers/nvme/host/nvme.h | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
index b334af8aa264..98d7627cfdce 100644
--- a/drivers/nvme/host/nvme.h
+++ b/drivers/nvme/host/nvme.h
@@ -153,7 +153,9 @@ enum nvme_quirks {
struct nvme_request {
struct nvme_command *cmd;
union nvme_result result;
+#ifdef CONFIG_NVME_DEBUG_USE_CID_GENCTR
u8 genctr;
+#endif
u8 retries;
u8 flags;
u16 status;
@@ -496,6 +498,7 @@ struct nvme_ctrl_ops {
int (*get_address)(struct nvme_ctrl *ctrl, char *buf, int size);
};
+#ifdef CONFIG_NVME_DEBUG_USE_CID_GENCTR
/*
* nvme command_id is constructed as such:
* | xxxx | xxxxxxxxxxxx |
@@ -538,6 +541,32 @@ static inline struct request *nvme_cid_to_rq(struct blk_mq_tags *tags,
{
return blk_mq_tag_to_rq(tags, nvme_tag_from_cid(command_id));
}
+#else
+#define nvme_tag_from_cid(cid) (cid)
+static inline u16 nvme_cid(struct request *rq)
+{
+ return rq->tag;
+}
+
+static inline struct request *nvme_cid_to_rq(struct blk_mq_tags *tags,
+ u16 command_id)
+{
+ return blk_mq_tag_to_rq(tags, command_id);
+}
+
+static inline struct request *nvme_find_rq(struct blk_mq_tags *tags,
+ u16 command_id)
+{
+ u16 tag = nvme_tag_from_cid(command_id);
+ struct request *rq;
+
+ rq = blk_mq_tag_to_rq(tags, tag);
+ if (unlikely(!rq))
+ pr_err("could not locate request for tag %#x\n", tag);
+
+ return rq;
+}
+#endif /* CONFIG_NVME_DEBUG_USE_CID_GENCTR */
#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS
void nvme_fault_inject_init(struct nvme_fault_inject *fault_inj,
--
2.29.0
More information about the Linux-nvme
mailing list