mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-04 01:49:36 +00:00
![Thomas Gleixner](/assets/img/avatar_default.png)
Based on 1 normalized pattern(s): 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 extracted by the scancode license scanner the SPDX license identifier GPL-2.0-only has been chosen to replace the boilerplate/reference in 655 file(s). Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Reviewed-by: Allison Randal <allison@lohutok.net> Reviewed-by: Kate Stewart <kstewart@linuxfoundation.org> Reviewed-by: Richard Fontana <rfontana@redhat.com> Cc: linux-spdx@vger.kernel.org Link: https://lkml.kernel.org/r/20190527070034.575739538@linutronix.de Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
145 lines
4.3 KiB
C
145 lines
4.3 KiB
C
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
/*
|
|
* Copyright (C) 2014 Felix Fietkau <nbd@nbd.name>
|
|
* Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
|
|
*/
|
|
|
|
#ifndef _LINUX_BITFIELD_H
|
|
#define _LINUX_BITFIELD_H
|
|
|
|
#include <linux/build_bug.h>
|
|
#include <asm/byteorder.h>
|
|
|
|
/*
|
|
* 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"); \
|
|
BUILD_BUG_ON_MSG((_mask) == 0, _pfx "mask is zero"); \
|
|
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))); \
|
|
})
|
|
|
|
/**
|
|
* 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)); \
|
|
})
|
|
|
|
/**
|
|
* 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
|
|
* @_reg: value of entire bitfield
|
|
*
|
|
* 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)); \
|
|
})
|
|
|
|
extern void __compiletime_error("value doesn't fit into mask")
|
|
__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) \
|
|
{ \
|
|
if (__builtin_constant_p(v) && (v & ~field_mask(field))) \
|
|
__field_overflow(); \
|
|
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,,)
|
|
____MAKE_OP(u8,u8,,)
|
|
__MAKE_OP(16)
|
|
__MAKE_OP(32)
|
|
__MAKE_OP(64)
|
|
#undef __MAKE_OP
|
|
#undef ____MAKE_OP
|
|
|
|
#endif
|