diff options
Diffstat (limited to 'kernel/resource.c')
| -rw-r--r-- | kernel/resource.c | 16 | 
1 files changed, 15 insertions, 1 deletions
| 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 @@  #include <linux/spinlock.h>  #include <linux/fs.h>  #include <linux/proc_fs.h> +#include <linux/sched.h>  #include <linux/seq_file.h>  #include <linux/device.h>  #include <linux/pfn.h> @@ -681,6 +682,8 @@ resource_size_t resource_alignment(struct resource *res)   * release_region releases a matching busy region.   */ +static DECLARE_WAIT_QUEUE_HEAD(muxed_resource_wait); +  /**   * __request_region - create a new busy resource region   * @parent: parent resource descriptor @@ -693,6 +696,7 @@ struct resource * __request_region(struct resource *parent,  				   resource_size_t start, resource_size_t n,  				   const char *name, int flags)  { +	DECLARE_WAITQUEUE(wait, current);  	struct resource *res = kzalloc(sizeof(*res), GFP_KERNEL);  	if (!res) @@ -717,7 +721,15 @@ struct resource * __request_region(struct resource *parent,  			if (!(conflict->flags & IORESOURCE_BUSY))  				continue;  		} - +		if (conflict->flags & flags & IORESOURCE_MUXED) { +			add_wait_queue(&muxed_resource_wait, &wait); +			write_unlock(&resource_lock); +			set_current_state(TASK_UNINTERRUPTIBLE); +			schedule(); +			remove_wait_queue(&muxed_resource_wait, &wait); +			write_lock(&resource_lock); +			continue; +		}  		/* Uhhuh, that didn't work out.. */  		kfree(res);  		res = NULL; @@ -791,6 +803,8 @@ void __release_region(struct resource *parent, resource_size_t start,  				break;  			*p = res->sibling;  			write_unlock(&resource_lock); +			if (res->flags & IORESOURCE_MUXED) +				wake_up(&muxed_resource_wait);  			kfree(res);  			return;  		} | 
