gpu: nvgpu: posix: fix GPL dependencies in bitmap

Fix up GPL issues in posix version of bitops.

Bug 2919200

Change-Id: I57fdb035b811f47e119cca2278431d3701717d89
Signed-off-by: Peter Daifuku <pdaifuku@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2340983
Reviewed-by: automaticguardword <automaticguardword@nvidia.com>
Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com>
Reviewed-by: svc-mobile-misra <svc-mobile-misra@nvidia.com>
Reviewed-by: svc-mobile-cert <svc-mobile-cert@nvidia.com>
Reviewed-by: Alex Waterman <alexw@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
GVS: Gerrit_Virtual_Submit
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
Peter Daifuku
2020-05-07 19:39:31 -07:00
committed by Alex Waterman
parent 681077d578
commit f0f126d7cc
5 changed files with 97 additions and 136 deletions

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2017-2019, NVIDIA CORPORATION. All rights reserved. * Copyright (c) 2017-2020, NVIDIA CORPORATION. All rights reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a * Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"), * copy of this software and associated documentation files (the "Software"),
@@ -97,13 +97,13 @@
* @brief Loop for each set bit. * @brief Loop for each set bit.
* *
* @param bit [in] Each set bit, this is the loop index. * @param bit [in] Each set bit, this is the loop index.
* @param addr [in] Starting of the bitmap. * @param address [in] Starting of the bitmap.
* @param size [in] Size of the bitmap. * @param size [in] Size of the bitmap.
*/ */
#define for_each_set_bit(bit, addr, size) \ #define for_each_set_bit(bit, address, size) \
for ((bit) = find_first_bit((addr), (size)); \ for ((bit) = find_first_bit((address), (size)); \
(bit) < (size); \ (bit) < (size); \
(bit) = find_next_bit((addr), (size), (bit) + 1U)) (bit) = find_next_bit((address), (size), (bit) + 1U))
/** /**
* @brief Find first set bit. * @brief Find first set bit.
@@ -153,77 +153,79 @@ unsigned long nvgpu_posix_fls(unsigned long word);
/** /**
* @brief Find the first set bit. * @brief Find the first set bit.
* *
* @param addr [in] Input value to search for set bit. * @param address [in] Input value to search for set bit.
* @param size [in] Size of the input value in bits. * @param size [in] Size of the input value in bits.
* *
* Finds the first set bit position in the input data \a addr. * Finds the first set bit position in the input data \a address.
* *
* @return Returns the position of first set bit. * @return Returns the position of first set bit.
*/ */
unsigned long find_first_bit(const unsigned long *addr, unsigned long size); unsigned long find_first_bit(const unsigned long *address, unsigned long size);
/** /**
* @brief Finds the next set bit. * @brief Finds the next set bit.
* *
* @param addr [in] Input value to search for next set bit. * @param address [in] Input value to search for next set bit.
* @param size [in] Size of the input value in bits. * @param size [in] Size of the input value in bits.
* @param offset [in] Offset to start from the input data. * @param offset [in] Offset to start from the input data.
* *
* Finds the next set bit position in the input data \a addr. * Finds the next set bit position in the input data \a address.
* *
* @return Returns the position of next set bit. * @return Returns the position of next set bit.
*/ */
unsigned long find_next_bit(const unsigned long *addr, unsigned long size, unsigned long find_next_bit(const unsigned long *address, unsigned long size,
unsigned long offset); unsigned long offset);
/** /**
* @brief Finds the first zero bit. * @brief Finds the first zero bit.
* *
* @param addr [in] Input value to search. * @param address [in] Input value to search.
* @param size [in] Size of the input value in bits. * @param size [in] Size of the input value in bits.
* *
* Finds the first zero bit position in the input data \a addr. * Finds the first zero bit position in the input data \a address.
* *
* @return Returns the position of first zero bit. * @return Returns the position of first zero bit.
*/ */
unsigned long find_first_zero_bit(const unsigned long *addr, unsigned long find_first_zero_bit(const unsigned long *address,
unsigned long size); unsigned long size);
/** /**
* @brief Test the bit value at given position. * @brief Test the bit value at given position.
* *
* @param nr [in] Bit position to check. * @param bit [in] Bit position to check.
* @param addr [in] Input data stream. * @param address [in] Input data stream.
* *
* Checks if the bit at position mentioned by \a nr in \a addr is set or not. * Checks if the bit at position mentioned by \a bit in \a address is set
* or not.
* *
* @return Returns true if bit position \a nr is set, else returns false. * @return Returns true if bit position \a bit is set, else returns false.
*/ */
bool nvgpu_test_bit(unsigned int nr, const volatile unsigned long *addr); bool nvgpu_test_bit(unsigned int bit, const volatile unsigned long *address);
/** /**
* @brief Test and set the bit at given position. * @brief Test and set the bit at given position.
* *
* @param nr [in] Bit position to test and set. * @param bit [in] Bit position to test and set.
* @param addr [in] Input data stream. * @param address [in] Input data stream.
* *
* Tests and sets the bit at position \a nr in \a addr. * Tests and sets the bit at position \a bit in \a address.
* *
* @return Returns true if the bit position was already set, else returns false. * @return Returns true if the bit position was already set, else returns false.
*/ */
bool nvgpu_test_and_set_bit(unsigned int nr, volatile unsigned long *addr); bool nvgpu_test_and_set_bit(unsigned int bit, volatile unsigned long *address);
/** /**
* @brief Test and clear the bit at given position. * @brief Test and clear the bit at given position.
* *
* @param nr [in] Bit position to test and clear. * @param bit [in] Bit position to test and clear.
* @param addr [in] Input data stream. * @param address [in] Input data stream.
* *
* Tests and clears the bit at position \a nr in \a addr. * Tests and clears the bit at position \a bit in \a address.
* *
* @return Returns true if the bit position was already set, else returns false. * @return Returns true if the bit position was already set, else returns false.
*/ */
bool nvgpu_test_and_clear_bit(unsigned int nr, volatile unsigned long *addr); bool nvgpu_test_and_clear_bit(unsigned int bit,
volatile unsigned long *address);
/* /*
* These two are atomic. * These two are atomic.
@@ -232,22 +234,22 @@ bool nvgpu_test_and_clear_bit(unsigned int nr, volatile unsigned long *addr);
/** /**
* @brief Sets the bit at given position. * @brief Sets the bit at given position.
* *
* @param nr [in] Bit position to set. * @param bit [in] Bit position to set.
* @param addr [in] Input data stream. * @param address [in] Input data stream.
* *
* Sets the bit atomically at bit position \a nr in \a addr. * Sets the bit atomically at bit position \a bit in \a address.
*/ */
void nvgpu_set_bit(unsigned int nr, volatile unsigned long *addr); void nvgpu_set_bit(unsigned int bit, volatile unsigned long *address);
/** /**
* @brief Clears the bit at given position. * @brief Clears the bit at given position.
* *
* @param nr [in] Bit position to clear. * @param bit [in] Bit position to clear.
* @param addr [in] Input data stream. * @param address [in] Input data stream.
* *
* Clears the bit atomically at bit position \a nr in \a addr. * Clears the bit atomically at bit position \a bit in \a address.
*/ */
void nvgpu_clear_bit(unsigned int nr, volatile unsigned long *addr); void nvgpu_clear_bit(unsigned int bit, volatile unsigned long *address);
/** /**
* @brief Sets a bitmap. * @brief Sets a bitmap.
@@ -274,37 +276,13 @@ void nvgpu_bitmap_set(unsigned long *map, unsigned int start, unsigned int len);
void nvgpu_bitmap_clear(unsigned long *map, unsigned int start, void nvgpu_bitmap_clear(unsigned long *map, unsigned int start,
unsigned int len); unsigned int len);
/**
* @brief Find first bitmap space from an offset.
*
* @param map [in] Input data stream.
* @param size [in] Size of the input data.
* @param start [in] Start position in input.
* @param nr [in] Number of bits in bitmap.
* @param align_mask [in] Align mask for start.
* @param align_offset [in] Align offset from Input data.
*
* Finds the first space of contiguous zeros in input data stream which can
* accommodate a bitmap of length \a nr starting from position \a start.
*
* @return Returns the position at which the bitmap starts if enough free space
* is present in the input stream to accommodate the bitmap; otherwise, return
* the size of the input data.
*/
unsigned long bitmap_find_next_zero_area_off(unsigned long *map,
unsigned long size,
unsigned long start,
unsigned int nr,
unsigned long align_mask,
unsigned long align_offset);
/** /**
* @brief Find first bitmap space. * @brief Find first bitmap space.
* *
* @param map [in] Input data stream. * @param map [in] Input data stream.
* @param size [in] Size of the input data. * @param size [in] Size of the input data.
* @param start [in] Start position in input. * @param start [in] Start position in input.
* @param nr [in] Number of bits in bitmap. * @param bit [in] Number of bits in bitmap.
* @param align_mask [in] Align mask for start. * @param align_mask [in] Align mask for start.
* *
* Searches a bitmap for the first space of contiguous zeros that is large * Searches a bitmap for the first space of contiguous zeros that is large
@@ -317,7 +295,7 @@ unsigned long bitmap_find_next_zero_area_off(unsigned long *map,
unsigned long bitmap_find_next_zero_area(unsigned long *map, unsigned long bitmap_find_next_zero_area(unsigned long *map,
unsigned long size, unsigned long size,
unsigned long start, unsigned long start,
unsigned int nr, unsigned int bit,
unsigned long align_mask); unsigned long align_mask);
#endif /* NVGPU_POSIX_BITOPS_H */ #endif /* NVGPU_POSIX_BITOPS_H */

View File

@@ -28,8 +28,18 @@
#include <nvgpu/posix/bitops.h> #include <nvgpu/posix/bitops.h>
#include <nvgpu/posix/atomic.h> #include <nvgpu/posix/atomic.h>
#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG)) static inline unsigned long get_mask(unsigned int bit)
#define BIT_WORD(nr) ((nr) / BITS_PER_LONG) {
unsigned long lbit = bit;
lbit %= BITS_PER_LONG;
return (1UL << lbit);
}
static inline unsigned int get_index(unsigned int bit)
{
unsigned long bpl = BITS_PER_LONG;
return (bit / nvgpu_safe_cast_u64_to_u32(bpl));
}
unsigned long nvgpu_posix_ffs(unsigned long word) unsigned long nvgpu_posix_ffs(unsigned long word)
{ {
@@ -67,7 +77,7 @@ unsigned long nvgpu_posix_fls(unsigned long word)
return ret; return ret;
} }
static unsigned long nvgpu_posix_find_next_bit(const unsigned long *addr, static unsigned long nvgpu_posix_find_next_bit(const unsigned long *address,
unsigned long n, unsigned long n,
unsigned long start, unsigned long start,
bool invert) bool invert)
@@ -75,7 +85,7 @@ static unsigned long nvgpu_posix_find_next_bit(const unsigned long *addr,
unsigned long idx, idx_max; unsigned long idx, idx_max;
unsigned long w; unsigned long w;
unsigned long start_mask; unsigned long start_mask;
const unsigned long *base_addr = (const unsigned long *)&addr[0]; const unsigned long *base_addr = (const unsigned long *)&address[0];
/* /*
* We make a mask we can XOR into the word so that we can invert the * We make a mask we can XOR into the word so that we can invert the
@@ -124,27 +134,27 @@ static unsigned long nvgpu_posix_find_next_bit(const unsigned long *addr,
(nvgpu_safe_mult_u64(idx, BITS_PER_LONG))))); (nvgpu_safe_mult_u64(idx, BITS_PER_LONG)))));
} }
unsigned long find_first_bit(const unsigned long *addr, unsigned long size) unsigned long find_first_bit(const unsigned long *address, unsigned long size)
{ {
return nvgpu_posix_find_next_bit(addr, size, 0, false); return nvgpu_posix_find_next_bit(address, size, 0, false);
} }
unsigned long find_first_zero_bit(const unsigned long *addr, unsigned long size) unsigned long find_first_zero_bit(const unsigned long *address, unsigned long size)
{ {
return nvgpu_posix_find_next_bit(addr, size, 0, true); return nvgpu_posix_find_next_bit(address, size, 0, true);
} }
unsigned long find_next_bit(const unsigned long *addr, unsigned long size, unsigned long find_next_bit(const unsigned long *address, unsigned long size,
unsigned long offset) unsigned long offset)
{ {
return nvgpu_posix_find_next_bit(addr, size, offset, false); return nvgpu_posix_find_next_bit(address, size, offset, false);
} }
static unsigned long find_next_zero_bit(const unsigned long *addr, static unsigned long find_next_zero_bit(const unsigned long *address,
unsigned long size, unsigned long size,
unsigned long offset) unsigned long offset)
{ {
return nvgpu_posix_find_next_bit(addr, size, offset, true); return nvgpu_posix_find_next_bit(address, size, offset, true);
} }
void nvgpu_bitmap_set(unsigned long *map, unsigned int start, unsigned int len) void nvgpu_bitmap_set(unsigned long *map, unsigned int start, unsigned int len)
@@ -175,33 +185,29 @@ void nvgpu_bitmap_clear(unsigned long *map,
* That means that this is not a vary smart allocator. But it is fast relative * That means that this is not a vary smart allocator. But it is fast relative
* to an allocator that goes looking for an optimal location. * to an allocator that goes looking for an optimal location.
*/ */
unsigned long bitmap_find_next_zero_area_off(unsigned long *map, unsigned long bitmap_find_next_zero_area(unsigned long *map,
unsigned long size, unsigned long size,
unsigned long start, unsigned long start,
unsigned int nr, unsigned int bit,
unsigned long align_mask, unsigned long align_mask)
unsigned long align_offset)
{ {
unsigned long offs; unsigned long offs;
while ((nvgpu_safe_add_u64(start, (unsigned long)nr)) <= size) { while ((nvgpu_safe_add_u64(start, (unsigned long)bit)) <= size) {
start = find_next_zero_bit(map, size, start); start = find_next_zero_bit(map, size, start);
start = nvgpu_safe_sub_u64( start = ALIGN_MASK(start, align_mask);
ALIGN_MASK(nvgpu_safe_add_u64(start, align_offset),
align_mask),
align_offset);
/* /*
* Not enough space left to satisfy the requested area. * Not enough space left to satisfy the requested area.
*/ */
if ((nvgpu_safe_add_u64(start, (unsigned long)nr)) > size) { if ((nvgpu_safe_add_u64(start, (unsigned long)bit)) > size) {
return size; return size;
} }
offs = find_next_bit(map, size, start); offs = find_next_bit(map, size, start);
if ((offs - start) >= nr) { if ((offs - start) >= bit) {
return start; return start;
} }
@@ -211,54 +217,44 @@ unsigned long bitmap_find_next_zero_area_off(unsigned long *map,
return size; return size;
} }
unsigned long bitmap_find_next_zero_area(unsigned long *map, bool nvgpu_test_bit(unsigned int bit, const volatile unsigned long *address)
unsigned long size,
unsigned long start,
unsigned int nr,
unsigned long align_mask)
{ {
return bitmap_find_next_zero_area_off(map, size, start, nr, return (1UL & (address[get_index(bit)] >>
align_mask, 0); (bit & (BITS_PER_LONG-1UL)))) != 0UL;
} }
bool nvgpu_test_bit(unsigned int nr, const volatile unsigned long *addr) bool nvgpu_test_and_set_bit(unsigned int bit, volatile unsigned long *address)
{ {
return (1UL & (addr[BIT_WORD(nr)] >> unsigned long mask = get_mask(bit);
(nr & (BITS_PER_LONG-1UL)))) != 0UL;
}
bool nvgpu_test_and_set_bit(unsigned int nr, volatile unsigned long *addr)
{
unsigned long mask = BIT_MASK(nr);
volatile unsigned _Atomic long *p = volatile unsigned _Atomic long *p =
(volatile unsigned _Atomic long *)addr + BIT_WORD(nr); (volatile unsigned _Atomic long *)address + get_index(bit);
return (atomic_fetch_or(p, mask) & mask) != 0ULL; return (atomic_fetch_or(p, mask) & mask) != 0ULL;
} }
bool nvgpu_test_and_clear_bit(unsigned int nr, volatile unsigned long *addr) bool nvgpu_test_and_clear_bit(unsigned int bit, volatile unsigned long *address)
{ {
unsigned long mask = BIT_MASK(nr); unsigned long mask = get_mask(bit);
volatile unsigned _Atomic long *p = volatile unsigned _Atomic long *p =
(volatile unsigned _Atomic long *)addr + BIT_WORD(nr); (volatile unsigned _Atomic long *)address + get_index(bit);
return (atomic_fetch_and(p, ~mask) & mask) != 0ULL; return (atomic_fetch_and(p, ~mask) & mask) != 0ULL;
} }
void nvgpu_set_bit(unsigned int nr, volatile unsigned long *addr) void nvgpu_set_bit(unsigned int bit, volatile unsigned long *address)
{ {
unsigned long mask = BIT_MASK(nr); unsigned long mask = get_mask(bit);
volatile unsigned _Atomic long *p = volatile unsigned _Atomic long *p =
(unsigned volatile _Atomic long *)addr + BIT_WORD(nr); (unsigned volatile _Atomic long *)address + get_index(bit);
(void)atomic_fetch_or(p, mask); (void)atomic_fetch_or(p, mask);
} }
void nvgpu_clear_bit(unsigned int nr, volatile unsigned long *addr) void nvgpu_clear_bit(unsigned int bit, volatile unsigned long *address)
{ {
unsigned long mask = BIT_MASK(nr); unsigned long mask = get_mask(bit);
volatile unsigned _Atomic long *p = volatile unsigned _Atomic long *p =
(volatile unsigned _Atomic long *)addr + BIT_WORD(nr); (volatile unsigned _Atomic long *)address + get_index(bit);
(void)atomic_fetch_and(p, ~mask); (void)atomic_fetch_and(p, ~mask);
} }

View File

@@ -1,6 +1,5 @@
# Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved. # Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved.
bitmap_find_next_zero_area_off
bitmap_find_next_zero_area bitmap_find_next_zero_area
fb_gv11b_write_mmu_fault_buffer_get fb_gv11b_write_mmu_fault_buffer_get
find_first_bit find_first_bit

View File

@@ -1,6 +1,5 @@
# Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved. # Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved.
bitmap_find_next_zero_area_off
bitmap_find_next_zero_area bitmap_find_next_zero_area
fb_gv11b_write_mmu_fault_buffer_get fb_gv11b_write_mmu_fault_buffer_get
find_first_bit find_first_bit

View File

@@ -348,29 +348,29 @@ int test_find_zero_area(struct unit_module *m, struct gk20a *g, void *unused)
} }
for (i = 0; i < TEST_BITMAP_SIZE; i++) { for (i = 0; i < TEST_BITMAP_SIZE; i++) {
result = bitmap_find_next_zero_area_off(bmap_all_zeros, result = bitmap_find_next_zero_area(bmap_all_zeros,
TEST_BITMAP_SIZE, TEST_BITMAP_SIZE,
i, i,
TEST_BITMAP_SIZE - i, TEST_BITMAP_SIZE - i,
0, 0); 0);
if (result != i) if (result != i)
unit_return_fail(m, FAIL_MSG, unit_return_fail(m, FAIL_MSG,
"all_zeros: alloc-to-end", i); "all_zeros: alloc-to-end", i);
result = bitmap_find_next_zero_area_off(bmap_all_zeros, result = bitmap_find_next_zero_area(bmap_all_zeros,
TEST_BITMAP_SIZE, TEST_BITMAP_SIZE,
i, i,
1, 1,
0, 0); 0);
if (result != i) if (result != i)
unit_return_fail(m, FAIL_MSG, unit_return_fail(m, FAIL_MSG,
"all_zeros: alloc-one-bit", i); "all_zeros: alloc-one-bit", i);
result = bitmap_find_next_zero_area_off(bmap_all_zeros, result = bitmap_find_next_zero_area(bmap_all_zeros,
TEST_BITMAP_SIZE, TEST_BITMAP_SIZE,
0, 0,
TEST_BITMAP_SIZE - i, TEST_BITMAP_SIZE - i,
0, 0); 0);
if (result != 0) if (result != 0)
unit_return_fail(m, FAIL_MSG, unit_return_fail(m, FAIL_MSG,
"all_zeros: alloc-i-bits-at-0", i); "all_zeros: alloc-i-bits-at-0", i);
@@ -382,11 +382,11 @@ int test_find_zero_area(struct unit_module *m, struct gk20a *g, void *unused)
*/ */
for (i = 0; i < TEST_BITMAP_SIZE; i++) { for (i = 0; i < TEST_BITMAP_SIZE; i++) {
for (j = 0; j < (TEST_BITMAP_SIZE - i); j++) { for (j = 0; j < (TEST_BITMAP_SIZE - i); j++) {
result = bitmap_find_next_zero_area_off(bmap_all_ones, result = bitmap_find_next_zero_area(bmap_all_ones,
TEST_BITMAP_SIZE, TEST_BITMAP_SIZE,
i, i,
j, j,
0, 0); 0);
if (result != TEST_BITMAP_SIZE) if (result != TEST_BITMAP_SIZE)
unit_return_fail(m, FAIL_MSG_EX, unit_return_fail(m, FAIL_MSG_EX,
"all_ones: failed", i, j); "all_ones: failed", i, j);
@@ -402,11 +402,11 @@ int test_find_zero_area(struct unit_module *m, struct gk20a *g, void *unused)
memset(words, 0x0f, sizeof(words)); memset(words, 0x0f, sizeof(words));
for (i = 0; i < ((NUM_WORDS * BITS_PER_LONG) - 8); i++) { for (i = 0; i < ((NUM_WORDS * BITS_PER_LONG) - 8); i++) {
for (j = 0; j < ((NUM_WORDS * BITS_PER_LONG) - i - 8); j++) { for (j = 0; j < ((NUM_WORDS * BITS_PER_LONG) - i - 8); j++) {
result = bitmap_find_next_zero_area_off(words, result = bitmap_find_next_zero_area(words,
NUM_WORDS * BITS_PER_LONG, NUM_WORDS * BITS_PER_LONG,
i, i,
j, j,
0, 0); 0);
/* /*
* Should only return a valid result when j < 4 (since * Should only return a valid result when j < 4 (since
@@ -422,27 +422,16 @@ int test_find_zero_area(struct unit_module *m, struct gk20a *g, void *unused)
"alternating-nibbles: failed", "alternating-nibbles: failed",
i, j); i, j);
result = bitmap_find_next_zero_area_off(words, result = bitmap_find_next_zero_area(words,
NUM_WORDS * BITS_PER_LONG, NUM_WORDS * BITS_PER_LONG,
i, i,
(j % 4) + 1, (j % 4) + 1,
0x3, 0); 0x3);
if (result % 8 != 4) if (result % 8 != 4)
unit_return_fail(m, FAIL_MSG_EX, unit_return_fail(m, FAIL_MSG_EX,
"basic-align_mask: failed", "basic-align_mask: failed",
i, j); i, j);
result = bitmap_find_next_zero_area_off(words,
NUM_WORDS * BITS_PER_LONG,
i,
(j % 2) + 1,
0x7, 2);
if (result % 8 != 6)
unit_return_fail(m, FAIL_MSG_EX,
"basic-align_offset: failed",
i, j);
} }
} }