Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dfbac8c7 authored by Keith Busch's avatar Keith Busch Committed by Jens Axboe
Browse files

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: default avatarKeith Busch <keith.busch@intel.com>
Signed-off-by: default avatarJens Axboe <axboe@fb.com>
parent b2b1ec9b
Loading
Loading
Loading
Loading
+10 −1
Original line number Original line Diff line number Diff line
@@ -1735,6 +1735,12 @@ static int nvme_configure_admin_queue(struct nvme_dev *dev)
		page_shift = dev_page_max;
		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);
	result = nvme_disable_ctrl(dev, cap);
	if (result < 0)
	if (result < 0)
		return result;
		return result;
@@ -2059,7 +2065,10 @@ static int nvme_kthread(void *data)
		spin_lock(&dev_list_lock);
		spin_lock(&dev_list_lock);
		list_for_each_entry_safe(dev, next, &dev_list, node) {
		list_for_each_entry_safe(dev, next, &dev_list, node) {
			int i;
			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))
				if (work_busy(&dev->reset_work))
					continue;
					continue;
				list_del_init(&dev->node);
				list_del_init(&dev->node);
+3 −0
Original line number Original line Diff line number Diff line
@@ -39,6 +39,7 @@ struct nvme_bar {
#define NVME_CAP_MQES(cap)	((cap) & 0xffff)
#define NVME_CAP_MQES(cap)	((cap) & 0xffff)
#define NVME_CAP_TIMEOUT(cap)	(((cap) >> 24) & 0xff)
#define NVME_CAP_TIMEOUT(cap)	(((cap) >> 24) & 0xff)
#define NVME_CAP_STRIDE(cap)	(((cap) >> 32) & 0xf)
#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_MPSMIN(cap)	(((cap) >> 48) & 0xf)
#define NVME_CAP_MPSMAX(cap)	(((cap) >> 52) & 0xf)
#define NVME_CAP_MPSMAX(cap)	(((cap) >> 52) & 0xf)


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