Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3aa56885 authored by Yury Norov's avatar Yury Norov Committed by Linus Torvalds
Browse files

bitmap: replace bitmap_{from,to}_u32array

with bitmap_{from,to}_arr32 over the kernel. Additionally to it:
* __check_eq_bitmap() now takes single nbits argument.
* __check_eq_u32_array is not used in new test but may be used in
  future. So I don't remove it here, but annotate as __used.

Tested on arm64 and 32-bit BE mips.

[arnd@arndb.de: perf: arm_dsu_pmu: convert to bitmap_from_arr32]
  Link: http://lkml.kernel.org/r/20180201172508.5739-2-ynorov@caviumnetworks.com
[ynorov@caviumnetworks.com: fix net/core/ethtool.c]
  Link: http://lkml.kernel.org/r/20180205071747.4ekxtsbgxkj5b2fz@yury-thinkpad
Link: http://lkml.kernel.org/r/20171228150019.27953-2-ynorov@caviumnetworks.com


Signed-off-by: default avatarYury Norov <ynorov@caviumnetworks.com>
Signed-off-by: default avatarArnd Bergmann <arnd@arndb.de>
Cc: Ben Hutchings <ben@decadent.org.uk>
Cc: David Decotigny <decot@googlers.com>,
Cc: David S. Miller <davem@davemloft.net>,
Cc: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: Matthew Wilcox <mawilcox@microsoft.com>
Cc: Rasmus Villemoes <linux@rasmusvillemoes.dk>
Cc: Heiner Kallweit <hkallweit1@gmail.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent c724f193
Loading
Loading
Loading
Loading
+2 −3
Original line number Diff line number Diff line
@@ -925,9 +925,8 @@ static void __armv8pmu_probe_pmu(void *info)
	pmceid[0] = read_sysreg(pmceid0_el0);
	pmceid[1] = read_sysreg(pmceid1_el0);

	bitmap_from_u32array(cpu_pmu->pmceid_bitmap,
			     ARMV8_PMUV3_MAX_COMMON_EVENTS, pmceid,
			     ARRAY_SIZE(pmceid));
	bitmap_from_arr32(cpu_pmu->pmceid_bitmap,
			     pmceid, ARMV8_PMUV3_MAX_COMMON_EVENTS);
}

static int armv8pmu_probe_pmu(struct arm_pmu *cpu_pmu)
+2 −4
Original line number Diff line number Diff line
@@ -658,10 +658,8 @@ static void dsu_pmu_probe_pmu(struct dsu_pmu *dsu_pmu)
		return;
	cpmceid[0] = __dsu_pmu_read_pmceid(0);
	cpmceid[1] = __dsu_pmu_read_pmceid(1);
	bitmap_from_u32array(dsu_pmu->cpmceid_bitmap,
				DSU_PMU_MAX_COMMON_EVENTS,
				cpmceid,
				ARRAY_SIZE(cpmceid));
	bitmap_from_arr32(dsu_pmu->cpmceid_bitmap, cpmceid,
			  DSU_PMU_MAX_COMMON_EVENTS);
}

static void dsu_pmu_set_active_cpu(int cpu, struct dsu_pmu *dsu_pmu)
+1 −10
Original line number Diff line number Diff line
@@ -64,8 +64,6 @@
 *  bitmap_find_free_region(bitmap, bits, order)  Find and allocate bit region
 *  bitmap_release_region(bitmap, pos, order)   Free specified bit region
 *  bitmap_allocate_region(bitmap, pos, order)  Allocate specified bit region
 *  bitmap_from_u32array(dst, nbits, buf, nwords)  *dst = *buf (nwords 32b words)
 *  bitmap_to_u32array(buf, nwords, src, nbits) *buf = *dst (nwords 32b words)
 *  bitmap_from_arr32(dst, buf, nbits)          Copy nbits from u32[] buf to dst
 *  bitmap_to_arr32(buf, src, nbits)            Copy nbits from buf to u32[] dst
 *
@@ -176,14 +174,7 @@ extern void bitmap_fold(unsigned long *dst, const unsigned long *orig,
extern int bitmap_find_free_region(unsigned long *bitmap, unsigned int bits, int order);
extern void bitmap_release_region(unsigned long *bitmap, unsigned int pos, int order);
extern int bitmap_allocate_region(unsigned long *bitmap, unsigned int pos, int order);
extern unsigned int bitmap_from_u32array(unsigned long *bitmap,
					 unsigned int nbits,
					 const u32 *buf,
					 unsigned int nwords);
extern unsigned int bitmap_to_u32array(u32 *buf,
				       unsigned int nwords,
				       const unsigned long *bitmap,
				       unsigned int nbits);

#ifdef __BIG_ENDIAN
extern void bitmap_copy_le(unsigned long *dst, const unsigned long *src, unsigned int nbits);
#else
+0 −87
Original line number Diff line number Diff line
@@ -1105,93 +1105,6 @@ int bitmap_allocate_region(unsigned long *bitmap, unsigned int pos, int order)
}
EXPORT_SYMBOL(bitmap_allocate_region);

/**
 * bitmap_from_u32array - copy the contents of a u32 array of bits to bitmap
 *	@bitmap: array of unsigned longs, the destination bitmap, non NULL
 *	@nbits: number of bits in @bitmap
 *	@buf: array of u32 (in host byte order), the source bitmap, non NULL
 *	@nwords: number of u32 words in @buf
 *
 * copy min(nbits, 32*nwords) bits from @buf to @bitmap, remaining
 * bits between nword and nbits in @bitmap (if any) are cleared. In
 * last word of @bitmap, the bits beyond nbits (if any) are kept
 * unchanged.
 *
 * Return the number of bits effectively copied.
 */
unsigned int
bitmap_from_u32array(unsigned long *bitmap, unsigned int nbits,
		     const u32 *buf, unsigned int nwords)
{
	unsigned int dst_idx, src_idx;

	for (src_idx = dst_idx = 0; dst_idx < BITS_TO_LONGS(nbits); ++dst_idx) {
		unsigned long part = 0;

		if (src_idx < nwords)
			part = buf[src_idx++];

#if BITS_PER_LONG == 64
		if (src_idx < nwords)
			part |= ((unsigned long) buf[src_idx++]) << 32;
#endif

		if (dst_idx < nbits/BITS_PER_LONG)
			bitmap[dst_idx] = part;
		else {
			unsigned long mask = BITMAP_LAST_WORD_MASK(nbits);

			bitmap[dst_idx] = (bitmap[dst_idx] & ~mask)
				| (part & mask);
		}
	}

	return min_t(unsigned int, nbits, 32*nwords);
}
EXPORT_SYMBOL(bitmap_from_u32array);

/**
 * bitmap_to_u32array - copy the contents of bitmap to a u32 array of bits
 *	@buf: array of u32 (in host byte order), the dest bitmap, non NULL
 *	@nwords: number of u32 words in @buf
 *	@bitmap: array of unsigned longs, the source bitmap, non NULL
 *	@nbits: number of bits in @bitmap
 *
 * copy min(nbits, 32*nwords) bits from @bitmap to @buf. Remaining
 * bits after nbits in @buf (if any) are cleared.
 *
 * Return the number of bits effectively copied.
 */
unsigned int
bitmap_to_u32array(u32 *buf, unsigned int nwords,
		   const unsigned long *bitmap, unsigned int nbits)
{
	unsigned int dst_idx = 0, src_idx = 0;

	while (dst_idx < nwords) {
		unsigned long part = 0;

		if (src_idx < BITS_TO_LONGS(nbits)) {
			part = bitmap[src_idx];
			if (src_idx >= nbits/BITS_PER_LONG)
				part &= BITMAP_LAST_WORD_MASK(nbits);
			src_idx++;
		}

		buf[dst_idx++] = part & 0xffffffffUL;

#if BITS_PER_LONG == 64
		if (dst_idx < nwords) {
			part >>= 32;
			buf[dst_idx++] = part & 0xffffffffUL;
		}
#endif
	}

	return min_t(unsigned int, nbits, 32*nwords);
}
EXPORT_SYMBOL(bitmap_to_u32array);

/**
 * bitmap_copy_le - copy a bitmap, putting the bits into little-endian order.
 * @dst:   destination buffer
+31 −175
Original line number Diff line number Diff line
@@ -23,7 +23,7 @@ __check_eq_uint(const char *srcfile, unsigned int line,
		const unsigned int exp_uint, unsigned int x)
{
	if (exp_uint != x) {
		pr_warn("[%s:%u] expected %u, got %u\n",
		pr_err("[%s:%u] expected %u, got %u\n",
			srcfile, line, exp_uint, x);
		return false;
	}
@@ -33,19 +33,13 @@ __check_eq_uint(const char *srcfile, unsigned int line,

static bool __init
__check_eq_bitmap(const char *srcfile, unsigned int line,
		  const unsigned long *exp_bmap, unsigned int exp_nbits,
		  const unsigned long *bmap, unsigned int nbits)
		  const unsigned long *exp_bmap, const unsigned long *bmap,
		  unsigned int nbits)
{
	if (exp_nbits != nbits) {
		pr_warn("[%s:%u] bitmap length mismatch: expected %u, got %u\n",
			srcfile, line, exp_nbits, nbits);
		return false;
	}

	if (!bitmap_equal(exp_bmap, bmap, nbits)) {
		pr_warn("[%s:%u] bitmaps contents differ: expected \"%*pbl\", got \"%*pbl\"\n",
			srcfile, line,
			exp_nbits, exp_bmap, nbits, bmap);
			nbits, exp_bmap, nbits, bmap);
		return false;
	}
	return true;
@@ -66,6 +60,10 @@ __check_eq_pbl(const char *srcfile, unsigned int line,
	return true;
}

static bool __init
__check_eq_u32_array(const char *srcfile, unsigned int line,
		     const u32 *exp_arr, unsigned int exp_len,
		     const u32 *arr, unsigned int len) __used;
static bool __init
__check_eq_u32_array(const char *srcfile, unsigned int line,
		     const u32 *exp_arr, unsigned int exp_len,
@@ -255,171 +253,29 @@ static void __init test_bitmap_parselist(void)
	}
}

static void __init test_bitmap_u32_array_conversions(void)
static void __init test_bitmap_arr32(void)
{
	DECLARE_BITMAP(bmap1, 1024);
	DECLARE_BITMAP(bmap2, 1024);
	u32 exp_arr[32], arr[32];
	unsigned nbits;

	for (nbits = 0 ; nbits < 257 ; ++nbits) {
		const unsigned int used_u32s = DIV_ROUND_UP(nbits, 32);
		unsigned int i, rv;

		bitmap_zero(bmap1, nbits);
		bitmap_set(bmap1, nbits, 1024 - nbits);  /* garbage */

		memset(arr, 0xff, sizeof(arr));
		rv = bitmap_to_u32array(arr, used_u32s, bmap1, nbits);
		expect_eq_uint(nbits, rv);

		memset(exp_arr, 0xff, sizeof(exp_arr));
		memset(exp_arr, 0, used_u32s*sizeof(*exp_arr));
		expect_eq_u32_array(exp_arr, 32, arr, 32);

		bitmap_fill(bmap2, 1024);
		rv = bitmap_from_u32array(bmap2, nbits, arr, used_u32s);
		expect_eq_uint(nbits, rv);
		expect_eq_bitmap(bmap1, 1024, bmap2, 1024);

		for (i = 0 ; i < nbits ; ++i) {
			/*
			 * test conversion bitmap -> u32[]
			 */

			bitmap_zero(bmap1, 1024);
			__set_bit(i, bmap1);
			bitmap_set(bmap1, nbits, 1024 - nbits);  /* garbage */

			memset(arr, 0xff, sizeof(arr));
			rv = bitmap_to_u32array(arr, used_u32s, bmap1, nbits);
			expect_eq_uint(nbits, rv);

			/* 1st used u32 words contain expected bit set, the
			 * remaining words are left unchanged (0xff)
			 */
			memset(exp_arr, 0xff, sizeof(exp_arr));
			memset(exp_arr, 0, used_u32s*sizeof(*exp_arr));
			exp_arr[i/32] = (1U<<(i%32));
			expect_eq_u32_array(exp_arr, 32, arr, 32);


			/* same, with longer array to fill
			 */
			memset(arr, 0xff, sizeof(arr));
			rv = bitmap_to_u32array(arr, 32, bmap1, nbits);
			expect_eq_uint(nbits, rv);

			/* 1st used u32 words contain expected bit set, the
			 * remaining words are all 0s
			 */
			memset(exp_arr, 0, sizeof(exp_arr));
			exp_arr[i/32] = (1U<<(i%32));
			expect_eq_u32_array(exp_arr, 32, arr, 32);

			/*
			 * test conversion u32[] -> bitmap
			 */

			/* the 1st nbits of bmap2 are identical to
			 * bmap1, the remaining bits of bmap2 are left
			 * unchanged (all 1s)
			 */
			bitmap_fill(bmap2, 1024);
			rv = bitmap_from_u32array(bmap2, nbits,
						  exp_arr, used_u32s);
			expect_eq_uint(nbits, rv);

			expect_eq_bitmap(bmap1, 1024, bmap2, 1024);

			/* same, with more bits to fill
			 */
			memset(arr, 0xff, sizeof(arr));  /* garbage */
			memset(arr, 0, used_u32s*sizeof(u32));
			arr[i/32] = (1U<<(i%32));

			bitmap_fill(bmap2, 1024);
			rv = bitmap_from_u32array(bmap2, 1024, arr, used_u32s);
			expect_eq_uint(used_u32s*32, rv);

			/* the 1st nbits of bmap2 are identical to
			 * bmap1, the remaining bits of bmap2 are cleared
			 */
			bitmap_zero(bmap1, 1024);
			__set_bit(i, bmap1);
			expect_eq_bitmap(bmap1, 1024, bmap2, 1024);


			/*
			 * test short conversion bitmap -> u32[] (1
			 * word too short)
			 */
			if (used_u32s > 1) {
				bitmap_zero(bmap1, 1024);
				__set_bit(i, bmap1);
				bitmap_set(bmap1, nbits,
					   1024 - nbits);  /* garbage */
				memset(arr, 0xff, sizeof(arr));

				rv = bitmap_to_u32array(arr, used_u32s - 1,
							bmap1, nbits);
				expect_eq_uint((used_u32s - 1)*32, rv);

				/* 1st used u32 words contain expected
				 * bit set, the remaining words are
				 * left unchanged (0xff)
				 */
				memset(exp_arr, 0xff, sizeof(exp_arr));
				memset(exp_arr, 0,
				       (used_u32s-1)*sizeof(*exp_arr));
				if ((i/32) < (used_u32s - 1))
					exp_arr[i/32] = (1U<<(i%32));
				expect_eq_u32_array(exp_arr, 32, arr, 32);
			}

			/*
			 * test short conversion u32[] -> bitmap (3
			 * bits too short)
			 */
			if (nbits > 3) {
				memset(arr, 0xff, sizeof(arr));  /* garbage */
				memset(arr, 0, used_u32s*sizeof(*arr));
				arr[i/32] = (1U<<(i%32));

				bitmap_zero(bmap1, 1024);
				rv = bitmap_from_u32array(bmap1, nbits - 3,
							  arr, used_u32s);
				expect_eq_uint(nbits - 3, rv);

				/* we are expecting the bit < nbits -
				 * 3 (none otherwise), and the rest of
				 * bmap1 unchanged (0-filled)
				 */
				bitmap_zero(bmap2, 1024);
				if (i < nbits - 3)
					__set_bit(i, bmap2);
				expect_eq_bitmap(bmap2, 1024, bmap1, 1024);

				/* do the same with bmap1 initially
				 * 1-filled
				 */

				bitmap_fill(bmap1, 1024);
				rv = bitmap_from_u32array(bmap1, nbits - 3,
							 arr, used_u32s);
				expect_eq_uint(nbits - 3, rv);

				/* we are expecting the bit < nbits -
				 * 3 (none otherwise), and the rest of
				 * bmap1 unchanged (1-filled)
				 */
				bitmap_zero(bmap2, 1024);
				if (i < nbits - 3)
					__set_bit(i, bmap2);
				bitmap_set(bmap2, nbits-3, 1024 - nbits + 3);
				expect_eq_bitmap(bmap2, 1024, bmap1, 1024);
			}
		}
	unsigned int nbits, next_bit, len = sizeof(exp) * 8;
	u32 arr[sizeof(exp) / 4];
	DECLARE_BITMAP(bmap2, len);

	memset(arr, 0xa5, sizeof(arr));

	for (nbits = 0; nbits < len; ++nbits) {
		bitmap_to_arr32(arr, exp, nbits);
		bitmap_from_arr32(bmap2, arr, nbits);
		expect_eq_bitmap(bmap2, exp, nbits);

		next_bit = find_next_bit(bmap2,
				round_up(nbits, BITS_PER_LONG), nbits);
		if (next_bit < round_up(nbits, BITS_PER_LONG))
			pr_err("bitmap_copy_arr32(nbits == %d:"
				" tail is not safely cleared: %d\n",
				nbits, next_bit);

		if (nbits < len - 32)
			expect_eq_uint(arr[DIV_ROUND_UP(nbits, 32)],
								0xa5a5a5a5);
	}
}

@@ -454,7 +310,7 @@ static void noinline __init test_mem_optimisations(void)
static int __init test_bitmap_init(void)
{
	test_zero_fill_copy();
	test_bitmap_u32_array_conversions();
	test_bitmap_arr32();
	test_bitmap_parselist();
	test_mem_optimisations();

Loading