aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/resource.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/resource.c')
-rw-r--r--kernel/resource.c126
1 files changed, 109 insertions, 17 deletions
diff --git a/kernel/resource.c b/kernel/resource.c
index af96c1e4b54b..7b36976e5dea 100644
--- a/kernel/resource.c
+++ b/kernel/resource.c
@@ -15,6 +15,7 @@
15#include <linux/spinlock.h> 15#include <linux/spinlock.h>
16#include <linux/fs.h> 16#include <linux/fs.h>
17#include <linux/proc_fs.h> 17#include <linux/proc_fs.h>
18#include <linux/sched.h>
18#include <linux/seq_file.h> 19#include <linux/seq_file.h>
19#include <linux/device.h> 20#include <linux/device.h>
20#include <linux/pfn.h> 21#include <linux/pfn.h>
@@ -188,20 +189,65 @@ static int __release_resource(struct resource *old)
188 return -EINVAL; 189 return -EINVAL;
189} 190}
190 191
192static void __release_child_resources(struct resource *r)
193{
194 struct resource *tmp, *p;
195 resource_size_t size;
196
197 p = r->child;
198 r->child = NULL;
199 while (p) {
200 tmp = p;
201 p = p->sibling;
202
203 tmp->parent = NULL;
204 tmp->sibling = NULL;
205 __release_child_resources(tmp);
206
207 printk(KERN_DEBUG "release child resource %pR\n", tmp);
208 /* need to restore size, and keep flags */
209 size = resource_size(tmp);
210 tmp->start = 0;
211 tmp->end = size - 1;
212 }
213}
214
215void release_child_resources(struct resource *r)
216{
217 write_lock(&resource_lock);
218 __release_child_resources(r);
219 write_unlock(&resource_lock);
220}
221
191/** 222/**
192 * request_resource - request and reserve an I/O or memory resource 223 * request_resource_conflict - request and reserve an I/O or memory resource
193 * @root: root resource descriptor 224 * @root: root resource descriptor
194 * @new: resource descriptor desired by caller 225 * @new: resource descriptor desired by caller
195 * 226 *
196 * Returns 0 for success, negative error code on error. 227 * Returns 0 for success, conflict resource on error.
197 */ 228 */
198int request_resource(struct resource *root, struct resource *new) 229struct resource *request_resource_conflict(struct resource *root, struct resource *new)
199{ 230{
200 struct resource *conflict; 231 struct resource *conflict;
201 232
202 write_lock(&resource_lock); 233 write_lock(&resource_lock);
203 conflict = __request_resource(root, new); 234 conflict = __request_resource(root, new);
204 write_unlock(&resource_lock); 235 write_unlock(&resource_lock);
236 return conflict;
237}
238
239/**
240 * request_resource - request and reserve an I/O or memory resource
241 * @root: root resource descriptor
242 * @new: resource descriptor desired by caller
243 *
244 * Returns 0 for success, negative error code on error.
245 */
246int request_resource(struct resource *root, struct resource *new)
247{
248 struct resource *conflict;
249
250 conflict = request_resource_conflict(root, new);
205 return conflict ? -EBUSY : 0; 251 return conflict ? -EBUSY : 0;
206} 252}
207 253
@@ -274,7 +320,7 @@ int walk_system_ram_range(unsigned long start_pfn, unsigned long nr_pages,
274 void *arg, int (*func)(unsigned long, unsigned long, void *)) 320 void *arg, int (*func)(unsigned long, unsigned long, void *))
275{ 321{
276 struct resource res; 322 struct resource res;
277 unsigned long pfn, len; 323 unsigned long pfn, end_pfn;
278 u64 orig_end; 324 u64 orig_end;
279 int ret = -1; 325 int ret = -1;
280 326
@@ -284,9 +330,10 @@ int walk_system_ram_range(unsigned long start_pfn, unsigned long nr_pages,
284 orig_end = res.end; 330 orig_end = res.end;
285 while ((res.start < res.end) && 331 while ((res.start < res.end) &&
286 (find_next_system_ram(&res, "System RAM") >= 0)) { 332 (find_next_system_ram(&res, "System RAM") >= 0)) {
287 pfn = (unsigned long)(res.start >> PAGE_SHIFT); 333 pfn = (res.start + PAGE_SIZE - 1) >> PAGE_SHIFT;
288 len = (unsigned long)((res.end + 1 - res.start) >> PAGE_SHIFT); 334 end_pfn = (res.end + 1) >> PAGE_SHIFT;
289 ret = (*func)(pfn, len, arg); 335 if (end_pfn > pfn)
336 ret = (*func)(pfn, end_pfn - pfn, arg);
290 if (ret) 337 if (ret)
291 break; 338 break;
292 res.start = res.end + 1; 339 res.start = res.end + 1;
@@ -297,14 +344,29 @@ int walk_system_ram_range(unsigned long start_pfn, unsigned long nr_pages,
297 344
298#endif 345#endif
299 346
347static int __is_ram(unsigned long pfn, unsigned long nr_pages, void *arg)
348{
349 return 1;
350}
351/*
352 * This generic page_is_ram() returns true if specified address is
353 * registered as "System RAM" in iomem_resource list.
354 */
355int __weak page_is_ram(unsigned long pfn)
356{
357 return walk_system_ram_range(pfn, 1, NULL, __is_ram) == 1;
358}
359
300/* 360/*
301 * Find empty slot in the resource tree given range and alignment. 361 * Find empty slot in the resource tree given range and alignment.
302 */ 362 */
303static int find_resource(struct resource *root, struct resource *new, 363static int find_resource(struct resource *root, struct resource *new,
304 resource_size_t size, resource_size_t min, 364 resource_size_t size, resource_size_t min,
305 resource_size_t max, resource_size_t align, 365 resource_size_t max, resource_size_t align,
306 void (*alignf)(void *, struct resource *, 366 resource_size_t (*alignf)(void *,
307 resource_size_t, resource_size_t), 367 const struct resource *,
368 resource_size_t,
369 resource_size_t),
308 void *alignf_data) 370 void *alignf_data)
309{ 371{
310 struct resource *this = root->child; 372 struct resource *this = root->child;
@@ -330,7 +392,7 @@ static int find_resource(struct resource *root, struct resource *new,
330 tmp.end = max; 392 tmp.end = max;
331 tmp.start = ALIGN(tmp.start, align); 393 tmp.start = ALIGN(tmp.start, align);
332 if (alignf) 394 if (alignf)
333 alignf(alignf_data, &tmp, size, align); 395 tmp.start = alignf(alignf_data, &tmp, size, align);
334 if (tmp.start < tmp.end && tmp.end - tmp.start >= size - 1) { 396 if (tmp.start < tmp.end && tmp.end - tmp.start >= size - 1) {
335 new->start = tmp.start; 397 new->start = tmp.start;
336 new->end = tmp.start + size - 1; 398 new->end = tmp.start + size - 1;
@@ -358,8 +420,10 @@ static int find_resource(struct resource *root, struct resource *new,
358int allocate_resource(struct resource *root, struct resource *new, 420int allocate_resource(struct resource *root, struct resource *new,
359 resource_size_t size, resource_size_t min, 421 resource_size_t size, resource_size_t min,
360 resource_size_t max, resource_size_t align, 422 resource_size_t max, resource_size_t align,
361 void (*alignf)(void *, struct resource *, 423 resource_size_t (*alignf)(void *,
362 resource_size_t, resource_size_t), 424 const struct resource *,
425 resource_size_t,
426 resource_size_t),
363 void *alignf_data) 427 void *alignf_data)
364{ 428{
365 int err; 429 int err;
@@ -426,25 +490,40 @@ static struct resource * __insert_resource(struct resource *parent, struct resou
426} 490}
427 491
428/** 492/**
429 * insert_resource - Inserts a resource in the resource tree 493 * insert_resource_conflict - Inserts resource in the resource tree
430 * @parent: parent of the new resource 494 * @parent: parent of the new resource
431 * @new: new resource to insert 495 * @new: new resource to insert
432 * 496 *
433 * Returns 0 on success, -EBUSY if the resource can't be inserted. 497 * Returns 0 on success, conflict resource if the resource can't be inserted.
434 * 498 *
435 * This function is equivalent to request_resource when no conflict 499 * This function is equivalent to request_resource_conflict when no conflict
436 * happens. If a conflict happens, and the conflicting resources 500 * happens. If a conflict happens, and the conflicting resources
437 * entirely fit within the range of the new resource, then the new 501 * entirely fit within the range of the new resource, then the new
438 * resource is inserted and the conflicting resources become children of 502 * resource is inserted and the conflicting resources become children of
439 * the new resource. 503 * the new resource.
440 */ 504 */
441int insert_resource(struct resource *parent, struct resource *new) 505struct resource *insert_resource_conflict(struct resource *parent, struct resource *new)
442{ 506{
443 struct resource *conflict; 507 struct resource *conflict;
444 508
445 write_lock(&resource_lock); 509 write_lock(&resource_lock);
446 conflict = __insert_resource(parent, new); 510 conflict = __insert_resource(parent, new);
447 write_unlock(&resource_lock); 511 write_unlock(&resource_lock);
512 return conflict;
513}
514
515/**
516 * insert_resource - Inserts a resource in the resource tree
517 * @parent: parent of the new resource
518 * @new: new resource to insert
519 *
520 * Returns 0 on success, -EBUSY if the resource can't be inserted.
521 */
522int insert_resource(struct resource *parent, struct resource *new)
523{
524 struct resource *conflict;
525
526 conflict = insert_resource_conflict(parent, new);
448 return conflict ? -EBUSY : 0; 527 return conflict ? -EBUSY : 0;
449} 528}
450 529
@@ -603,6 +682,8 @@ resource_size_t resource_alignment(struct resource *res)
603 * release_region releases a matching busy region. 682 * release_region releases a matching busy region.
604 */ 683 */
605 684
685static DECLARE_WAIT_QUEUE_HEAD(muxed_resource_wait);
686
606/** 687/**
607 * __request_region - create a new busy resource region 688 * __request_region - create a new busy resource region
608 * @parent: parent resource descriptor 689 * @parent: parent resource descriptor
@@ -615,6 +696,7 @@ struct resource * __request_region(struct resource *parent,
615 resource_size_t start, resource_size_t n, 696 resource_size_t start, resource_size_t n,
616 const char *name, int flags) 697 const char *name, int flags)
617{ 698{
699 DECLARE_WAITQUEUE(wait, current);
618 struct resource *res = kzalloc(sizeof(*res), GFP_KERNEL); 700 struct resource *res = kzalloc(sizeof(*res), GFP_KERNEL);
619 701
620 if (!res) 702 if (!res)
@@ -639,7 +721,15 @@ struct resource * __request_region(struct resource *parent,
639 if (!(conflict->flags & IORESOURCE_BUSY)) 721 if (!(conflict->flags & IORESOURCE_BUSY))
640 continue; 722 continue;
641 } 723 }
642 724 if (conflict->flags & flags & IORESOURCE_MUXED) {
725 add_wait_queue(&muxed_resource_wait, &wait);
726 write_unlock(&resource_lock);
727 set_current_state(TASK_UNINTERRUPTIBLE);
728 schedule();
729 remove_wait_queue(&muxed_resource_wait, &wait);
730 write_lock(&resource_lock);
731 continue;
732 }
643 /* Uhhuh, that didn't work out.. */ 733 /* Uhhuh, that didn't work out.. */
644 kfree(res); 734 kfree(res);
645 res = NULL; 735 res = NULL;
@@ -713,6 +803,8 @@ void __release_region(struct resource *parent, resource_size_t start,
713 break; 803 break;
714 *p = res->sibling; 804 *p = res->sibling;
715 write_unlock(&resource_lock); 805 write_unlock(&resource_lock);
806 if (res->flags & IORESOURCE_MUXED)
807 wake_up(&muxed_resource_wait);
716 kfree(res); 808 kfree(res);
717 return; 809 return;
718 } 810 }