.. | .. |
---|
398 | 398 | dev_dbg(dev, "%s\n", __func__); |
---|
399 | 399 | |
---|
400 | 400 | kill_dev_dax(dev_dax); |
---|
401 | | - free_dev_dax_ranges(dev_dax); |
---|
402 | 401 | device_del(dev); |
---|
| 402 | + free_dev_dax_ranges(dev_dax); |
---|
403 | 403 | put_device(dev); |
---|
404 | 404 | } |
---|
| 405 | + |
---|
| 406 | +static void dax_region_free(struct kref *kref) |
---|
| 407 | +{ |
---|
| 408 | + struct dax_region *dax_region; |
---|
| 409 | + |
---|
| 410 | + dax_region = container_of(kref, struct dax_region, kref); |
---|
| 411 | + kfree(dax_region); |
---|
| 412 | +} |
---|
| 413 | + |
---|
| 414 | +void dax_region_put(struct dax_region *dax_region) |
---|
| 415 | +{ |
---|
| 416 | + kref_put(&dax_region->kref, dax_region_free); |
---|
| 417 | +} |
---|
| 418 | +EXPORT_SYMBOL_GPL(dax_region_put); |
---|
405 | 419 | |
---|
406 | 420 | /* a return value >= 0 indicates this invocation invalidated the id */ |
---|
407 | 421 | static int __free_dev_dax_id(struct dev_dax *dev_dax) |
---|
408 | 422 | { |
---|
409 | | - struct dax_region *dax_region = dev_dax->region; |
---|
410 | 423 | struct device *dev = &dev_dax->dev; |
---|
| 424 | + struct dax_region *dax_region; |
---|
411 | 425 | int rc = dev_dax->id; |
---|
412 | 426 | |
---|
413 | 427 | device_lock_assert(dev); |
---|
414 | 428 | |
---|
415 | | - if (is_static(dax_region) || dev_dax->id < 0) |
---|
| 429 | + if (!dev_dax->dyn_id || dev_dax->id < 0) |
---|
416 | 430 | return -1; |
---|
| 431 | + dax_region = dev_dax->region; |
---|
417 | 432 | ida_free(&dax_region->ida, dev_dax->id); |
---|
| 433 | + dax_region_put(dax_region); |
---|
418 | 434 | dev_dax->id = -1; |
---|
419 | 435 | return rc; |
---|
420 | 436 | } |
---|
.. | .. |
---|
428 | 444 | rc = __free_dev_dax_id(dev_dax); |
---|
429 | 445 | device_unlock(dev); |
---|
430 | 446 | return rc; |
---|
| 447 | +} |
---|
| 448 | + |
---|
| 449 | +static int alloc_dev_dax_id(struct dev_dax *dev_dax) |
---|
| 450 | +{ |
---|
| 451 | + struct dax_region *dax_region = dev_dax->region; |
---|
| 452 | + int id; |
---|
| 453 | + |
---|
| 454 | + id = ida_alloc(&dax_region->ida, GFP_KERNEL); |
---|
| 455 | + if (id < 0) |
---|
| 456 | + return id; |
---|
| 457 | + kref_get(&dax_region->kref); |
---|
| 458 | + dev_dax->dyn_id = true; |
---|
| 459 | + dev_dax->id = id; |
---|
| 460 | + return id; |
---|
431 | 461 | } |
---|
432 | 462 | |
---|
433 | 463 | static ssize_t delete_store(struct device *dev, struct device_attribute *attr, |
---|
.. | .. |
---|
517 | 547 | NULL, |
---|
518 | 548 | }; |
---|
519 | 549 | |
---|
520 | | -static void dax_region_free(struct kref *kref) |
---|
521 | | -{ |
---|
522 | | - struct dax_region *dax_region; |
---|
523 | | - |
---|
524 | | - dax_region = container_of(kref, struct dax_region, kref); |
---|
525 | | - kfree(dax_region); |
---|
526 | | -} |
---|
527 | | - |
---|
528 | | -void dax_region_put(struct dax_region *dax_region) |
---|
529 | | -{ |
---|
530 | | - kref_put(&dax_region->kref, dax_region_free); |
---|
531 | | -} |
---|
532 | | -EXPORT_SYMBOL_GPL(dax_region_put); |
---|
533 | | - |
---|
534 | 550 | static void dax_region_unregister(void *region) |
---|
535 | 551 | { |
---|
536 | 552 | struct dax_region *dax_region = region; |
---|
.. | .. |
---|
592 | 608 | static void dax_mapping_release(struct device *dev) |
---|
593 | 609 | { |
---|
594 | 610 | struct dax_mapping *mapping = to_dax_mapping(dev); |
---|
595 | | - struct dev_dax *dev_dax = to_dev_dax(dev->parent); |
---|
| 611 | + struct device *parent = dev->parent; |
---|
| 612 | + struct dev_dax *dev_dax = to_dev_dax(parent); |
---|
596 | 613 | |
---|
597 | 614 | ida_free(&dev_dax->ida, mapping->id); |
---|
598 | 615 | kfree(mapping); |
---|
| 616 | + put_device(parent); |
---|
599 | 617 | } |
---|
600 | 618 | |
---|
601 | 619 | static void unregister_dax_mapping(void *data) |
---|
.. | .. |
---|
735 | 753 | dev = &mapping->dev; |
---|
736 | 754 | device_initialize(dev); |
---|
737 | 755 | dev->parent = &dev_dax->dev; |
---|
| 756 | + get_device(dev->parent); |
---|
738 | 757 | dev->type = &dax_mapping_type; |
---|
739 | 758 | dev_set_name(dev, "mapping%d", mapping->id); |
---|
740 | 759 | rc = device_add(dev); |
---|
.. | .. |
---|
1267 | 1286 | static void dev_dax_release(struct device *dev) |
---|
1268 | 1287 | { |
---|
1269 | 1288 | struct dev_dax *dev_dax = to_dev_dax(dev); |
---|
1270 | | - struct dax_region *dax_region = dev_dax->region; |
---|
1271 | 1289 | struct dax_device *dax_dev = dev_dax->dax_dev; |
---|
1272 | 1290 | |
---|
1273 | 1291 | put_dax(dax_dev); |
---|
1274 | 1292 | free_dev_dax_id(dev_dax); |
---|
1275 | | - dax_region_put(dax_region); |
---|
1276 | 1293 | kfree(dev_dax->pgmap); |
---|
1277 | 1294 | kfree(dev_dax); |
---|
1278 | 1295 | } |
---|
.. | .. |
---|
1296 | 1313 | if (!dev_dax) |
---|
1297 | 1314 | return ERR_PTR(-ENOMEM); |
---|
1298 | 1315 | |
---|
| 1316 | + dev_dax->region = dax_region; |
---|
1299 | 1317 | if (is_static(dax_region)) { |
---|
1300 | 1318 | if (dev_WARN_ONCE(parent, data->id < 0, |
---|
1301 | 1319 | "dynamic id specified to static region\n")) { |
---|
.. | .. |
---|
1311 | 1329 | goto err_id; |
---|
1312 | 1330 | } |
---|
1313 | 1331 | |
---|
1314 | | - rc = ida_alloc(&dax_region->ida, GFP_KERNEL); |
---|
| 1332 | + rc = alloc_dev_dax_id(dev_dax); |
---|
1315 | 1333 | if (rc < 0) |
---|
1316 | 1334 | goto err_id; |
---|
1317 | | - dev_dax->id = rc; |
---|
1318 | 1335 | } |
---|
1319 | 1336 | |
---|
1320 | | - dev_dax->region = dax_region; |
---|
1321 | 1337 | dev = &dev_dax->dev; |
---|
1322 | 1338 | device_initialize(dev); |
---|
1323 | 1339 | dev_set_name(dev, "dax%d.%d", dax_region->id, dev_dax->id); |
---|
.. | .. |
---|
1355 | 1371 | dev_dax->target_node = dax_region->target_node; |
---|
1356 | 1372 | dev_dax->align = dax_region->align; |
---|
1357 | 1373 | ida_init(&dev_dax->ida); |
---|
1358 | | - kref_get(&dax_region->kref); |
---|
1359 | 1374 | |
---|
1360 | 1375 | inode = dax_inode(dax_dev); |
---|
1361 | 1376 | dev->devt = inode->i_rdev; |
---|