Resource handling: add 'insert_resource_expand_to_fit()' function

Not used anywhere yet, but this complements the existing plain
'insert_resource()' functionality with a version that can expand the
resource we are adding in order to fix up any conflicts it has with
existing resources.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

+64 -25
+1
include/linux/ioport.h
··· 109 109 extern int request_resource(struct resource *root, struct resource *new); 110 110 extern int release_resource(struct resource *new); 111 111 extern int insert_resource(struct resource *parent, struct resource *new); 112 + extern void insert_resource_expand_to_fit(struct resource *root, struct resource *new); 112 113 extern int allocate_resource(struct resource *root, struct resource *new, 113 114 resource_size_t size, resource_size_t min, 114 115 resource_size_t max, resource_size_t align,
+63 -25
kernel/resource.c
··· 362 362 363 363 EXPORT_SYMBOL(allocate_resource); 364 364 365 - /** 366 - * insert_resource - Inserts a resource in the resource tree 367 - * @parent: parent of the new resource 368 - * @new: new resource to insert 369 - * 370 - * Returns 0 on success, -EBUSY if the resource can't be inserted. 371 - * 372 - * This function is equivalent to request_resource when no conflict 373 - * happens. If a conflict happens, and the conflicting resources 374 - * entirely fit within the range of the new resource, then the new 375 - * resource is inserted and the conflicting resources become children of 376 - * the new resource. 365 + /* 366 + * Insert a resource into the resource tree. If successful, return NULL, 367 + * otherwise return the conflicting resource (compare to __request_resource()) 377 368 */ 378 - int insert_resource(struct resource *parent, struct resource *new) 369 + static struct resource * __insert_resource(struct resource *parent, struct resource *new) 379 370 { 380 - int result; 381 371 struct resource *first, *next; 382 372 383 - write_lock(&resource_lock); 384 - 385 373 for (;; parent = first) { 386 - result = 0; 387 374 first = __request_resource(parent, new); 388 375 if (!first) 389 - goto out; 376 + return first; 390 377 391 - result = -EBUSY; 392 378 if (first == parent) 393 - goto out; 379 + return first; 394 380 395 381 if ((first->start > new->start) || (first->end < new->end)) 396 382 break; ··· 387 401 for (next = first; ; next = next->sibling) { 388 402 /* Partial overlap? Bad, and unfixable */ 389 403 if (next->start < new->start || next->end > new->end) 390 - goto out; 404 + return next; 391 405 if (!next->sibling) 392 406 break; 393 407 if (next->sibling->start > new->end) 394 408 break; 395 409 } 396 - 397 - result = 0; 398 410 399 411 new->parent = parent; 400 412 new->sibling = next->sibling; ··· 410 426 next = next->sibling; 411 427 next->sibling = new; 412 428 } 429 + return NULL; 430 + } 413 431 414 - out: 432 + /** 433 + * insert_resource - Inserts a resource in the resource tree 434 + * @parent: parent of the new resource 435 + * @new: new resource to insert 436 + * 437 + * Returns 0 on success, -EBUSY if the resource can't be inserted. 438 + * 439 + * This function is equivalent to request_resource when no conflict 440 + * happens. If a conflict happens, and the conflicting resources 441 + * entirely fit within the range of the new resource, then the new 442 + * resource is inserted and the conflicting resources become children of 443 + * the new resource. 444 + */ 445 + int insert_resource(struct resource *parent, struct resource *new) 446 + { 447 + struct resource *conflict; 448 + 449 + write_lock(&resource_lock); 450 + conflict = __insert_resource(parent, new); 415 451 write_unlock(&resource_lock); 416 - return result; 452 + return conflict ? -EBUSY : 0; 453 + } 454 + 455 + /** 456 + * insert_resource_expand_to_fit - Insert a resource into the resource tree 457 + * @parent: parent of the new resource 458 + * @new: new resource to insert 459 + * 460 + * Insert a resource into the resource tree, possibly expanding it in order 461 + * to make it encompass any conflicting resources. 462 + */ 463 + void insert_resource_expand_to_fit(struct resource *root, struct resource *new) 464 + { 465 + if (new->parent) 466 + return; 467 + 468 + write_lock(&resource_lock); 469 + for (;;) { 470 + struct resource *conflict; 471 + 472 + conflict = __insert_resource(root, new); 473 + if (!conflict) 474 + break; 475 + if (conflict == root) 476 + break; 477 + 478 + /* Ok, expand resource to cover the conflict, then try again .. */ 479 + if (conflict->start < new->start) 480 + new->start = conflict->start; 481 + if (conflict->end > new->end) 482 + new->end = conflict->end; 483 + 484 + printk("Expanded resource %s due to conflict with %s\n", new->name, conflict->name); 485 + } 486 + write_unlock(&resource_lock); 417 487 } 418 488 419 489 /**