diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/infiniband/core/ucm.c | 53 |
1 files changed, 45 insertions, 8 deletions
diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c index 06c50d80f0d8..2e0d53eeec09 100644 --- a/drivers/infiniband/core/ucm.c +++ b/drivers/infiniband/core/ucm.c | |||
@@ -1215,7 +1215,10 @@ static void ib_ucm_release_dev(struct device *dev) | |||
1215 | 1215 | ||
1216 | ucm_dev = container_of(dev, struct ib_ucm_device, dev); | 1216 | ucm_dev = container_of(dev, struct ib_ucm_device, dev); |
1217 | cdev_del(&ucm_dev->cdev); | 1217 | cdev_del(&ucm_dev->cdev); |
1218 | clear_bit(ucm_dev->devnum, dev_map); | 1218 | if (ucm_dev->devnum < IB_UCM_MAX_DEVICES) |
1219 | clear_bit(ucm_dev->devnum, dev_map); | ||
1220 | else | ||
1221 | clear_bit(ucm_dev->devnum - IB_UCM_MAX_DEVICES, dev_map); | ||
1219 | kfree(ucm_dev); | 1222 | kfree(ucm_dev); |
1220 | } | 1223 | } |
1221 | 1224 | ||
@@ -1237,6 +1240,28 @@ static ssize_t show_ibdev(struct device *dev, struct device_attribute *attr, | |||
1237 | } | 1240 | } |
1238 | static DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL); | 1241 | static DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL); |
1239 | 1242 | ||
1243 | static dev_t overflow_maj; | ||
1244 | static DECLARE_BITMAP(overflow_map, IB_UCM_MAX_DEVICES); | ||
1245 | static int find_overflow_devnum(void) | ||
1246 | { | ||
1247 | int ret; | ||
1248 | |||
1249 | if (!overflow_maj) { | ||
1250 | ret = alloc_chrdev_region(&overflow_maj, 0, IB_UCM_MAX_DEVICES, | ||
1251 | "infiniband_cm"); | ||
1252 | if (ret) { | ||
1253 | printk(KERN_ERR "ucm: couldn't register dynamic device number\n"); | ||
1254 | return ret; | ||
1255 | } | ||
1256 | } | ||
1257 | |||
1258 | ret = find_first_zero_bit(overflow_map, IB_UCM_MAX_DEVICES); | ||
1259 | if (ret >= IB_UCM_MAX_DEVICES) | ||
1260 | return -1; | ||
1261 | |||
1262 | return ret; | ||
1263 | } | ||
1264 | |||
1240 | static void ib_ucm_add_one(struct ib_device *device) | 1265 | static void ib_ucm_add_one(struct ib_device *device) |
1241 | { | 1266 | { |
1242 | int devnum; | 1267 | int devnum; |
@@ -1254,12 +1279,19 @@ static void ib_ucm_add_one(struct ib_device *device) | |||
1254 | ucm_dev->ib_dev = device; | 1279 | ucm_dev->ib_dev = device; |
1255 | 1280 | ||
1256 | devnum = find_first_zero_bit(dev_map, IB_UCM_MAX_DEVICES); | 1281 | devnum = find_first_zero_bit(dev_map, IB_UCM_MAX_DEVICES); |
1257 | if (devnum >= IB_UCM_MAX_DEVICES) | 1282 | if (devnum >= IB_UCM_MAX_DEVICES) { |
1258 | goto err; | 1283 | devnum = find_overflow_devnum(); |
1259 | 1284 | if (devnum < 0) | |
1260 | ucm_dev->devnum = devnum; | 1285 | goto err; |
1261 | base = devnum + IB_UCM_BASE_DEV; | 1286 | |
1262 | set_bit(devnum, dev_map); | 1287 | ucm_dev->devnum = devnum + IB_UCM_MAX_DEVICES; |
1288 | base = devnum + overflow_maj; | ||
1289 | set_bit(devnum, overflow_map); | ||
1290 | } else { | ||
1291 | ucm_dev->devnum = devnum; | ||
1292 | base = devnum + IB_UCM_BASE_DEV; | ||
1293 | set_bit(devnum, dev_map); | ||
1294 | } | ||
1263 | 1295 | ||
1264 | cdev_init(&ucm_dev->cdev, &ucm_fops); | 1296 | cdev_init(&ucm_dev->cdev, &ucm_fops); |
1265 | ucm_dev->cdev.owner = THIS_MODULE; | 1297 | ucm_dev->cdev.owner = THIS_MODULE; |
@@ -1285,7 +1317,10 @@ err_dev: | |||
1285 | device_unregister(&ucm_dev->dev); | 1317 | device_unregister(&ucm_dev->dev); |
1286 | err_cdev: | 1318 | err_cdev: |
1287 | cdev_del(&ucm_dev->cdev); | 1319 | cdev_del(&ucm_dev->cdev); |
1288 | clear_bit(devnum, dev_map); | 1320 | if (ucm_dev->devnum < IB_UCM_MAX_DEVICES) |
1321 | clear_bit(devnum, dev_map); | ||
1322 | else | ||
1323 | clear_bit(devnum, overflow_map); | ||
1289 | err: | 1324 | err: |
1290 | kfree(ucm_dev); | 1325 | kfree(ucm_dev); |
1291 | return; | 1326 | return; |
@@ -1344,6 +1379,8 @@ static void __exit ib_ucm_cleanup(void) | |||
1344 | ib_unregister_client(&ucm_client); | 1379 | ib_unregister_client(&ucm_client); |
1345 | class_remove_file(&cm_class, &class_attr_abi_version); | 1380 | class_remove_file(&cm_class, &class_attr_abi_version); |
1346 | unregister_chrdev_region(IB_UCM_BASE_DEV, IB_UCM_MAX_DEVICES); | 1381 | unregister_chrdev_region(IB_UCM_BASE_DEV, IB_UCM_MAX_DEVICES); |
1382 | if (overflow_maj) | ||
1383 | unregister_chrdev_region(overflow_maj, IB_UCM_MAX_DEVICES); | ||
1347 | idr_destroy(&ctx_id_table); | 1384 | idr_destroy(&ctx_id_table); |
1348 | } | 1385 | } |
1349 | 1386 | ||