mirror of
https://github.com/freebsd/freebsd-src
synced 2024-07-23 19:28:36 +00:00
Add a rman_reserve_resource_bound() function that takes an additional
argument specifying the boundary for the resource allocation. Use ulmin()/ulmax() instead of min()/max() in some places to correctly deal with the u_long resource range specifications.
This commit is contained in:
parent
70527a680b
commit
13fb665772
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=88372
|
@ -175,12 +175,13 @@ rman_fini(struct rman *rm)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct resource *
|
struct resource *
|
||||||
rman_reserve_resource(struct rman *rm, u_long start, u_long end, u_long count,
|
rman_reserve_resource_bound(struct rman *rm, u_long start, u_long end,
|
||||||
u_int flags, struct device *dev)
|
u_long count, u_long bound, u_int flags,
|
||||||
|
struct device *dev)
|
||||||
{
|
{
|
||||||
u_int want_activate;
|
u_int want_activate;
|
||||||
struct resource *r, *s, *rv;
|
struct resource *r, *s, *rv;
|
||||||
u_long rstart, rend;
|
u_long rstart, rend, amask, bmask;
|
||||||
|
|
||||||
rv = 0;
|
rv = 0;
|
||||||
|
|
||||||
|
@ -202,6 +203,9 @@ rman_reserve_resource(struct rman *rm, u_long start, u_long end, u_long count,
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
amask = (1ul << RF_ALIGNMENT(flags)) - 1;
|
||||||
|
/* If bound is 0, bmask will also be 0 */
|
||||||
|
bmask = ~(bound - 1);
|
||||||
/*
|
/*
|
||||||
* First try to find an acceptable totally-unshared region.
|
* First try to find an acceptable totally-unshared region.
|
||||||
*/
|
*/
|
||||||
|
@ -215,10 +219,19 @@ rman_reserve_resource(struct rman *rm, u_long start, u_long end, u_long count,
|
||||||
DPRINTF(("region is allocated\n"));
|
DPRINTF(("region is allocated\n"));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
rstart = max(s->r_start, start);
|
rstart = ulmax(s->r_start, start);
|
||||||
rstart = (rstart + ((1ul << RF_ALIGNMENT(flags))) - 1) &
|
/*
|
||||||
~((1ul << RF_ALIGNMENT(flags)) - 1);
|
* Try to find a region by adjusting to boundary and alignment
|
||||||
rend = min(s->r_end, max(rstart + count, end));
|
* until both conditions are satisfied. This is not an optimal
|
||||||
|
* algorithm, but in most cases it isn't really bad, either.
|
||||||
|
*/
|
||||||
|
do {
|
||||||
|
rstart = (rstart + amask) & ~amask;
|
||||||
|
if (((rstart ^ (rstart + count)) & bmask) != 0)
|
||||||
|
rstart += bound - (rstart & ~bmask);
|
||||||
|
} while ((rstart & amask) != 0 && rstart < end &&
|
||||||
|
rstart < s->r_end);
|
||||||
|
rend = ulmin(s->r_end, ulmax(rstart + count, end));
|
||||||
DPRINTF(("truncated region: [%#lx, %#lx]; size %#lx (requested %#lx)\n",
|
DPRINTF(("truncated region: [%#lx, %#lx]; size %#lx (requested %#lx)\n",
|
||||||
rstart, rend, (rend - rstart + 1), count));
|
rstart, rend, (rend - rstart + 1), count));
|
||||||
|
|
||||||
|
@ -313,10 +326,12 @@ rman_reserve_resource(struct rman *rm, u_long start, u_long end, u_long count,
|
||||||
break;
|
break;
|
||||||
if ((s->r_flags & flags) != flags)
|
if ((s->r_flags & flags) != flags)
|
||||||
continue;
|
continue;
|
||||||
rstart = max(s->r_start, start);
|
rstart = ulmax(s->r_start, start);
|
||||||
rend = min(s->r_end, max(start + count, end));
|
rend = ulmin(s->r_end, ulmax(start + count, end));
|
||||||
if (s->r_start >= start && s->r_end <= end
|
if (s->r_start >= start && s->r_end <= end
|
||||||
&& (s->r_end - s->r_start + 1) == count) {
|
&& (s->r_end - s->r_start + 1) == count &&
|
||||||
|
(s->r_start & amask) == 0 &&
|
||||||
|
((s->r_start ^ s->r_end) & bmask) == 0) {
|
||||||
rv = malloc(sizeof *rv, M_RMAN, M_NOWAIT | M_ZERO);
|
rv = malloc(sizeof *rv, M_RMAN, M_NOWAIT | M_ZERO);
|
||||||
if (rv == 0)
|
if (rv == 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -368,6 +383,15 @@ rman_reserve_resource(struct rman *rm, u_long start, u_long end, u_long count,
|
||||||
return (rv);
|
return (rv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct resource *
|
||||||
|
rman_reserve_resource(struct rman *rm, u_long start, u_long end, u_long count,
|
||||||
|
u_int flags, struct device *dev)
|
||||||
|
{
|
||||||
|
|
||||||
|
return (rman_reserve_resource_bound(rm, start, end, count, 0, flags,
|
||||||
|
dev));
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
int_rman_activate_resource(struct rman *rm, struct resource *r,
|
int_rman_activate_resource(struct rman *rm, struct resource *r,
|
||||||
struct resource **whohas)
|
struct resource **whohas)
|
||||||
|
@ -575,7 +599,7 @@ rman_make_alignment_flags(uint32_t size)
|
||||||
* Find the hightest bit set, and add one if more than one bit
|
* Find the hightest bit set, and add one if more than one bit
|
||||||
* set. We're effectively computing the ceil(log2(size)) here.
|
* set. We're effectively computing the ceil(log2(size)) here.
|
||||||
*/
|
*/
|
||||||
for (i = 32; i > 0; i--)
|
for (i = 31; i > 0; i--)
|
||||||
if ((1 << i) & size)
|
if ((1 << i) & size)
|
||||||
break;
|
break;
|
||||||
if (~(1 << i) & size)
|
if (~(1 << i) & size)
|
||||||
|
|
|
@ -126,6 +126,9 @@ int rman_release_resource(struct resource *r);
|
||||||
struct resource *rman_reserve_resource(struct rman *rm, u_long start,
|
struct resource *rman_reserve_resource(struct rman *rm, u_long start,
|
||||||
u_long end, u_long count,
|
u_long end, u_long count,
|
||||||
u_int flags, struct device *dev);
|
u_int flags, struct device *dev);
|
||||||
|
struct resource *rman_reserve_resource_bound(struct rman *rm, u_long start,
|
||||||
|
u_long end, u_long count, u_long bound,
|
||||||
|
u_int flags, struct device *dev);
|
||||||
uint32_t rman_make_alignment_flags(uint32_t size);
|
uint32_t rman_make_alignment_flags(uint32_t size);
|
||||||
|
|
||||||
#define rman_get_start(r) ((r)->r_start)
|
#define rman_get_start(r) ((r)->r_start)
|
||||||
|
|
Loading…
Reference in a new issue