diff options
-rw-r--r-- | drivers/block/nvme-core.c | 79 | ||||
-rw-r--r-- | include/linux/nvme.h | 3 |
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") | |||
69 | static int nvme_major; | 70 | static int nvme_major; |
70 | module_param(nvme_major, int, 0); | 71 | module_param(nvme_major, int, 0); |
71 | 72 | ||
73 | static int nvme_char_major; | ||
74 | module_param(nvme_char_major, int, 0); | ||
75 | |||
72 | static int use_threaded_interrupts; | 76 | static int use_threaded_interrupts; |
73 | module_param(use_threaded_interrupts, int, 0); | 77 | module_param(use_threaded_interrupts, int, 0); |
74 | 78 | ||
@@ -79,6 +83,8 @@ static struct workqueue_struct *nvme_workq; | |||
79 | static wait_queue_head_t nvme_kthread_wait; | 83 | static wait_queue_head_t nvme_kthread_wait; |
80 | static struct notifier_block nvme_nb; | 84 | static struct notifier_block nvme_nb; |
81 | 85 | ||
86 | static struct class *nvme_class; | ||
87 | |||
82 | static void nvme_reset_failed_dev(struct work_struct *ws); | 88 | static void nvme_reset_failed_dev(struct work_struct *ws); |
83 | static int nvme_process_cq(struct nvme_queue *nvmeq); | 89 | static 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 | ||
2787 | static int nvme_dev_open(struct inode *inode, struct file *f) | 2794 | static 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 | ||
2796 | static int nvme_dev_release(struct inode *inode, struct file *f) | 2815 | static 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]; |