diff options
Diffstat (limited to 'kernel/resource.c')
| -rw-r--r-- | kernel/resource.c | 128 |
1 files changed, 84 insertions, 44 deletions
diff --git a/kernel/resource.c b/kernel/resource.c index e3080fcc66a3..9db38a1a7520 100644 --- a/kernel/resource.c +++ b/kernel/resource.c | |||
| @@ -7,7 +7,6 @@ | |||
| 7 | * Arbitrary resource management. | 7 | * Arbitrary resource management. |
| 8 | */ | 8 | */ |
| 9 | 9 | ||
| 10 | #include <linux/config.h> | ||
| 11 | #include <linux/module.h> | 10 | #include <linux/module.h> |
| 12 | #include <linux/sched.h> | 11 | #include <linux/sched.h> |
| 13 | #include <linux/errno.h> | 12 | #include <linux/errno.h> |
| @@ -23,20 +22,18 @@ | |||
| 23 | 22 | ||
| 24 | struct resource ioport_resource = { | 23 | struct resource ioport_resource = { |
| 25 | .name = "PCI IO", | 24 | .name = "PCI IO", |
| 26 | .start = 0x0000, | 25 | .start = 0, |
| 27 | .end = IO_SPACE_LIMIT, | 26 | .end = IO_SPACE_LIMIT, |
| 28 | .flags = IORESOURCE_IO, | 27 | .flags = IORESOURCE_IO, |
| 29 | }; | 28 | }; |
| 30 | |||
| 31 | EXPORT_SYMBOL(ioport_resource); | 29 | EXPORT_SYMBOL(ioport_resource); |
| 32 | 30 | ||
| 33 | struct resource iomem_resource = { | 31 | struct resource iomem_resource = { |
| 34 | .name = "PCI mem", | 32 | .name = "PCI mem", |
| 35 | .start = 0UL, | 33 | .start = 0, |
| 36 | .end = ~0UL, | 34 | .end = -1, |
| 37 | .flags = IORESOURCE_MEM, | 35 | .flags = IORESOURCE_MEM, |
| 38 | }; | 36 | }; |
| 39 | |||
| 40 | EXPORT_SYMBOL(iomem_resource); | 37 | EXPORT_SYMBOL(iomem_resource); |
| 41 | 38 | ||
| 42 | static DEFINE_RWLOCK(resource_lock); | 39 | static DEFINE_RWLOCK(resource_lock); |
| @@ -83,10 +80,10 @@ static int r_show(struct seq_file *m, void *v) | |||
| 83 | for (depth = 0, p = r; depth < MAX_IORES_LEVEL; depth++, p = p->parent) | 80 | for (depth = 0, p = r; depth < MAX_IORES_LEVEL; depth++, p = p->parent) |
| 84 | if (p->parent == root) | 81 | if (p->parent == root) |
| 85 | break; | 82 | break; |
| 86 | seq_printf(m, "%*s%0*lx-%0*lx : %s\n", | 83 | seq_printf(m, "%*s%0*llx-%0*llx : %s\n", |
| 87 | depth * 2, "", | 84 | depth * 2, "", |
| 88 | width, r->start, | 85 | width, (unsigned long long) r->start, |
| 89 | width, r->end, | 86 | width, (unsigned long long) r->end, |
| 90 | r->name ? r->name : "<BAD>"); | 87 | r->name ? r->name : "<BAD>"); |
| 91 | return 0; | 88 | return 0; |
| 92 | } | 89 | } |
| @@ -151,8 +148,8 @@ __initcall(ioresources_init); | |||
| 151 | /* Return the conflict entry if you can't request it */ | 148 | /* Return the conflict entry if you can't request it */ |
| 152 | static struct resource * __request_resource(struct resource *root, struct resource *new) | 149 | static struct resource * __request_resource(struct resource *root, struct resource *new) |
| 153 | { | 150 | { |
| 154 | unsigned long start = new->start; | 151 | resource_size_t start = new->start; |
| 155 | unsigned long end = new->end; | 152 | resource_size_t end = new->end; |
| 156 | struct resource *tmp, **p; | 153 | struct resource *tmp, **p; |
| 157 | 154 | ||
| 158 | if (end < start) | 155 | if (end < start) |
| @@ -232,15 +229,55 @@ int release_resource(struct resource *old) | |||
| 232 | 229 | ||
| 233 | EXPORT_SYMBOL(release_resource); | 230 | EXPORT_SYMBOL(release_resource); |
| 234 | 231 | ||
| 232 | #ifdef CONFIG_MEMORY_HOTPLUG | ||
| 233 | /* | ||
| 234 | * Finds the lowest memory reosurce exists within [res->start.res->end) | ||
| 235 | * the caller must specify res->start, res->end, res->flags. | ||
| 236 | * If found, returns 0, res is overwritten, if not found, returns -1. | ||
| 237 | */ | ||
| 238 | int find_next_system_ram(struct resource *res) | ||
| 239 | { | ||
| 240 | resource_size_t start, end; | ||
| 241 | struct resource *p; | ||
| 242 | |||
| 243 | BUG_ON(!res); | ||
| 244 | |||
| 245 | start = res->start; | ||
| 246 | end = res->end; | ||
| 247 | BUG_ON(start >= end); | ||
| 248 | |||
| 249 | read_lock(&resource_lock); | ||
| 250 | for (p = iomem_resource.child; p ; p = p->sibling) { | ||
| 251 | /* system ram is just marked as IORESOURCE_MEM */ | ||
| 252 | if (p->flags != res->flags) | ||
| 253 | continue; | ||
| 254 | if (p->start > end) { | ||
| 255 | p = NULL; | ||
| 256 | break; | ||
| 257 | } | ||
| 258 | if ((p->end >= start) && (p->start < end)) | ||
| 259 | break; | ||
| 260 | } | ||
| 261 | read_unlock(&resource_lock); | ||
| 262 | if (!p) | ||
| 263 | return -1; | ||
| 264 | /* copy data */ | ||
| 265 | if (res->start < p->start) | ||
| 266 | res->start = p->start; | ||
| 267 | if (res->end > p->end) | ||
| 268 | res->end = p->end; | ||
| 269 | return 0; | ||
| 270 | } | ||
| 271 | #endif | ||
| 272 | |||
| 235 | /* | 273 | /* |
| 236 | * Find empty slot in the resource tree given range and alignment. | 274 | * Find empty slot in the resource tree given range and alignment. |
| 237 | */ | 275 | */ |
| 238 | static int find_resource(struct resource *root, struct resource *new, | 276 | static int find_resource(struct resource *root, struct resource *new, |
| 239 | unsigned long size, | 277 | resource_size_t size, resource_size_t min, |
| 240 | unsigned long min, unsigned long max, | 278 | resource_size_t max, resource_size_t align, |
| 241 | unsigned long align, | ||
| 242 | void (*alignf)(void *, struct resource *, | 279 | void (*alignf)(void *, struct resource *, |
| 243 | unsigned long, unsigned long), | 280 | resource_size_t, resource_size_t), |
| 244 | void *alignf_data) | 281 | void *alignf_data) |
| 245 | { | 282 | { |
| 246 | struct resource *this = root->child; | 283 | struct resource *this = root->child; |
| @@ -282,11 +319,10 @@ static int find_resource(struct resource *root, struct resource *new, | |||
| 282 | * Allocate empty slot in the resource tree given range and alignment. | 319 | * Allocate empty slot in the resource tree given range and alignment. |
| 283 | */ | 320 | */ |
| 284 | int allocate_resource(struct resource *root, struct resource *new, | 321 | int allocate_resource(struct resource *root, struct resource *new, |
| 285 | unsigned long size, | 322 | resource_size_t size, resource_size_t min, |
| 286 | unsigned long min, unsigned long max, | 323 | resource_size_t max, resource_size_t align, |
| 287 | unsigned long align, | ||
| 288 | void (*alignf)(void *, struct resource *, | 324 | void (*alignf)(void *, struct resource *, |
| 289 | unsigned long, unsigned long), | 325 | resource_size_t, resource_size_t), |
| 290 | void *alignf_data) | 326 | void *alignf_data) |
| 291 | { | 327 | { |
| 292 | int err; | 328 | int err; |
| @@ -308,12 +344,11 @@ EXPORT_SYMBOL(allocate_resource); | |||
| 308 | * | 344 | * |
| 309 | * Returns 0 on success, -EBUSY if the resource can't be inserted. | 345 | * Returns 0 on success, -EBUSY if the resource can't be inserted. |
| 310 | * | 346 | * |
| 311 | * This function is equivalent of request_resource when no conflict | 347 | * This function is equivalent to request_resource when no conflict |
| 312 | * happens. If a conflict happens, and the conflicting resources | 348 | * happens. If a conflict happens, and the conflicting resources |
| 313 | * entirely fit within the range of the new resource, then the new | 349 | * entirely fit within the range of the new resource, then the new |
| 314 | * resource is inserted and the conflicting resources become childs of | 350 | * resource is inserted and the conflicting resources become children of |
| 315 | * the new resource. Otherwise the new resource becomes the child of | 351 | * the new resource. |
| 316 | * the conflicting resource | ||
| 317 | */ | 352 | */ |
| 318 | int insert_resource(struct resource *parent, struct resource *new) | 353 | int insert_resource(struct resource *parent, struct resource *new) |
| 319 | { | 354 | { |
| @@ -321,20 +356,21 @@ int insert_resource(struct resource *parent, struct resource *new) | |||
| 321 | struct resource *first, *next; | 356 | struct resource *first, *next; |
| 322 | 357 | ||
| 323 | write_lock(&resource_lock); | 358 | write_lock(&resource_lock); |
| 324 | begin: | ||
| 325 | result = 0; | ||
| 326 | first = __request_resource(parent, new); | ||
| 327 | if (!first) | ||
| 328 | goto out; | ||
| 329 | 359 | ||
| 330 | result = -EBUSY; | 360 | for (;; parent = first) { |
| 331 | if (first == parent) | 361 | result = 0; |
| 332 | goto out; | 362 | first = __request_resource(parent, new); |
| 363 | if (!first) | ||
| 364 | goto out; | ||
| 365 | |||
| 366 | result = -EBUSY; | ||
| 367 | if (first == parent) | ||
| 368 | goto out; | ||
| 333 | 369 | ||
| 334 | /* Resource fully contained by the clashing resource? Recurse into it */ | 370 | if ((first->start > new->start) || (first->end < new->end)) |
| 335 | if (first->start <= new->start && first->end >= new->end) { | 371 | break; |
| 336 | parent = first; | 372 | if ((first->start == new->start) && (first->end == new->end)) |
| 337 | goto begin; | 373 | break; |
| 338 | } | 374 | } |
| 339 | 375 | ||
| 340 | for (next = first; ; next = next->sibling) { | 376 | for (next = first; ; next = next->sibling) { |
| @@ -371,17 +407,15 @@ int insert_resource(struct resource *parent, struct resource *new) | |||
| 371 | return result; | 407 | return result; |
| 372 | } | 408 | } |
| 373 | 409 | ||
| 374 | EXPORT_SYMBOL(insert_resource); | ||
| 375 | |||
| 376 | /* | 410 | /* |
| 377 | * Given an existing resource, change its start and size to match the | 411 | * Given an existing resource, change its start and size to match the |
| 378 | * arguments. Returns -EBUSY if it can't fit. Existing children of | 412 | * arguments. Returns -EBUSY if it can't fit. Existing children of |
| 379 | * the resource are assumed to be immutable. | 413 | * the resource are assumed to be immutable. |
| 380 | */ | 414 | */ |
| 381 | int adjust_resource(struct resource *res, unsigned long start, unsigned long size) | 415 | int adjust_resource(struct resource *res, resource_size_t start, resource_size_t size) |
| 382 | { | 416 | { |
| 383 | struct resource *tmp, *parent = res->parent; | 417 | struct resource *tmp, *parent = res->parent; |
| 384 | unsigned long end = start + size - 1; | 418 | resource_size_t end = start + size - 1; |
| 385 | int result = -EBUSY; | 419 | int result = -EBUSY; |
| 386 | 420 | ||
| 387 | write_lock(&resource_lock); | 421 | write_lock(&resource_lock); |
| @@ -428,7 +462,9 @@ EXPORT_SYMBOL(adjust_resource); | |||
| 428 | * | 462 | * |
| 429 | * Release-region releases a matching busy region. | 463 | * Release-region releases a matching busy region. |
| 430 | */ | 464 | */ |
| 431 | struct resource * __request_region(struct resource *parent, unsigned long start, unsigned long n, const char *name) | 465 | struct resource * __request_region(struct resource *parent, |
| 466 | resource_size_t start, resource_size_t n, | ||
| 467 | const char *name) | ||
| 432 | { | 468 | { |
| 433 | struct resource *res = kzalloc(sizeof(*res), GFP_KERNEL); | 469 | struct resource *res = kzalloc(sizeof(*res), GFP_KERNEL); |
| 434 | 470 | ||
| @@ -464,7 +500,8 @@ struct resource * __request_region(struct resource *parent, unsigned long start, | |||
| 464 | 500 | ||
| 465 | EXPORT_SYMBOL(__request_region); | 501 | EXPORT_SYMBOL(__request_region); |
| 466 | 502 | ||
| 467 | int __check_region(struct resource *parent, unsigned long start, unsigned long n) | 503 | int __check_region(struct resource *parent, resource_size_t start, |
| 504 | resource_size_t n) | ||
| 468 | { | 505 | { |
| 469 | struct resource * res; | 506 | struct resource * res; |
| 470 | 507 | ||
| @@ -479,10 +516,11 @@ int __check_region(struct resource *parent, unsigned long start, unsigned long n | |||
| 479 | 516 | ||
| 480 | EXPORT_SYMBOL(__check_region); | 517 | EXPORT_SYMBOL(__check_region); |
| 481 | 518 | ||
| 482 | void __release_region(struct resource *parent, unsigned long start, unsigned long n) | 519 | void __release_region(struct resource *parent, resource_size_t start, |
| 520 | resource_size_t n) | ||
| 483 | { | 521 | { |
| 484 | struct resource **p; | 522 | struct resource **p; |
| 485 | unsigned long end; | 523 | resource_size_t end; |
| 486 | 524 | ||
| 487 | p = &parent->child; | 525 | p = &parent->child; |
| 488 | end = start + n - 1; | 526 | end = start + n - 1; |
| @@ -511,7 +549,9 @@ void __release_region(struct resource *parent, unsigned long start, unsigned lon | |||
| 511 | 549 | ||
| 512 | write_unlock(&resource_lock); | 550 | write_unlock(&resource_lock); |
| 513 | 551 | ||
| 514 | printk(KERN_WARNING "Trying to free nonexistent resource <%08lx-%08lx>\n", start, end); | 552 | printk(KERN_WARNING "Trying to free nonexistent resource " |
| 553 | "<%016llx-%016llx>\n", (unsigned long long)start, | ||
| 554 | (unsigned long long)end); | ||
| 515 | } | 555 | } |
| 516 | 556 | ||
| 517 | EXPORT_SYMBOL(__release_region); | 557 | EXPORT_SYMBOL(__release_region); |
