linux/kernel/resource.c
<<
>>
Prefs
   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/errno.h>
  12#include <linux/ioport.h>
  13#include <linux/init.h>
  14#include <linux/slab.h>
  15#include <linux/spinlock.h>
  16#include <linux/fs.h>
  17#include <linux/proc_fs.h>
  18#include <linux/seq_file.h>
  19#include <linux/device.h>
  20#include <asm/io.h>
  21
  22
  23struct resource ioport_resource = {
  24        .name   = "PCI IO",
  25        .start  = 0,
  26        .end    = IO_SPACE_LIMIT,
  27        .flags  = IORESOURCE_IO,
  28};
  29EXPORT_SYMBOL(ioport_resource);
  30
  31struct resource iomem_resource = {
  32        .name   = "PCI mem",
  33        .start  = 0,
  34        .end    = -1,
  35        .flags  = IORESOURCE_MEM,
  36};
  37EXPORT_SYMBOL(iomem_resource);
  38
  39static DEFINE_RWLOCK(resource_lock);
  40
  41#ifdef CONFIG_PROC_FS
  42
  43enum { MAX_IORES_LEVEL = 5 };
  44
  45static 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
  56static 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
  67static void r_stop(struct seq_file *m, void *v)
  68        __releases(resource_lock)
  69{
  70        read_unlock(&resource_lock);
  71}
  72
  73static 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
  91static const struct seq_operations resource_op = {
  92        .start  = r_start,
  93        .next   = r_next,
  94        .stop   = r_stop,
  95        .show   = r_show,
  96};
  97
  98static 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
 108static 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
 118static 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
 125static 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
 132static int __init ioresources_init(void)
 133{
 134        proc_create("ioports", 0, NULL, &proc_ioports_operations);
 135        proc_create("iomem", 0, NULL, &proc_iomem_operations);
 136        return 0;
 137}
 138__initcall(ioresources_init);
 139
 140#endif /* CONFIG_PROC_FS */
 141
 142/* Return the conflict entry if you can't request it */
 143static struct resource * __request_resource(struct resource *root, struct resource *new)
 144{
 145        resource_size_t start = new->start;
 146        resource_size_t end = new->end;
 147        struct resource *tmp, **p;
 148
 149        if (end < start)
 150                return root;
 151        if (start < root->start)
 152                return root;
 153        if (end > root->end)
 154                return root;
 155        p = &root->child;
 156        for (;;) {
 157                tmp = *p;
 158                if (!tmp || tmp->start > end) {
 159                        new->sibling = tmp;
 160                        *p = new;
 161                        new->parent = root;
 162                        return NULL;
 163                }
 164                p = &tmp->sibling;
 165                if (tmp->end < start)
 166                        continue;
 167                return tmp;
 168        }
 169}
 170
 171static int __release_resource(struct resource *old)
 172{
 173        struct resource *tmp, **p;
 174
 175        p = &old->parent->child;
 176        for (;;) {
 177                tmp = *p;
 178                if (!tmp)
 179                        break;
 180                if (tmp == old) {
 181                        *p = tmp->sibling;
 182                        old->parent = NULL;
 183                        return 0;
 184                }
 185                p = &tmp->sibling;
 186        }
 187        return -EINVAL;
 188}
 189
 190/**
 191 * request_resource - request and reserve an I/O or memory resource
 192 * @root: root resource descriptor
 193 * @new: resource descriptor desired by caller
 194 *
 195 * Returns 0 for success, negative error code on error.
 196 */
 197int request_resource(struct resource *root, struct resource *new)
 198{
 199        struct resource *conflict;
 200
 201        write_lock(&resource_lock);
 202        conflict = __request_resource(root, new);
 203        write_unlock(&resource_lock);
 204        return conflict ? -EBUSY : 0;
 205}
 206
 207EXPORT_SYMBOL(request_resource);
 208
 209/**
 210 * release_resource - release a previously reserved resource
 211 * @old: resource pointer
 212 */
 213int release_resource(struct resource *old)
 214{
 215        int retval;
 216
 217        write_lock(&resource_lock);
 218        retval = __release_resource(old);
 219        write_unlock(&resource_lock);
 220        return retval;
 221}
 222
 223EXPORT_SYMBOL(release_resource);
 224
 225#if defined(CONFIG_MEMORY_HOTPLUG) && !defined(CONFIG_ARCH_HAS_WALK_MEMORY)
 226/*
 227 * Finds the lowest memory reosurce exists within [res->start.res->end)
 228 * the caller must specify res->start, res->end, res->flags.
 229 * If found, returns 0, res is overwritten, if not found, returns -1.
 230 */
 231static int find_next_system_ram(struct resource *res)
 232{
 233        resource_size_t start, end;
 234        struct resource *p;
 235
 236        BUG_ON(!res);
 237
 238        start = res->start;
 239        end = res->end;
 240        BUG_ON(start >= end);
 241
 242        read_lock(&resource_lock);
 243        for (p = iomem_resource.child; p ; p = p->sibling) {
 244                /* system ram is just marked as IORESOURCE_MEM */
 245                if (p->flags != res->flags)
 246                        continue;
 247                if (p->start > end) {
 248                        p = NULL;
 249                        break;
 250                }
 251                if ((p->end >= start) && (p->start < end))
 252                        break;
 253        }
 254        read_unlock(&resource_lock);
 255        if (!p)
 256                return -1;
 257        /* copy data */
 258        if (res->start < p->start)
 259                res->start = p->start;
 260        if (res->end > p->end)
 261                res->end = p->end;
 262        return 0;
 263}
 264int
 265walk_memory_resource(unsigned long start_pfn, unsigned long nr_pages, void *arg,
 266                        int (*func)(unsigned long, unsigned long, void *))
 267{
 268        struct resource res;
 269        unsigned long pfn, len;
 270        u64 orig_end;
 271        int ret = -1;
 272        res.start = (u64) start_pfn << PAGE_SHIFT;
 273        res.end = ((u64)(start_pfn + nr_pages) << PAGE_SHIFT) - 1;
 274        res.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
 275        orig_end = res.end;
 276        while ((res.start < res.end) && (find_next_system_ram(&res) >= 0)) {
 277                pfn = (unsigned long)(res.start >> PAGE_SHIFT);
 278                len = (unsigned long)((res.end + 1 - res.start) >> PAGE_SHIFT);
 279                ret = (*func)(pfn, len, arg);
 280                if (ret)
 281                        break;
 282                res.start = res.end + 1;
 283                res.end = orig_end;
 284        }
 285        return ret;
 286}
 287
 288#endif
 289
 290/*
 291 * Find empty slot in the resource tree given range and alignment.
 292 */
 293static int find_resource(struct resource *root, struct resource *new,
 294                         resource_size_t size, resource_size_t min,
 295                         resource_size_t max, resource_size_t align,
 296                         void (*alignf)(void *, struct resource *,
 297                                        resource_size_t, resource_size_t),
 298                         void *alignf_data)
 299{
 300        struct resource *this = root->child;
 301
 302        new->start = root->start;
 303        /*
 304         * Skip past an allocated resource that starts at 0, since the assignment
 305         * of this->start - 1 to new->end below would cause an underflow.
 306         */
 307        if (this && this->start == 0) {
 308                new->start = this->end + 1;
 309                this = this->sibling;
 310        }
 311        for(;;) {
 312                if (this)
 313                        new->end = this->start - 1;
 314                else
 315                        new->end = root->end;
 316                if (new->start < min)
 317                        new->start = min;
 318                if (new->end > max)
 319                        new->end = max;
 320                new->start = ALIGN(new->start, align);
 321                if (alignf)
 322                        alignf(alignf_data, new, size, align);
 323                if (new->start < new->end && new->end - new->start >= size - 1) {
 324                        new->end = new->start + size - 1;
 325                        return 0;
 326                }
 327                if (!this)
 328                        break;
 329                new->start = this->end + 1;
 330                this = this->sibling;
 331        }
 332        return -EBUSY;
 333}
 334
 335/**
 336 * allocate_resource - allocate empty slot in the resource tree given range & alignment
 337 * @root: root resource descriptor
 338 * @new: resource descriptor desired by caller
 339 * @size: requested resource region size
 340 * @min: minimum size to allocate
 341 * @max: maximum size to allocate
 342 * @align: alignment requested, in bytes
 343 * @alignf: alignment function, optional, called if not NULL
 344 * @alignf_data: arbitrary data to pass to the @alignf function
 345 */
 346int allocate_resource(struct resource *root, struct resource *new,
 347                      resource_size_t size, resource_size_t min,
 348                      resource_size_t max, resource_size_t align,
 349                      void (*alignf)(void *, struct resource *,
 350                                     resource_size_t, resource_size_t),
 351                      void *alignf_data)
 352{
 353        int err;
 354
 355        write_lock(&resource_lock);
 356        err = find_resource(root, new, size, min, max, align, alignf, alignf_data);
 357        if (err >= 0 && __request_resource(root, new))
 358                err = -EBUSY;
 359        write_unlock(&resource_lock);
 360        return err;
 361}
 362
 363EXPORT_SYMBOL(allocate_resource);
 364
 365/*
 366 * Insert a resource into the resource tree. If successful, return NULL,
 367 * otherwise return the conflicting resource (compare to __request_resource())
 368 */
 369static struct resource * __insert_resource(struct resource *parent, struct resource *new)
 370{
 371        struct resource *first, *next;
 372
 373        for (;; parent = first) {
 374                first = __request_resource(parent, new);
 375                if (!first)
 376                        return first;
 377
 378                if (first == parent)
 379                        return first;
 380
 381                if ((first->start > new->start) || (first->end < new->end))
 382                        break;
 383                if ((first->start == new->start) && (first->end == new->end))
 384                        break;
 385        }
 386
 387        for (next = first; ; next = next->sibling) {
 388                /* Partial overlap? Bad, and unfixable */
 389                if (next->start < new->start || next->end > new->end)
 390                        return next;
 391                if (!next->sibling)
 392                        break;
 393                if (next->sibling->start > new->end)
 394                        break;
 395        }
 396
 397        new->parent = parent;
 398        new->sibling = next->sibling;
 399        new->child = first;
 400
 401        next->sibling = NULL;
 402        for (next = first; next; next = next->sibling)
 403                next->parent = new;
 404
 405        if (parent->child == first) {
 406                parent->child = new;
 407        } else {
 408                next = parent->child;
 409                while (next->sibling != first)
 410                        next = next->sibling;
 411                next->sibling = new;
 412        }
 413        return NULL;
 414}
 415
 416/**
 417 * insert_resource - Inserts a resource in the resource tree
 418 * @parent: parent of the new resource
 419 * @new: new resource to insert
 420 *
 421 * Returns 0 on success, -EBUSY if the resource can't be inserted.
 422 *
 423 * This function is equivalent to request_resource when no conflict
 424 * happens. If a conflict happens, and the conflicting resources
 425 * entirely fit within the range of the new resource, then the new
 426 * resource is inserted and the conflicting resources become children of
 427 * the new resource.
 428 */
 429int insert_resource(struct resource *parent, struct resource *new)
 430{
 431        struct resource *conflict;
 432
 433        write_lock(&resource_lock);
 434        conflict = __insert_resource(parent, new);
 435        write_unlock(&resource_lock);
 436        return conflict ? -EBUSY : 0;
 437}
 438
 439/**
 440 * insert_resource_expand_to_fit - Insert a resource into the resource tree
 441 * @root: root resource descriptor
 442 * @new: new resource to insert
 443 *
 444 * Insert a resource into the resource tree, possibly expanding it in order
 445 * to make it encompass any conflicting resources.
 446 */
 447void insert_resource_expand_to_fit(struct resource *root, struct resource *new)
 448{
 449        if (new->parent)
 450                return;
 451
 452        write_lock(&resource_lock);
 453        for (;;) {
 454                struct resource *conflict;
 455
 456                conflict = __insert_resource(root, new);
 457                if (!conflict)
 458                        break;
 459                if (conflict == root)
 460                        break;
 461
 462                /* Ok, expand resource to cover the conflict, then try again .. */
 463                if (conflict->start < new->start)
 464                        new->start = conflict->start;
 465                if (conflict->end > new->end)
 466                        new->end = conflict->end;
 467
 468                printk("Expanded resource %s due to conflict with %s\n", new->name, conflict->name);
 469        }
 470        write_unlock(&resource_lock);
 471}
 472
 473/**
 474 * adjust_resource - modify a resource's start and size
 475 * @res: resource to modify
 476 * @start: new start value
 477 * @size: new size
 478 *
 479 * Given an existing resource, change its start and size to match the
 480 * arguments.  Returns 0 on success, -EBUSY if it can't fit.
 481 * Existing children of the resource are assumed to be immutable.
 482 */
 483int adjust_resource(struct resource *res, resource_size_t start, resource_size_t size)
 484{
 485        struct resource *tmp, *parent = res->parent;
 486        resource_size_t end = start + size - 1;
 487        int result = -EBUSY;
 488
 489        write_lock(&resource_lock);
 490
 491        if ((start < parent->start) || (end > parent->end))
 492                goto out;
 493
 494        for (tmp = res->child; tmp; tmp = tmp->sibling) {
 495                if ((tmp->start < start) || (tmp->end > end))
 496                        goto out;
 497        }
 498
 499        if (res->sibling && (res->sibling->start <= end))
 500                goto out;
 501
 502        tmp = parent->child;
 503        if (tmp != res) {
 504                while (tmp->sibling != res)
 505                        tmp = tmp->sibling;
 506                if (start <= tmp->end)
 507                        goto out;
 508        }
 509
 510        res->start = start;
 511        res->end = end;
 512        result = 0;
 513
 514 out:
 515        write_unlock(&resource_lock);
 516        return result;
 517}
 518
 519EXPORT_SYMBOL(adjust_resource);
 520
 521/**
 522 * resource_alignment - calculate resource's alignment
 523 * @res: resource pointer
 524 *
 525 * Returns alignment on success, 0 (invalid alignment) on failure.
 526 */
 527resource_size_t resource_alignment(struct resource *res)
 528{
 529        switch (res->flags & (IORESOURCE_SIZEALIGN | IORESOURCE_STARTALIGN)) {
 530        case IORESOURCE_SIZEALIGN:
 531                return resource_size(res);
 532        case IORESOURCE_STARTALIGN:
 533                return res->start;
 534        default:
 535                return 0;
 536        }
 537}
 538
 539/*
 540 * This is compatibility stuff for IO resources.
 541 *
 542 * Note how this, unlike the above, knows about
 543 * the IO flag meanings (busy etc).
 544 *
 545 * request_region creates a new busy region.
 546 *
 547 * check_region returns non-zero if the area is already busy.
 548 *
 549 * release_region releases a matching busy region.
 550 */
 551
 552/**
 553 * __request_region - create a new busy resource region
 554 * @parent: parent resource descriptor
 555 * @start: resource start address
 556 * @n: resource region size
 557 * @name: reserving caller's ID string
 558 */
 559struct resource * __request_region(struct resource *parent,
 560                                   resource_size_t start, resource_size_t n,
 561                                   const char *name)
 562{
 563        struct resource *res = kzalloc(sizeof(*res), GFP_KERNEL);
 564
 565        if (res) {
 566                res->name = name;
 567                res->start = start;
 568                res->end = start + n - 1;
 569                res->flags = IORESOURCE_BUSY;
 570
 571                write_lock(&resource_lock);
 572
 573                for (;;) {
 574                        struct resource *conflict;
 575
 576                        conflict = __request_resource(parent, res);
 577                        if (!conflict)
 578                                break;
 579                        if (conflict != parent) {
 580                                parent = conflict;
 581                                if (!(conflict->flags & IORESOURCE_BUSY))
 582                                        continue;
 583                        }
 584
 585                        /* Uhhuh, that didn't work out.. */
 586                        kfree(res);
 587                        res = NULL;
 588                        break;
 589                }
 590                write_unlock(&resource_lock);
 591        }
 592        return res;
 593}
 594EXPORT_SYMBOL(__request_region);
 595
 596/**
 597 * __check_region - check if a resource region is busy or free
 598 * @parent: parent resource descriptor
 599 * @start: resource start address
 600 * @n: resource region size
 601 *
 602 * Returns 0 if the region is free at the moment it is checked,
 603 * returns %-EBUSY if the region is busy.
 604 *
 605 * NOTE:
 606 * This function is deprecated because its use is racy.
 607 * Even if it returns 0, a subsequent call to request_region()
 608 * may fail because another driver etc. just allocated the region.
 609 * Do NOT use it.  It will be removed from the kernel.
 610 */
 611int __check_region(struct resource *parent, resource_size_t start,
 612                        resource_size_t n)
 613{
 614        struct resource * res;
 615
 616        res = __request_region(parent, start, n, "check-region");
 617        if (!res)
 618                return -EBUSY;
 619
 620        release_resource(res);
 621        kfree(res);
 622        return 0;
 623}
 624EXPORT_SYMBOL(__check_region);
 625
 626/**
 627 * __release_region - release a previously reserved resource region
 628 * @parent: parent resource descriptor
 629 * @start: resource start address
 630 * @n: resource region size
 631 *
 632 * The described resource region must match a currently busy region.
 633 */
 634void __release_region(struct resource *parent, resource_size_t start,
 635                        resource_size_t n)
 636{
 637        struct resource **p;
 638        resource_size_t end;
 639
 640        p = &parent->child;
 641        end = start + n - 1;
 642
 643        write_lock(&resource_lock);
 644
 645        for (;;) {
 646                struct resource *res = *p;
 647
 648                if (!res)
 649                        break;
 650                if (res->start <= start && res->end >= end) {
 651                        if (!(res->flags & IORESOURCE_BUSY)) {
 652                                p = &res->child;
 653                                continue;
 654                        }
 655                        if (res->start != start || res->end != end)
 656                                break;
 657                        *p = res->sibling;
 658                        write_unlock(&resource_lock);
 659                        kfree(res);
 660                        return;
 661                }
 662                p = &res->sibling;
 663        }
 664
 665        write_unlock(&resource_lock);
 666
 667        printk(KERN_WARNING "Trying to free nonexistent resource "
 668                "<%016llx-%016llx>\n", (unsigned long long)start,
 669                (unsigned long long)end);
 670}
 671EXPORT_SYMBOL(__release_region);
 672
 673/*
 674 * Managed region resource
 675 */
 676struct region_devres {
 677        struct resource *parent;
 678        resource_size_t start;
 679        resource_size_t n;
 680};
 681
 682static void devm_region_release(struct device *dev, void *res)
 683{
 684        struct region_devres *this = res;
 685
 686        __release_region(this->parent, this->start, this->n);
 687}
 688
 689static int devm_region_match(struct device *dev, void *res, void *match_data)
 690{
 691        struct region_devres *this = res, *match = match_data;
 692
 693        return this->parent == match->parent &&
 694                this->start == match->start && this->n == match->n;
 695}
 696
 697struct resource * __devm_request_region(struct device *dev,
 698                                struct resource *parent, resource_size_t start,
 699                                resource_size_t n, const char *name)
 700{
 701        struct region_devres *dr = NULL;
 702        struct resource *res;
 703
 704        dr = devres_alloc(devm_region_release, sizeof(struct region_devres),
 705                          GFP_KERNEL);
 706        if (!dr)
 707                return NULL;
 708
 709        dr->parent = parent;
 710        dr->start = start;
 711        dr->n = n;
 712
 713        res = __request_region(parent, start, n, name);
 714        if (res)
 715                devres_add(dev, dr);
 716        else
 717                devres_free(dr);
 718
 719        return res;
 720}
 721EXPORT_SYMBOL(__devm_request_region);
 722
 723void __devm_release_region(struct device *dev, struct resource *parent,
 724                           resource_size_t start, resource_size_t n)
 725{
 726        struct region_devres match_data = { parent, start, n };
 727
 728        __release_region(parent, start, n);
 729        WARN_ON(devres_destroy(dev, devm_region_release, devm_region_match,
 730                               &match_data));
 731}
 732EXPORT_SYMBOL(__devm_release_region);
 733
 734/*
 735 * Called from init/main.c to reserve IO ports.
 736 */
 737#define MAXRESERVE 4
 738static int __init reserve_setup(char *str)
 739{
 740        static int reserved;
 741        static struct resource reserve[MAXRESERVE];
 742
 743        for (;;) {
 744                unsigned int io_start, io_num;
 745                int x = reserved;
 746
 747                if (get_option (&str, &io_start) != 2)
 748                        break;
 749                if (get_option (&str, &io_num)   == 0)
 750                        break;
 751                if (x < MAXRESERVE) {
 752                        struct resource *res = reserve + x;
 753                        res->name = "reserved";
 754                        res->start = io_start;
 755                        res->end = io_start + io_num - 1;
 756                        res->flags = IORESOURCE_BUSY;
 757                        res->child = NULL;
 758                        if (request_resource(res->start >= 0x10000 ? &iomem_resource : &ioport_resource, res) == 0)
 759                                reserved = x+1;
 760                }
 761        }
 762        return 1;
 763}
 764
 765__setup("reserve=", reserve_setup);
 766