diff options
Diffstat (limited to 'include/linux/bitfield.h')
| -rw-r--r-- | include/linux/bitfield.h | 26 | 
1 files changed, 26 insertions, 0 deletions
diff --git a/include/linux/bitfield.h b/include/linux/bitfield.h index c9be1657f03d..ebfa12f69501 100644 --- a/include/linux/bitfield.h +++ b/include/linux/bitfield.h @@ -115,6 +115,32 @@  		((typeof(_mask))(_val) << __bf_shf(_mask)) & (_mask);	\  	}) +#define __BF_CHECK_POW2(n)	BUILD_BUG_ON_ZERO(((n) & ((n) - 1)) != 0) + +/** + * FIELD_PREP_CONST() - prepare a constant bitfield element + * @_mask: shifted mask defining the field's length and position + * @_val:  value to put in the field + * + * FIELD_PREP_CONST() masks and shifts up the value.  The result should + * be combined with other fields of the bitfield using logical OR. + * + * Unlike FIELD_PREP() this is a constant expression and can therefore + * be used in initializers. Error checking is less comfortable for this + * version, and non-constant masks cannot be used. + */ +#define FIELD_PREP_CONST(_mask, _val)					\ +	(								\ +		/* mask must be non-zero */				\ +		BUILD_BUG_ON_ZERO((_mask) == 0) +			\ +		/* check if value fits */				\ +		BUILD_BUG_ON_ZERO(~((_mask) >> __bf_shf(_mask)) & (_val)) + \ +		/* check if mask is contiguous */			\ +		__BF_CHECK_POW2((_mask) + (1ULL << __bf_shf(_mask))) +	\ +		/* and create the value */				\ +		(((typeof(_mask))(_val) << __bf_shf(_mask)) & (_mask))	\ +	) +  /**   * FIELD_GET() - extract a bitfield element   * @_mask: shifted mask defining the field's length and position  |