1/*
2 * Copyright 1998 Massachusetts Institute of Technology
3 *
4 * Permission to use, copy, modify, and distribute this software and
5 * its documentation for any purpose and without fee is hereby
6 * granted, provided that both the above copyright notice and this
7 * permission notice appear in all copies, that both the above
8 * copyright notice and this permission notice appear in all
--- 12 unchanged lines hidden (view full) ---
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * $Id: subr_rman.c,v 1.6 1999/04/11 02:27:06 eivind Exp $
30 */
31
32/*
33 * The kernel resource manager. This code is responsible for keeping track
34 * of hardware resources which are apportioned out to various drivers.
35 * It does not actually assign those resources, and it is not expected
36 * that end-device drivers will call into this code directly. Rather,
37 * the code which implements the buses that those devices are attached to,
--- 19 unchanged lines hidden (view full) ---
57 * permitted.
58 */
59
60#include <sys/param.h>
61#include <sys/systm.h>
62#include <sys/kernel.h>
63#include <sys/lock.h>
64#include <sys/malloc.h>
65#include <sys/bus.h> /* XXX debugging */
66#include <machine/bus.h>
67#include <sys/rman.h>
68
69static MALLOC_DEFINE(M_RMAN, "rman", "Resource manager");
70
71struct rman_head rman_head;
72#ifndef NULL_SIMPLELOCKS
73static struct simplelock rman_lock; /* mutex to protect rman_head */
74#endif
75static int int_rman_activate_resource(struct rman *rm, struct resource *r,
76 struct resource **whohas);
77static int int_rman_deactivate_resource(struct resource *r);
78static int int_rman_release_resource(struct rman *rm, struct resource *r);
79
80#define CIRCLEQ_TERMCOND(var, head) (var == (void *)&(head))
81
82int
83rman_init(struct rman *rm)
84{
85 static int once;
--- 28 unchanged lines hidden (view full) ---
114int
115rman_manage_region(struct rman *rm, u_long start, u_long end)
116{
117 struct resource *r, *s;
118
119 r = malloc(sizeof *r, M_RMAN, M_NOWAIT);
120 if (r == 0)
121 return ENOMEM;
122 bzero(r, sizeof *r);
123 r->r_sharehead = 0;
124 r->r_start = start;
125 r->r_end = end;
126 r->r_flags = 0;
127 r->r_dev = 0;
128 r->r_rm = rm;
129
130 simple_lock(rm->rm_slock);
--- 15 unchanged lines hidden (view full) ---
146int
147rman_fini(struct rman *rm)
148{
149 struct resource *r;
150
151 simple_lock(rm->rm_slock);
152 for (r = rm->rm_list.cqh_first; !CIRCLEQ_TERMCOND(r, rm->rm_list);
153 r = r->r_link.cqe_next) {
154 if (r->r_flags & RF_ALLOCATED) {
155 simple_unlock(rm->rm_slock);
156 return EBUSY;
157 }
158 }
159
160 /*
161 * There really should only be one of these if we are in this
162 * state and the code is working properly, but it can't hurt.
163 */
164 for (r = rm->rm_list.cqh_first; !CIRCLEQ_TERMCOND(r, rm->rm_list);
165 r = rm->rm_list.cqh_first) {
--- 88 unchanged lines hidden (view full) ---
254 * s->r_end > rstart + count - 1, then
255 * we need to split the region into three pieces
256 * (the middle one will get returned to the user).
257 * Otherwise, we are allocating at either the
258 * beginning or the end of s, so we only need to
259 * split it in two. The first case requires
260 * two new allocations; the second requires but one.
261 */
262 rv = malloc(sizeof *rv, M_RMAN, M_NOWAIT);
263 if (rv == 0)
264 goto out;
265 bzero(rv, sizeof *rv);
266 rv->r_start = rstart;
267 rv->r_end = rstart + count - 1;
268 rv->r_flags = flags | RF_ALLOCATED;
269 rv->r_dev = dev;
270 rv->r_sharehead = 0;
271 rv->r_rm = rm;
272
273 if (s->r_start < rv->r_start && s->r_end > rv->r_end) {
274#ifdef RMAN_DEBUG
275 printf("splitting region in three parts: "
276 "[%#lx, %#lx]; [%#lx, %#lx]; [%#lx, %#lx]\n",
277 s->r_start, rv->r_start - 1,
278 rv->r_start, rv->r_end,
279 rv->r_end + 1, s->r_end);
280#endif /* RMAN_DEBUG */
281 /*
282 * We are allocating in the middle.
283 */
284 r = malloc(sizeof *r, M_RMAN, M_NOWAIT);
285 if (r == 0) {
286 free(rv, M_RMAN);
287 rv = 0;
288 goto out;
289 }
290 bzero(r, sizeof *r);
291 r->r_start = rv->r_end + 1;
292 r->r_end = s->r_end;
293 r->r_flags = s->r_flags;
294 r->r_dev = 0;
295 r->r_sharehead = 0;
296 r->r_rm = rm;
297 s->r_end = rv->r_start - 1;
298 CIRCLEQ_INSERT_AFTER(&rm->rm_list, s, rv,
299 r_link);
300 CIRCLEQ_INSERT_AFTER(&rm->rm_list, rv, r,
301 r_link);
302 } else if (s->r_start == rv->r_start) {
303#ifdef RMAN_DEBUG
304 printf("allocating from the beginning\n");
--- 41 unchanged lines hidden (view full) ---
346 continue;
347 rstart = max(s->r_start, start);
348 rend = min(s->r_end, max(start + count, end));
349 if (s->r_start >= start && s->r_end <= end
350 && (s->r_end - s->r_start + 1) == count) {
351 rv = malloc(sizeof *rv, M_RMAN, M_NOWAIT);
352 if (rv == 0)
353 goto out;
354 bzero(rv, sizeof *rv);
355 rv->r_start = s->r_start;
356 rv->r_end = s->r_end;
357 rv->r_flags = s->r_flags &
358 (RF_ALLOCATED | RF_SHAREABLE | RF_TIMESHARE);
359 rv->r_dev = dev;
360 rv->r_rm = rm;
361 if (s->r_sharehead == 0) {
362 s->r_sharehead = malloc(sizeof *s->r_sharehead,
363 M_RMAN, M_NOWAIT);
364 if (s->r_sharehead == 0) {
365 free(rv, M_RMAN);
366 rv = 0;
367 goto out;
368 }
369 bzero(s->r_sharehead, sizeof *s->r_sharehead);
370 LIST_INIT(s->r_sharehead);
371 LIST_INSERT_HEAD(s->r_sharehead, s,
372 r_sharelink);
373 s->r_flags |= RF_FIRSTSHARE;
374 }
375 rv->r_sharehead = s->r_sharehead;
376 LIST_INSERT_HEAD(s->r_sharehead, rv, r_sharelink);
377 goto out;
--- 79 unchanged lines hidden (view full) ---
457 struct resource *whohas;
458 struct rman *rm;
459
460 rm = r->r_rm;
461 for (;;) {
462 simple_lock(rm->rm_slock);
463 rv = int_rman_activate_resource(rm, r, &whohas);
464 if (rv != EBUSY)
465 return (rv); /* returns with simplelock */
466
467 if (r->r_sharehead == 0)
468 panic("rman_await_resource");
469 /*
470 * splhigh hopefully will prevent a race between
471 * simple_unlock and tsleep where a process
472 * could conceivably get in and release the resource
473 * before we have a chance to sleep on it.
--- 6 unchanged lines hidden (view full) ---
480 splx(s);
481 return rv;
482 }
483 simple_lock(rm->rm_slock);
484 splx(s);
485 }
486}
487
488static int
489int_rman_deactivate_resource(struct resource *r)
490{
491 struct rman *rm;
492
493 rm = r->r_rm;
494 r->r_flags &= ~RF_ACTIVE;
495 if (r->r_flags & RF_WANTED) {
496 r->r_flags &= ~RF_WANTED;
497 wakeup(r->r_sharehead);
498 }
499 return 0;
500}
501
502int
503rman_deactivate_resource(struct resource *r)
504{
505 struct rman *rm;
506
507 rm = r->r_rm;
508 simple_lock(rm->rm_slock);
509 int_rman_deactivate_resource(r);
510 simple_unlock(rm->rm_slock);
511 return 0;
512}
513
514static int
515int_rman_release_resource(struct rman *rm, struct resource *r)
516{
517 struct resource *s, *t;
518
519 if (r->r_flags & RF_ACTIVE)
520 int_rman_deactivate_resource(r);
521
522 /*
523 * Check for a sharing list first. If there is one, then we don't
524 * have to think as hard.
525 */
526 if (r->r_sharehead) {
527 /*
528 * If a sharing list exists, then we know there are at
--- 84 unchanged lines hidden ---
2 * Copyright 1998 Massachusetts Institute of Technology
3 *
4 * Permission to use, copy, modify, and distribute this software and
5 * its documentation for any purpose and without fee is hereby
6 * granted, provided that both the above copyright notice and this
7 * permission notice appear in all copies, that both the above
8 * copyright notice and this permission notice appear in all
--- 12 unchanged lines hidden (view full) ---
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * $Id: subr_rman.c,v 1.6 1999/04/11 02:27:06 eivind Exp $
30 */
31
32/*
33 * The kernel resource manager. This code is responsible for keeping track
34 * of hardware resources which are apportioned out to various drivers.
35 * It does not actually assign those resources, and it is not expected
36 * that end-device drivers will call into this code directly. Rather,
37 * the code which implements the buses that those devices are attached to,
--- 19 unchanged lines hidden (view full) ---
57 * permitted.
58 */
59
60#include <sys/param.h>
61#include <sys/systm.h>
62#include <sys/kernel.h>
63#include <sys/lock.h>
64#include <sys/malloc.h>
65#include <sys/bus.h> /* XXX debugging */
66#include <machine/bus.h>
67#include <sys/rman.h>
68
69static MALLOC_DEFINE(M_RMAN, "rman", "Resource manager");
70
71struct rman_head rman_head;
72#ifndef NULL_SIMPLELOCKS
73static struct simplelock rman_lock; /* mutex to protect rman_head */
74#endif
75static int int_rman_activate_resource(struct rman *rm, struct resource *r,
76 struct resource **whohas);
77static int int_rman_deactivate_resource(struct resource *r);
78static int int_rman_release_resource(struct rman *rm, struct resource *r);
79
80#define CIRCLEQ_TERMCOND(var, head) (var == (void *)&(head))
81
82int
83rman_init(struct rman *rm)
84{
85 static int once;
--- 28 unchanged lines hidden (view full) ---
114int
115rman_manage_region(struct rman *rm, u_long start, u_long end)
116{
117 struct resource *r, *s;
118
119 r = malloc(sizeof *r, M_RMAN, M_NOWAIT);
120 if (r == 0)
121 return ENOMEM;
122 bzero(r, sizeof *r);
123 r->r_sharehead = 0;
124 r->r_start = start;
125 r->r_end = end;
126 r->r_flags = 0;
127 r->r_dev = 0;
128 r->r_rm = rm;
129
130 simple_lock(rm->rm_slock);
--- 15 unchanged lines hidden (view full) ---
146int
147rman_fini(struct rman *rm)
148{
149 struct resource *r;
150
151 simple_lock(rm->rm_slock);
152 for (r = rm->rm_list.cqh_first; !CIRCLEQ_TERMCOND(r, rm->rm_list);
153 r = r->r_link.cqe_next) {
154 if (r->r_flags & RF_ALLOCATED) {
155 simple_unlock(rm->rm_slock);
156 return EBUSY;
157 }
158 }
159
160 /*
161 * There really should only be one of these if we are in this
162 * state and the code is working properly, but it can't hurt.
163 */
164 for (r = rm->rm_list.cqh_first; !CIRCLEQ_TERMCOND(r, rm->rm_list);
165 r = rm->rm_list.cqh_first) {
--- 88 unchanged lines hidden (view full) ---
254 * s->r_end > rstart + count - 1, then
255 * we need to split the region into three pieces
256 * (the middle one will get returned to the user).
257 * Otherwise, we are allocating at either the
258 * beginning or the end of s, so we only need to
259 * split it in two. The first case requires
260 * two new allocations; the second requires but one.
261 */
262 rv = malloc(sizeof *rv, M_RMAN, M_NOWAIT);
263 if (rv == 0)
264 goto out;
265 bzero(rv, sizeof *rv);
266 rv->r_start = rstart;
267 rv->r_end = rstart + count - 1;
268 rv->r_flags = flags | RF_ALLOCATED;
269 rv->r_dev = dev;
270 rv->r_sharehead = 0;
271 rv->r_rm = rm;
272
273 if (s->r_start < rv->r_start && s->r_end > rv->r_end) {
274#ifdef RMAN_DEBUG
275 printf("splitting region in three parts: "
276 "[%#lx, %#lx]; [%#lx, %#lx]; [%#lx, %#lx]\n",
277 s->r_start, rv->r_start - 1,
278 rv->r_start, rv->r_end,
279 rv->r_end + 1, s->r_end);
280#endif /* RMAN_DEBUG */
281 /*
282 * We are allocating in the middle.
283 */
284 r = malloc(sizeof *r, M_RMAN, M_NOWAIT);
285 if (r == 0) {
286 free(rv, M_RMAN);
287 rv = 0;
288 goto out;
289 }
290 bzero(r, sizeof *r);
291 r->r_start = rv->r_end + 1;
292 r->r_end = s->r_end;
293 r->r_flags = s->r_flags;
294 r->r_dev = 0;
295 r->r_sharehead = 0;
296 r->r_rm = rm;
297 s->r_end = rv->r_start - 1;
298 CIRCLEQ_INSERT_AFTER(&rm->rm_list, s, rv,
299 r_link);
300 CIRCLEQ_INSERT_AFTER(&rm->rm_list, rv, r,
301 r_link);
302 } else if (s->r_start == rv->r_start) {
303#ifdef RMAN_DEBUG
304 printf("allocating from the beginning\n");
--- 41 unchanged lines hidden (view full) ---
346 continue;
347 rstart = max(s->r_start, start);
348 rend = min(s->r_end, max(start + count, end));
349 if (s->r_start >= start && s->r_end <= end
350 && (s->r_end - s->r_start + 1) == count) {
351 rv = malloc(sizeof *rv, M_RMAN, M_NOWAIT);
352 if (rv == 0)
353 goto out;
354 bzero(rv, sizeof *rv);
355 rv->r_start = s->r_start;
356 rv->r_end = s->r_end;
357 rv->r_flags = s->r_flags &
358 (RF_ALLOCATED | RF_SHAREABLE | RF_TIMESHARE);
359 rv->r_dev = dev;
360 rv->r_rm = rm;
361 if (s->r_sharehead == 0) {
362 s->r_sharehead = malloc(sizeof *s->r_sharehead,
363 M_RMAN, M_NOWAIT);
364 if (s->r_sharehead == 0) {
365 free(rv, M_RMAN);
366 rv = 0;
367 goto out;
368 }
369 bzero(s->r_sharehead, sizeof *s->r_sharehead);
370 LIST_INIT(s->r_sharehead);
371 LIST_INSERT_HEAD(s->r_sharehead, s,
372 r_sharelink);
373 s->r_flags |= RF_FIRSTSHARE;
374 }
375 rv->r_sharehead = s->r_sharehead;
376 LIST_INSERT_HEAD(s->r_sharehead, rv, r_sharelink);
377 goto out;
--- 79 unchanged lines hidden (view full) ---
457 struct resource *whohas;
458 struct rman *rm;
459
460 rm = r->r_rm;
461 for (;;) {
462 simple_lock(rm->rm_slock);
463 rv = int_rman_activate_resource(rm, r, &whohas);
464 if (rv != EBUSY)
465 return (rv); /* returns with simplelock */
466
467 if (r->r_sharehead == 0)
468 panic("rman_await_resource");
469 /*
470 * splhigh hopefully will prevent a race between
471 * simple_unlock and tsleep where a process
472 * could conceivably get in and release the resource
473 * before we have a chance to sleep on it.
--- 6 unchanged lines hidden (view full) ---
480 splx(s);
481 return rv;
482 }
483 simple_lock(rm->rm_slock);
484 splx(s);
485 }
486}
487
488static int
489int_rman_deactivate_resource(struct resource *r)
490{
491 struct rman *rm;
492
493 rm = r->r_rm;
494 r->r_flags &= ~RF_ACTIVE;
495 if (r->r_flags & RF_WANTED) {
496 r->r_flags &= ~RF_WANTED;
497 wakeup(r->r_sharehead);
498 }
499 return 0;
500}
501
502int
503rman_deactivate_resource(struct resource *r)
504{
505 struct rman *rm;
506
507 rm = r->r_rm;
508 simple_lock(rm->rm_slock);
509 int_rman_deactivate_resource(r);
510 simple_unlock(rm->rm_slock);
511 return 0;
512}
513
514static int
515int_rman_release_resource(struct rman *rm, struct resource *r)
516{
517 struct resource *s, *t;
518
519 if (r->r_flags & RF_ACTIVE)
520 int_rman_deactivate_resource(r);
521
522 /*
523 * Check for a sharing list first. If there is one, then we don't
524 * have to think as hard.
525 */
526 if (r->r_sharehead) {
527 /*
528 * If a sharing list exists, then we know there are at
--- 84 unchanged lines hidden ---