From: Chaitanya Kulkarni 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 --- 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