aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeith Busch <keith.busch@intel.com>2015-08-10 17:20:40 -0400
committerJens Axboe <axboe@fb.com>2015-08-18 13:56:11 -0400
commitdfbac8c7ac5f58448b2216fe42ff52aaf175421d (patch)
tree7c04b5a9131d80100f2c0955fe783022af74dc96
parentb2b1ec9b55ed0840956db15f823c4a73383c08be (diff)
NVMe: Add nvme subsystem reset support
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>
-rw-r--r--drivers/block/nvme-core.c11
-rw-r--r--include/linux/nvme.h3
2 files changed, 13 insertions, 1 deletions
diff --git a/drivers/block/nvme-core.c b/drivers/block/nvme-core.c
index 85cd33bf9607..e318a992e2e6 100644
--- a/drivers/block/nvme-core.c
+++ b/drivers/block/nvme-core.c
@@ -1735,6 +1735,12 @@ static int nvme_configure_admin_queue(struct nvme_dev *dev)
1735 page_shift = dev_page_max; 1735 page_shift = dev_page_max;
1736 } 1736 }
1737 1737
1738 dev->subsystem = readl(&dev->bar->vs) >= NVME_VS(1, 1) ?
1739 NVME_CAP_NSSRC(cap) : 0;
1740
1741 if (dev->subsystem && (readl(&dev->bar->csts) & NVME_CSTS_NSSRO))
1742 writel(NVME_CSTS_NSSRO, &dev->bar->csts);
1743
1738 result = nvme_disable_ctrl(dev, cap); 1744 result = nvme_disable_ctrl(dev, cap);
1739 if (result < 0) 1745 if (result < 0)
1740 return result; 1746 return result;
@@ -2059,7 +2065,10 @@ static int nvme_kthread(void *data)
2059 spin_lock(&dev_list_lock); 2065 spin_lock(&dev_list_lock);
2060 list_for_each_entry_safe(dev, next, &dev_list, node) { 2066 list_for_each_entry_safe(dev, next, &dev_list, node) {
2061 int i; 2067 int i;
2062 if (readl(&dev->bar->csts) & NVME_CSTS_CFS) { 2068 u32 csts = readl(&dev->bar->csts);
2069
2070 if ((dev->subsystem && (csts & NVME_CSTS_NSSRO)) ||
2071 csts & NVME_CSTS_CFS) {
2063 if (work_busy(&dev->reset_work)) 2072 if (work_busy(&dev->reset_work))
2064 continue; 2073 continue;
2065 list_del_init(&dev->node); 2074 list_del_init(&dev->node);
diff --git a/include/linux/nvme.h b/include/linux/nvme.h
index fa3fe160c6cb..d6b5600cfa47 100644
--- a/include/linux/nvme.h
+++ b/include/linux/nvme.h
@@ -39,6 +39,7 @@ struct nvme_bar {
39#define NVME_CAP_MQES(cap) ((cap) & 0xffff) 39#define NVME_CAP_MQES(cap) ((cap) & 0xffff)
40#define NVME_CAP_TIMEOUT(cap) (((cap) >> 24) & 0xff) 40#define NVME_CAP_TIMEOUT(cap) (((cap) >> 24) & 0xff)
41#define NVME_CAP_STRIDE(cap) (((cap) >> 32) & 0xf) 41#define NVME_CAP_STRIDE(cap) (((cap) >> 32) & 0xf)
42#define NVME_CAP_NSSRC(cap) (((cap) >> 36) & 0x1)
42#define NVME_CAP_MPSMIN(cap) (((cap) >> 48) & 0xf) 43#define NVME_CAP_MPSMIN(cap) (((cap) >> 48) & 0xf)
43#define NVME_CAP_MPSMAX(cap) (((cap) >> 52) & 0xf) 44#define NVME_CAP_MPSMAX(cap) (((cap) >> 52) & 0xf)
44 45
@@ -68,6 +69,7 @@ enum {
68 NVME_CC_IOCQES = 4 << 20, 69 NVME_CC_IOCQES = 4 << 20,
69 NVME_CSTS_RDY = 1 << 0, 70 NVME_CSTS_RDY = 1 << 0,
70 NVME_CSTS_CFS = 1 << 1, 71 NVME_CSTS_CFS = 1 << 1,
72 NVME_CSTS_NSSRO = 1 << 4,
71 NVME_CSTS_SHST_NORMAL = 0 << 2, 73 NVME_CSTS_SHST_NORMAL = 0 << 2,
72 NVME_CSTS_SHST_OCCUR = 1 << 2, 74 NVME_CSTS_SHST_OCCUR = 1 << 2,
73 NVME_CSTS_SHST_CMPLT = 2 << 2, 75 NVME_CSTS_SHST_CMPLT = 2 << 2,
@@ -110,6 +112,7 @@ struct nvme_dev {
110 char serial[20]; 112 char serial[20];
111 char model[40]; 113 char model[40];
112 char firmware_rev[8]; 114 char firmware_rev[8];
115 bool subsystem;
113 u32 max_hw_sectors; 116 u32 max_hw_sectors;
114 u32 stripe_size; 117 u32 stripe_size;
115 u32 page_size; 118 u32 page_size;