bhndb(4): Drop MIPS-incompatible __builtin_ctz dependency.
This replaces the bitfield representation of the bhndb register window freelist with the bitstring API, eliminating a dependency on (MIPS-unsupported) __builtin_ctz(). Approved by: adrian (mentor) Differential Revision: https://reviews.freebsd.org/D7495
This commit is contained in:
parent
988fd417a0
commit
9dfeb4140c
@ -33,6 +33,7 @@
|
||||
#define _BHND_BHNDB_PRIVATE_H_
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bitstring.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/systm.h>
|
||||
|
||||
@ -184,21 +185,23 @@ struct bhndb_resources {
|
||||
|
||||
struct bhndb_dw_alloc *dw_alloc; /**< dynamic window allocation records */
|
||||
size_t dwa_count; /**< number of dynamic windows available. */
|
||||
uint32_t dwa_freelist; /**< dynamic window free list */
|
||||
bitstr_t *dwa_freelist; /**< dynamic window free list */
|
||||
bhndb_priority_t min_prio; /**< minimum resource priority required to
|
||||
allocate a dynamic window */
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns true if the all dynamic windows have been exhausted, false
|
||||
* Returns true if the all dynamic windows are marked free, false
|
||||
* otherwise.
|
||||
*
|
||||
* @param br The resource state to check.
|
||||
*/
|
||||
static inline bool
|
||||
bhndb_dw_exhausted(struct bhndb_resources *br)
|
||||
bhndb_dw_all_free(struct bhndb_resources *br)
|
||||
{
|
||||
return (br->dwa_freelist == 0);
|
||||
int bit;
|
||||
bit_ffs(br->dwa_freelist, br->dwa_count, &bit);
|
||||
return (bit == -1);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -209,12 +212,14 @@ bhndb_dw_exhausted(struct bhndb_resources *br)
|
||||
static inline struct bhndb_dw_alloc *
|
||||
bhndb_dw_next_free(struct bhndb_resources *br)
|
||||
{
|
||||
struct bhndb_dw_alloc *dw_free;
|
||||
struct bhndb_dw_alloc *dw_free;
|
||||
int bit;
|
||||
|
||||
if (bhndb_dw_exhausted(br))
|
||||
bit_ffc(br->dwa_freelist, br->dwa_count, &bit);
|
||||
if (bit == -1)
|
||||
return (NULL);
|
||||
|
||||
dw_free = &br->dw_alloc[__builtin_ctz(br->dwa_freelist)];
|
||||
dw_free = &br->dw_alloc[bit];
|
||||
|
||||
KASSERT(LIST_EMPTY(&dw_free->refs),
|
||||
("free list out of sync with refs"));
|
||||
@ -233,7 +238,7 @@ bhndb_dw_is_free(struct bhndb_resources *br, struct bhndb_dw_alloc *dwa)
|
||||
{
|
||||
bool is_free = LIST_EMPTY(&dwa->refs);
|
||||
|
||||
KASSERT(is_free == ((br->dwa_freelist & (1 << dwa->rnid)) != 0),
|
||||
KASSERT(is_free == !bit_test(br->dwa_freelist, dwa->rnid),
|
||||
("refs out of sync with free list"));
|
||||
|
||||
return (is_free);
|
||||
|
@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/limits.h>
|
||||
|
||||
#include "bhndb_private.h"
|
||||
#include "bhndbvar.h"
|
||||
@ -264,7 +265,7 @@ bhndb_alloc_resources(device_t dev, device_t parent_dev,
|
||||
const struct bhndb_regwin *win;
|
||||
bus_size_t last_window_size;
|
||||
size_t res_num;
|
||||
u_int rnid;
|
||||
int rnid;
|
||||
int error;
|
||||
bool free_parent_res;
|
||||
bool free_ht_mem, free_br_mem;
|
||||
@ -371,10 +372,10 @@ bhndb_alloc_resources(device_t dev, device_t parent_dev,
|
||||
}
|
||||
|
||||
/* Fetch the dynamic regwin count and verify that it does not exceed
|
||||
* what is representable via our freelist bitmask. */
|
||||
* what is representable via our freelist bitstring. */
|
||||
r->dwa_count = bhndb_regwin_count(cfg->register_windows,
|
||||
BHNDB_REGWIN_T_DYN);
|
||||
if (r->dwa_count >= (8 * sizeof(r->dwa_freelist))) {
|
||||
if (r->dwa_count >= INT_MAX) {
|
||||
device_printf(r->dev, "max dynamic regwin count exceeded\n");
|
||||
goto failed;
|
||||
}
|
||||
@ -385,8 +386,12 @@ bhndb_alloc_resources(device_t dev, device_t parent_dev,
|
||||
if (r->dw_alloc == NULL)
|
||||
goto failed;
|
||||
|
||||
/* Initialize the dynamic window table and freelist. */
|
||||
r->dwa_freelist = 0;
|
||||
/* Allocate the dynamic window allocation freelist */
|
||||
r->dwa_freelist = bit_alloc(r->dwa_count, M_BHND, M_NOWAIT);
|
||||
if (r->dwa_freelist == NULL)
|
||||
goto failed;
|
||||
|
||||
/* Initialize the dynamic window table */
|
||||
rnid = 0;
|
||||
last_window_size = 0;
|
||||
for (win = cfg->register_windows;
|
||||
@ -446,9 +451,6 @@ bhndb_alloc_resources(device_t dev, device_t parent_dev,
|
||||
goto failed;
|
||||
}
|
||||
|
||||
/* Add to freelist */
|
||||
r->dwa_freelist |= (1 << rnid);
|
||||
|
||||
rnid++;
|
||||
}
|
||||
|
||||
@ -473,6 +475,9 @@ failed:
|
||||
if (r->dw_alloc != NULL)
|
||||
free(r->dw_alloc, M_BHND);
|
||||
|
||||
if (r->dwa_freelist != NULL)
|
||||
free(r->dwa_freelist, M_BHND);
|
||||
|
||||
free (r, M_BHND);
|
||||
|
||||
return (NULL);
|
||||
@ -491,9 +496,17 @@ bhndb_free_resources(struct bhndb_resources *br)
|
||||
struct bhndb_dw_rentry *dwr, *dwr_next;
|
||||
|
||||
/* No window regions may still be held */
|
||||
if (__builtin_popcount(br->dwa_freelist) != br->dwa_count) {
|
||||
device_printf(br->dev, "leaked %llu dynamic register regions\n",
|
||||
(unsigned long long) br->dwa_count - br->dwa_freelist);
|
||||
if (!bhndb_dw_all_free(br)) {
|
||||
for (int i = 0; i < br->dwa_count; i++) {
|
||||
dwa = &br->dw_alloc[i];
|
||||
|
||||
/* Skip free dynamic windows */
|
||||
if (bhndb_dw_is_free(br, dwa))
|
||||
continue;
|
||||
|
||||
device_printf(br->dev,
|
||||
"leaked dynamic register window %d\n", dwa->rnid);
|
||||
}
|
||||
}
|
||||
|
||||
/* Release resources allocated through our parent. */
|
||||
@ -523,6 +536,7 @@ bhndb_free_resources(struct bhndb_resources *br)
|
||||
free(br->res, M_BHND);
|
||||
free(br->res_spec, M_BHND);
|
||||
free(br->dw_alloc, M_BHND);
|
||||
free(br->dwa_freelist, M_BHND);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -765,7 +779,7 @@ bhndb_dw_retain(struct bhndb_resources *br, struct bhndb_dw_alloc *dwa,
|
||||
LIST_INSERT_HEAD(&dwa->refs, rentry, dw_link);
|
||||
|
||||
/* Update the free list */
|
||||
br->dwa_freelist &= ~(1 << (dwa->rnid));
|
||||
bit_set(br->dwa_freelist, dwa->rnid);
|
||||
|
||||
return (0);
|
||||
}
|
||||
@ -794,7 +808,7 @@ bhndb_dw_release(struct bhndb_resources *br, struct bhndb_dw_alloc *dwa,
|
||||
|
||||
/* If this was the last reference, update the free list */
|
||||
if (LIST_EMPTY(&dwa->refs))
|
||||
br->dwa_freelist |= (1 << (dwa->rnid));
|
||||
bit_clear(br->dwa_freelist, dwa->rnid);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user