From: Joey Zhong <[email protected]> Add ba_find_prev_inuse() and ba_find_prev_inuse_free(), the backward-searching counterparts of the existing ba_find_next_inuse() and ba_find_next_inuse_free(). The new helpers walk the multi-level bitalloc tree from a given index down towards index 0, using ba_fls() to locate the highest in-use bit at or below the starting position, mirroring the forward-search helpers which use ba_ffs() to locate the lowest in-use bit at or above the starting position.
Signed-off-by: Joey Zhong <[email protected]> Signed-off-by: Manish Kurup <[email protected]> --- .mailmap | 1 + drivers/net/bnxt/tf_core/bitalloc.c | 81 +++++++++++++++++++++++++++++ drivers/net/bnxt/tf_core/bitalloc.h | 14 +++++ 3 files changed, 96 insertions(+) diff --git a/.mailmap b/.mailmap index 2e348c3bce..9763a95d09 100644 --- a/.mailmap +++ b/.mailmap @@ -785,6 +785,7 @@ Job Abraham <[email protected]> Jochen Behrens <[email protected]> <[email protected]> Joel Kavanagh <[email protected]> Joey Xing <[email protected]> +Joey Zhong <[email protected]> Johan Faltstrom <[email protected]> Johan Källström <[email protected]> Johan Samuelsson <[email protected]> diff --git a/drivers/net/bnxt/tf_core/bitalloc.c b/drivers/net/bnxt/tf_core/bitalloc.c index 136263b6a4..dc0a2c8834 100644 --- a/drivers/net/bnxt/tf_core/bitalloc.c +++ b/drivers/net/bnxt/tf_core/bitalloc.c @@ -470,3 +470,84 @@ ba_find_next_inuse_free(struct bitalloc *pool, int index) return ba_find_next_helper(pool, 0, 1, 32, &index, 1); } + +static int +ba_find_prev_helper(struct bitalloc *pool, + int offset, + int words, + unsigned int size, + int *index, + int free) +{ + bitalloc_word_t *storage = &pool->storage[offset]; + int loc, r, bottom = 0; + + if (pool->size > size) + r = ba_find_prev_helper(pool, + offset + words + 1, + storage[words], + size * 32, + index, + free); + else + bottom = 1; /* Bottom of tree */ + + loc = (*index % 32); + *index = *index / 32; + + if (bottom) { + int bit_index = *index * 32; + + loc = ba_fls(~storage[*index] & ((bitalloc_word_t)-1 >> (31 - loc))); + if (loc > 0) { + loc--; + r = (bit_index + loc); + } else { + /* Loop over array at bottom of tree */ + r = -1; + bit_index -= 32; + *index = *index - 1; + while (bit_index >= 0) { + loc = ba_fls(~storage[*index]); + + if (loc > 0) { + loc--; + r = (bit_index + loc); + break; + } + bit_index -= 32; + *index = *index - 1; + } + } + } + + if (r >= 0 && (free)) { + if (bottom) + pool->free_count++; + storage[*index] |= (1 << loc); + } + + return r; +} + +int +ba_find_prev_inuse(struct bitalloc *pool, int index) +{ + if (index < 0 || + index >= (int)pool->size || + pool->free_count == pool->size) + return -1; + + return ba_find_prev_helper(pool, 0, 1, 32, &index, 0); +} + +int +ba_find_prev_inuse_free(struct bitalloc *pool, int index) +{ + if (index < 0 || + index >= (int)pool->size || + pool->free_count == pool->size) + return -1; + + return ba_find_prev_helper(pool, 0, 1, 32, &index, 1); +} diff --git a/drivers/net/bnxt/tf_core/bitalloc.h b/drivers/net/bnxt/tf_core/bitalloc.h index bf15cbc87b..6c8e325675 100644 --- a/drivers/net/bnxt/tf_core/bitalloc.h +++ b/drivers/net/bnxt/tf_core/bitalloc.h @@ -106,6 +106,20 @@ int ba_find_next_inuse(struct bitalloc *pool, int idx); */ int ba_find_next_inuse_free(struct bitalloc *pool, int idx); +/** + * Find prev index that is in use, start checking at index 'idx' + * + * Returns prev index that is in use on success, or + * -1 if no in use index is found + */ +int ba_find_prev_inuse(struct bitalloc *pool, int idx); + +/** + * Variant of ba_find_prev_inuse that also frees the prev in use index, + * same return codes as ba_find_prev_inuse + */ +int ba_find_prev_inuse_free(struct bitalloc *pool, int idx); + /** * Multiple freeing of the same index has no negative side effects, * but will return -1. returns -1 on failure, 0 on success. -- 2.31.1

