Message ID | 20200629182642.1170387-4-its@irrelevant.dk |
---|---|
State | New |
Headers | show |
Series | hw/block/nvme: bump to v1.3 | expand |
Looks good, Reviewed-by: Dmitry Fomichev <dmitry.fomichev@wdc.com> On Mon, 2020-06-29 at 20:26 +0200, Klaus Jensen wrote: > From: Klaus Jensen <k.jensen@samsung.com> > > Required for compliance with NVMe revision 1.3d. See NVM Express 1.3d, > Section 5.1 ("Abort command"). > > The Abort command is a best effort command; for now, the device always > fails to abort the given command. > > Signed-off-by: Klaus Jensen <klaus.jensen@cnexlabs.com> > Signed-off-by: Klaus Jensen <k.jensen@samsung.com> > Acked-by: Keith Busch <kbusch@kernel.org> > Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com> > --- > hw/block/nvme.c | 27 +++++++++++++++++++++++++++ > 1 file changed, 27 insertions(+) > > diff --git a/hw/block/nvme.c b/hw/block/nvme.c > index f5d9148f0936..b7037a7d3504 100644 > --- a/hw/block/nvme.c > +++ b/hw/block/nvme.c > @@ -761,6 +761,18 @@ static uint16_t nvme_identify(NvmeCtrl *n, NvmeCmd *cmd) > } > } > > +static uint16_t nvme_abort(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req) > +{ > + uint16_t sqid = le32_to_cpu(cmd->cdw10) & 0xffff; > + > + req->cqe.result = 1; > + if (nvme_check_sqid(n, sqid)) { > + return NVME_INVALID_FIELD | NVME_DNR; > + } > + > + return NVME_SUCCESS; > +} > + > static inline void nvme_set_timestamp(NvmeCtrl *n, uint64_t ts) > { > trace_pci_nvme_setfeat_timestamp(ts); > @@ -897,6 +909,8 @@ static uint16_t nvme_admin_cmd(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req) > return nvme_create_cq(n, cmd); > case NVME_ADM_CMD_IDENTIFY: > return nvme_identify(n, cmd); > + case NVME_ADM_CMD_ABORT: > + return nvme_abort(n, cmd, req); > case NVME_ADM_CMD_SET_FEATURES: > return nvme_set_feature(n, cmd, req); > case NVME_ADM_CMD_GET_FEATURES: > @@ -1582,6 +1596,19 @@ static void nvme_init_ctrl(NvmeCtrl *n, PCIDevice *pci_dev) > id->ieee[1] = 0x02; > id->ieee[2] = 0xb3; > id->oacs = cpu_to_le16(0); > + > + /* > + * Because the controller always completes the Abort command immediately, > + * there can never be more than one concurrently executing Abort command, > + * so this value is never used for anything. Note that there can easily be > + * many Abort commands in the queues, but they are not considered > + * "executing" until processed by nvme_abort. > + * > + * The specification recommends a value of 3 for Abort Command Limit (four > + * concurrently outstanding Abort commands), so lets use that though it is > + * inconsequential. > + */ > + id->acl = 3; > id->frmw = 7 << 1; > id->lpa = 1 << 0; > id->sqes = (0x6 << 4) | 0x6;
diff --git a/hw/block/nvme.c b/hw/block/nvme.c index f5d9148f0936..b7037a7d3504 100644 --- a/hw/block/nvme.c +++ b/hw/block/nvme.c @@ -761,6 +761,18 @@ static uint16_t nvme_identify(NvmeCtrl *n, NvmeCmd *cmd) } } +static uint16_t nvme_abort(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req) +{ + uint16_t sqid = le32_to_cpu(cmd->cdw10) & 0xffff; + + req->cqe.result = 1; + if (nvme_check_sqid(n, sqid)) { + return NVME_INVALID_FIELD | NVME_DNR; + } + + return NVME_SUCCESS; +} + static inline void nvme_set_timestamp(NvmeCtrl *n, uint64_t ts) { trace_pci_nvme_setfeat_timestamp(ts); @@ -897,6 +909,8 @@ static uint16_t nvme_admin_cmd(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req) return nvme_create_cq(n, cmd); case NVME_ADM_CMD_IDENTIFY: return nvme_identify(n, cmd); + case NVME_ADM_CMD_ABORT: + return nvme_abort(n, cmd, req); case NVME_ADM_CMD_SET_FEATURES: return nvme_set_feature(n, cmd, req); case NVME_ADM_CMD_GET_FEATURES: @@ -1582,6 +1596,19 @@ static void nvme_init_ctrl(NvmeCtrl *n, PCIDevice *pci_dev) id->ieee[1] = 0x02; id->ieee[2] = 0xb3; id->oacs = cpu_to_le16(0); + + /* + * Because the controller always completes the Abort command immediately, + * there can never be more than one concurrently executing Abort command, + * so this value is never used for anything. Note that there can easily be + * many Abort commands in the queues, but they are not considered + * "executing" until processed by nvme_abort. + * + * The specification recommends a value of 3 for Abort Command Limit (four + * concurrently outstanding Abort commands), so lets use that though it is + * inconsequential. + */ + id->acl = 3; id->frmw = 7 << 1; id->lpa = 1 << 0; id->sqes = (0x6 << 4) | 0x6;