summaryrefslogtreecommitdiffstats
path: root/drivers/block
diff options
context:
space:
mode:
authorMatthew Wilcox <matthew.r.wilcox@intel.com>2011-04-19 15:04:20 -0400
committerMatthew Wilcox <matthew.r.wilcox@intel.com>2011-11-04 15:53:02 -0400
commit22605f96810d073eb74051d0295b6577d6a6a563 (patch)
treef5af6aebe31f92cd6fe6bc343a931984ef7aa0f2 /drivers/block
parentaba2080f3f1639f9202f1a52993669844abcfb80 (diff)
downloadop-kernel-dev-22605f96810d073eb74051d0295b6577d6a6a563.zip
op-kernel-dev-22605f96810d073eb74051d0295b6577d6a6a563.tar.gz
NVMe: Time out initialisation after a few seconds
THe device reports (in its capability register) how long it will take to initialise. If that time elapses before the ready bit becomes set, conclude the device is broken and refuse to initialise it. Log a nice error message so the user knows why we did nothing. Signed-off-by: Matthew Wilcox <matthew.r.wilcox@intel.com>
Diffstat (limited to 'drivers/block')
-rw-r--r--drivers/block/nvme.c10
1 files changed, 10 insertions, 0 deletions
diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c
index bcc780a..57f2b33a 100644
--- a/drivers/block/nvme.c
+++ b/drivers/block/nvme.c
@@ -893,6 +893,8 @@ static int __devinit nvme_configure_admin_queue(struct nvme_dev *dev)
{
int result;
u32 aqa;
+ u64 cap;
+ unsigned long timeout;
struct nvme_queue *nvmeq;
dev->dbs = ((void __iomem *)dev->bar) + 4096;
@@ -915,10 +917,18 @@ static int __devinit nvme_configure_admin_queue(struct nvme_dev *dev)
writeq(nvmeq->cq_dma_addr, &dev->bar->acq);
writel(dev->ctrl_config, &dev->bar->cc);
+ cap = readq(&dev->bar->cap);
+ timeout = ((NVME_CAP_TIMEOUT(cap) + 1) * HZ / 2) + jiffies;
+
while (!(readl(&dev->bar->csts) & NVME_CSTS_RDY)) {
msleep(100);
if (fatal_signal_pending(current))
return -EINTR;
+ if (time_after(jiffies, timeout)) {
+ dev_err(&dev->pci_dev->dev,
+ "Device not ready; aborting initialisation\n");
+ return -ENODEV;
+ }
}
result = queue_request_irq(dev, nvmeq, "nvme admin");
OpenPOWER on IntegriCloud