diff options
| -rw-r--r-- | drivers/block/nvme-core.c | 35 | ||||
| -rw-r--r-- | include/linux/nvme.h | 2 |
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); | |||
| 73 | static struct task_struct *nvme_thread; | 73 | static struct task_struct *nvme_thread; |
| 74 | static struct workqueue_struct *nvme_workq; | 74 | static struct workqueue_struct *nvme_workq; |
| 75 | static wait_queue_head_t nvme_kthread_wait; | 75 | static wait_queue_head_t nvme_kthread_wait; |
| 76 | static struct notifier_block nvme_nb; | ||
| 76 | 77 | ||
| 77 | static void nvme_reset_failed_dev(struct work_struct *ws); | 78 | static 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 | ||
| 2119 | static 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 | |||
| 2118 | static int nvme_cpu_notify(struct notifier_block *self, | 2126 | static 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) | |||
| 2938 | static void __exit nvme_exit(void) | 2952 | static 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]; |
