aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/resource.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/resource.c')
-rw-r--r--kernel/resource.c141
1 files changed, 63 insertions, 78 deletions
diff --git a/kernel/resource.c b/kernel/resource.c
index 30e1bc68503b..b3a3a1fc499e 100644
--- a/kernel/resource.c
+++ b/kernel/resource.c
@@ -318,33 +318,34 @@ int release_resource(struct resource *old)
318 318
319EXPORT_SYMBOL(release_resource); 319EXPORT_SYMBOL(release_resource);
320 320
321/* 321/**
322 * Finds the lowest iomem resource existing within [res->start.res->end). 322 * Finds the lowest iomem resource that covers part of [start..end]. The
323 * The caller must specify res->start, res->end, res->flags, and optionally 323 * caller must specify start, end, flags, and desc (which may be
324 * desc. If found, returns 0, res is overwritten, if not found, returns -1. 324 * IORES_DESC_NONE).
325 * This function walks the whole tree and not just first level children until 325 *
326 * and unless first_level_children_only is true. 326 * If a resource is found, returns 0 and *res is overwritten with the part
327 * of the resource that's within [start..end]; if none is found, returns
328 * -1.
329 *
330 * This function walks the whole tree and not just first level children
331 * unless @first_lvl is true.
327 */ 332 */
328static int find_next_iomem_res(struct resource *res, unsigned long desc, 333static int find_next_iomem_res(resource_size_t start, resource_size_t end,
329 bool first_level_children_only) 334 unsigned long flags, unsigned long desc,
335 bool first_lvl, struct resource *res)
330{ 336{
331 resource_size_t start, end;
332 struct resource *p; 337 struct resource *p;
333 bool sibling_only = false;
334 338
335 BUG_ON(!res); 339 if (!res)
336 340 return -EINVAL;
337 start = res->start;
338 end = res->end;
339 BUG_ON(start >= end);
340 341
341 if (first_level_children_only) 342 if (start >= end)
342 sibling_only = true; 343 return -EINVAL;
343 344
344 read_lock(&resource_lock); 345 read_lock(&resource_lock);
345 346
346 for (p = iomem_resource.child; p; p = next_resource(p, sibling_only)) { 347 for (p = iomem_resource.child; p; p = next_resource(p, first_lvl)) {
347 if ((p->flags & res->flags) != res->flags) 348 if ((p->flags & flags) != flags)
348 continue; 349 continue;
349 if ((desc != IORES_DESC_NONE) && (desc != p->desc)) 350 if ((desc != IORES_DESC_NONE) && (desc != p->desc))
350 continue; 351 continue;
@@ -352,45 +353,43 @@ static int find_next_iomem_res(struct resource *res, unsigned long desc,
352 p = NULL; 353 p = NULL;
353 break; 354 break;
354 } 355 }
355 if ((p->end >= start) && (p->start < end)) 356 if ((p->end >= start) && (p->start <= end))
356 break; 357 break;
357 } 358 }
358 359
359 read_unlock(&resource_lock); 360 read_unlock(&resource_lock);
360 if (!p) 361 if (!p)
361 return -1; 362 return -1;
363
362 /* copy data */ 364 /* copy data */
363 if (res->start < p->start) 365 res->start = max(start, p->start);
364 res->start = p->start; 366 res->end = min(end, p->end);
365 if (res->end > p->end)
366 res->end = p->end;
367 res->flags = p->flags; 367 res->flags = p->flags;
368 res->desc = p->desc; 368 res->desc = p->desc;
369 return 0; 369 return 0;
370} 370}
371 371
372static int __walk_iomem_res_desc(struct resource *res, unsigned long desc, 372static int __walk_iomem_res_desc(resource_size_t start, resource_size_t end,
373 bool first_level_children_only, 373 unsigned long flags, unsigned long desc,
374 void *arg, 374 bool first_lvl, void *arg,
375 int (*func)(struct resource *, void *)) 375 int (*func)(struct resource *, void *))
376{ 376{
377 u64 orig_end = res->end; 377 struct resource res;
378 int ret = -1; 378 int ret = -1;
379 379
380 while ((res->start < res->end) && 380 while (start < end &&
381 !find_next_iomem_res(res, desc, first_level_children_only)) { 381 !find_next_iomem_res(start, end, flags, desc, first_lvl, &res)) {
382 ret = (*func)(res, arg); 382 ret = (*func)(&res, arg);
383 if (ret) 383 if (ret)
384 break; 384 break;
385 385
386 res->start = res->end + 1; 386 start = res.end + 1;
387 res->end = orig_end;
388 } 387 }
389 388
390 return ret; 389 return ret;
391} 390}
392 391
393/* 392/**
394 * Walks through iomem resources and calls func() with matching resource 393 * Walks through iomem resources and calls func() with matching resource
395 * ranges. This walks through whole tree and not just first level children. 394 * ranges. This walks through whole tree and not just first level children.
396 * All the memory ranges which overlap start,end and also match flags and 395 * All the memory ranges which overlap start,end and also match flags and
@@ -407,13 +406,7 @@ static int __walk_iomem_res_desc(struct resource *res, unsigned long desc,
407int walk_iomem_res_desc(unsigned long desc, unsigned long flags, u64 start, 406int walk_iomem_res_desc(unsigned long desc, unsigned long flags, u64 start,
408 u64 end, void *arg, int (*func)(struct resource *, void *)) 407 u64 end, void *arg, int (*func)(struct resource *, void *))
409{ 408{
410 struct resource res; 409 return __walk_iomem_res_desc(start, end, flags, desc, false, arg, func);
411
412 res.start = start;
413 res.end = end;
414 res.flags = flags;
415
416 return __walk_iomem_res_desc(&res, desc, false, arg, func);
417} 410}
418EXPORT_SYMBOL_GPL(walk_iomem_res_desc); 411EXPORT_SYMBOL_GPL(walk_iomem_res_desc);
419 412
@@ -425,15 +418,11 @@ EXPORT_SYMBOL_GPL(walk_iomem_res_desc);
425 * ranges. 418 * ranges.
426 */ 419 */
427int walk_system_ram_res(u64 start, u64 end, void *arg, 420int walk_system_ram_res(u64 start, u64 end, void *arg,
428 int (*func)(struct resource *, void *)) 421 int (*func)(struct resource *, void *))
429{ 422{
430 struct resource res; 423 unsigned long flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
431 424
432 res.start = start; 425 return __walk_iomem_res_desc(start, end, flags, IORES_DESC_NONE, true,
433 res.end = end;
434 res.flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
435
436 return __walk_iomem_res_desc(&res, IORES_DESC_NONE, true,
437 arg, func); 426 arg, func);
438} 427}
439 428
@@ -444,13 +433,9 @@ int walk_system_ram_res(u64 start, u64 end, void *arg,
444int walk_mem_res(u64 start, u64 end, void *arg, 433int walk_mem_res(u64 start, u64 end, void *arg,
445 int (*func)(struct resource *, void *)) 434 int (*func)(struct resource *, void *))
446{ 435{
447 struct resource res; 436 unsigned long flags = IORESOURCE_MEM | IORESOURCE_BUSY;
448
449 res.start = start;
450 res.end = end;
451 res.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
452 437
453 return __walk_iomem_res_desc(&res, IORES_DESC_NONE, true, 438 return __walk_iomem_res_desc(start, end, flags, IORES_DESC_NONE, true,
454 arg, func); 439 arg, func);
455} 440}
456 441
@@ -462,27 +447,27 @@ int walk_mem_res(u64 start, u64 end, void *arg,
462 * It is to be used only for System RAM. 447 * It is to be used only for System RAM.
463 */ 448 */
464int walk_system_ram_range(unsigned long start_pfn, unsigned long nr_pages, 449int walk_system_ram_range(unsigned long start_pfn, unsigned long nr_pages,
465 void *arg, int (*func)(unsigned long, unsigned long, void *)) 450 void *arg, int (*func)(unsigned long, unsigned long, void *))
466{ 451{
452 resource_size_t start, end;
453 unsigned long flags;
467 struct resource res; 454 struct resource res;
468 unsigned long pfn, end_pfn; 455 unsigned long pfn, end_pfn;
469 u64 orig_end;
470 int ret = -1; 456 int ret = -1;
471 457
472 res.start = (u64) start_pfn << PAGE_SHIFT; 458 start = (u64) start_pfn << PAGE_SHIFT;
473 res.end = ((u64)(start_pfn + nr_pages) << PAGE_SHIFT) - 1; 459 end = ((u64)(start_pfn + nr_pages) << PAGE_SHIFT) - 1;
474 res.flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY; 460 flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
475 orig_end = res.end; 461 while (start < end &&
476 while ((res.start < res.end) && 462 !find_next_iomem_res(start, end, flags, IORES_DESC_NONE,
477 (find_next_iomem_res(&res, IORES_DESC_NONE, true) >= 0)) { 463 true, &res)) {
478 pfn = (res.start + PAGE_SIZE - 1) >> PAGE_SHIFT; 464 pfn = (res.start + PAGE_SIZE - 1) >> PAGE_SHIFT;
479 end_pfn = (res.end + 1) >> PAGE_SHIFT; 465 end_pfn = (res.end + 1) >> PAGE_SHIFT;
480 if (end_pfn > pfn) 466 if (end_pfn > pfn)
481 ret = (*func)(pfn, end_pfn - pfn, arg); 467 ret = (*func)(pfn, end_pfn - pfn, arg);
482 if (ret) 468 if (ret)
483 break; 469 break;
484 res.start = res.end + 1; 470 start = res.end + 1;
485 res.end = orig_end;
486 } 471 }
487 return ret; 472 return ret;
488} 473}
@@ -658,8 +643,8 @@ static int find_resource(struct resource *root, struct resource *new,
658 * @constraint: the size and alignment constraints to be met. 643 * @constraint: the size and alignment constraints to be met.
659 */ 644 */
660static int reallocate_resource(struct resource *root, struct resource *old, 645static int reallocate_resource(struct resource *root, struct resource *old,
661 resource_size_t newsize, 646 resource_size_t newsize,
662 struct resource_constraint *constraint) 647 struct resource_constraint *constraint)
663{ 648{
664 int err=0; 649 int err=0;
665 struct resource new = *old; 650 struct resource new = *old;
@@ -972,7 +957,7 @@ skip:
972 * Existing children of the resource are assumed to be immutable. 957 * Existing children of the resource are assumed to be immutable.
973 */ 958 */
974int adjust_resource(struct resource *res, resource_size_t start, 959int adjust_resource(struct resource *res, resource_size_t start,
975 resource_size_t size) 960 resource_size_t size)
976{ 961{
977 int result; 962 int result;
978 963
@@ -983,9 +968,9 @@ int adjust_resource(struct resource *res, resource_size_t start,
983} 968}
984EXPORT_SYMBOL(adjust_resource); 969EXPORT_SYMBOL(adjust_resource);
985 970
986static void __init __reserve_region_with_split(struct resource *root, 971static void __init
987 resource_size_t start, resource_size_t end, 972__reserve_region_with_split(struct resource *root, resource_size_t start,
988 const char *name) 973 resource_size_t end, const char *name)
989{ 974{
990 struct resource *parent = root; 975 struct resource *parent = root;
991 struct resource *conflict; 976 struct resource *conflict;
@@ -1044,9 +1029,9 @@ static void __init __reserve_region_with_split(struct resource *root,
1044 1029
1045} 1030}
1046 1031
1047void __init reserve_region_with_split(struct resource *root, 1032void __init
1048 resource_size_t start, resource_size_t end, 1033reserve_region_with_split(struct resource *root, resource_size_t start,
1049 const char *name) 1034 resource_size_t end, const char *name)
1050{ 1035{
1051 int abort = 0; 1036 int abort = 0;
1052 1037
@@ -1172,7 +1157,7 @@ EXPORT_SYMBOL(__request_region);
1172 * The described resource region must match a currently busy region. 1157 * The described resource region must match a currently busy region.
1173 */ 1158 */
1174void __release_region(struct resource *parent, resource_size_t start, 1159void __release_region(struct resource *parent, resource_size_t start,
1175 resource_size_t n) 1160 resource_size_t n)
1176{ 1161{
1177 struct resource **p; 1162 struct resource **p;
1178 resource_size_t end; 1163 resource_size_t end;
@@ -1234,7 +1219,7 @@ EXPORT_SYMBOL(__release_region);
1234 * simplicity. Enhance this logic when necessary. 1219 * simplicity. Enhance this logic when necessary.
1235 */ 1220 */
1236int release_mem_region_adjustable(struct resource *parent, 1221int release_mem_region_adjustable(struct resource *parent,
1237 resource_size_t start, resource_size_t size) 1222 resource_size_t start, resource_size_t size)
1238{ 1223{
1239 struct resource **p; 1224 struct resource **p;
1240 struct resource *res; 1225 struct resource *res;
@@ -1410,9 +1395,9 @@ static int devm_region_match(struct device *dev, void *res, void *match_data)
1410 this->start == match->start && this->n == match->n; 1395 this->start == match->start && this->n == match->n;
1411} 1396}
1412 1397
1413struct resource * __devm_request_region(struct device *dev, 1398struct resource *
1414 struct resource *parent, resource_size_t start, 1399__devm_request_region(struct device *dev, struct resource *parent,
1415 resource_size_t n, const char *name) 1400 resource_size_t start, resource_size_t n, const char *name)
1416{ 1401{
1417 struct region_devres *dr = NULL; 1402 struct region_devres *dr = NULL;
1418 struct resource *res; 1403 struct resource *res;