aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block
diff options
context:
space:
mode:
authorKeith Busch <keith.busch@intel.com>2015-02-12 17:33:00 -0500
committerKeith Busch <keith.busch@intel.com>2015-02-19 18:15:36 -0500
commit2e1d8448196ba85cd78a18723413a3c92aabe0f3 (patch)
treeac1e4f9df21d4eb478c4cf95c5ee3488824a1021 /drivers/block
parentb3fffdefabab266ae5176a136d93b6670b07bb30 (diff)
NVMe: Asynchronous controller probe
This performs the longest parts of nvme device probe in scheduled work. This speeds up probe significantly when multiple devices are in use. Signed-off-by: Keith Busch <keith.busch@intel.com>
Diffstat (limited to 'drivers/block')
-rw-r--r--drivers/block/nvme-core.c48
1 files changed, 31 insertions, 17 deletions
diff --git a/drivers/block/nvme-core.c b/drivers/block/nvme-core.c
index bb2b861cfed9..a57685f74e5e 100644
--- a/drivers/block/nvme-core.c
+++ b/drivers/block/nvme-core.c
@@ -2800,6 +2800,10 @@ static int nvme_dev_open(struct inode *inode, struct file *f)
2800 spin_lock(&dev_list_lock); 2800 spin_lock(&dev_list_lock);
2801 list_for_each_entry(dev, &dev_list, node) { 2801 list_for_each_entry(dev, &dev_list, node) {
2802 if (dev->instance == instance) { 2802 if (dev->instance == instance) {
2803 if (!dev->admin_q) {
2804 ret = -EWOULDBLOCK;
2805 break;
2806 }
2803 if (!kref_get_unless_zero(&dev->kref)) 2807 if (!kref_get_unless_zero(&dev->kref))
2804 break; 2808 break;
2805 f->private_data = dev; 2809 f->private_data = dev;
@@ -2982,6 +2986,7 @@ static void nvme_reset_workfn(struct work_struct *work)
2982 dev->reset_workfn(work); 2986 dev->reset_workfn(work);
2983} 2987}
2984 2988
2989static void nvme_async_probe(struct work_struct *work);
2985static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id) 2990static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
2986{ 2991{
2987 int node, result = -ENOMEM; 2992 int node, result = -ENOMEM;
@@ -3017,34 +3022,20 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
3017 goto release; 3022 goto release;
3018 3023
3019 kref_init(&dev->kref); 3024 kref_init(&dev->kref);
3020 result = nvme_dev_start(dev);
3021 if (result)
3022 goto release_pools;
3023
3024 dev->device = device_create(nvme_class, &pdev->dev, 3025 dev->device = device_create(nvme_class, &pdev->dev,
3025 MKDEV(nvme_char_major, dev->instance), 3026 MKDEV(nvme_char_major, dev->instance),
3026 dev, "nvme%d", dev->instance); 3027 dev, "nvme%d", dev->instance);
3027 if (IS_ERR(dev->device)) { 3028 if (IS_ERR(dev->device)) {
3028 result = PTR_ERR(dev->device); 3029 result = PTR_ERR(dev->device);
3029 goto shutdown; 3030 goto release_pools;
3030 } 3031 }
3031 get_device(dev->device); 3032 get_device(dev->device);
3032 3033
3033 if (dev->online_queues > 1) 3034 INIT_WORK(&dev->probe_work, nvme_async_probe);
3034 result = nvme_dev_add(dev); 3035 schedule_work(&dev->probe_work);
3035 if (result)
3036 goto device_del;
3037
3038 nvme_set_irq_hints(dev);
3039 dev->initialized = 1;
3040 return 0; 3036 return 0;
3041 3037
3042 device_del:
3043 device_destroy(nvme_class, MKDEV(nvme_char_major, dev->instance));
3044 shutdown:
3045 nvme_dev_shutdown(dev);
3046 release_pools: 3038 release_pools:
3047 nvme_free_queues(dev, 0);
3048 nvme_release_prp_pools(dev); 3039 nvme_release_prp_pools(dev);
3049 release: 3040 release:
3050 nvme_release_instance(dev); 3041 nvme_release_instance(dev);
@@ -3057,6 +3048,28 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
3057 return result; 3048 return result;
3058} 3049}
3059 3050
3051static void nvme_async_probe(struct work_struct *work)
3052{
3053 struct nvme_dev *dev = container_of(work, struct nvme_dev, probe_work);
3054 int result;
3055
3056 result = nvme_dev_start(dev);
3057 if (result)
3058 goto reset;
3059
3060 if (dev->online_queues > 1)
3061 result = nvme_dev_add(dev);
3062 if (result)
3063 goto reset;
3064
3065 nvme_set_irq_hints(dev);
3066 dev->initialized = 1;
3067 return;
3068 reset:
3069 dev->reset_workfn = nvme_reset_failed_dev;
3070 queue_work(nvme_workq, &dev->reset_work);
3071}
3072
3060static void nvme_reset_notify(struct pci_dev *pdev, bool prepare) 3073static void nvme_reset_notify(struct pci_dev *pdev, bool prepare)
3061{ 3074{
3062 struct nvme_dev *dev = pci_get_drvdata(pdev); 3075 struct nvme_dev *dev = pci_get_drvdata(pdev);
@@ -3082,6 +3095,7 @@ static void nvme_remove(struct pci_dev *pdev)
3082 spin_unlock(&dev_list_lock); 3095 spin_unlock(&dev_list_lock);
3083 3096
3084 pci_set_drvdata(pdev, NULL); 3097 pci_set_drvdata(pdev, NULL);
3098 flush_work(&dev->probe_work);
3085 flush_work(&dev->reset_work); 3099 flush_work(&dev->reset_work);
3086 nvme_dev_shutdown(dev); 3100 nvme_dev_shutdown(dev);
3087 nvme_dev_remove(dev); 3101 nvme_dev_remove(dev);