aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/nvme-scsi.c
diff options
context:
space:
mode:
authorKeith Busch <keith.busch@intel.com>2014-04-03 18:45:23 -0400
committerMatthew Wilcox <matthew.r.wilcox@intel.com>2014-04-10 17:11:59 -0400
commitedd10d33283899fb15d99a290dcc9ceb3604ca78 (patch)
tree870dc908379694e20ea319ba11c81bec5864cef7 /drivers/block/nvme-scsi.c
parent4cc09e2dc4cbe6009c935b6f12a8376f09124bc5 (diff)
NVMe: Retry failed commands with non-fatal errors
For commands returned with failed status, queue these for resubmission and continue retrying them until success or for a limited amount of time. The final timeout was arbitrarily chosen so requests can't be retried indefinitely. Since these are requeued on the nvmeq that submitted the command, the callbacks have to take an nvmeq instead of an nvme_dev as a parameter so that we can use the locked queue to append the iod to retry later. The nvme_iod conviently can be used to track how long we've been trying to successfully complete an iod request. The nvme_iod also provides the nvme prp dma mappings, so I had to move a few things around so we can keep those mappings. Signed-off-by: Keith Busch <keith.busch@intel.com> [fixed checkpatch issue with long line] Signed-off-by: Matthew Wilcox <matthew.r.wilcox@intel.com>
Diffstat (limited to 'drivers/block/nvme-scsi.c')
-rw-r--r--drivers/block/nvme-scsi.c10
1 files changed, 6 insertions, 4 deletions
diff --git a/drivers/block/nvme-scsi.c b/drivers/block/nvme-scsi.c
index 111c920c1574..2c3f5be06da1 100644
--- a/drivers/block/nvme-scsi.c
+++ b/drivers/block/nvme-scsi.c
@@ -1562,13 +1562,14 @@ static int nvme_trans_send_fw_cmd(struct nvme_ns *ns, struct sg_io_hdr *hdr,
1562 res = PTR_ERR(iod); 1562 res = PTR_ERR(iod);
1563 goto out; 1563 goto out;
1564 } 1564 }
1565 length = nvme_setup_prps(dev, &c.common, iod, tot_len, 1565 length = nvme_setup_prps(dev, iod, tot_len, GFP_KERNEL);
1566 GFP_KERNEL);
1567 if (length != tot_len) { 1566 if (length != tot_len) {
1568 res = -ENOMEM; 1567 res = -ENOMEM;
1569 goto out_unmap; 1568 goto out_unmap;
1570 } 1569 }
1571 1570
1571 c.dlfw.prp1 = cpu_to_le64(sg_dma_address(iod->sg));
1572 c.dlfw.prp2 = cpu_to_le64(iod->first_dma);
1572 c.dlfw.numd = cpu_to_le32((tot_len/BYTES_TO_DWORDS) - 1); 1573 c.dlfw.numd = cpu_to_le32((tot_len/BYTES_TO_DWORDS) - 1);
1573 c.dlfw.offset = cpu_to_le32(offset/BYTES_TO_DWORDS); 1574 c.dlfw.offset = cpu_to_le32(offset/BYTES_TO_DWORDS);
1574 } else if (opcode == nvme_admin_activate_fw) { 1575 } else if (opcode == nvme_admin_activate_fw) {
@@ -2092,8 +2093,7 @@ static int nvme_trans_do_nvme_io(struct nvme_ns *ns, struct sg_io_hdr *hdr,
2092 res = PTR_ERR(iod); 2093 res = PTR_ERR(iod);
2093 goto out; 2094 goto out;
2094 } 2095 }
2095 retcode = nvme_setup_prps(dev, &c.common, iod, unit_len, 2096 retcode = nvme_setup_prps(dev, iod, unit_len, GFP_KERNEL);
2096 GFP_KERNEL);
2097 if (retcode != unit_len) { 2097 if (retcode != unit_len) {
2098 nvme_unmap_user_pages(dev, 2098 nvme_unmap_user_pages(dev,
2099 (is_write) ? DMA_TO_DEVICE : DMA_FROM_DEVICE, 2099 (is_write) ? DMA_TO_DEVICE : DMA_FROM_DEVICE,
@@ -2102,6 +2102,8 @@ static int nvme_trans_do_nvme_io(struct nvme_ns *ns, struct sg_io_hdr *hdr,
2102 res = -ENOMEM; 2102 res = -ENOMEM;
2103 goto out; 2103 goto out;
2104 } 2104 }
2105 c.rw.prp1 = cpu_to_le64(sg_dma_address(iod->sg));
2106 c.rw.prp2 = cpu_to_le64(iod->first_dma);
2105 2107
2106 nvme_offset += unit_num_blocks; 2108 nvme_offset += unit_num_blocks;
2107 2109