aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/block/nvme-core.c79
-rw-r--r--include/linux/nvme.h3
2 files changed, 57 insertions, 25 deletions
diff --git a/drivers/block/nvme-core.c b/drivers/block/nvme-core.c
index 3ffa57a932ea..bb2b861cfed9 100644
--- a/drivers/block/nvme-core.c
+++ b/drivers/block/nvme-core.c
@@ -42,6 +42,7 @@
42#include <scsi/sg.h> 42#include <scsi/sg.h>
43#include <asm-generic/io-64-nonatomic-lo-hi.h> 43#include <asm-generic/io-64-nonatomic-lo-hi.h>
44 44
45#define NVME_MINORS (1U << MINORBITS)
45#define NVME_Q_DEPTH 1024 46#define NVME_Q_DEPTH 1024
46#define NVME_AQ_DEPTH 64 47#define NVME_AQ_DEPTH 64
47#define SQ_SIZE(depth) (depth * sizeof(struct nvme_command)) 48#define SQ_SIZE(depth) (depth * sizeof(struct nvme_command))
@@ -69,6 +70,9 @@ MODULE_PARM_DESC(shutdown_timeout, "timeout in seconds for controller shutdown")
69static int nvme_major; 70static int nvme_major;
70module_param(nvme_major, int, 0); 71module_param(nvme_major, int, 0);
71 72
73static int nvme_char_major;
74module_param(nvme_char_major, int, 0);
75
72static int use_threaded_interrupts; 76static int use_threaded_interrupts;
73module_param(use_threaded_interrupts, int, 0); 77module_param(use_threaded_interrupts, int, 0);
74 78
@@ -79,6 +83,8 @@ static struct workqueue_struct *nvme_workq;
79static wait_queue_head_t nvme_kthread_wait; 83static wait_queue_head_t nvme_kthread_wait;
80static struct notifier_block nvme_nb; 84static struct notifier_block nvme_nb;
81 85
86static struct class *nvme_class;
87
82static void nvme_reset_failed_dev(struct work_struct *ws); 88static void nvme_reset_failed_dev(struct work_struct *ws);
83static int nvme_process_cq(struct nvme_queue *nvmeq); 89static int nvme_process_cq(struct nvme_queue *nvmeq);
84 90
@@ -2189,7 +2195,7 @@ static void nvme_alloc_ns(struct nvme_dev *dev, unsigned nsid)
2189 disk->fops = &nvme_fops; 2195 disk->fops = &nvme_fops;
2190 disk->private_data = ns; 2196 disk->private_data = ns;
2191 disk->queue = ns->queue; 2197 disk->queue = ns->queue;
2192 disk->driverfs_dev = &dev->pci_dev->dev; 2198 disk->driverfs_dev = dev->device;
2193 disk->flags = GENHD_FL_EXT_DEVT; 2199 disk->flags = GENHD_FL_EXT_DEVT;
2194 sprintf(disk->disk_name, "nvme%dn%d", dev->instance, nsid); 2200 sprintf(disk->disk_name, "nvme%dn%d", dev->instance, nsid);
2195 2201
@@ -2775,6 +2781,7 @@ static void nvme_free_dev(struct kref *kref)
2775 struct nvme_dev *dev = container_of(kref, struct nvme_dev, kref); 2781 struct nvme_dev *dev = container_of(kref, struct nvme_dev, kref);
2776 2782
2777 pci_dev_put(dev->pci_dev); 2783 pci_dev_put(dev->pci_dev);
2784 put_device(dev->device);
2778 nvme_free_namespaces(dev); 2785 nvme_free_namespaces(dev);
2779 nvme_release_instance(dev); 2786 nvme_release_instance(dev);
2780 blk_mq_free_tag_set(&dev->tagset); 2787 blk_mq_free_tag_set(&dev->tagset);
@@ -2786,11 +2793,23 @@ static void nvme_free_dev(struct kref *kref)
2786 2793
2787static int nvme_dev_open(struct inode *inode, struct file *f) 2794static int nvme_dev_open(struct inode *inode, struct file *f)
2788{ 2795{
2789 struct nvme_dev *dev = container_of(f->private_data, struct nvme_dev, 2796 struct nvme_dev *dev;
2790 miscdev); 2797 int instance = iminor(inode);
2791 kref_get(&dev->kref); 2798 int ret = -ENODEV;
2792 f->private_data = dev; 2799
2793 return 0; 2800 spin_lock(&dev_list_lock);
2801 list_for_each_entry(dev, &dev_list, node) {
2802 if (dev->instance == instance) {
2803 if (!kref_get_unless_zero(&dev->kref))
2804 break;
2805 f->private_data = dev;
2806 ret = 0;
2807 break;
2808 }
2809 }
2810 spin_unlock(&dev_list_lock);
2811
2812 return ret;
2794} 2813}
2795 2814
2796static int nvme_dev_release(struct inode *inode, struct file *f) 2815static int nvme_dev_release(struct inode *inode, struct file *f)
@@ -3002,29 +3021,26 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
3002 if (result) 3021 if (result)
3003 goto release_pools; 3022 goto release_pools;
3004 3023
3005 if (dev->online_queues > 1) 3024 dev->device = device_create(nvme_class, &pdev->dev,
3006 result = nvme_dev_add(dev); 3025 MKDEV(nvme_char_major, dev->instance),
3007 if (result) 3026 dev, "nvme%d", dev->instance);
3027 if (IS_ERR(dev->device)) {
3028 result = PTR_ERR(dev->device);
3008 goto shutdown; 3029 goto shutdown;
3030 }
3031 get_device(dev->device);
3009 3032
3010 scnprintf(dev->name, sizeof(dev->name), "nvme%d", dev->instance); 3033 if (dev->online_queues > 1)
3011 dev->miscdev.minor = MISC_DYNAMIC_MINOR; 3034 result = nvme_dev_add(dev);
3012 dev->miscdev.parent = &pdev->dev;
3013 dev->miscdev.name = dev->name;
3014 dev->miscdev.fops = &nvme_dev_fops;
3015 result = misc_register(&dev->miscdev);
3016 if (result) 3035 if (result)
3017 goto remove; 3036 goto device_del;
3018 3037
3019 nvme_set_irq_hints(dev); 3038 nvme_set_irq_hints(dev);
3020
3021 dev->initialized = 1; 3039 dev->initialized = 1;
3022 return 0; 3040 return 0;
3023 3041
3024 remove: 3042 device_del:
3025 nvme_dev_remove(dev); 3043 device_destroy(nvme_class, MKDEV(nvme_char_major, dev->instance));
3026 nvme_dev_remove_admin(dev);
3027 nvme_free_namespaces(dev);
3028 shutdown: 3044 shutdown:
3029 nvme_dev_shutdown(dev); 3045 nvme_dev_shutdown(dev);
3030 release_pools: 3046 release_pools:
@@ -3067,10 +3083,10 @@ static void nvme_remove(struct pci_dev *pdev)
3067 3083
3068 pci_set_drvdata(pdev, NULL); 3084 pci_set_drvdata(pdev, NULL);
3069 flush_work(&dev->reset_work); 3085 flush_work(&dev->reset_work);
3070 misc_deregister(&dev->miscdev);
3071 nvme_dev_shutdown(dev); 3086 nvme_dev_shutdown(dev);
3072 nvme_dev_remove(dev); 3087 nvme_dev_remove(dev);
3073 nvme_dev_remove_admin(dev); 3088 nvme_dev_remove_admin(dev);
3089 device_destroy(nvme_class, MKDEV(nvme_char_major, dev->instance));
3074 nvme_free_queues(dev, 0); 3090 nvme_free_queues(dev, 0);
3075 nvme_release_prp_pools(dev); 3091 nvme_release_prp_pools(dev);
3076 kref_put(&dev->kref, nvme_free_dev); 3092 kref_put(&dev->kref, nvme_free_dev);
@@ -3154,11 +3170,26 @@ static int __init nvme_init(void)
3154 else if (result > 0) 3170 else if (result > 0)
3155 nvme_major = result; 3171 nvme_major = result;
3156 3172
3173 result = __register_chrdev(nvme_char_major, 0, NVME_MINORS, "nvme",
3174 &nvme_dev_fops);
3175 if (result < 0)
3176 goto unregister_blkdev;
3177 else if (result > 0)
3178 nvme_char_major = result;
3179
3180 nvme_class = class_create(THIS_MODULE, "nvme");
3181 if (!nvme_class)
3182 goto unregister_chrdev;
3183
3157 result = pci_register_driver(&nvme_driver); 3184 result = pci_register_driver(&nvme_driver);
3158 if (result) 3185 if (result)
3159 goto unregister_blkdev; 3186 goto destroy_class;
3160 return 0; 3187 return 0;
3161 3188
3189 destroy_class:
3190 class_destroy(nvme_class);
3191 unregister_chrdev:
3192 __unregister_chrdev(nvme_char_major, 0, NVME_MINORS, "nvme");
3162 unregister_blkdev: 3193 unregister_blkdev:
3163 unregister_blkdev(nvme_major, "nvme"); 3194 unregister_blkdev(nvme_major, "nvme");
3164 kill_workq: 3195 kill_workq:
@@ -3172,6 +3203,8 @@ static void __exit nvme_exit(void)
3172 unregister_hotcpu_notifier(&nvme_nb); 3203 unregister_hotcpu_notifier(&nvme_nb);
3173 unregister_blkdev(nvme_major, "nvme"); 3204 unregister_blkdev(nvme_major, "nvme");
3174 destroy_workqueue(nvme_workq); 3205 destroy_workqueue(nvme_workq);
3206 class_destroy(nvme_class);
3207 __unregister_chrdev(nvme_char_major, 0, NVME_MINORS, "nvme");
3175 BUG_ON(nvme_thread && !IS_ERR(nvme_thread)); 3208 BUG_ON(nvme_thread && !IS_ERR(nvme_thread));
3176 _nvme_check_size(); 3209 _nvme_check_size();
3177} 3210}
diff --git a/include/linux/nvme.h b/include/linux/nvme.h
index 1f062a9e521d..383d495c5e4c 100644
--- a/include/linux/nvme.h
+++ b/include/linux/nvme.h
@@ -17,7 +17,6 @@
17 17
18#include <uapi/linux/nvme.h> 18#include <uapi/linux/nvme.h>
19#include <linux/pci.h> 19#include <linux/pci.h>
20#include <linux/miscdevice.h>
21#include <linux/kref.h> 20#include <linux/kref.h>
22#include <linux/blk-mq.h> 21#include <linux/blk-mq.h>
23 22
@@ -89,7 +88,7 @@ struct nvme_dev {
89 struct nvme_bar __iomem *bar; 88 struct nvme_bar __iomem *bar;
90 struct list_head namespaces; 89 struct list_head namespaces;
91 struct kref kref; 90 struct kref kref;
92 struct miscdevice miscdev; 91 struct device *device;
93 work_func_t reset_workfn; 92 work_func_t reset_workfn;
94 struct work_struct reset_work; 93 struct work_struct reset_work;
95 char name[12]; 94 char name[12];