aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dax/device.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/dax/device.c')
-rw-r--r--drivers/dax/device.c33
1 files changed, 23 insertions, 10 deletions
diff --git a/drivers/dax/device.c b/drivers/dax/device.c
index 12943d19bfc4..e9f3b3e4bbf4 100644
--- a/drivers/dax/device.c
+++ b/drivers/dax/device.c
@@ -529,7 +529,8 @@ static void dev_dax_release(struct device *dev)
529 struct dax_region *dax_region = dev_dax->region; 529 struct dax_region *dax_region = dev_dax->region;
530 struct dax_device *dax_dev = dev_dax->dax_dev; 530 struct dax_device *dax_dev = dev_dax->dax_dev;
531 531
532 ida_simple_remove(&dax_region->ida, dev_dax->id); 532 if (dev_dax->id >= 0)
533 ida_simple_remove(&dax_region->ida, dev_dax->id);
533 dax_region_put(dax_region); 534 dax_region_put(dax_region);
534 put_dax(dax_dev); 535 put_dax(dax_dev);
535 kfree(dev_dax); 536 kfree(dev_dax);
@@ -559,7 +560,7 @@ static void unregister_dev_dax(void *dev)
559} 560}
560 561
561struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region, 562struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region,
562 struct resource *res, int count) 563 int id, struct resource *res, int count)
563{ 564{
564 struct device *parent = dax_region->dev; 565 struct device *parent = dax_region->dev;
565 struct dax_device *dax_dev; 566 struct dax_device *dax_dev;
@@ -567,7 +568,10 @@ struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region,
567 struct inode *inode; 568 struct inode *inode;
568 struct device *dev; 569 struct device *dev;
569 struct cdev *cdev; 570 struct cdev *cdev;
570 int rc = 0, i; 571 int rc, i;
572
573 if (!count)
574 return ERR_PTR(-EINVAL);
571 575
572 dev_dax = kzalloc(sizeof(*dev_dax) + sizeof(*res) * count, GFP_KERNEL); 576 dev_dax = kzalloc(sizeof(*dev_dax) + sizeof(*res) * count, GFP_KERNEL);
573 if (!dev_dax) 577 if (!dev_dax)
@@ -587,10 +591,16 @@ struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region,
587 if (i < count) 591 if (i < count)
588 goto err_id; 592 goto err_id;
589 593
590 dev_dax->id = ida_simple_get(&dax_region->ida, 0, 0, GFP_KERNEL); 594 if (id < 0) {
591 if (dev_dax->id < 0) { 595 id = ida_simple_get(&dax_region->ida, 0, 0, GFP_KERNEL);
592 rc = dev_dax->id; 596 dev_dax->id = id;
593 goto err_id; 597 if (id < 0) {
598 rc = id;
599 goto err_id;
600 }
601 } else {
602 /* region provider owns @id lifetime */
603 dev_dax->id = -1;
594 } 604 }
595 605
596 /* 606 /*
@@ -598,8 +608,10 @@ struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region,
598 * device outside of mmap of the resulting character device. 608 * device outside of mmap of the resulting character device.
599 */ 609 */
600 dax_dev = alloc_dax(dev_dax, NULL, NULL); 610 dax_dev = alloc_dax(dev_dax, NULL, NULL);
601 if (!dax_dev) 611 if (!dax_dev) {
612 rc = -ENOMEM;
602 goto err_dax; 613 goto err_dax;
614 }
603 615
604 /* from here on we're committed to teardown via dax_dev_release() */ 616 /* from here on we're committed to teardown via dax_dev_release() */
605 dev = &dev_dax->dev; 617 dev = &dev_dax->dev;
@@ -620,7 +632,7 @@ struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region,
620 dev->parent = parent; 632 dev->parent = parent;
621 dev->groups = dax_attribute_groups; 633 dev->groups = dax_attribute_groups;
622 dev->release = dev_dax_release; 634 dev->release = dev_dax_release;
623 dev_set_name(dev, "dax%d.%d", dax_region->id, dev_dax->id); 635 dev_set_name(dev, "dax%d.%d", dax_region->id, id);
624 636
625 rc = cdev_device_add(cdev, dev); 637 rc = cdev_device_add(cdev, dev);
626 if (rc) { 638 if (rc) {
@@ -636,7 +648,8 @@ struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region,
636 return dev_dax; 648 return dev_dax;
637 649
638 err_dax: 650 err_dax:
639 ida_simple_remove(&dax_region->ida, dev_dax->id); 651 if (dev_dax->id >= 0)
652 ida_simple_remove(&dax_region->ida, dev_dax->id);
640 err_id: 653 err_id:
641 kfree(dev_dax); 654 kfree(dev_dax);
642 655