Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/subr_rman.c
Context not available. | |||||
TAILQ_ENTRY(resource_i) r_link; | TAILQ_ENTRY(resource_i) r_link; | ||||
LIST_ENTRY(resource_i) r_sharelink; | LIST_ENTRY(resource_i) r_sharelink; | ||||
LIST_HEAD(, resource_i) *r_sharehead; | LIST_HEAD(, resource_i) *r_sharehead; | ||||
u_long r_start; /* index of the first entry in this resource */ | rman_res_t r_start; /* index of the first entry in this resource */ | ||||
u_long r_end; /* index of the last entry (inclusive) */ | rman_res_t r_end; /* index of the last entry (inclusive) */ | ||||
u_int r_flags; | u_int r_flags; | ||||
void *r_virtual; /* virtual address of this resource */ | void *r_virtual; /* virtual address of this resource */ | ||||
struct device *r_dev; /* device which has allocated this resource */ | struct device *r_dev; /* device which has allocated this resource */ | ||||
Context not available. | |||||
} | } | ||||
if (rm->rm_start == 0 && rm->rm_end == 0) | if (rm->rm_start == 0 && rm->rm_end == 0) | ||||
rm->rm_end = ~0ul; | rm->rm_end = RM_MAX_END; | ||||
if (rm->rm_type == RMAN_UNINIT) | if (rm->rm_type == RMAN_UNINIT) | ||||
panic("rman_init"); | panic("rman_init"); | ||||
if (rm->rm_type == RMAN_GAUGE) | if (rm->rm_type == RMAN_GAUGE) | ||||
Context not available. | |||||
} | } | ||||
int | int | ||||
rman_manage_region(struct rman *rm, u_long start, u_long 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; | ||||
Context not available. | |||||
/* 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 == RM_MAX_END) | ||||
break; | break; | ||||
if (s->r_end + 1 >= r->r_start) | if (s->r_end + 1 >= r->r_start) | ||||
break; | break; | ||||
Context not available. | |||||
} | } | ||||
int | int | ||||
rman_first_free_region(struct rman *rm, u_long *start, u_long *end) | rman_first_free_region(struct rman *rm, rman_res_t *start, rman_res_t *end) | ||||
{ | { | ||||
struct resource_i *r; | struct resource_i *r; | ||||
Context not available. | |||||
} | } | ||||
int | int | ||||
rman_last_free_region(struct rman *rm, u_long *start, u_long *end) | rman_last_free_region(struct rman *rm, rman_res_t *start, rman_res_t *end) | ||||
{ | { | ||||
struct resource_i *r; | struct resource_i *r; | ||||
Context not available. | |||||
/* Shrink or extend one or both ends of an allocated resource. */ | /* Shrink or extend one or both ends of an allocated resource. */ | ||||
int | int | ||||
rman_adjust_resource(struct resource *rr, u_long start, u_long end) | rman_adjust_resource(struct resource *rr, rman_res_t start, rman_res_t end) | ||||
{ | { | ||||
struct resource_i *r, *s, *t, *new; | struct resource_i *r, *s, *t, *new; | ||||
struct rman *rm; | struct rman *rm; | ||||
Context not available. | |||||
#define SHARE_TYPE(f) (f & (RF_SHAREABLE | RF_PREFETCHABLE)) | #define SHARE_TYPE(f) (f & (RF_SHAREABLE | RF_PREFETCHABLE)) | ||||
struct resource * | struct resource * | ||||
rman_reserve_resource_bound(struct rman *rm, u_long start, u_long end, | rman_reserve_resource_bound(struct rman *rm, rman_res_t start, rman_res_t end, | ||||
u_long count, u_long bound, u_int flags, | rman_res_t count, rman_res_t bound, u_int flags, | ||||
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; | ||||
u_long 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, | ||||
Context not available. | |||||
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")); | ||||
Context not available. | |||||
goto out; | goto out; | ||||
} | } | ||||
amask = (1ul << RF_ALIGNMENT(flags)) - 1; | amask = (1ull << RF_ALIGNMENT(flags)) - 1; | ||||
KASSERT(start <= ULONG_MAX - amask, | KASSERT(start <= BUS_SPACE_MAXADDR - 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); | ||||
Context not available. | |||||
* 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 > BUS_SPACE_MAXADDR - amask) { | ||||
DPRINTF(("s->r_start (%#lx) + amask (%#lx) too large\n", | DPRINTF(("s->r_start (%#jx) + amask (%#jx) too large\n", | ||||
Done Inline ActionsHere as well. jhb: Here as well. | |||||
s->r_start, amask)); | s->r_start, amask)); | ||||
break; | break; | ||||
} | } | ||||
Context not available. | |||||
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 | ||||
Context not available. | |||||
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")); | ||||
Context not available. | |||||
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)); | ||||
Context not available. | |||||
} | } | ||||
struct resource * | struct resource * | ||||
rman_reserve_resource(struct rman *rm, u_long start, u_long end, u_long count, | rman_reserve_resource(struct rman *rm, rman_res_t start, rman_res_t end, | ||||
u_int flags, struct device *dev) | rman_res_t count, u_int flags, struct device *dev) | ||||
{ | { | ||||
return (rman_reserve_resource_bound(rm, start, end, count, 0, flags, | return (rman_reserve_resource_bound(rm, start, end, count, 0, flags, | ||||
Context not available. | |||||
} | } | ||||
void | void | ||||
rman_set_start(struct resource *r, u_long start) | rman_set_start(struct resource *r, rman_res_t start) | ||||
{ | { | ||||
r->__r_i->r_start = start; | r->__r_i->r_start = start; | ||||
} | } | ||||
u_long | rman_res_t | ||||
rman_get_start(struct resource *r) | rman_get_start(struct resource *r) | ||||
{ | { | ||||
Context not available. | |||||
} | } | ||||
void | void | ||||
rman_set_end(struct resource *r, u_long end) | rman_set_end(struct resource *r, rman_res_t end) | ||||
{ | { | ||||
r->__r_i->r_end = end; | r->__r_i->r_end = end; | ||||
} | } | ||||
u_long | rman_res_t | ||||
rman_get_end(struct resource *r) | rman_get_end(struct resource *r) | ||||
{ | { | ||||
Context not available. | |||||
return (r->__r_i->r_end); | return (r->__r_i->r_end); | ||||
} | } | ||||
u_long | rman_res_t | ||||
rman_get_size(struct resource *r) | rman_get_size(struct resource *r) | ||||
{ | { | ||||
Context not available. | |||||
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 | ||||
Context not available. | |||||
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); | ||||
Context not available. |
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.