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]; |
