aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeith Busch <keith.busch@intel.com>2015-02-03 13:21:42 -0500
committerKeith Busch <keith.busch@intel.com>2015-02-19 18:15:36 -0500
commitb3fffdefabab266ae5176a136d93b6670b07bb30 (patch)
treefcfc462210dc041f7341f959799174d95ce83c83
parent4f1982b4e262c45475a91b4253e9bc7f7c991c13 (diff)
NVMe: Register management handle under nvme class
This creates a new class type for nvme devices to register their management character devices with. This is so we do not rely on miscdev to provide enough minors for as many nvme devices some people plan to use. The previous limit was approximately 60 NVMe controllers, depending on the platform and kernel. Now the limit is 1M, which ought to be enough for anybody. Since we have a new device class, it makes sense to attach the block devices under this as well, so part of this patch moves the management handle initialization prior to the namespaces discovery. Signed-off-by: Keith Busch <keith.busch@intel.com>
-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];