Skip to content

Commit

Permalink
NVMe: Use normal shutdown
Browse files Browse the repository at this point in the history
The NVMe spec recommends using the shutdown normal sequence when safely
taking the controller offline instead of hitting CC.EN on the next
start-up to reset the controller. The spec recommends a minimum of 1
second for the shutdown complete. This patch waits 2 seconds to be on
the safe side.

Signed-off-by: Keith Busch <keith.busch@intel.com>
Signed-off-by: Matthew Wilcox <matthew.r.wilcox@intel.com>
  • Loading branch information
Keith Busch authored and Matthew Wilcox committed Sep 3, 2013
1 parent f0b5073 commit 1894d8f
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 0 deletions.
26 changes: 26 additions & 0 deletions drivers/block/nvme-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -1221,6 +1221,30 @@ static int nvme_enable_ctrl(struct nvme_dev *dev, u64 cap)
return nvme_wait_ready(dev, cap, true);
}

static int nvme_shutdown_ctrl(struct nvme_dev *dev)
{
unsigned long timeout;
u32 cc;

cc = (readl(&dev->bar->cc) & ~NVME_CC_SHN_MASK) | NVME_CC_SHN_NORMAL;
writel(cc, &dev->bar->cc);

timeout = 2 * HZ + jiffies;
while ((readl(&dev->bar->csts) & NVME_CSTS_SHST_MASK) !=
NVME_CSTS_SHST_CMPLT) {
msleep(100);
if (fatal_signal_pending(current))
return -EINTR;
if (time_after(jiffies, timeout)) {
dev_err(&dev->pci_dev->dev,
"Device shutdown incomplete; abort shutdown\n");
return -ENODEV;
}
}

return 0;
}

static int nvme_configure_admin_queue(struct nvme_dev *dev)
{
int result;
Expand Down Expand Up @@ -1943,6 +1967,8 @@ static void nvme_dev_shutdown(struct nvme_dev *dev)
list_del_init(&dev->node);
spin_unlock(&dev_list_lock);

if (dev->bar)
nvme_shutdown_ctrl(dev);
nvme_dev_unmap(dev);
}

Expand Down
2 changes: 2 additions & 0 deletions include/linux/nvme.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,15 @@ enum {
NVME_CC_SHN_NONE = 0 << 14,
NVME_CC_SHN_NORMAL = 1 << 14,
NVME_CC_SHN_ABRUPT = 2 << 14,
NVME_CC_SHN_MASK = 3 << 14,
NVME_CC_IOSQES = 6 << 16,
NVME_CC_IOCQES = 4 << 20,
NVME_CSTS_RDY = 1 << 0,
NVME_CSTS_CFS = 1 << 1,
NVME_CSTS_SHST_NORMAL = 0 << 2,
NVME_CSTS_SHST_OCCUR = 1 << 2,
NVME_CSTS_SHST_CMPLT = 2 << 2,
NVME_CSTS_SHST_MASK = 3 << 2,
};

#define NVME_VS(major, minor) (major << 16 | minor)
Expand Down

0 comments on commit 1894d8f

Please sign in to comment.