All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/2] NVMe: Controller resets
@ 2013-08-07 20:44 Keith Busch
  2013-08-07 20:44 ` [PATCH 1/2] NVMe: Reset failed controller Keith Busch
  2013-08-07 20:44 ` [PATCH 2/2] NVMe: User initiated controller reset Keith Busch
  0 siblings, 2 replies; 3+ messages in thread
From: Keith Busch @ 2013-08-07 20:44 UTC (permalink / raw)


Some controller reset action. These depend on this patch set here:

http://merlin.infradead.org/pipermail/linux-nvme/2013-July/000331.html

Keith Busch (2):
  NVMe: Reset failed controller
  NVMe: User initiated controller reset

 drivers/block/nvme-core.c |   43 ++++++++++++++++++++++++++++++++++++++++++-
 include/linux/nvme.h      |    1 +
 2 files changed, 43 insertions(+), 1 deletion(-)

-- 
1.7.10.4

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH 1/2] NVMe: Reset failed controller
  2013-08-07 20:44 [PATCH 0/2] NVMe: Controller resets Keith Busch
@ 2013-08-07 20:44 ` Keith Busch
  2013-08-07 20:44 ` [PATCH 2/2] NVMe: User initiated controller reset Keith Busch
  1 sibling, 0 replies; 3+ messages in thread
From: Keith Busch @ 2013-08-07 20:44 UTC (permalink / raw)


Polls on the controller fatal status bit and resets the controller per
the nvme spec on this condition.

Signed-off-by: Keith Busch <keith.busch at intel.com>
---
 drivers/block/nvme-core.c |   30 +++++++++++++++++++++++++++++-
 include/linux/nvme.h      |    1 +
 2 files changed, 30 insertions(+), 1 deletion(-)

diff --git a/drivers/block/nvme-core.c b/drivers/block/nvme-core.c
index 52cf479..f401e2b 100644
--- a/drivers/block/nvme-core.c
+++ b/drivers/block/nvme-core.c
@@ -58,6 +58,7 @@ module_param(use_threaded_interrupts, int, 0);
 static DEFINE_SPINLOCK(dev_list_lock);
 static LIST_HEAD(dev_list);
 static struct task_struct *nvme_thread;
+static struct workqueue_struct *nvme_workq;
 
 /*
  * An NVM Express queue.  Each device has at least two (one for admin
@@ -1605,6 +1606,12 @@ static int nvme_kthread(void *data)
 		spin_lock(&dev_list_lock);
 		list_for_each_entry(dev, &dev_list, node) {
 			int i;
+			if (readl(&dev->bar->csts) & NVME_CSTS_CFS) {
+				dev_warn(&dev->pci_dev->dev,
+					"failed status, reset controller\n");
+				queue_work(nvme_workq, &dev->ws);
+				continue;
+			}
 			for (i = 0; i < dev->queue_count; i++) {
 				struct nvme_queue *nvmeq = dev->queues[i];
 				if (!nvmeq)
@@ -2151,6 +2158,19 @@ static int nvme_dev_start(struct nvme_dev *dev)
 	return result;
 }
 
+static void nvme_dev_reset(struct nvme_dev *dev)
+{
+	nvme_dev_shutdown(dev);
+	if (nvme_dev_start(dev))
+		nvme_free_queues(dev);
+}
+
+static void nvme_reset_failed_dev(struct work_struct *ws)
+{
+	struct nvme_dev *dev = container_of(ws, struct nvme_dev, ws);
+	nvme_dev_reset(dev);
+}
+
 static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
 	int result = -ENOMEM;
@@ -2178,6 +2198,7 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	if (result)
 		goto release;
 
+	INIT_WORK(&dev->ws, nvme_reset_failed_dev);
 	result = nvme_dev_start(dev);
 	if (result)
 		goto release_pools;
@@ -2288,9 +2309,14 @@ static int __init nvme_init(void)
 	if (IS_ERR(nvme_thread))
 		return PTR_ERR(nvme_thread);
 
+	result = -ENOMEM;
+	nvme_workq = create_workqueue("nvme");
+	if (!nvme_workq)
+		goto kill_kthread;
+
 	result = register_blkdev(nvme_major, "nvme");
 	if (result < 0)
-		goto kill_thread;
+		goto kill_workq;
 	else if (result > 0)
 		nvme_major = result;
 
@@ -2301,6 +2327,8 @@ static int __init nvme_init(void)
 
  unregister_blkdev:
 	unregister_blkdev(nvme_major, "nvme");
+ kill_workq:
+	destroy_workqueue(nvme_workq);
  kill_kthread:
 	kthread_stop(nvme_thread);
 	return result;
diff --git a/include/linux/nvme.h b/include/linux/nvme.h
index 26ebcf4..612e640 100644
--- a/include/linux/nvme.h
+++ b/include/linux/nvme.h
@@ -87,6 +87,7 @@ struct nvme_dev {
 	struct list_head namespaces;
 	struct kref kref;
 	struct miscdevice miscdev;
+	struct work_struct ws;
 	char name[12];
 	char serial[20];
 	char model[40];
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [PATCH 2/2] NVMe: User initiated controller reset
  2013-08-07 20:44 [PATCH 0/2] NVMe: Controller resets Keith Busch
  2013-08-07 20:44 ` [PATCH 1/2] NVMe: Reset failed controller Keith Busch
@ 2013-08-07 20:44 ` Keith Busch
  1 sibling, 0 replies; 3+ messages in thread
From: Keith Busch @ 2013-08-07 20:44 UTC (permalink / raw)


Creates a sysfs entry for each nvme controller that when written to
initiates a controller reset. This may be done by a user if they need
to reset the controller for any reason. For example, it may be required
as part of an firmware activate procedure.

Signed-off-by: Keith Busch <keith.busch at intel.com>
---
 drivers/block/nvme-core.c |   13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/drivers/block/nvme-core.c b/drivers/block/nvme-core.c
index f401e2b..ee29e2e 100644
--- a/drivers/block/nvme-core.c
+++ b/drivers/block/nvme-core.c
@@ -2171,6 +2171,17 @@ static void nvme_reset_failed_dev(struct work_struct *ws)
 	nvme_dev_reset(dev);
 }
 
+static ssize_t nvme_reset(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct pci_dev  *pdev = container_of(dev, struct pci_dev, dev);
+	struct nvme_dev *ndev = pci_get_drvdata(pdev);
+
+	nvme_dev_reset(ndev);	
+	return count;
+}
+static DEVICE_ATTR(reset_controller, S_IWUSR, NULL, nvme_reset);
+
 static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
 	int result = -ENOMEM;
@@ -2217,6 +2228,7 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 		goto remove;
 
 	kref_init(&dev->kref);
+	device_create_file(&pdev->dev, &dev_attr_reset_controller);
 	return 0;
 
  remove:
@@ -2238,6 +2250,7 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 static void nvme_remove(struct pci_dev *pdev)
 {
 	struct nvme_dev *dev = pci_get_drvdata(pdev);
+	device_remove_file(&pdev->dev, &dev_attr_reset_controller);
 	misc_deregister(&dev->miscdev);
 	kref_put(&dev->kref, nvme_free_dev);
 }
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2013-08-07 20:44 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-08-07 20:44 [PATCH 0/2] NVMe: Controller resets Keith Busch
2013-08-07 20:44 ` [PATCH 1/2] NVMe: Reset failed controller Keith Busch
2013-08-07 20:44 ` [PATCH 2/2] NVMe: User initiated controller reset Keith Busch

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.