diff options
-rw-r--r-- | include/linux/ioport.h | 4 | ||||
-rw-r--r-- | kernel/resource.c | 16 |
2 files changed, 18 insertions, 2 deletions
diff --git a/include/linux/ioport.h b/include/linux/ioport.h index 26fad187d661..b22790268b64 100644 --- a/include/linux/ioport.h +++ b/include/linux/ioport.h | |||
@@ -52,6 +52,7 @@ struct resource_list { | |||
52 | 52 | ||
53 | #define IORESOURCE_MEM_64 0x00100000 | 53 | #define IORESOURCE_MEM_64 0x00100000 |
54 | #define IORESOURCE_WINDOW 0x00200000 /* forwarded by bridge */ | 54 | #define IORESOURCE_WINDOW 0x00200000 /* forwarded by bridge */ |
55 | #define IORESOURCE_MUXED 0x00400000 /* Resource is software muxed */ | ||
55 | 56 | ||
56 | #define IORESOURCE_EXCLUSIVE 0x08000000 /* Userland may not map this resource */ | 57 | #define IORESOURCE_EXCLUSIVE 0x08000000 /* Userland may not map this resource */ |
57 | #define IORESOURCE_DISABLED 0x10000000 | 58 | #define IORESOURCE_DISABLED 0x10000000 |
@@ -143,7 +144,8 @@ static inline unsigned long resource_type(const struct resource *res) | |||
143 | } | 144 | } |
144 | 145 | ||
145 | /* Convenience shorthand with allocation */ | 146 | /* Convenience shorthand with allocation */ |
146 | #define request_region(start,n,name) __request_region(&ioport_resource, (start), (n), (name), 0) | 147 | #define request_region(start,n,name) __request_region(&ioport_resource, (start), (n), (name), 0) |
148 | #define request_muxed_region(start,n,name) __request_region(&ioport_resource, (start), (n), (name), IORESOURCE_MUXED) | ||
147 | #define __request_mem_region(start,n,name, excl) __request_region(&iomem_resource, (start), (n), (name), excl) | 149 | #define __request_mem_region(start,n,name, excl) __request_region(&iomem_resource, (start), (n), (name), excl) |
148 | #define request_mem_region(start,n,name) __request_region(&iomem_resource, (start), (n), (name), 0) | 150 | #define request_mem_region(start,n,name) __request_region(&iomem_resource, (start), (n), (name), 0) |
149 | #define request_mem_region_exclusive(start,n,name) \ | 151 | #define request_mem_region_exclusive(start,n,name) \ |
diff --git a/kernel/resource.c b/kernel/resource.c index 9c358e263534..7b36976e5dea 100644 --- a/kernel/resource.c +++ b/kernel/resource.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/spinlock.h> | 15 | #include <linux/spinlock.h> |
16 | #include <linux/fs.h> | 16 | #include <linux/fs.h> |
17 | #include <linux/proc_fs.h> | 17 | #include <linux/proc_fs.h> |
18 | #include <linux/sched.h> | ||
18 | #include <linux/seq_file.h> | 19 | #include <linux/seq_file.h> |
19 | #include <linux/device.h> | 20 | #include <linux/device.h> |
20 | #include <linux/pfn.h> | 21 | #include <linux/pfn.h> |
@@ -681,6 +682,8 @@ resource_size_t resource_alignment(struct resource *res) | |||
681 | * release_region releases a matching busy region. | 682 | * release_region releases a matching busy region. |
682 | */ | 683 | */ |
683 | 684 | ||
685 | static DECLARE_WAIT_QUEUE_HEAD(muxed_resource_wait); | ||
686 | |||
684 | /** | 687 | /** |
685 | * __request_region - create a new busy resource region | 688 | * __request_region - create a new busy resource region |
686 | * @parent: parent resource descriptor | 689 | * @parent: parent resource descriptor |
@@ -693,6 +696,7 @@ struct resource * __request_region(struct resource *parent, | |||
693 | resource_size_t start, resource_size_t n, | 696 | resource_size_t start, resource_size_t n, |
694 | const char *name, int flags) | 697 | const char *name, int flags) |
695 | { | 698 | { |
699 | DECLARE_WAITQUEUE(wait, current); | ||
696 | struct resource *res = kzalloc(sizeof(*res), GFP_KERNEL); | 700 | struct resource *res = kzalloc(sizeof(*res), GFP_KERNEL); |
697 | 701 | ||
698 | if (!res) | 702 | if (!res) |
@@ -717,7 +721,15 @@ struct resource * __request_region(struct resource *parent, | |||
717 | if (!(conflict->flags & IORESOURCE_BUSY)) | 721 | if (!(conflict->flags & IORESOURCE_BUSY)) |
718 | continue; | 722 | continue; |
719 | } | 723 | } |
720 | 724 | if (conflict->flags & flags & IORESOURCE_MUXED) { | |
725 | add_wait_queue(&muxed_resource_wait, &wait); | ||
726 | write_unlock(&resource_lock); | ||
727 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
728 | schedule(); | ||
729 | remove_wait_queue(&muxed_resource_wait, &wait); | ||
730 | write_lock(&resource_lock); | ||
731 | continue; | ||
732 | } | ||
721 | /* Uhhuh, that didn't work out.. */ | 733 | /* Uhhuh, that didn't work out.. */ |
722 | kfree(res); | 734 | kfree(res); |
723 | res = NULL; | 735 | res = NULL; |
@@ -791,6 +803,8 @@ void __release_region(struct resource *parent, resource_size_t start, | |||
791 | break; | 803 | break; |
792 | *p = res->sibling; | 804 | *p = res->sibling; |
793 | write_unlock(&resource_lock); | 805 | write_unlock(&resource_lock); |
806 | if (res->flags & IORESOURCE_MUXED) | ||
807 | wake_up(&muxed_resource_wait); | ||
794 | kfree(res); | 808 | kfree(res); |
795 | return; | 809 | return; |
796 | } | 810 | } |