diff options
Diffstat (limited to 'kernel/resource.c')
-rw-r--r-- | kernel/resource.c | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/kernel/resource.c b/kernel/resource.c index 7b9a497419d9..2a3f88636580 100644 --- a/kernel/resource.c +++ b/kernel/resource.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/fs.h> | 17 | #include <linux/fs.h> |
18 | #include <linux/proc_fs.h> | 18 | #include <linux/proc_fs.h> |
19 | #include <linux/seq_file.h> | 19 | #include <linux/seq_file.h> |
20 | #include <linux/device.h> | ||
20 | #include <asm/io.h> | 21 | #include <asm/io.h> |
21 | 22 | ||
22 | 23 | ||
@@ -618,6 +619,67 @@ void __release_region(struct resource *parent, resource_size_t start, | |||
618 | EXPORT_SYMBOL(__release_region); | 619 | EXPORT_SYMBOL(__release_region); |
619 | 620 | ||
620 | /* | 621 | /* |
622 | * Managed region resource | ||
623 | */ | ||
624 | struct region_devres { | ||
625 | struct resource *parent; | ||
626 | resource_size_t start; | ||
627 | resource_size_t n; | ||
628 | }; | ||
629 | |||
630 | static void devm_region_release(struct device *dev, void *res) | ||
631 | { | ||
632 | struct region_devres *this = res; | ||
633 | |||
634 | __release_region(this->parent, this->start, this->n); | ||
635 | } | ||
636 | |||
637 | static int devm_region_match(struct device *dev, void *res, void *match_data) | ||
638 | { | ||
639 | struct region_devres *this = res, *match = match_data; | ||
640 | |||
641 | return this->parent == match->parent && | ||
642 | this->start == match->start && this->n == match->n; | ||
643 | } | ||
644 | |||
645 | struct resource * __devm_request_region(struct device *dev, | ||
646 | struct resource *parent, resource_size_t start, | ||
647 | resource_size_t n, const char *name) | ||
648 | { | ||
649 | struct region_devres *dr = NULL; | ||
650 | struct resource *res; | ||
651 | |||
652 | dr = devres_alloc(devm_region_release, sizeof(struct region_devres), | ||
653 | GFP_KERNEL); | ||
654 | if (!dr) | ||
655 | return NULL; | ||
656 | |||
657 | dr->parent = parent; | ||
658 | dr->start = start; | ||
659 | dr->n = n; | ||
660 | |||
661 | res = __request_region(parent, start, n, name); | ||
662 | if (res) | ||
663 | devres_add(dev, dr); | ||
664 | else | ||
665 | devres_free(dr); | ||
666 | |||
667 | return res; | ||
668 | } | ||
669 | EXPORT_SYMBOL(__devm_request_region); | ||
670 | |||
671 | void __devm_release_region(struct device *dev, struct resource *parent, | ||
672 | resource_size_t start, resource_size_t n) | ||
673 | { | ||
674 | struct region_devres match_data = { parent, start, n }; | ||
675 | |||
676 | __release_region(parent, start, n); | ||
677 | WARN_ON(devres_destroy(dev, devm_region_release, devm_region_match, | ||
678 | &match_data)); | ||
679 | } | ||
680 | EXPORT_SYMBOL(__devm_release_region); | ||
681 | |||
682 | /* | ||
621 | * Called from init/main.c to reserve IO ports. | 683 | * Called from init/main.c to reserve IO ports. |
622 | */ | 684 | */ |
623 | #define MAXRESERVE 4 | 685 | #define MAXRESERVE 4 |