Skip to content

Commit

Permalink
NVMe: Add nvme subsystem reset support
Browse files Browse the repository at this point in the history
Controllers part of an NVMe subsystem may be reset by any other controller
in the subsystem. If the device is capable of subsystem resets, this
patch adds detection for such events and performs appropriate controller
initialization upon subsystem reset detection.

The register bit is a RW1C type, so the driver needs to write a 1 to the
status bit to clear the subsystem reset occured bit during initialization.

Signed-off-by: Keith Busch <keith.busch@intel.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
  • Loading branch information
Keith Busch authored and Jens Axboe committed Aug 18, 2015
1 parent b2b1ec9 commit dfbac8c
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 1 deletion.
11 changes: 10 additions & 1 deletion drivers/block/nvme-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -1735,6 +1735,12 @@ static int nvme_configure_admin_queue(struct nvme_dev *dev)
page_shift = dev_page_max;
}

dev->subsystem = readl(&dev->bar->vs) >= NVME_VS(1, 1) ?
NVME_CAP_NSSRC(cap) : 0;

if (dev->subsystem && (readl(&dev->bar->csts) & NVME_CSTS_NSSRO))
writel(NVME_CSTS_NSSRO, &dev->bar->csts);

result = nvme_disable_ctrl(dev, cap);
if (result < 0)
return result;
Expand Down Expand Up @@ -2059,7 +2065,10 @@ static int nvme_kthread(void *data)
spin_lock(&dev_list_lock);
list_for_each_entry_safe(dev, next, &dev_list, node) {
int i;
if (readl(&dev->bar->csts) & NVME_CSTS_CFS) {
u32 csts = readl(&dev->bar->csts);

if ((dev->subsystem && (csts & NVME_CSTS_NSSRO)) ||
csts & NVME_CSTS_CFS) {
if (work_busy(&dev->reset_work))
continue;
list_del_init(&dev->node);
Expand Down
3 changes: 3 additions & 0 deletions include/linux/nvme.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ struct nvme_bar {
#define NVME_CAP_MQES(cap) ((cap) & 0xffff)
#define NVME_CAP_TIMEOUT(cap) (((cap) >> 24) & 0xff)
#define NVME_CAP_STRIDE(cap) (((cap) >> 32) & 0xf)
#define NVME_CAP_NSSRC(cap) (((cap) >> 36) & 0x1)
#define NVME_CAP_MPSMIN(cap) (((cap) >> 48) & 0xf)
#define NVME_CAP_MPSMAX(cap) (((cap) >> 52) & 0xf)

Expand Down Expand Up @@ -68,6 +69,7 @@ enum {
NVME_CC_IOCQES = 4 << 20,
NVME_CSTS_RDY = 1 << 0,
NVME_CSTS_CFS = 1 << 1,
NVME_CSTS_NSSRO = 1 << 4,
NVME_CSTS_SHST_NORMAL = 0 << 2,
NVME_CSTS_SHST_OCCUR = 1 << 2,
NVME_CSTS_SHST_CMPLT = 2 << 2,
Expand Down Expand Up @@ -110,6 +112,7 @@ struct nvme_dev {
char serial[20];
char model[40];
char firmware_rev[8];
bool subsystem;
u32 max_hw_sectors;
u32 stripe_size;
u32 page_size;
Expand Down

0 comments on commit dfbac8c

Please sign in to comment.