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/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
  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 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 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 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        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 */
 149static 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
 177static 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 */
 203int 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
 213EXPORT_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 */
 224struct 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
 234EXPORT_SYMBOL(____request_resource);
 235
 236/**
 237 * release_resource - release a previously reserved resource
 238 * @old: resource pointer
 239 */
 240int 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
 250EXPORT_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 */
 258int 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 */
 296static 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 */
 349int 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
 366EXPORT_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 */
 381int 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 */
 448int 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
 484EXPORT_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 */
 506struct 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}
 541EXPORT_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 */
 558int __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}
 571EXPORT_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 */
 581void __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}
 618EXPORT_SYMBOL(__release_region);
 619
 620/*
 621 * Called from init/main.c to reserve IO ports.
 622 */
 623#define MAXRESERVE 4
 624static 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