diff options
author | Ayush Mishra <ayush.m55@samsung.com> | 2024-07-02 13:32:32 +0530 |
---|---|---|
committer | Klaus Jensen <k.jensen@samsung.com> | 2024-07-22 14:36:15 +0200 |
commit | 75209c071aab4488aef63c38fb53d0e4e3aaa062 (patch) | |
tree | eb7d9531a2169d49ff3d1f41d318f5d30876665b | |
parent | d522aef88d42a05e46290c97602936a7f6d307e3 (diff) | |
download | qemu-75209c071aab4488aef63c38fb53d0e4e3aaa062.zip qemu-75209c071aab4488aef63c38fb53d0e4e3aaa062.tar.gz qemu-75209c071aab4488aef63c38fb53d0e4e3aaa062.tar.bz2 |
hw/nvme: actually implement abort
Abort was not implemented previously, but we can implement it for AERs
and asynchrnously for I/O.
Signed-off-by: Ayush Mishra <ayush.m55@samsung.com>
Reviewed-by: Klaus Jensen <k.jensen@samsung.com>
Signed-off-by: Klaus Jensen <k.jensen@samsung.com>
-rw-r--r-- | hw/nvme/ctrl.c | 32 |
1 files changed, 32 insertions, 0 deletions
diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c index 385438a..39782dd 100644 --- a/hw/nvme/ctrl.c +++ b/hw/nvme/ctrl.c @@ -1758,6 +1758,10 @@ static void nvme_aio_err(NvmeRequest *req, int ret) break; } + if (ret == -ECANCELED) { + status = NVME_CMD_ABORT_REQ; + } + trace_pci_nvme_err_aio(nvme_cid(req), strerror(-ret), status); error_setg_errno(&local_err, -ret, "aio failed"); @@ -5950,12 +5954,40 @@ static uint16_t nvme_identify(NvmeCtrl *n, NvmeRequest *req) static uint16_t nvme_abort(NvmeCtrl *n, NvmeRequest *req) { uint16_t sqid = le32_to_cpu(req->cmd.cdw10) & 0xffff; + uint16_t cid = (le32_to_cpu(req->cmd.cdw10) >> 16) & 0xffff; + NvmeSQueue *sq = n->sq[sqid]; + NvmeRequest *r, *next; + int i; req->cqe.result = 1; if (nvme_check_sqid(n, sqid)) { return NVME_INVALID_FIELD | NVME_DNR; } + if (sqid == 0) { + for (i = 0; i < n->outstanding_aers; i++) { + NvmeRequest *re = n->aer_reqs[i]; + if (re->cqe.cid == cid) { + memmove(n->aer_reqs + i, n->aer_reqs + i + 1, + (n->outstanding_aers - i - 1) * sizeof(NvmeRequest *)); + n->outstanding_aers--; + re->status = NVME_CMD_ABORT_REQ; + req->cqe.result = 0; + nvme_enqueue_req_completion(&n->admin_cq, re); + return NVME_SUCCESS; + } + } + } + + QTAILQ_FOREACH_SAFE(r, &sq->out_req_list, entry, next) { + if (r->cqe.cid == cid) { + if (r->aiocb) { + blk_aio_cancel_async(r->aiocb); + } + break; + } + } + return NVME_SUCCESS; } |