2016-08-31 19:46:44 +08:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2014 Felix Fietkau <nbd@nbd.name>
|
|
|
|
* Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License version 2
|
|
|
|
* as published by the Free Software Foundation
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef _LINUX_BITFIELD_H
|
|
|
|
#define _LINUX_BITFIELD_H
|
|
|
|
|
2017-11-18 07:27:49 +08:00
|
|
|
#include <linux/build_bug.h>
|
Add primitives for manipulating bitfields both in host- and fixed-endian.
The following primitives are defined in linux/bitfield.h:
* u32 le32_get_bits(__le32 val, u32 field) extracts the contents of the
bitfield specified by @field in little-endian 32bit object @val and
converts it to host-endian.
* void le32p_replace_bits(__le32 *p, u32 v, u32 field) replaces
the contents of the bitfield specified by @field in little-endian
32bit object pointed to by @p with the value of @v. New value is
given in host-endian and stored as little-endian.
* __le32 le32_replace_bits(__le32 old, u32 v, u32 field) is equivalent to
({__le32 tmp = old; le32p_replace_bits(&tmp, v, field); tmp;})
In other words, instead of modifying an object in memory, it takes
the initial value and returns the modified one.
* __le32 le32_encode_bits(u32 v, u32 field) is equivalent to
le32_replace_bits(0, v, field). In other words, it returns a little-endian
32bit object with the bitfield specified by @field containing the
value of @v and all bits outside that bitfield being zero.
Such set of helpers is defined for each of little-, big- and host-endian
types; e.g. u64_get_bits(val, field) will return the contents of the bitfield
specified by @field in host-endian 64bit object @val, etc. Of course, for
host-endian no conversion is involved.
Fields to access are specified as GENMASK() values - an N-bit field
starting at bit #M is encoded as GENMASK(M + N - 1, M). Note that
bit numbers refer to endianness of the object we are working with -
e.g. GENMASK(11, 0) in __be16 refers to the second byte and the lower
4 bits of the first byte. In __le16 it would refer to the first byte
and the lower 4 bits of the second byte, etc.
Field specification must be a constant; __builtin_constant_p() doesn't
have to be true for it, but compiler must be able to evaluate it at
build time. If it cannot or if the value does not encode any bitfield,
the build will fail.
If the value being stored in a bitfield is a constant that does not fit
into that bitfield, a warning will be generated at compile time.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2017-12-15 10:27:55 +08:00
|
|
|
#include <asm/byteorder.h>
|
2016-08-31 19:46:44 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Bitfield access macros
|
|
|
|
*
|
|
|
|
* FIELD_{GET,PREP} macros take as first parameter shifted mask
|
|
|
|
* from which they extract the base mask and shift amount.
|
|
|
|
* Mask must be a compilation time constant.
|
|
|
|
*
|
|
|
|
* Example:
|
|
|
|
*
|
|
|
|
* #define REG_FIELD_A GENMASK(6, 0)
|
|
|
|
* #define REG_FIELD_B BIT(7)
|
|
|
|
* #define REG_FIELD_C GENMASK(15, 8)
|
|
|
|
* #define REG_FIELD_D GENMASK(31, 16)
|
|
|
|
*
|
|
|
|
* Get:
|
|
|
|
* a = FIELD_GET(REG_FIELD_A, reg);
|
|
|
|
* b = FIELD_GET(REG_FIELD_B, reg);
|
|
|
|
*
|
|
|
|
* Set:
|
|
|
|
* reg = FIELD_PREP(REG_FIELD_A, 1) |
|
|
|
|
* FIELD_PREP(REG_FIELD_B, 0) |
|
|
|
|
* FIELD_PREP(REG_FIELD_C, c) |
|
|
|
|
* FIELD_PREP(REG_FIELD_D, 0x40);
|
|
|
|
*
|
|
|
|
* Modify:
|
|
|
|
* reg &= ~REG_FIELD_C;
|
|
|
|
* reg |= FIELD_PREP(REG_FIELD_C, c);
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define __bf_shf(x) (__builtin_ffsll(x) - 1)
|
|
|
|
|
|
|
|
#define __BF_FIELD_CHECK(_mask, _reg, _val, _pfx) \
|
|
|
|
({ \
|
|
|
|
BUILD_BUG_ON_MSG(!__builtin_constant_p(_mask), \
|
|
|
|
_pfx "mask is not constant"); \
|
bitfield: avoid gcc-8 -Wint-in-bool-context warning
Passing an enum into FIELD_GET() produces a long but harmless warning on
newer compilers:
from include/linux/linkage.h:7,
from include/linux/kernel.h:7,
from include/linux/skbuff.h:17,
from include/linux/if_ether.h:23,
from include/linux/etherdevice.h:25,
from drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c:63:
drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c: In function 'iwl_mvm_rx_mpdu_mq':
include/linux/bitfield.h:56:20: error: enum constant in boolean context [-Werror=int-in-bool-context]
BUILD_BUG_ON_MSG(!(_mask), _pfx "mask is zero"); \
^
...
include/linux/bitfield.h:103:3: note: in expansion of macro '__BF_FIELD_CHECK'
__BF_FIELD_CHECK(_mask, _reg, 0U, "FIELD_GET: "); \
^~~~~~~~~~~~~~~~
drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c:1025:21: note: in expansion of macro 'FIELD_GET'
le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_SIBG_SYM_OR_USER_NUM_MASK,
The problem here is that the caller has no idea how the macro gets
expanding, leading to a false-positive. It can be trivially avoided by
doing a comparison against zero.
This only recently started appearing as the iwlwifi driver was patched
to use FIELD_GET.
Link: http://lkml.kernel.org/r/20180813220950.194841-1-arnd@arndb.de
Fixes: 514c30696fbc ("iwlwifi: add support for IEEE802.11ax")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Cc: Masahiro Yamada <yamada.masahiro@socionext.com>
Cc: Johannes Berg <johannes@sipsolutions.net>
Cc: Jakub Kicinski <jakub.kicinski@netronome.com>
Cc: Andy Shevchenko <andy.shevchenko@gmail.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: David Laight <David.Laight@ACULAB.COM>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2018-08-18 06:43:36 +08:00
|
|
|
BUILD_BUG_ON_MSG((_mask) == 0, _pfx "mask is zero"); \
|
2016-08-31 19:46:44 +08:00
|
|
|
BUILD_BUG_ON_MSG(__builtin_constant_p(_val) ? \
|
|
|
|
~((_mask) >> __bf_shf(_mask)) & (_val) : 0, \
|
|
|
|
_pfx "value too large for the field"); \
|
|
|
|
BUILD_BUG_ON_MSG((_mask) > (typeof(_reg))~0ull, \
|
|
|
|
_pfx "type of reg too small for mask"); \
|
|
|
|
__BUILD_BUG_ON_NOT_POWER_OF_2((_mask) + \
|
|
|
|
(1ULL << __bf_shf(_mask))); \
|
|
|
|
})
|
|
|
|
|
2017-02-10 01:17:27 +08:00
|
|
|
/**
|
|
|
|
* FIELD_FIT() - check if value fits in the field
|
|
|
|
* @_mask: shifted mask defining the field's length and position
|
|
|
|
* @_val: value to test against the field
|
|
|
|
*
|
|
|
|
* Return: true if @_val can fit inside @_mask, false if @_val is too big.
|
|
|
|
*/
|
|
|
|
#define FIELD_FIT(_mask, _val) \
|
|
|
|
({ \
|
|
|
|
__BF_FIELD_CHECK(_mask, 0ULL, _val, "FIELD_FIT: "); \
|
|
|
|
!((((typeof(_mask))_val) << __bf_shf(_mask)) & ~(_mask)); \
|
|
|
|
})
|
|
|
|
|
2016-08-31 19:46:44 +08:00
|
|
|
/**
|
|
|
|
* FIELD_PREP() - prepare a bitfield element
|
|
|
|
* @_mask: shifted mask defining the field's length and position
|
|
|
|
* @_val: value to put in the field
|
|
|
|
*
|
|
|
|
* FIELD_PREP() masks and shifts up the value. The result should
|
|
|
|
* be combined with other fields of the bitfield using logical OR.
|
|
|
|
*/
|
|
|
|
#define FIELD_PREP(_mask, _val) \
|
|
|
|
({ \
|
|
|
|
__BF_FIELD_CHECK(_mask, 0ULL, _val, "FIELD_PREP: "); \
|
|
|
|
((typeof(_mask))(_val) << __bf_shf(_mask)) & (_mask); \
|
|
|
|
})
|
|
|
|
|
|
|
|
/**
|
|
|
|
* FIELD_GET() - extract a bitfield element
|
|
|
|
* @_mask: shifted mask defining the field's length and position
|
2017-10-04 07:16:04 +08:00
|
|
|
* @_reg: value of entire bitfield
|
2016-08-31 19:46:44 +08:00
|
|
|
*
|
|
|
|
* FIELD_GET() extracts the field specified by @_mask from the
|
|
|
|
* bitfield passed in as @_reg by masking and shifting it down.
|
|
|
|
*/
|
|
|
|
#define FIELD_GET(_mask, _reg) \
|
|
|
|
({ \
|
|
|
|
__BF_FIELD_CHECK(_mask, _reg, 0U, "FIELD_GET: "); \
|
|
|
|
(typeof(_mask))(((_reg) & (_mask)) >> __bf_shf(_mask)); \
|
|
|
|
})
|
|
|
|
|
2018-06-20 14:58:28 +08:00
|
|
|
extern void __compiletime_error("value doesn't fit into mask")
|
Add primitives for manipulating bitfields both in host- and fixed-endian.
The following primitives are defined in linux/bitfield.h:
* u32 le32_get_bits(__le32 val, u32 field) extracts the contents of the
bitfield specified by @field in little-endian 32bit object @val and
converts it to host-endian.
* void le32p_replace_bits(__le32 *p, u32 v, u32 field) replaces
the contents of the bitfield specified by @field in little-endian
32bit object pointed to by @p with the value of @v. New value is
given in host-endian and stored as little-endian.
* __le32 le32_replace_bits(__le32 old, u32 v, u32 field) is equivalent to
({__le32 tmp = old; le32p_replace_bits(&tmp, v, field); tmp;})
In other words, instead of modifying an object in memory, it takes
the initial value and returns the modified one.
* __le32 le32_encode_bits(u32 v, u32 field) is equivalent to
le32_replace_bits(0, v, field). In other words, it returns a little-endian
32bit object with the bitfield specified by @field containing the
value of @v and all bits outside that bitfield being zero.
Such set of helpers is defined for each of little-, big- and host-endian
types; e.g. u64_get_bits(val, field) will return the contents of the bitfield
specified by @field in host-endian 64bit object @val, etc. Of course, for
host-endian no conversion is involved.
Fields to access are specified as GENMASK() values - an N-bit field
starting at bit #M is encoded as GENMASK(M + N - 1, M). Note that
bit numbers refer to endianness of the object we are working with -
e.g. GENMASK(11, 0) in __be16 refers to the second byte and the lower
4 bits of the first byte. In __le16 it would refer to the first byte
and the lower 4 bits of the second byte, etc.
Field specification must be a constant; __builtin_constant_p() doesn't
have to be true for it, but compiler must be able to evaluate it at
build time. If it cannot or if the value does not encode any bitfield,
the build will fail.
If the value being stored in a bitfield is a constant that does not fit
into that bitfield, a warning will be generated at compile time.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2017-12-15 10:27:55 +08:00
|
|
|
__field_overflow(void);
|
|
|
|
extern void __compiletime_error("bad bitfield mask")
|
|
|
|
__bad_mask(void);
|
|
|
|
static __always_inline u64 field_multiplier(u64 field)
|
|
|
|
{
|
|
|
|
if ((field | (field - 1)) & ((field | (field - 1)) + 1))
|
|
|
|
__bad_mask();
|
|
|
|
return field & -field;
|
|
|
|
}
|
|
|
|
static __always_inline u64 field_mask(u64 field)
|
|
|
|
{
|
|
|
|
return field / field_multiplier(field);
|
|
|
|
}
|
|
|
|
#define ____MAKE_OP(type,base,to,from) \
|
|
|
|
static __always_inline __##type type##_encode_bits(base v, base field) \
|
|
|
|
{ \
|
2018-06-20 14:58:28 +08:00
|
|
|
if (__builtin_constant_p(v) && (v & ~field_mask(field))) \
|
|
|
|
__field_overflow(); \
|
Add primitives for manipulating bitfields both in host- and fixed-endian.
The following primitives are defined in linux/bitfield.h:
* u32 le32_get_bits(__le32 val, u32 field) extracts the contents of the
bitfield specified by @field in little-endian 32bit object @val and
converts it to host-endian.
* void le32p_replace_bits(__le32 *p, u32 v, u32 field) replaces
the contents of the bitfield specified by @field in little-endian
32bit object pointed to by @p with the value of @v. New value is
given in host-endian and stored as little-endian.
* __le32 le32_replace_bits(__le32 old, u32 v, u32 field) is equivalent to
({__le32 tmp = old; le32p_replace_bits(&tmp, v, field); tmp;})
In other words, instead of modifying an object in memory, it takes
the initial value and returns the modified one.
* __le32 le32_encode_bits(u32 v, u32 field) is equivalent to
le32_replace_bits(0, v, field). In other words, it returns a little-endian
32bit object with the bitfield specified by @field containing the
value of @v and all bits outside that bitfield being zero.
Such set of helpers is defined for each of little-, big- and host-endian
types; e.g. u64_get_bits(val, field) will return the contents of the bitfield
specified by @field in host-endian 64bit object @val, etc. Of course, for
host-endian no conversion is involved.
Fields to access are specified as GENMASK() values - an N-bit field
starting at bit #M is encoded as GENMASK(M + N - 1, M). Note that
bit numbers refer to endianness of the object we are working with -
e.g. GENMASK(11, 0) in __be16 refers to the second byte and the lower
4 bits of the first byte. In __le16 it would refer to the first byte
and the lower 4 bits of the second byte, etc.
Field specification must be a constant; __builtin_constant_p() doesn't
have to be true for it, but compiler must be able to evaluate it at
build time. If it cannot or if the value does not encode any bitfield,
the build will fail.
If the value being stored in a bitfield is a constant that does not fit
into that bitfield, a warning will be generated at compile time.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2017-12-15 10:27:55 +08:00
|
|
|
return to((v & field_mask(field)) * field_multiplier(field)); \
|
|
|
|
} \
|
|
|
|
static __always_inline __##type type##_replace_bits(__##type old, \
|
|
|
|
base val, base field) \
|
|
|
|
{ \
|
|
|
|
return (old & ~to(field)) | type##_encode_bits(val, field); \
|
|
|
|
} \
|
|
|
|
static __always_inline void type##p_replace_bits(__##type *p, \
|
|
|
|
base val, base field) \
|
|
|
|
{ \
|
|
|
|
*p = (*p & ~to(field)) | type##_encode_bits(val, field); \
|
|
|
|
} \
|
|
|
|
static __always_inline base type##_get_bits(__##type v, base field) \
|
|
|
|
{ \
|
|
|
|
return (from(v) & field)/field_multiplier(field); \
|
|
|
|
}
|
|
|
|
#define __MAKE_OP(size) \
|
|
|
|
____MAKE_OP(le##size,u##size,cpu_to_le##size,le##size##_to_cpu) \
|
|
|
|
____MAKE_OP(be##size,u##size,cpu_to_be##size,be##size##_to_cpu) \
|
|
|
|
____MAKE_OP(u##size,u##size,,)
|
2018-06-20 14:58:29 +08:00
|
|
|
____MAKE_OP(u8,u8,,)
|
Add primitives for manipulating bitfields both in host- and fixed-endian.
The following primitives are defined in linux/bitfield.h:
* u32 le32_get_bits(__le32 val, u32 field) extracts the contents of the
bitfield specified by @field in little-endian 32bit object @val and
converts it to host-endian.
* void le32p_replace_bits(__le32 *p, u32 v, u32 field) replaces
the contents of the bitfield specified by @field in little-endian
32bit object pointed to by @p with the value of @v. New value is
given in host-endian and stored as little-endian.
* __le32 le32_replace_bits(__le32 old, u32 v, u32 field) is equivalent to
({__le32 tmp = old; le32p_replace_bits(&tmp, v, field); tmp;})
In other words, instead of modifying an object in memory, it takes
the initial value and returns the modified one.
* __le32 le32_encode_bits(u32 v, u32 field) is equivalent to
le32_replace_bits(0, v, field). In other words, it returns a little-endian
32bit object with the bitfield specified by @field containing the
value of @v and all bits outside that bitfield being zero.
Such set of helpers is defined for each of little-, big- and host-endian
types; e.g. u64_get_bits(val, field) will return the contents of the bitfield
specified by @field in host-endian 64bit object @val, etc. Of course, for
host-endian no conversion is involved.
Fields to access are specified as GENMASK() values - an N-bit field
starting at bit #M is encoded as GENMASK(M + N - 1, M). Note that
bit numbers refer to endianness of the object we are working with -
e.g. GENMASK(11, 0) in __be16 refers to the second byte and the lower
4 bits of the first byte. In __le16 it would refer to the first byte
and the lower 4 bits of the second byte, etc.
Field specification must be a constant; __builtin_constant_p() doesn't
have to be true for it, but compiler must be able to evaluate it at
build time. If it cannot or if the value does not encode any bitfield,
the build will fail.
If the value being stored in a bitfield is a constant that does not fit
into that bitfield, a warning will be generated at compile time.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2017-12-15 10:27:55 +08:00
|
|
|
__MAKE_OP(16)
|
|
|
|
__MAKE_OP(32)
|
|
|
|
__MAKE_OP(64)
|
|
|
|
#undef __MAKE_OP
|
|
|
|
#undef ____MAKE_OP
|
|
|
|
|
2016-08-31 19:46:44 +08:00
|
|
|
#endif
|