diff options
Diffstat (limited to 'drivers/dax')
-rw-r--r-- | drivers/dax/device-dax.h | 2 | ||||
-rw-r--r-- | drivers/dax/device.c | 33 | ||||
-rw-r--r-- | drivers/dax/pmem.c | 12 |
3 files changed, 31 insertions, 16 deletions
diff --git a/drivers/dax/device-dax.h b/drivers/dax/device-dax.h index fdcd9769ffde..688b051750bd 100644 --- a/drivers/dax/device-dax.h +++ b/drivers/dax/device-dax.h | |||
@@ -21,5 +21,5 @@ struct dax_region *alloc_dax_region(struct device *parent, | |||
21 | int region_id, struct resource *res, unsigned int align, | 21 | int region_id, struct resource *res, unsigned int align, |
22 | void *addr, unsigned long flags); | 22 | void *addr, unsigned long flags); |
23 | struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region, | 23 | struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region, |
24 | struct resource *res, int count); | 24 | int id, struct resource *res, int count); |
25 | #endif /* __DEVICE_DAX_H__ */ | 25 | #endif /* __DEVICE_DAX_H__ */ |
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 | ||
diff --git a/drivers/dax/pmem.c b/drivers/dax/pmem.c index 9f2a0b4fd801..8d8c852ba8f2 100644 --- a/drivers/dax/pmem.c +++ b/drivers/dax/pmem.c | |||
@@ -58,13 +58,12 @@ static void dax_pmem_percpu_kill(void *data) | |||
58 | 58 | ||
59 | static int dax_pmem_probe(struct device *dev) | 59 | static int dax_pmem_probe(struct device *dev) |
60 | { | 60 | { |
61 | int rc; | ||
62 | void *addr; | 61 | void *addr; |
63 | struct resource res; | 62 | struct resource res; |
63 | int rc, id, region_id; | ||
64 | struct nd_pfn_sb *pfn_sb; | 64 | struct nd_pfn_sb *pfn_sb; |
65 | struct dev_dax *dev_dax; | 65 | struct dev_dax *dev_dax; |
66 | struct dax_pmem *dax_pmem; | 66 | struct dax_pmem *dax_pmem; |
67 | struct nd_region *nd_region; | ||
68 | struct nd_namespace_io *nsio; | 67 | struct nd_namespace_io *nsio; |
69 | struct dax_region *dax_region; | 68 | struct dax_region *dax_region; |
70 | struct nd_namespace_common *ndns; | 69 | struct nd_namespace_common *ndns; |
@@ -123,14 +122,17 @@ static int dax_pmem_probe(struct device *dev) | |||
123 | /* adjust the dax_region resource to the start of data */ | 122 | /* adjust the dax_region resource to the start of data */ |
124 | res.start += le64_to_cpu(pfn_sb->dataoff); | 123 | res.start += le64_to_cpu(pfn_sb->dataoff); |
125 | 124 | ||
126 | nd_region = to_nd_region(dev->parent); | 125 | rc = sscanf(dev_name(&ndns->dev), "namespace%d.%d", ®ion_id, &id); |
127 | dax_region = alloc_dax_region(dev, nd_region->id, &res, | 126 | if (rc != 2) |
127 | return -EINVAL; | ||
128 | |||
129 | dax_region = alloc_dax_region(dev, region_id, &res, | ||
128 | le32_to_cpu(pfn_sb->align), addr, PFN_DEV|PFN_MAP); | 130 | le32_to_cpu(pfn_sb->align), addr, PFN_DEV|PFN_MAP); |
129 | if (!dax_region) | 131 | if (!dax_region) |
130 | return -ENOMEM; | 132 | return -ENOMEM; |
131 | 133 | ||
132 | /* TODO: support for subdividing a dax region... */ | 134 | /* TODO: support for subdividing a dax region... */ |
133 | dev_dax = devm_create_dev_dax(dax_region, &res, 1); | 135 | dev_dax = devm_create_dev_dax(dax_region, id, &res, 1); |
134 | 136 | ||
135 | /* child dev_dax instances now own the lifetime of the dax_region */ | 137 | /* child dev_dax instances now own the lifetime of the dax_region */ |
136 | dax_region_put(dax_region); | 138 | dax_region_put(dax_region); |