kernel/resource: refactor __request_region to allow external locking

Refactor the portion of __request_region() done whilst holding the
resource_lock into a separate function to allow callers to hold the lock.

Link: https://lkml.kernel.org/r/20210419070109.4780-2-apopple@nvidia.com
Signed-off-by: Alistair Popple <apopple@nvidia.com>
Reviewed-by: David Hildenbrand <david@redhat.com>
Cc: Balbir Singh <bsingharora@gmail.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Jerome Glisse <jglisse@redhat.com>
Cc: John Hubbard <jhubbard@nvidia.com>
Cc: Muchun Song <smuchun@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Alistair Popple 2021-05-06 18:05:27 -07:00 committed by Linus Torvalds
parent d486ccb252
commit 63cdafe0af
1 changed files with 32 additions and 20 deletions

View File

@ -1160,31 +1160,16 @@ struct address_space *iomem_get_mapping(void)
return smp_load_acquire(&iomem_inode)->i_mapping;
}
/**
* __request_region - create a new busy resource region
* @parent: parent resource descriptor
* @start: resource start address
* @n: resource region size
* @name: reserving caller's ID string
* @flags: IO resource flags
*/
struct resource * __request_region(struct resource *parent,
static int __request_region_locked(struct resource *res, struct resource *parent,
resource_size_t start, resource_size_t n,
const char *name, int flags)
{
DECLARE_WAITQUEUE(wait, current);
struct resource *res = alloc_resource(GFP_KERNEL);
struct resource *orig_parent = parent;
if (!res)
return NULL;
res->name = name;
res->start = start;
res->end = start + n - 1;
write_lock(&resource_lock);
for (;;) {
struct resource *conflict;
@ -1220,13 +1205,40 @@ struct resource * __request_region(struct resource *parent,
continue;
}
/* Uhhuh, that didn't work out.. */
free_resource(res);
res = NULL;
break;
return -EBUSY;
}
return 0;
}
/**
* __request_region - create a new busy resource region
* @parent: parent resource descriptor
* @start: resource start address
* @n: resource region size
* @name: reserving caller's ID string
* @flags: IO resource flags
*/
struct resource *__request_region(struct resource *parent,
resource_size_t start, resource_size_t n,
const char *name, int flags)
{
struct resource *res = alloc_resource(GFP_KERNEL);
int ret;
if (!res)
return NULL;
write_lock(&resource_lock);
ret = __request_region_locked(res, parent, start, n, name, flags);
write_unlock(&resource_lock);
if (res && orig_parent == &iomem_resource)
if (ret) {
free_resource(res);
return NULL;
}
if (parent == &iomem_resource)
revoke_iomem(res);
return res;