diff options
Diffstat (limited to 'drivers/dax/device.c')
-rw-r--r-- | drivers/dax/device.c | 33 |
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 | ||
561 | struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region, | 562 | struct 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 | ||