diff options
author | Alexander Chiang <achiang@hp.com> | 2010-02-02 14:08:09 -0500 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2010-02-24 13:23:41 -0500 |
commit | 6d6a0e71eec5886f2511632a38f28f1ed7794d70 (patch) | |
tree | f00a26094daa8b221e9f2075be1206e4219f8a65 /drivers/infiniband | |
parent | ddbd6883013dcc9f9ca5c0b26f79d9334a95926c (diff) |
IB/uverbs: Increase maximum devices supported
Some large systems may support more than IB_UVERBS_MAX_DEVICES
(currently 32).
This change allows us to support more devices in a backwards-compatible
manner. The first IB_UVERBS_MAX_DEVICES keep the same major/minor
device numbers that they've always had.
If there are more than IB_UVERBS_MAX_DEVICES, we then dynamically
request a new major device number (new minors start at 0).
This change increases the maximum number of HCAs to 64 (from 32).
Signed-off-by: Alex Chiang <achiang@hp.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r-- | drivers/infiniband/core/uverbs_main.c | 56 |
1 files changed, 50 insertions, 6 deletions
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c index 8c594cde8a1d..7d42d550e87e 100644 --- a/drivers/infiniband/core/uverbs_main.c +++ b/drivers/infiniband/core/uverbs_main.c | |||
@@ -728,6 +728,34 @@ static ssize_t show_abi_version(struct class *class, char *buf) | |||
728 | } | 728 | } |
729 | static CLASS_ATTR(abi_version, S_IRUGO, show_abi_version, NULL); | 729 | static CLASS_ATTR(abi_version, S_IRUGO, show_abi_version, NULL); |
730 | 730 | ||
731 | static dev_t overflow_maj; | ||
732 | static DECLARE_BITMAP(overflow_map, IB_UVERBS_MAX_DEVICES); | ||
733 | |||
734 | /* | ||
735 | * If we have more than IB_UVERBS_MAX_DEVICES, dynamically overflow by | ||
736 | * requesting a new major number and doubling the number of max devices we | ||
737 | * support. It's stupid, but simple. | ||
738 | */ | ||
739 | static int find_overflow_devnum(void) | ||
740 | { | ||
741 | int ret; | ||
742 | |||
743 | if (!overflow_maj) { | ||
744 | ret = alloc_chrdev_region(&overflow_maj, 0, IB_UVERBS_MAX_DEVICES, | ||
745 | "infiniband_verbs"); | ||
746 | if (ret) { | ||
747 | printk(KERN_ERR "user_verbs: couldn't register dynamic device number\n"); | ||
748 | return ret; | ||
749 | } | ||
750 | } | ||
751 | |||
752 | ret = find_first_zero_bit(overflow_map, IB_UVERBS_MAX_DEVICES); | ||
753 | if (ret >= IB_UVERBS_MAX_DEVICES) | ||
754 | return -1; | ||
755 | |||
756 | return ret; | ||
757 | } | ||
758 | |||
731 | static void ib_uverbs_add_one(struct ib_device *device) | 759 | static void ib_uverbs_add_one(struct ib_device *device) |
732 | { | 760 | { |
733 | int devnum; | 761 | int devnum; |
@@ -748,11 +776,19 @@ static void ib_uverbs_add_one(struct ib_device *device) | |||
748 | devnum = find_first_zero_bit(dev_map, IB_UVERBS_MAX_DEVICES); | 776 | devnum = find_first_zero_bit(dev_map, IB_UVERBS_MAX_DEVICES); |
749 | if (devnum >= IB_UVERBS_MAX_DEVICES) { | 777 | if (devnum >= IB_UVERBS_MAX_DEVICES) { |
750 | spin_unlock(&map_lock); | 778 | spin_unlock(&map_lock); |
751 | goto err; | 779 | devnum = find_overflow_devnum(); |
780 | if (devnum < 0) | ||
781 | goto err; | ||
782 | |||
783 | spin_lock(&map_lock); | ||
784 | uverbs_dev->devnum = devnum + IB_UVERBS_MAX_DEVICES; | ||
785 | base = devnum + overflow_maj; | ||
786 | set_bit(devnum, overflow_map); | ||
787 | } else { | ||
788 | uverbs_dev->devnum = devnum; | ||
789 | base = devnum + IB_UVERBS_BASE_DEV; | ||
790 | set_bit(devnum, dev_map); | ||
752 | } | 791 | } |
753 | uverbs_dev->devnum = devnum; | ||
754 | base = devnum + IB_UVERBS_BASE_DEV; | ||
755 | set_bit(devnum, dev_map); | ||
756 | spin_unlock(&map_lock); | 792 | spin_unlock(&map_lock); |
757 | 793 | ||
758 | uverbs_dev->ib_dev = device; | 794 | uverbs_dev->ib_dev = device; |
@@ -785,7 +821,10 @@ err_class: | |||
785 | 821 | ||
786 | err_cdev: | 822 | err_cdev: |
787 | cdev_del(&uverbs_dev->cdev); | 823 | cdev_del(&uverbs_dev->cdev); |
788 | clear_bit(devnum, dev_map); | 824 | if (uverbs_dev->devnum < IB_UVERBS_MAX_DEVICES) |
825 | clear_bit(devnum, dev_map); | ||
826 | else | ||
827 | clear_bit(devnum, overflow_map); | ||
789 | 828 | ||
790 | err: | 829 | err: |
791 | kref_put(&uverbs_dev->ref, ib_uverbs_release_dev); | 830 | kref_put(&uverbs_dev->ref, ib_uverbs_release_dev); |
@@ -805,7 +844,10 @@ static void ib_uverbs_remove_one(struct ib_device *device) | |||
805 | device_destroy(uverbs_class, uverbs_dev->cdev.dev); | 844 | device_destroy(uverbs_class, uverbs_dev->cdev.dev); |
806 | cdev_del(&uverbs_dev->cdev); | 845 | cdev_del(&uverbs_dev->cdev); |
807 | 846 | ||
808 | clear_bit(uverbs_dev->devnum, dev_map); | 847 | if (uverbs_dev->devnum < IB_UVERBS_MAX_DEVICES) |
848 | clear_bit(uverbs_dev->devnum, dev_map); | ||
849 | else | ||
850 | clear_bit(uverbs_dev->devnum - IB_UVERBS_MAX_DEVICES, overflow_map); | ||
809 | 851 | ||
810 | kref_put(&uverbs_dev->ref, ib_uverbs_release_dev); | 852 | kref_put(&uverbs_dev->ref, ib_uverbs_release_dev); |
811 | wait_for_completion(&uverbs_dev->comp); | 853 | wait_for_completion(&uverbs_dev->comp); |
@@ -895,6 +937,8 @@ static void __exit ib_uverbs_cleanup(void) | |||
895 | unregister_filesystem(&uverbs_event_fs); | 937 | unregister_filesystem(&uverbs_event_fs); |
896 | class_destroy(uverbs_class); | 938 | class_destroy(uverbs_class); |
897 | unregister_chrdev_region(IB_UVERBS_BASE_DEV, IB_UVERBS_MAX_DEVICES); | 939 | unregister_chrdev_region(IB_UVERBS_BASE_DEV, IB_UVERBS_MAX_DEVICES); |
940 | if (overflow_maj) | ||
941 | unregister_chrdev_region(overflow_maj, IB_UVERBS_MAX_DEVICES); | ||
898 | idr_destroy(&ib_uverbs_pd_idr); | 942 | idr_destroy(&ib_uverbs_pd_idr); |
899 | idr_destroy(&ib_uverbs_mr_idr); | 943 | idr_destroy(&ib_uverbs_mr_idr); |
900 | idr_destroy(&ib_uverbs_mw_idr); | 944 | idr_destroy(&ib_uverbs_mw_idr); |