]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
NVMe: Add nvme subsystem reset support
authorKeith Busch <keith.busch@intel.com>
Mon, 10 Aug 2015 21:20:40 +0000 (15:20 -0600)
committerChuck Anderson <chuck.anderson@oracle.com>
Wed, 6 Jul 2016 23:31:51 +0000 (16:31 -0700)
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>
(cherry picked from commit dfbac8c7ac5f58448b2216fe42ff52aaf175421d)

Orabug: 22620486
Signed-off-by: Jason Luo <zhangqing.luo@oracle.com>
drivers/block/nvme-core.c
include/linux/nvme.h

index 9b75742699b9c0321acc0e3cbd0c429292800e01..ccb93ba506bb56b18a110e638a9eab8beb1e21eb 100644 (file)
@@ -1737,6 +1737,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;
@@ -2056,7 +2062,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);
index fa3fe160c6cbcd0b8bae05baf6488d03067d5e07..d6b5600cfa47d68dbad490090e3453e8516aa31e 100644 (file)
@@ -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)
 
@@ -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,
@@ -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;