[PATCH 2/5] nvme-core: add a function to submit a cancel command
Maurizio Lombardi
mlombard at redhat.com
Fri May 10 09:30:23 PDT 2024
Add a function to send a cancel command to abort the specified request.
To execute the task, the "single command" cancel action is used.
When the cancel command completes, the host driver will print the
number of deferred and immediate aborts performed by the target.
Signed-off-by: Maurizio Lombardi <mlombard at redhat.com>
---
drivers/nvme/host/core.c | 54 ++++++++++++++++++++++++++++++++++++++++
drivers/nvme/host/nvme.h | 2 ++
2 files changed, 56 insertions(+)
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index b48967c98114..3d8c31d5f8ae 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -2965,6 +2965,60 @@ int nvme_get_log(struct nvme_ctrl *ctrl, u32 nsid, u8 log_page, u8 lsp, u8 csi,
return nvme_submit_sync_cmd(ctrl->admin_q, &c, log, size);
}
+static enum rq_end_io_ret nvme_cancel_endio(struct request *req, blk_status_t error)
+{
+ struct nvme_ctrl *ctrl = req->end_io_data;
+ u32 result;
+ u16 imm_abrts, def_abrts;
+ u16 status = nvme_req(req)->status;
+
+ result = le32_to_cpu(nvme_req(req)->result.u32);
+
+ def_abrts = upper_16_bits(result);
+ imm_abrts = lower_16_bits(result);
+
+ dev_warn(ctrl->device,
+ "Cancel status: 0x%x imm abrts = %u def abrts = %u",
+ status, imm_abrts, def_abrts);
+
+ blk_mq_free_request(req);
+ return RQ_END_IO_NONE;
+}
+
+int nvme_submit_cancel_req(struct nvme_ctrl *ctrl, struct request *rq,
+ unsigned int sqid)
+{
+ struct nvme_command c = { };
+ struct request *cancel_req;
+
+ if (sqid == 0)
+ return -EINVAL;
+
+ c.cancel.opcode = nvme_cmd_cancel;
+ c.cancel.cid = nvme_cid(rq);
+ c.cancel.sqid = cpu_to_le32(sqid);
+ c.cancel.nsid = NVME_NSID_ALL;
+ c.cancel.action = NVME_CANCEL_ACTION_SINGLE_CMD;
+
+ cancel_req = blk_mq_alloc_request_hctx(rq->q, nvme_req_op(&c),
+ BLK_MQ_REQ_NOWAIT |
+ BLK_MQ_REQ_RESERVED,
+ sqid - 1);
+ if (IS_ERR(cancel_req)) {
+ dev_warn(ctrl->device, "Cancel command failed!\n");
+ return PTR_ERR(cancel_req);
+ }
+
+ nvme_init_request(cancel_req, &c);
+ cancel_req->end_io = nvme_cancel_endio;
+ cancel_req->end_io_data = ctrl;
+
+ blk_execute_rq_nowait(cancel_req, false);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(nvme_submit_cancel_req);
+
static int nvme_get_effects_log(struct nvme_ctrl *ctrl, u8 csi,
struct nvme_effects_log **log)
{
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
index b564c5f1450c..c4cea8b948a8 100644
--- a/drivers/nvme/host/nvme.h
+++ b/drivers/nvme/host/nvme.h
@@ -895,6 +895,8 @@ int nvme_delete_ctrl(struct nvme_ctrl *ctrl);
void nvme_queue_scan(struct nvme_ctrl *ctrl);
int nvme_get_log(struct nvme_ctrl *ctrl, u32 nsid, u8 log_page, u8 lsp, u8 csi,
void *log, size_t size, u64 offset);
+int nvme_submit_cancel_req(struct nvme_ctrl *ctrl, struct request *rq,
+ unsigned int sqid);
bool nvme_tryget_ns_head(struct nvme_ns_head *head);
void nvme_put_ns_head(struct nvme_ns_head *head);
int nvme_cdev_add(struct cdev *cdev, struct device *cdev_device,
--
2.39.3
More information about the Linux-nvme
mailing list