aboutsummaryrefslogtreecommitdiff
path: root/hw/block/nvme.c
diff options
context:
space:
mode:
authorGollu Appalanaidu <anaidu.gollu@samsung.com>2020-10-19 12:41:31 +0530
committerKlaus Jensen <k.jensen@samsung.com>2020-10-27 11:29:25 +0100
commit28fee5b5d02d59a2b039c71a0a72292b1bc7f75b (patch)
tree5c905de76cc0640f0c76724d540347d835f1dc7b /hw/block/nvme.c
parentb865cabf735be793789ad2c7eac97f47a1325966 (diff)
hw/block/nvme: fix prp mapping status codes
Address 0 is not an invalid address. Remove those invalikd checks. Unaligned PRP2 and PRP list entries should result in Invalid PRP Offset status code and not Invalid Field. Fix that. See NVMe Express v1.3d, Section 4.3 ("Physical Region Page Entry and List"). Suggested-by: Keith Busch <kbusch@kernel.org> Signed-off-by: Gollu Appalanaidu <anaidu.gollu@samsung.com> Signed-off-by: Klaus Jensen <k.jensen@samsung.com> Reviewed-by: Keith Busch <kbusch@kernel.org>
Diffstat (limited to 'hw/block/nvme.c')
-rw-r--r--hw/block/nvme.c20
1 files changed, 5 insertions, 15 deletions
diff --git a/hw/block/nvme.c b/hw/block/nvme.c
index b8c6be6318..2896bb49b9 100644
--- a/hw/block/nvme.c
+++ b/hw/block/nvme.c
@@ -327,11 +327,6 @@ static uint16_t nvme_map_prp(NvmeCtrl *n, uint64_t prp1, uint64_t prp2,
trace_pci_nvme_map_prp(trans_len, len, prp1, prp2, num_prps);
- if (unlikely(!prp1)) {
- trace_pci_nvme_err_invalid_prp();
- return NVME_INVALID_FIELD | NVME_DNR;
- }
-
if (nvme_addr_is_cmb(n, prp1)) {
qemu_iovec_init(iov, num_prps);
} else {
@@ -345,11 +340,6 @@ static uint16_t nvme_map_prp(NvmeCtrl *n, uint64_t prp1, uint64_t prp2,
len -= trans_len;
if (len) {
- if (unlikely(!prp2)) {
- trace_pci_nvme_err_invalid_prp2_missing();
- return NVME_INVALID_FIELD | NVME_DNR;
- }
-
if (len > n->page_size) {
uint64_t prp_list[n->max_prp_ents];
uint32_t nents, prp_trans;
@@ -370,9 +360,9 @@ static uint16_t nvme_map_prp(NvmeCtrl *n, uint64_t prp1, uint64_t prp2,
uint64_t prp_ent = le64_to_cpu(prp_list[i]);
if (i == n->max_prp_ents - 1 && len > n->page_size) {
- if (unlikely(!prp_ent || prp_ent & (n->page_size - 1))) {
+ if (unlikely(prp_ent & (n->page_size - 1))) {
trace_pci_nvme_err_invalid_prplist_ent(prp_ent);
- return NVME_INVALID_FIELD | NVME_DNR;
+ return NVME_INVALID_PRP_OFFSET | NVME_DNR;
}
if (prp_list_in_cmb != nvme_addr_is_cmb(n, prp_ent)) {
@@ -391,9 +381,9 @@ static uint16_t nvme_map_prp(NvmeCtrl *n, uint64_t prp1, uint64_t prp2,
prp_ent = le64_to_cpu(prp_list[i]);
}
- if (unlikely(!prp_ent || prp_ent & (n->page_size - 1))) {
+ if (unlikely(prp_ent & (n->page_size - 1))) {
trace_pci_nvme_err_invalid_prplist_ent(prp_ent);
- return NVME_INVALID_FIELD | NVME_DNR;
+ return NVME_INVALID_PRP_OFFSET | NVME_DNR;
}
trans_len = MIN(len, n->page_size);
@@ -408,7 +398,7 @@ static uint16_t nvme_map_prp(NvmeCtrl *n, uint64_t prp1, uint64_t prp2,
} else {
if (unlikely(prp2 & (n->page_size - 1))) {
trace_pci_nvme_err_invalid_prp2_align(prp2);
- return NVME_INVALID_FIELD | NVME_DNR;
+ return NVME_INVALID_PRP_OFFSET | NVME_DNR;
}
status = nvme_map_addr(n, qsg, iov, prp2, len);
if (status) {