[PATCH RFC V2 4/7] nvme-core: add a function to submit a cancel command
Maurizio Lombardi
mlombard at redhat.com
Thu Sep 12 01:15:07 PDT 2024
Add a function to send a cancel command to abort the specified request.
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 | 61 ++++++++++++++++++++++++++++++++++++++++
drivers/nvme/host/nvme.h | 2 ++
2 files changed, 63 insertions(+)
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index 60b56404d3fb..a6e50bf2948a 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -3069,6 +3069,67 @@ 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;
+
+ if (!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: 0x0 imm abrts = %u def abrts = %u",
+ imm_abrts, def_abrts);
+ } else {
+ dev_warn(ctrl->device, "Cancel status: 0x%x", status);
+ }
+
+ 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, int action)
+{
+ struct nvme_command c = { };
+ struct request *cancel_req;
+
+ if (sqid == 0)
+ return -EINVAL;
+
+ c.cancel.opcode = nvme_cmd_cancel;
+ c.cancel.sqid = cpu_to_le32(sqid);
+ c.cancel.nsid = NVME_NSID_ALL;
+ c.cancel.action = action;
+ if (action == NVME_CANCEL_ACTION_SINGLE_CMD)
+ c.cancel.cid = nvme_cid(rq);
+ else
+ c.cancel.cid = 0xFFFF;
+
+ 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, "%s: Could not allocate the Cancel "
+ "command", __func__);
+ 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 c014192bd623..4ffa5f252fda 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, int action);
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.43.5
More information about the Linux-nvme
mailing list