1 /* 2 * linux/kernel/resource.c 3 * 4 * Copyright (C) 1999 Linus Torvalds 5 * Copyright (C) 1999 Martin Mares <mj@ucw.cz> 6 * 7 * Arbitrary resource management. 8 */ 9 10 #include <linux/module.h> 11 #include <linux/sched.h> 12 #include <linux/errno.h> 13 #include <linux/ioport.h> 14 #include <linux/init.h> 15 #include <linux/slab.h> 16 #include <linux/spinlock.h> 17 #include <linux/fs.h> 18 #include <linux/proc_fs.h> 19 #include <linux/seq_file.h> 20 #include <asm/io.h> 21 22 23 struct resource ioport_resource = { 24 .name = "PCI IO", 25 .start = 0, 26 .end = IO_SPACE_LIMIT, 27 .flags = IORESOURCE_IO, 28 }; 29 EXPORT_SYMBOL(ioport_resource); 30 31 struct resource iomem_resource = { 32 .name = "PCI mem", 33 .start = 0, 34 .end = -1, 35 .flags = IORESOURCE_MEM, 36 }; 37 EXPORT_SYMBOL(iomem_resource); 38 39 static DEFINE_RWLOCK(resource_lock); 40 41 #ifdef CONFIG_PROC_FS 42 43 enum { MAX_IORES_LEVEL = 5 }; 44 45 static void *r_next(struct seq_file *m, void *v, loff_t *pos) 46 { 47 struct resource *p = v; 48 (*pos)++; 49 if (p->child) 50 return p->child; 51 while (!p->sibling && p->parent) 52 p = p->parent; 53 return p->sibling; 54 } 55 56 static void *r_start(struct seq_file *m, loff_t *pos) 57 __acquires(resource_lock) 58 { 59 struct resource *p = m->private; 60 loff_t l = 0; 61 read_lock(&resource_lock); 62 for (p = p->child; p && l < *pos; p = r_next(m, p, &l)) 63 ; 64 return p; 65 } 66 67 static void r_stop(struct seq_file *m, void *v) 68 __releases(resource_lock) 69 { 70 read_unlock(&resource_lock); 71 } 72 73 static int r_show(struct seq_file *m, void *v) 74 { 75 struct resource *root = m->private; 76 struct resource *r = v, *p; 77 int width = root->end < 0x10000 ? 4 : 8; 78 int depth; 79 80 for (depth = 0, p = r; depth < MAX_IORES_LEVEL; depth++, p = p->parent) 81 if (p->parent == root) 82 break; 83 seq_printf(m, "%*s%0*llx-%0*llx : %s\n", 84 depth * 2, "", 85 width, (unsigned long long) r->start, 86 width, (unsigned long long) r->end, 87 r->name ? r->name : "<BAD>"); 88 return 0; 89 } 90 91 static const struct seq_operations resource_op = { 92 .start = r_start, 93 .next = r_next, 94 .stop = r_stop, 95 .show = r_show, 96 }; 97 98 static int ioports_open(struct inode *inode, struct file *file) 99 { 100 int res = seq_open(file, &resource_op); 101 if (!res) { 102 struct seq_file *m = file->private_data; 103 m->private = &ioport_resource; 104 } 105 return res; 106 } 107 108 static int iomem_open(struct inode *inode, struct file *file) 109 { 110 int res = seq_open(file, &resource_op); 111 if (!res) { 112 struct seq_file *m = file->private_data; 113 m->private = &iomem_resource; 114 } 115 return res; 116 } 117 118 static const struct file_operations proc_ioports_operations = { 119 .open = ioports_open, 120 .read = seq_read, 121 .llseek = seq_lseek, 122 .release = seq_release, 123 }; 124 125 static const struct file_operations proc_iomem_operations = { 126 .open = iomem_open, 127 .read = seq_read, 128 .llseek = seq_lseek, 129 .release = seq_release, 130 }; 131 132 static int __init ioresources_init(void) 133 { 134 struct proc_dir_entry *entry; 135 136 entry = create_proc_entry("ioports", 0, NULL); 137 if (entry) 138 entry->proc_fops = &proc_ioports_operations; 139 entry = create_proc_entry("iomem", 0, NULL); 140 if (entry) 141 entry->proc_fops = &proc_iomem_operations; 142 return 0; 143 } 144 __initcall(ioresources_init); 145 146 #endif /* CONFIG_PROC_FS */ 147 148 /* Return the conflict entry if you can't request it */ 149 static struct resource * __request_resource(struct resource *root, struct resource *new) 150 { 151 resource_size_t start = new->start; 152 resource_size_t end = new->end; 153 struct resource *tmp, **p; 154 155 if (end < start) 156 return root; 157 if (start < root->start) 158 return root; 159 if (end > root->end) 160 return root; 161 p = &root->child; 162 for (;;) { 163 tmp = *p; 164 if (!tmp || tmp->start > end) { 165 new->sibling = tmp; 166 *p = new; 167 new->parent = root; 168 return NULL; 169 } 170 p = &tmp->sibling; 171 if (tmp->end < start) 172 continue; 173 return tmp; 174 } 175 } 176 177 static int __release_resource(struct resource *old) 178 { 179 struct resource *tmp, **p; 180 181 p = &old->parent->child; 182 for (;;) { 183 tmp = *p; 184 if (!tmp) 185 break; 186 if (tmp == old) { 187 *p = tmp->sibling; 188 old->parent = NULL; 189 return 0; 190 } 191 p = &tmp->sibling; 192 } 193 return -EINVAL; 194 } 195 196 /** 197 * request_resource - request and reserve an I/O or memory resource 198 * @root: root resource descriptor 199 * @new: resource descriptor desired by caller 200 * 201 * Returns 0 for success, negative error code on error. 202 */ 203 int request_resource(struct resource *root, struct resource *new) 204 { 205 struct resource *conflict; 206 207 write_lock(&resource_lock); 208 conflict = __request_resource(root, new); 209 write_unlock(&resource_lock); 210 return conflict ? -EBUSY : 0; 211 } 212 213 EXPORT_SYMBOL(request_resource); 214 215 /** 216 * ____request_resource - reserve a resource, with resource conflict returned 217 * @root: root resource descriptor 218 * @new: resource descriptor desired by caller 219 * 220 * Returns: 221 * On success, NULL is returned. 222 * On error, a pointer to the conflicting resource is returned. 223 */ 224 struct resource *____request_resource(struct resource *root, struct resource *new) 225 { 226 struct resource *conflict; 227 228 write_lock(&resource_lock); 229 conflict = __request_resource(root, new); 230 write_unlock(&resource_lock); 231 return conflict; 232 } 233 234 EXPORT_SYMBOL(____request_resource); 235 236 /** 237 * release_resource - release a previously reserved resource 238 * @old: resource pointer 239 */ 240 int release_resource(struct resource *old) 241 { 242 int retval; 243 244 write_lock(&resource_lock); 245 retval = __release_resource(old); 246 write_unlock(&resource_lock); 247 return retval; 248 } 249 250 EXPORT_SYMBOL(release_resource); 251 252 #ifdef CONFIG_MEMORY_HOTPLUG 253 /* 254 * Finds the lowest memory reosurce exists within [res->start.res->end) 255 * the caller must specify res->start, res->end, res->flags. 256 * If found, returns 0, res is overwritten, if not found, returns -1. 257 */ 258 int find_next_system_ram(struct resource *res) 259 { 260 resource_size_t start, end; 261 struct resource *p; 262 263 BUG_ON(!res); 264 265 start = res->start; 266 end = res->end; 267 BUG_ON(start >= end); 268 269 read_lock(&resource_lock); 270 for (p = iomem_resource.child; p ; p = p->sibling) { 271 /* system ram is just marked as IORESOURCE_MEM */ 272 if (p->flags != res->flags) 273 continue; 274 if (p->start > end) { 275 p = NULL; 276 break; 277 } 278 if ((p->end >= start) && (p->start < end)) 279 break; 280 } 281 read_unlock(&resource_lock); 282 if (!p) 283 return -1; 284 /* copy data */ 285 if (res->start < p->start) 286 res->start = p->start; 287 if (res->end > p->end) 288 res->end = p->end; 289 return 0; 290 } 291 #endif 292 293 /* 294 * Find empty slot in the resource tree given range and alignment. 295 */ 296 static int find_resource(struct resource *root, struct resource *new, 297 resource_size_t size, resource_size_t min, 298 resource_size_t max, resource_size_t align, 299 void (*alignf)(void *, struct resource *, 300 resource_size_t, resource_size_t), 301 void *alignf_data) 302 { 303 struct resource *this = root->child; 304 305 new->start = root->start; 306 /* 307 * Skip past an allocated resource that starts at 0, since the assignment 308 * of this->start - 1 to new->end below would cause an underflow. 309 */ 310 if (this && this->start == 0) { 311 new->start = this->end + 1; 312 this = this->sibling; 313 } 314 for(;;) { 315 if (this) 316 new->end = this->start - 1; 317 else 318 new->end = root->end; 319 if (new->start < min) 320 new->start = min; 321 if (new->end > max) 322 new->end = max; 323 new->start = ALIGN(new->start, align); 324 if (alignf) 325 alignf(alignf_data, new, size, align); 326 if (new->start < new->end && new->end - new->start >= size - 1) { 327 new->end = new->start + size - 1; 328 return 0; 329 } 330 if (!this) 331 break; 332 new->start = this->end + 1; 333 this = this->sibling; 334 } 335 return -EBUSY; 336 } 337 338 /** 339 * allocate_resource - allocate empty slot in the resource tree given range & alignment 340 * @root: root resource descriptor 341 * @new: resource descriptor desired by caller 342 * @size: requested resource region size 343 * @min: minimum size to allocate 344 * @max: maximum size to allocate 345 * @align: alignment requested, in bytes 346 * @alignf: alignment function, optional, called if not NULL 347 * @alignf_data: arbitrary data to pass to the @alignf function 348 */ 349 int allocate_resource(struct resource *root, struct resource *new, 350 resource_size_t size, resource_size_t min, 351 resource_size_t max, resource_size_t align, 352 void (*alignf)(void *, struct resource *, 353 resource_size_t, resource_size_t), 354 void *alignf_data) 355 { 356 int err; 357 358 write_lock(&resource_lock); 359 err = find_resource(root, new, size, min, max, align, alignf, alignf_data); 360 if (err >= 0 && __request_resource(root, new)) 361 err = -EBUSY; 362 write_unlock(&resource_lock); 363 return err; 364 } 365 366 EXPORT_SYMBOL(allocate_resource); 367 368 /** 369 * insert_resource - Inserts a resource in the resource tree 370 * @parent: parent of the new resource 371 * @new: new resource to insert 372 * 373 * Returns 0 on success, -EBUSY if the resource can't be inserted. 374 * 375 * This function is equivalent to request_resource when no conflict 376 * happens. If a conflict happens, and the conflicting resources 377 * entirely fit within the range of the new resource, then the new 378 * resource is inserted and the conflicting resources become children of 379 * the new resource. 380 */ 381 int insert_resource(struct resource *parent, struct resource *new) 382 { 383 int result; 384 struct resource *first, *next; 385 386 write_lock(&resource_lock); 387 388 for (;; parent = first) { 389 result = 0; 390 first = __request_resource(parent, new); 391 if (!first) 392 goto out; 393 394 result = -EBUSY; 395 if (first == parent) 396 goto out; 397 398 if ((first->start > new->start) || (first->end < new->end)) 399 break; 400 if ((first->start == new->start) && (first->end == new->end)) 401 break; 402 } 403 404 for (next = first; ; next = next->sibling) { 405 /* Partial overlap? Bad, and unfixable */ 406 if (next->start < new->start || next->end > new->end) 407 goto out; 408 if (!next->sibling) 409 break; 410 if (next->sibling->start > new->end) 411 break; 412 } 413 414 result = 0; 415 416 new->parent = parent; 417 new->sibling = next->sibling; 418 new->child = first; 419 420 next->sibling = NULL; 421 for (next = first; next; next = next->sibling) 422 next->parent = new; 423 424 if (parent->child == first) { 425 parent->child = new; 426 } else { 427 next = parent->child; 428 while (next->sibling != first) 429 next = next->sibling; 430 next->sibling = new; 431 } 432 433 out: 434 write_unlock(&resource_lock); 435 return result; 436 } 437 438 /** 439 * adjust_resource - modify a resource's start and size 440 * @res: resource to modify 441 * @start: new start value 442 * @size: new size 443 * 444 * Given an existing resource, change its start and size to match the 445 * arguments. Returns 0 on success, -EBUSY if it can't fit. 446 * Existing children of the resource are assumed to be immutable. 447 */ 448 int adjust_resource(struct resource *res, resource_size_t start, resource_size_t size) 449 { 450 struct resource *tmp, *parent = res->parent; 451 resource_size_t end = start + size - 1; 452 int result = -EBUSY; 453 454 write_lock(&resource_lock); 455 456 if ((start < parent->start) || (end > parent->end)) 457 goto out; 458 459 for (tmp = res->child; tmp; tmp = tmp->sibling) { 460 if ((tmp->start < start) || (tmp->end > end)) 461 goto out; 462 } 463 464 if (res->sibling && (res->sibling->start <= end)) 465 goto out; 466 467 tmp = parent->child; 468 if (tmp != res) { 469 while (tmp->sibling != res) 470 tmp = tmp->sibling; 471 if (start <= tmp->end) 472 goto out; 473 } 474 475 res->start = start; 476 res->end = end; 477 result = 0; 478 479 out: 480 write_unlock(&resource_lock); 481 return result; 482 } 483 484 EXPORT_SYMBOL(adjust_resource); 485 486 /* 487 * This is compatibility stuff for IO resources. 488 * 489 * Note how this, unlike the above, knows about 490 * the IO flag meanings (busy etc). 491 * 492 * request_region creates a new busy region. 493 * 494 * check_region returns non-zero if the area is already busy. 495 * 496 * release_region releases a matching busy region. 497 */ 498 499 /** 500 * __request_region - create a new busy resource region 501 * @parent: parent resource descriptor 502 * @start: resource start address 503 * @n: resource region size 504 * @name: reserving caller's ID string 505 */ 506 struct resource * __request_region(struct resource *parent, 507 resource_size_t start, resource_size_t n, 508 const char *name) 509 { 510 struct resource *res = kzalloc(sizeof(*res), GFP_KERNEL); 511 512 if (res) { 513 res->name = name; 514 res->start = start; 515 res->end = start + n - 1; 516 res->flags = IORESOURCE_BUSY; 517 518 write_lock(&resource_lock); 519 520 for (;;) { 521 struct resource *conflict; 522 523 conflict = __request_resource(parent, res); 524 if (!conflict) 525 break; 526 if (conflict != parent) { 527 parent = conflict; 528 if (!(conflict->flags & IORESOURCE_BUSY)) 529 continue; 530 } 531 532 /* Uhhuh, that didn't work out.. */ 533 kfree(res); 534 res = NULL; 535 break; 536 } 537 write_unlock(&resource_lock); 538 } 539 return res; 540 } 541 EXPORT_SYMBOL(__request_region); 542 543 /** 544 * __check_region - check if a resource region is busy or free 545 * @parent: parent resource descriptor 546 * @start: resource start address 547 * @n: resource region size 548 * 549 * Returns 0 if the region is free at the moment it is checked, 550 * returns %-EBUSY if the region is busy. 551 * 552 * NOTE: 553 * This function is deprecated because its use is racy. 554 * Even if it returns 0, a subsequent call to request_region() 555 * may fail because another driver etc. just allocated the region. 556 * Do NOT use it. It will be removed from the kernel. 557 */ 558 int __check_region(struct resource *parent, resource_size_t start, 559 resource_size_t n) 560 { 561 struct resource * res; 562 563 res = __request_region(parent, start, n, "check-region"); 564 if (!res) 565 return -EBUSY; 566 567 release_resource(res); 568 kfree(res); 569 return 0; 570 } 571 EXPORT_SYMBOL(__check_region); 572 573 /** 574 * __release_region - release a previously reserved resource region 575 * @parent: parent resource descriptor 576 * @start: resource start address 577 * @n: resource region size 578 * 579 * The described resource region must match a currently busy region. 580 */ 581 void __release_region(struct resource *parent, resource_size_t start, 582 resource_size_t n) 583 { 584 struct resource **p; 585 resource_size_t end; 586 587 p = &parent->child; 588 end = start + n - 1; 589 590 write_lock(&resource_lock); 591 592 for (;;) { 593 struct resource *res = *p; 594 595 if (!res) 596 break; 597 if (res->start <= start && res->end >= end) { 598 if (!(res->flags & IORESOURCE_BUSY)) { 599 p = &res->child; 600 continue; 601 } 602 if (res->start != start || res->end != end) 603 break; 604 *p = res->sibling; 605 write_unlock(&resource_lock); 606 kfree(res); 607 return; 608 } 609 p = &res->sibling; 610 } 611 612 write_unlock(&resource_lock); 613 614 printk(KERN_WARNING "Trying to free nonexistent resource " 615 "<%016llx-%016llx>\n", (unsigned long long)start, 616 (unsigned long long)end); 617 } 618 EXPORT_SYMBOL(__release_region); 619 620 /* 621 * Called from init/main.c to reserve IO ports. 622 */ 623 #define MAXRESERVE 4 624 static int __init reserve_setup(char *str) 625 { 626 static int reserved; 627 static struct resource reserve[MAXRESERVE]; 628 629 for (;;) { 630 int io_start, io_num; 631 int x = reserved; 632 633 if (get_option (&str, &io_start) != 2) 634 break; 635 if (get_option (&str, &io_num) == 0) 636 break; 637 if (x < MAXRESERVE) { 638 struct resource *res = reserve + x; 639 res->name = "reserved"; 640 res->start = io_start; 641 res->end = io_start + io_num - 1; 642 res->flags = IORESOURCE_BUSY; 643 res->child = NULL; 644 if (request_resource(res->start >= 0x10000 ? &iomem_resource : &ioport_resource, res) == 0) 645 reserved = x+1; 646 } 647 } 648 return 1; 649 } 650 651 __setup("reserve=", reserve_setup); 652