Skip to content

Commit

Permalink
kernel/resource: refactor __request_region to allow external locking
Browse files Browse the repository at this point in the history
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/[email protected]
Signed-off-by: Alistair Popple <[email protected]>
Reviewed-by: David Hildenbrand <[email protected]>
Cc: Balbir Singh <[email protected]>
Cc: Daniel Vetter <[email protected]>
Cc: Dan Williams <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Cc: Jerome Glisse <[email protected]>
Cc: John Hubbard <[email protected]>
Cc: Muchun Song <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
apopple-nvidia authored and torvalds committed May 7, 2021
1 parent d486ccb commit 63cdafe
Showing 1 changed file with 32 additions and 20 deletions.
52 changes: 32 additions & 20 deletions kernel/resource.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 63cdafe

Please sign in to comment.