aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/infiniband/core/user_mad.c50
1 files changed, 44 insertions, 6 deletions
diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c
index 5a66bd062389..57818aea9967 100644
--- a/drivers/infiniband/core/user_mad.c
+++ b/drivers/infiniband/core/user_mad.c
@@ -971,6 +971,28 @@ static ssize_t show_abi_version(struct class *class, char *buf)
971} 971}
972static CLASS_ATTR(abi_version, S_IRUGO, show_abi_version, NULL); 972static CLASS_ATTR(abi_version, S_IRUGO, show_abi_version, NULL);
973 973
974static dev_t overflow_maj;
975static DECLARE_BITMAP(overflow_map, IB_UMAD_MAX_PORTS);
976static int find_overflow_devnum(void)
977{
978 int ret;
979
980 if (!overflow_maj) {
981 ret = alloc_chrdev_region(&overflow_maj, 0, IB_UMAD_MAX_PORTS * 2,
982 "infiniband_mad");
983 if (ret) {
984 printk(KERN_ERR "user_mad: couldn't register dynamic device number\n");
985 return ret;
986 }
987 }
988
989 ret = find_first_zero_bit(overflow_map, IB_UMAD_MAX_PORTS);
990 if (ret >= IB_UMAD_MAX_PORTS)
991 return -1;
992
993 return ret;
994}
995
974static int ib_umad_init_port(struct ib_device *device, int port_num, 996static int ib_umad_init_port(struct ib_device *device, int port_num,
975 struct ib_umad_port *port) 997 struct ib_umad_port *port)
976{ 998{
@@ -981,11 +1003,19 @@ static int ib_umad_init_port(struct ib_device *device, int port_num,
981 devnum = find_first_zero_bit(dev_map, IB_UMAD_MAX_PORTS); 1003 devnum = find_first_zero_bit(dev_map, IB_UMAD_MAX_PORTS);
982 if (devnum >= IB_UMAD_MAX_PORTS) { 1004 if (devnum >= IB_UMAD_MAX_PORTS) {
983 spin_unlock(&port_lock); 1005 spin_unlock(&port_lock);
984 return -1; 1006 devnum = find_overflow_devnum();
1007 if (devnum < 0)
1008 return -1;
1009
1010 spin_lock(&port_lock);
1011 port->dev_num = devnum + IB_UMAD_MAX_PORTS;
1012 base = devnum + overflow_maj;
1013 set_bit(devnum, overflow_map);
1014 } else {
1015 port->dev_num = devnum;
1016 base = devnum + base_dev;
1017 set_bit(devnum, dev_map);
985 } 1018 }
986 port->dev_num = devnum;
987 base = devnum + base_dev;
988 set_bit(devnum, dev_map);
989 spin_unlock(&port_lock); 1019 spin_unlock(&port_lock);
990 1020
991 port->ib_dev = device; 1021 port->ib_dev = device;
@@ -1042,7 +1072,10 @@ err_dev:
1042 1072
1043err_cdev: 1073err_cdev:
1044 cdev_del(&port->cdev); 1074 cdev_del(&port->cdev);
1045 clear_bit(devnum, dev_map); 1075 if (port->dev_num < IB_UMAD_MAX_PORTS)
1076 clear_bit(devnum, dev_map);
1077 else
1078 clear_bit(devnum, overflow_map);
1046 1079
1047 return -1; 1080 return -1;
1048} 1081}
@@ -1079,7 +1112,10 @@ static void ib_umad_kill_port(struct ib_umad_port *port)
1079 1112
1080 mutex_unlock(&port->file_mutex); 1113 mutex_unlock(&port->file_mutex);
1081 1114
1082 clear_bit(port->dev_num, dev_map); 1115 if (port->dev_num < IB_UMAD_MAX_PORTS)
1116 clear_bit(port->dev_num, dev_map);
1117 else
1118 clear_bit(port->dev_num - IB_UMAD_MAX_PORTS, overflow_map);
1083} 1119}
1084 1120
1085static void ib_umad_add_one(struct ib_device *device) 1121static void ib_umad_add_one(struct ib_device *device)
@@ -1187,6 +1223,8 @@ static void __exit ib_umad_cleanup(void)
1187 ib_unregister_client(&umad_client); 1223 ib_unregister_client(&umad_client);
1188 class_destroy(umad_class); 1224 class_destroy(umad_class);
1189 unregister_chrdev_region(base_dev, IB_UMAD_MAX_PORTS * 2); 1225 unregister_chrdev_region(base_dev, IB_UMAD_MAX_PORTS * 2);
1226 if (overflow_maj)
1227 unregister_chrdev_region(overflow_maj, IB_UMAD_MAX_PORTS * 2);
1190} 1228}
1191 1229
1192module_init(ib_umad_init); 1230module_init(ib_umad_init);