Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/subr_rman.c
Show First 20 Lines • Show All 153 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
int | int | ||||
rman_manage_region(struct rman *rm, rman_res_t start, rman_res_t end) | rman_manage_region(struct rman *rm, rman_res_t start, rman_res_t end) | ||||
{ | { | ||||
struct resource_i *r, *s, *t; | struct resource_i *r, *s, *t; | ||||
int rv = 0; | int rv = 0; | ||||
DPRINTF(("rman_manage_region: <%s> request: start %#lx, end %#lx\n", | DPRINTF(("rman_manage_region: <%s> request: start %#jx, end %#jx\n", | ||||
rm->rm_descr, start, end)); | rm->rm_descr, start, end)); | ||||
if (start < rm->rm_start || end > rm->rm_end) | if (start < rm->rm_start || end > rm->rm_end) | ||||
return EINVAL; | return EINVAL; | ||||
r = int_alloc_resource(M_NOWAIT); | r = int_alloc_resource(M_NOWAIT); | ||||
if (r == NULL) | if (r == NULL) | ||||
return ENOMEM; | return ENOMEM; | ||||
r->r_start = start; | r->r_start = start; | ||||
r->r_end = end; | r->r_end = end; | ||||
r->r_rm = rm; | r->r_rm = rm; | ||||
mtx_lock(rm->rm_mtx); | mtx_lock(rm->rm_mtx); | ||||
/* Skip entries before us. */ | /* Skip entries before us. */ | ||||
TAILQ_FOREACH(s, &rm->rm_list, r_link) { | TAILQ_FOREACH(s, &rm->rm_list, r_link) { | ||||
if (s->r_end == ULONG_MAX) | if (s->r_end == ~0) | ||||
break; | break; | ||||
if (s->r_end + 1 >= r->r_start) | if (s->r_end + 1 >= r->r_start) | ||||
break; | break; | ||||
} | } | ||||
/* If we ran off the end of the list, insert at the tail. */ | /* If we ran off the end of the list, insert at the tail. */ | ||||
if (s == NULL) { | if (s == NULL) { | ||||
TAILQ_INSERT_TAIL(&rm->rm_list, r, r_link); | TAILQ_INSERT_TAIL(&rm->rm_list, r, r_link); | ||||
▲ Show 20 Lines • Show All 253 Lines • ▼ Show 20 Lines | rman_reserve_resource_bound(struct rman *rm, rman_res_t start, rman_res_t end, | ||||
struct device *dev) | struct device *dev) | ||||
{ | { | ||||
u_int new_rflags; | u_int new_rflags; | ||||
struct resource_i *r, *s, *rv; | struct resource_i *r, *s, *rv; | ||||
rman_res_t rstart, rend, amask, bmask; | rman_res_t rstart, rend, amask, bmask; | ||||
rv = NULL; | rv = NULL; | ||||
DPRINTF(("rman_reserve_resource_bound: <%s> request: [%#lx, %#lx], " | DPRINTF(("rman_reserve_resource_bound: <%s> request: [%#jx, %#jx], " | ||||
"length %#lx, flags %u, device %s\n", rm->rm_descr, start, end, | "length %#jx, flags %x, device %s\n", rm->rm_descr, start, end, | ||||
count, flags, | count, flags, | ||||
dev == NULL ? "<null>" : device_get_nameunit(dev))); | dev == NULL ? "<null>" : device_get_nameunit(dev))); | ||||
KASSERT((flags & RF_FIRSTSHARE) == 0, | KASSERT((flags & RF_FIRSTSHARE) == 0, | ||||
("invalid flags %#x", flags)); | ("invalid flags %#x", flags)); | ||||
new_rflags = (flags & ~RF_FIRSTSHARE) | RF_ALLOCATED; | new_rflags = (flags & ~RF_FIRSTSHARE) | RF_ALLOCATED; | ||||
mtx_lock(rm->rm_mtx); | mtx_lock(rm->rm_mtx); | ||||
r = TAILQ_FIRST(&rm->rm_list); | |||||
if (r == NULL) { | |||||
DPRINTF(("NULL list head\n")); | |||||
} else { | |||||
DPRINTF(("rman_reserve_resource_bound: trying %#jx <%#jx,%#jx>\n", | |||||
r->r_end, start, count-1)); | |||||
} | |||||
for (r = TAILQ_FIRST(&rm->rm_list); | for (r = TAILQ_FIRST(&rm->rm_list); | ||||
r && r->r_end < start + count - 1; | r && r->r_end < start + count - 1; | ||||
r = TAILQ_NEXT(r, r_link)) | r = TAILQ_NEXT(r, r_link)) { | ||||
; | ; | ||||
DPRINTF(("rman_reserve_resource_bound: tried %#jx <%#jx,%#jx>\n", | |||||
r->r_end, start, count-1)); | |||||
} | |||||
if (r == NULL) { | if (r == NULL) { | ||||
DPRINTF(("could not find a region\n")); | DPRINTF(("could not find a region\n")); | ||||
goto out; | goto out; | ||||
} | } | ||||
amask = (1ul << RF_ALIGNMENT(flags)) - 1; | amask = (1ull << RF_ALIGNMENT(flags)) - 1; | ||||
KASSERT(start <= ULONG_MAX - amask, | KASSERT(start <= RM_MAX_END - amask, | ||||
jhb: I think this should be RMAN_MAX_END, not BUS_SPACE_MAXADDR. BUS_SPACE_MAXADDR should (IMO)… | |||||
("start (%#lx) + amask (%#lx) would wrap around", start, amask)); | ("start (%#jx) + amask (%#jx) would wrap around", start, amask)); | ||||
/* If bound is 0, bmask will also be 0 */ | /* If bound is 0, bmask will also be 0 */ | ||||
bmask = ~(bound - 1); | bmask = ~(bound - 1); | ||||
/* | /* | ||||
* First try to find an acceptable totally-unshared region. | * First try to find an acceptable totally-unshared region. | ||||
*/ | */ | ||||
for (s = r; s; s = TAILQ_NEXT(s, r_link)) { | for (s = r; s; s = TAILQ_NEXT(s, r_link)) { | ||||
DPRINTF(("considering [%#lx, %#lx]\n", s->r_start, s->r_end)); | DPRINTF(("considering [%#jx, %#jx]\n", s->r_start, s->r_end)); | ||||
/* | /* | ||||
* The resource list is sorted, so there is no point in | * The resource list is sorted, so there is no point in | ||||
* searching further once r_start is too large. | * searching further once r_start is too large. | ||||
*/ | */ | ||||
if (s->r_start > end - (count - 1)) { | if (s->r_start > end - (count - 1)) { | ||||
DPRINTF(("s->r_start (%#lx) + count - 1> end (%#lx)\n", | DPRINTF(("s->r_start (%#jx) + count - 1> end (%#jx)\n", | ||||
s->r_start, end)); | s->r_start, end)); | ||||
break; | break; | ||||
} | } | ||||
if (s->r_start > ULONG_MAX - amask) { | if (s->r_start > RM_MAX_END - amask) { | ||||
Done Inline ActionsHere as well. jhb: Here as well. | |||||
DPRINTF(("s->r_start (%#lx) + amask (%#lx) too large\n", | DPRINTF(("s->r_start (%#jx) + amask (%#jx) too large\n", | ||||
s->r_start, amask)); | s->r_start, amask)); | ||||
break; | break; | ||||
} | } | ||||
if (s->r_flags & RF_ALLOCATED) { | if (s->r_flags & RF_ALLOCATED) { | ||||
DPRINTF(("region is allocated\n")); | DPRINTF(("region is allocated\n")); | ||||
continue; | continue; | ||||
} | } | ||||
rstart = ulmax(s->r_start, start); | rstart = ummax(s->r_start, start); | ||||
/* | /* | ||||
* Try to find a region by adjusting to boundary and alignment | * Try to find a region by adjusting to boundary and alignment | ||||
* until both conditions are satisfied. This is not an optimal | * until both conditions are satisfied. This is not an optimal | ||||
* algorithm, but in most cases it isn't really bad, either. | * algorithm, but in most cases it isn't really bad, either. | ||||
*/ | */ | ||||
do { | do { | ||||
rstart = (rstart + amask) & ~amask; | rstart = (rstart + amask) & ~amask; | ||||
if (((rstart ^ (rstart + count - 1)) & bmask) != 0) | if (((rstart ^ (rstart + count - 1)) & bmask) != 0) | ||||
rstart += bound - (rstart & ~bmask); | rstart += bound - (rstart & ~bmask); | ||||
} while ((rstart & amask) != 0 && rstart < end && | } while ((rstart & amask) != 0 && rstart < end && | ||||
rstart < s->r_end); | rstart < s->r_end); | ||||
rend = ulmin(s->r_end, ulmax(rstart + count - 1, end)); | rend = ummin(s->r_end, ummax(rstart + count - 1, end)); | ||||
if (rstart > rend) { | if (rstart > rend) { | ||||
DPRINTF(("adjusted start exceeds end\n")); | DPRINTF(("adjusted start exceeds end\n")); | ||||
continue; | continue; | ||||
} | } | ||||
DPRINTF(("truncated region: [%#lx, %#lx]; size %#lx (requested %#lx)\n", | DPRINTF(("truncated region: [%#jx, %#jx]; size %#jx (requested %#jx)\n", | ||||
rstart, rend, (rend - rstart + 1), count)); | rstart, rend, (rend - rstart + 1), count)); | ||||
if ((rend - rstart + 1) >= count) { | if ((rend - rstart + 1) >= count) { | ||||
DPRINTF(("candidate region: [%#lx, %#lx], size %#lx\n", | DPRINTF(("candidate region: [%#jx, %#jx], size %#jx\n", | ||||
rstart, rend, (rend - rstart + 1))); | rstart, rend, (rend - rstart + 1))); | ||||
if ((s->r_end - s->r_start + 1) == count) { | if ((s->r_end - s->r_start + 1) == count) { | ||||
DPRINTF(("candidate region is entire chunk\n")); | DPRINTF(("candidate region is entire chunk\n")); | ||||
rv = s; | rv = s; | ||||
rv->r_flags = new_rflags; | rv->r_flags = new_rflags; | ||||
rv->r_dev = dev; | rv->r_dev = dev; | ||||
goto out; | goto out; | ||||
} | } | ||||
Show All 14 Lines | if ((rend - rstart + 1) >= count) { | ||||
rv->r_start = rstart; | rv->r_start = rstart; | ||||
rv->r_end = rstart + count - 1; | rv->r_end = rstart + count - 1; | ||||
rv->r_flags = new_rflags; | rv->r_flags = new_rflags; | ||||
rv->r_dev = dev; | rv->r_dev = dev; | ||||
rv->r_rm = rm; | rv->r_rm = rm; | ||||
if (s->r_start < rv->r_start && s->r_end > rv->r_end) { | if (s->r_start < rv->r_start && s->r_end > rv->r_end) { | ||||
DPRINTF(("splitting region in three parts: " | DPRINTF(("splitting region in three parts: " | ||||
"[%#lx, %#lx]; [%#lx, %#lx]; [%#lx, %#lx]\n", | "[%#jx, %#jx]; [%#jx, %#jx]; [%#jx, %#jx]\n", | ||||
s->r_start, rv->r_start - 1, | s->r_start, rv->r_start - 1, | ||||
rv->r_start, rv->r_end, | rv->r_start, rv->r_end, | ||||
rv->r_end + 1, s->r_end)); | rv->r_end + 1, s->r_end)); | ||||
/* | /* | ||||
* We are allocating in the middle. | * We are allocating in the middle. | ||||
*/ | */ | ||||
r = int_alloc_resource(M_NOWAIT); | r = int_alloc_resource(M_NOWAIT); | ||||
if (r == NULL) { | if (r == NULL) { | ||||
▲ Show 20 Lines • Show All 470 Lines • ▼ Show 20 Lines | |||||
#ifdef DDB | #ifdef DDB | ||||
static void | static void | ||||
dump_rman_header(struct rman *rm) | dump_rman_header(struct rman *rm) | ||||
{ | { | ||||
if (db_pager_quit) | if (db_pager_quit) | ||||
return; | return; | ||||
db_printf("rman %p: %s (0x%lx-0x%lx full range)\n", | db_printf("rman %p: %s (0x%jx-0x%jx full range)\n", | ||||
rm, rm->rm_descr, rm->rm_start, rm->rm_end); | rm, rm->rm_descr, (rman_res_t)rm->rm_start, (rman_res_t)rm->rm_end); | ||||
} | } | ||||
static void | static void | ||||
dump_rman(struct rman *rm) | dump_rman(struct rman *rm) | ||||
{ | { | ||||
struct resource_i *r; | struct resource_i *r; | ||||
const char *devname; | const char *devname; | ||||
if (db_pager_quit) | if (db_pager_quit) | ||||
return; | return; | ||||
TAILQ_FOREACH(r, &rm->rm_list, r_link) { | TAILQ_FOREACH(r, &rm->rm_list, r_link) { | ||||
if (r->r_dev != NULL) { | if (r->r_dev != NULL) { | ||||
devname = device_get_nameunit(r->r_dev); | devname = device_get_nameunit(r->r_dev); | ||||
if (devname == NULL) | if (devname == NULL) | ||||
devname = "nomatch"; | devname = "nomatch"; | ||||
} else | } else | ||||
devname = NULL; | devname = NULL; | ||||
db_printf(" 0x%lx-0x%lx (RID=%d) ", | db_printf(" 0x%jx-0x%jx (RID=%d) ", | ||||
r->r_start, r->r_end, r->r_rid); | r->r_start, r->r_end, r->r_rid); | ||||
if (devname != NULL) | if (devname != NULL) | ||||
db_printf("(%s)\n", devname); | db_printf("(%s)\n", devname); | ||||
else | else | ||||
db_printf("----\n"); | db_printf("----\n"); | ||||
if (db_pager_quit) | if (db_pager_quit) | ||||
return; | return; | ||||
} | } | ||||
Show All 31 Lines |
I think this should be RMAN_MAX_END, not BUS_SPACE_MAXADDR. BUS_SPACE_MAXADDR should (IMO) only be used by consumers to set the bounds on various rmans. The rman code itself should only operate on opaque rman_res_t values.