aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthew Wilcox <matthew.r.wilcox@intel.com>2013-05-04 06:43:16 -0400
committerMatthew Wilcox <matthew.r.wilcox@intel.com>2013-05-08 09:53:49 -0400
commitba47e3865e8023e79b670793a41508222b5f0322 (patch)
treed222ea337ee683ce0a544a818d85721a71d125c9
parent78f8d2577bd79ce9d62f4d9e6d3b895bd1dd1d1d (diff)
NVMe: Wait for device to acknowledge shutdown
A recent update to the specification makes it clear that the host is expected to wait for the device to acknowledge the Enable bit transitioning to 0 as well as waiting for the device to acknowledge a transition to 1. Reported-by: Khosrow Panah <Khosrow.Panah@idt.com> Signed-off-by: Matthew Wilcox <matthew.r.wilcox@intel.com> Reviewed-by: Keith Busch <keith.busch@intel.com>
-rw-r--r--drivers/block/nvme-core.c65
1 files changed, 46 insertions, 19 deletions
diff --git a/drivers/block/nvme-core.c b/drivers/block/nvme-core.c
index a232dfc1cd4a..2b1b5a74dc72 100644
--- a/drivers/block/nvme-core.c
+++ b/drivers/block/nvme-core.c
@@ -1108,15 +1108,57 @@ static struct nvme_queue *nvme_create_queue(struct nvme_dev *dev, int qid,
1108 return ERR_PTR(result); 1108 return ERR_PTR(result);
1109} 1109}
1110 1110
1111static int nvme_wait_ready(struct nvme_dev *dev, u64 cap, bool enabled)
1112{
1113 unsigned long timeout;
1114 u32 bit = enabled ? NVME_CSTS_RDY : 0;
1115
1116 timeout = ((NVME_CAP_TIMEOUT(cap) + 1) * HZ / 2) + jiffies;
1117
1118 while ((readl(&dev->bar->csts) & NVME_CSTS_RDY) != bit) {
1119 msleep(100);
1120 if (fatal_signal_pending(current))
1121 return -EINTR;
1122 if (time_after(jiffies, timeout)) {
1123 dev_err(&dev->pci_dev->dev,
1124 "Device not ready; aborting initialisation\n");
1125 return -ENODEV;
1126 }
1127 }
1128
1129 return 0;
1130}
1131
1132/*
1133 * If the device has been passed off to us in an enabled state, just clear
1134 * the enabled bit. The spec says we should set the 'shutdown notification
1135 * bits', but doing so may cause the device to complete commands to the
1136 * admin queue ... and we don't know what memory that might be pointing at!
1137 */
1138static int nvme_disable_ctrl(struct nvme_dev *dev, u64 cap)
1139{
1140 writel(0, &dev->bar->cc);
1141 return nvme_wait_ready(dev, cap, false);
1142}
1143
1144static int nvme_enable_ctrl(struct nvme_dev *dev, u64 cap)
1145{
1146 return nvme_wait_ready(dev, cap, true);
1147}
1148
1111static int nvme_configure_admin_queue(struct nvme_dev *dev) 1149static int nvme_configure_admin_queue(struct nvme_dev *dev)
1112{ 1150{
1113 int result = 0; 1151 int result;
1114 u32 aqa; 1152 u32 aqa;
1115 u64 cap; 1153 u64 cap = readq(&dev->bar->cap);
1116 unsigned long timeout;
1117 struct nvme_queue *nvmeq; 1154 struct nvme_queue *nvmeq;
1118 1155
1119 dev->dbs = ((void __iomem *)dev->bar) + 4096; 1156 dev->dbs = ((void __iomem *)dev->bar) + 4096;
1157 dev->db_stride = NVME_CAP_STRIDE(cap);
1158
1159 result = nvme_disable_ctrl(dev, cap);
1160 if (result < 0)
1161 return result;
1120 1162
1121 nvmeq = nvme_alloc_queue(dev, 0, 64, 0); 1163 nvmeq = nvme_alloc_queue(dev, 0, 64, 0);
1122 if (!nvmeq) 1164 if (!nvmeq)
@@ -1130,27 +1172,12 @@ static int nvme_configure_admin_queue(struct nvme_dev *dev)
1130 dev->ctrl_config |= NVME_CC_ARB_RR | NVME_CC_SHN_NONE; 1172 dev->ctrl_config |= NVME_CC_ARB_RR | NVME_CC_SHN_NONE;
1131 dev->ctrl_config |= NVME_CC_IOSQES | NVME_CC_IOCQES; 1173 dev->ctrl_config |= NVME_CC_IOSQES | NVME_CC_IOCQES;
1132 1174
1133 writel(0, &dev->bar->cc);
1134 writel(aqa, &dev->bar->aqa); 1175 writel(aqa, &dev->bar->aqa);
1135 writeq(nvmeq->sq_dma_addr, &dev->bar->asq); 1176 writeq(nvmeq->sq_dma_addr, &dev->bar->asq);
1136 writeq(nvmeq->cq_dma_addr, &dev->bar->acq); 1177 writeq(nvmeq->cq_dma_addr, &dev->bar->acq);
1137 writel(dev->ctrl_config, &dev->bar->cc); 1178 writel(dev->ctrl_config, &dev->bar->cc);
1138 1179
1139 cap = readq(&dev->bar->cap); 1180 result = nvme_enable_ctrl(dev, cap);
1140 timeout = ((NVME_CAP_TIMEOUT(cap) + 1) * HZ / 2) + jiffies;
1141 dev->db_stride = NVME_CAP_STRIDE(cap);
1142
1143 while (!result && !(readl(&dev->bar->csts) & NVME_CSTS_RDY)) {
1144 msleep(100);
1145 if (fatal_signal_pending(current))
1146 result = -EINTR;
1147 if (time_after(jiffies, timeout)) {
1148 dev_err(&dev->pci_dev->dev,
1149 "Device not ready; aborting initialisation\n");
1150 result = -ENODEV;
1151 }
1152 }
1153
1154 if (result) 1181 if (result)
1155 goto free_q; 1182 goto free_q;
1156 1183