Skip to content

Commit

Permalink
NVMe: Time out initialisation after a few seconds
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Matthew Wilcox committed Nov 4, 2011
1 parent aba2080 commit 22605f9
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 0 deletions.
10 changes: 10 additions & 0 deletions drivers/block/nvme.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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");
Expand Down
2 changes: 2 additions & 0 deletions include/linux/nvme.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down

0 comments on commit 22605f9

Please sign in to comment.