aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/block/nvme-core.c35
-rw-r--r--include/linux/nvme.h2
2 files changed, 26 insertions, 11 deletions
diff --git a/drivers/block/nvme-core.c b/drivers/block/nvme-core.c
index 2af079e571fc..e0ac1210fe31 100644
--- a/drivers/block/nvme-core.c
+++ b/drivers/block/nvme-core.c
@@ -73,6 +73,7 @@ static LIST_HEAD(dev_list);
73static struct task_struct *nvme_thread; 73static struct task_struct *nvme_thread;
74static struct workqueue_struct *nvme_workq; 74static struct workqueue_struct *nvme_workq;
75static wait_queue_head_t nvme_kthread_wait; 75static wait_queue_head_t nvme_kthread_wait;
76static struct notifier_block nvme_nb;
76 77
77static void nvme_reset_failed_dev(struct work_struct *ws); 78static void nvme_reset_failed_dev(struct work_struct *ws);
78 79
@@ -2115,14 +2116,25 @@ static size_t db_bar_size(struct nvme_dev *dev, unsigned nr_io_queues)
2115 return 4096 + ((nr_io_queues + 1) * 8 * dev->db_stride); 2116 return 4096 + ((nr_io_queues + 1) * 8 * dev->db_stride);
2116} 2117}
2117 2118
2119static void nvme_cpu_workfn(struct work_struct *work)
2120{
2121 struct nvme_dev *dev = container_of(work, struct nvme_dev, cpu_work);
2122 if (dev->initialized)
2123 nvme_assign_io_queues(dev);
2124}
2125
2118static int nvme_cpu_notify(struct notifier_block *self, 2126static int nvme_cpu_notify(struct notifier_block *self,
2119 unsigned long action, void *hcpu) 2127 unsigned long action, void *hcpu)
2120{ 2128{
2121 struct nvme_dev *dev = container_of(self, struct nvme_dev, nb); 2129 struct nvme_dev *dev;
2130
2122 switch (action) { 2131 switch (action) {
2123 case CPU_ONLINE: 2132 case CPU_ONLINE:
2124 case CPU_DEAD: 2133 case CPU_DEAD:
2125 nvme_assign_io_queues(dev); 2134 spin_lock(&dev_list_lock);
2135 list_for_each_entry(dev, &dev_list, node)
2136 schedule_work(&dev->cpu_work);
2137 spin_unlock(&dev_list_lock);
2126 break; 2138 break;
2127 } 2139 }
2128 return NOTIFY_OK; 2140 return NOTIFY_OK;
@@ -2191,11 +2203,6 @@ static int nvme_setup_io_queues(struct nvme_dev *dev)
2191 nvme_free_queues(dev, nr_io_queues + 1); 2203 nvme_free_queues(dev, nr_io_queues + 1);
2192 nvme_assign_io_queues(dev); 2204 nvme_assign_io_queues(dev);
2193 2205
2194 dev->nb.notifier_call = &nvme_cpu_notify;
2195 result = register_hotcpu_notifier(&dev->nb);
2196 if (result)
2197 goto free_queues;
2198
2199 return 0; 2206 return 0;
2200 2207
2201 free_queues: 2208 free_queues:
@@ -2495,8 +2502,6 @@ static void nvme_dev_shutdown(struct nvme_dev *dev)
2495 int i; 2502 int i;
2496 2503
2497 dev->initialized = 0; 2504 dev->initialized = 0;
2498 unregister_hotcpu_notifier(&dev->nb);
2499
2500 nvme_dev_list_remove(dev); 2505 nvme_dev_list_remove(dev);
2501 2506
2502 if (!dev->bar || (dev->bar && readl(&dev->bar->csts) == -1)) { 2507 if (!dev->bar || (dev->bar && readl(&dev->bar->csts) == -1)) {
@@ -2767,6 +2772,7 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
2767 INIT_LIST_HEAD(&dev->namespaces); 2772 INIT_LIST_HEAD(&dev->namespaces);
2768 dev->reset_workfn = nvme_reset_failed_dev; 2773 dev->reset_workfn = nvme_reset_failed_dev;
2769 INIT_WORK(&dev->reset_work, nvme_reset_workfn); 2774 INIT_WORK(&dev->reset_work, nvme_reset_workfn);
2775 INIT_WORK(&dev->cpu_work, nvme_cpu_workfn);
2770 dev->pci_dev = pdev; 2776 dev->pci_dev = pdev;
2771 pci_set_drvdata(pdev, dev); 2777 pci_set_drvdata(pdev, dev);
2772 result = nvme_set_instance(dev); 2778 result = nvme_set_instance(dev);
@@ -2836,6 +2842,7 @@ static void nvme_remove(struct pci_dev *pdev)
2836 2842
2837 pci_set_drvdata(pdev, NULL); 2843 pci_set_drvdata(pdev, NULL);
2838 flush_work(&dev->reset_work); 2844 flush_work(&dev->reset_work);
2845 flush_work(&dev->cpu_work);
2839 misc_deregister(&dev->miscdev); 2846 misc_deregister(&dev->miscdev);
2840 nvme_dev_remove(dev); 2847 nvme_dev_remove(dev);
2841 nvme_dev_shutdown(dev); 2848 nvme_dev_shutdown(dev);
@@ -2923,11 +2930,18 @@ static int __init nvme_init(void)
2923 else if (result > 0) 2930 else if (result > 0)
2924 nvme_major = result; 2931 nvme_major = result;
2925 2932
2926 result = pci_register_driver(&nvme_driver); 2933 nvme_nb.notifier_call = &nvme_cpu_notify;
2934 result = register_hotcpu_notifier(&nvme_nb);
2927 if (result) 2935 if (result)
2928 goto unregister_blkdev; 2936 goto unregister_blkdev;
2937
2938 result = pci_register_driver(&nvme_driver);
2939 if (result)
2940 goto unregister_hotcpu;
2929 return 0; 2941 return 0;
2930 2942
2943 unregister_hotcpu:
2944 unregister_hotcpu_notifier(&nvme_nb);
2931 unregister_blkdev: 2945 unregister_blkdev:
2932 unregister_blkdev(nvme_major, "nvme"); 2946 unregister_blkdev(nvme_major, "nvme");
2933 kill_workq: 2947 kill_workq:
@@ -2938,6 +2952,7 @@ static int __init nvme_init(void)
2938static void __exit nvme_exit(void) 2952static void __exit nvme_exit(void)
2939{ 2953{
2940 pci_unregister_driver(&nvme_driver); 2954 pci_unregister_driver(&nvme_driver);
2955 unregister_hotcpu_notifier(&nvme_nb);
2941 unregister_blkdev(nvme_major, "nvme"); 2956 unregister_blkdev(nvme_major, "nvme");
2942 destroy_workqueue(nvme_workq); 2957 destroy_workqueue(nvme_workq);
2943 BUG_ON(nvme_thread && !IS_ERR(nvme_thread)); 2958 BUG_ON(nvme_thread && !IS_ERR(nvme_thread));
diff --git a/include/linux/nvme.h b/include/linux/nvme.h
index 8541dd920bb7..2bf403195c09 100644
--- a/include/linux/nvme.h
+++ b/include/linux/nvme.h
@@ -90,7 +90,7 @@ struct nvme_dev {
90 struct miscdevice miscdev; 90 struct miscdevice miscdev;
91 work_func_t reset_workfn; 91 work_func_t reset_workfn;
92 struct work_struct reset_work; 92 struct work_struct reset_work;
93 struct notifier_block nb; 93 struct work_struct cpu_work;
94 char name[12]; 94 char name[12];
95 char serial[20]; 95 char serial[20];
96 char model[40]; 96 char model[40];