]> Pileus Git - ~andy/linux/commitdiff
NVMe: Time out initialisation after a few seconds
authorMatthew Wilcox <matthew.r.wilcox@intel.com>
Tue, 19 Apr 2011 19:04:20 +0000 (15:04 -0400)
committerMatthew Wilcox <matthew.r.wilcox@intel.com>
Fri, 4 Nov 2011 19:53:02 +0000 (15:53 -0400)
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>
drivers/block/nvme.c
include/linux/nvme.h

index bcc780ac4ec0e21fbbc8f30394bb19a394d9c139..57f2b33a47dd187195f73ca8f789efc81bf8c445 100644 (file)
@@ -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");
index 9d6febb9152198ca220c2790a0fa4a4583072b63..a19304fefa7dc4f0b093df2b5ee63e14da2c242a 100644 (file)
@@ -35,6 +35,8 @@ struct nvme_bar {
        __u64                   acq;    /* Admin CQ Base Address */
 };
 
+#define NVME_CAP_TIMEOUT(cap)  (((cap) >> 24) & 0xff)
+
 enum {
        NVME_CC_ENABLE          = 1 << 0,
        NVME_CC_CSS_NVM         = 0 << 4,