xref: /openbmc/linux/include/rdma/iba.h (revision d05d4ac4)
1d05d4ac4SLeon Romanovsky /* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
2d05d4ac4SLeon Romanovsky /*
3d05d4ac4SLeon Romanovsky  * Copyright (c) 2020, Mellanox Technologies inc.  All rights reserved.
4d05d4ac4SLeon Romanovsky  */
5d05d4ac4SLeon Romanovsky #ifndef _IBA_DEFS_H_
6d05d4ac4SLeon Romanovsky #define _IBA_DEFS_H_
7d05d4ac4SLeon Romanovsky 
8d05d4ac4SLeon Romanovsky #include <linux/kernel.h>
9d05d4ac4SLeon Romanovsky #include <linux/bitfield.h>
10d05d4ac4SLeon Romanovsky #include <asm/unaligned.h>
11d05d4ac4SLeon Romanovsky 
_iba_get8(const u8 * ptr)12d05d4ac4SLeon Romanovsky static inline u32 _iba_get8(const u8 *ptr)
13d05d4ac4SLeon Romanovsky {
14d05d4ac4SLeon Romanovsky 	return *ptr;
15d05d4ac4SLeon Romanovsky }
16d05d4ac4SLeon Romanovsky 
_iba_set8(u8 * ptr,u32 mask,u32 prep_value)17d05d4ac4SLeon Romanovsky static inline void _iba_set8(u8 *ptr, u32 mask, u32 prep_value)
18d05d4ac4SLeon Romanovsky {
19d05d4ac4SLeon Romanovsky 	*ptr = (*ptr & ~mask) | prep_value;
20d05d4ac4SLeon Romanovsky }
21d05d4ac4SLeon Romanovsky 
_iba_get16(const __be16 * ptr)22d05d4ac4SLeon Romanovsky static inline u16 _iba_get16(const __be16 *ptr)
23d05d4ac4SLeon Romanovsky {
24d05d4ac4SLeon Romanovsky 	return be16_to_cpu(*ptr);
25d05d4ac4SLeon Romanovsky }
26d05d4ac4SLeon Romanovsky 
_iba_set16(__be16 * ptr,u16 mask,u16 prep_value)27d05d4ac4SLeon Romanovsky static inline void _iba_set16(__be16 *ptr, u16 mask, u16 prep_value)
28d05d4ac4SLeon Romanovsky {
29d05d4ac4SLeon Romanovsky 	*ptr = cpu_to_be16((be16_to_cpu(*ptr) & ~mask) | prep_value);
30d05d4ac4SLeon Romanovsky }
31d05d4ac4SLeon Romanovsky 
_iba_get32(const __be32 * ptr)32d05d4ac4SLeon Romanovsky static inline u32 _iba_get32(const __be32 *ptr)
33d05d4ac4SLeon Romanovsky {
34d05d4ac4SLeon Romanovsky 	return be32_to_cpu(*ptr);
35d05d4ac4SLeon Romanovsky }
36d05d4ac4SLeon Romanovsky 
_iba_set32(__be32 * ptr,u32 mask,u32 prep_value)37d05d4ac4SLeon Romanovsky static inline void _iba_set32(__be32 *ptr, u32 mask, u32 prep_value)
38d05d4ac4SLeon Romanovsky {
39d05d4ac4SLeon Romanovsky 	*ptr = cpu_to_be32((be32_to_cpu(*ptr) & ~mask) | prep_value);
40d05d4ac4SLeon Romanovsky }
41d05d4ac4SLeon Romanovsky 
_iba_get64(const __be64 * ptr)42d05d4ac4SLeon Romanovsky static inline u64 _iba_get64(const __be64 *ptr)
43d05d4ac4SLeon Romanovsky {
44d05d4ac4SLeon Romanovsky 	/*
45d05d4ac4SLeon Romanovsky 	 * The mads are constructed so that 32 bit and smaller are naturally
46d05d4ac4SLeon Romanovsky 	 * aligned, everything larger has a max alignment of 4 bytes.
47d05d4ac4SLeon Romanovsky 	 */
48d05d4ac4SLeon Romanovsky 	return be64_to_cpu(get_unaligned(ptr));
49d05d4ac4SLeon Romanovsky }
50d05d4ac4SLeon Romanovsky 
_iba_set64(__be64 * ptr,u64 mask,u64 prep_value)51d05d4ac4SLeon Romanovsky static inline void _iba_set64(__be64 *ptr, u64 mask, u64 prep_value)
52d05d4ac4SLeon Romanovsky {
53d05d4ac4SLeon Romanovsky 	put_unaligned(cpu_to_be64((_iba_get64(ptr) & ~mask) | prep_value), ptr);
54d05d4ac4SLeon Romanovsky }
55d05d4ac4SLeon Romanovsky 
56d05d4ac4SLeon Romanovsky #define _IBA_SET(field_struct, field_offset, field_mask, num_bits, ptr, value) \
57d05d4ac4SLeon Romanovsky 	({                                                                     \
58d05d4ac4SLeon Romanovsky 		field_struct *_ptr = ptr;                                      \
59d05d4ac4SLeon Romanovsky 		_iba_set##num_bits((void *)_ptr + (field_offset), field_mask,  \
60d05d4ac4SLeon Romanovsky 				   FIELD_PREP(field_mask, value));             \
61d05d4ac4SLeon Romanovsky 	})
62d05d4ac4SLeon Romanovsky #define IBA_SET(field, ptr, value) _IBA_SET(field, ptr, value)
63d05d4ac4SLeon Romanovsky 
64d05d4ac4SLeon Romanovsky #define _IBA_GET_MEM_PTR(field_struct, field_offset, type, num_bits, ptr)      \
65d05d4ac4SLeon Romanovsky 	({                                                                     \
66d05d4ac4SLeon Romanovsky 		field_struct *_ptr = ptr;                                      \
67d05d4ac4SLeon Romanovsky 		(type *)((void *)_ptr + (field_offset));                       \
68d05d4ac4SLeon Romanovsky 	})
69d05d4ac4SLeon Romanovsky #define IBA_GET_MEM_PTR(field, ptr) _IBA_GET_MEM_PTR(field, ptr)
70d05d4ac4SLeon Romanovsky 
71d05d4ac4SLeon Romanovsky /* FIXME: A set should always set the entire field, meaning we should zero the trailing bytes */
72d05d4ac4SLeon Romanovsky #define _IBA_SET_MEM(field_struct, field_offset, type, num_bits, ptr, in,      \
73d05d4ac4SLeon Romanovsky 		     bytes)                                                    \
74d05d4ac4SLeon Romanovsky 	({                                                                     \
75d05d4ac4SLeon Romanovsky 		const type *_in_ptr = in;                                      \
76d05d4ac4SLeon Romanovsky 		WARN_ON(bytes * 8 > num_bits);                                 \
77d05d4ac4SLeon Romanovsky 		if (in && bytes)                                               \
78d05d4ac4SLeon Romanovsky 			memcpy(_IBA_GET_MEM_PTR(field_struct, field_offset,    \
79d05d4ac4SLeon Romanovsky 						type, num_bits, ptr),          \
80d05d4ac4SLeon Romanovsky 			       _in_ptr, bytes);                                \
81d05d4ac4SLeon Romanovsky 	})
82d05d4ac4SLeon Romanovsky #define IBA_SET_MEM(field, ptr, in, bytes) _IBA_SET_MEM(field, ptr, in, bytes)
83d05d4ac4SLeon Romanovsky 
84d05d4ac4SLeon Romanovsky #define _IBA_GET(field_struct, field_offset, field_mask, num_bits, ptr)        \
85d05d4ac4SLeon Romanovsky 	({                                                                     \
86d05d4ac4SLeon Romanovsky 		const field_struct *_ptr = ptr;                                \
87d05d4ac4SLeon Romanovsky 		(u##num_bits) FIELD_GET(                                       \
88d05d4ac4SLeon Romanovsky 			field_mask, _iba_get##num_bits((const void *)_ptr +    \
89d05d4ac4SLeon Romanovsky 						       (field_offset)));       \
90d05d4ac4SLeon Romanovsky 	})
91d05d4ac4SLeon Romanovsky #define IBA_GET(field, ptr) _IBA_GET(field, ptr)
92d05d4ac4SLeon Romanovsky 
93d05d4ac4SLeon Romanovsky #define _IBA_GET_MEM(field_struct, field_offset, type, num_bits, ptr, out,     \
94d05d4ac4SLeon Romanovsky 		     bytes)                                                    \
95d05d4ac4SLeon Romanovsky 	({                                                                     \
96d05d4ac4SLeon Romanovsky 		type *_out_ptr = out;                                          \
97d05d4ac4SLeon Romanovsky 		WARN_ON(bytes * 8 > num_bits);                                 \
98d05d4ac4SLeon Romanovsky 		if (out && bytes)                                              \
99d05d4ac4SLeon Romanovsky 			memcpy(_out_ptr,                                       \
100d05d4ac4SLeon Romanovsky 			       _IBA_GET_MEM_PTR(field_struct, field_offset,    \
101d05d4ac4SLeon Romanovsky 						type, num_bits, ptr),          \
102d05d4ac4SLeon Romanovsky 			       bytes);                                         \
103d05d4ac4SLeon Romanovsky 	})
104d05d4ac4SLeon Romanovsky #define IBA_GET_MEM(field, ptr, out, bytes) _IBA_GET_MEM(field, ptr, out, bytes)
105d05d4ac4SLeon Romanovsky 
106d05d4ac4SLeon Romanovsky /*
107d05d4ac4SLeon Romanovsky  * The generated list becomes the parameters to the macros, the order is:
108d05d4ac4SLeon Romanovsky  *  - struct this applies to
109d05d4ac4SLeon Romanovsky  *  - starting offset of the max
110d05d4ac4SLeon Romanovsky  *  - GENMASK or GENMASK_ULL in CPU order
111d05d4ac4SLeon Romanovsky  *  - The width of data the mask operations should work on, in bits
112d05d4ac4SLeon Romanovsky  */
113d05d4ac4SLeon Romanovsky 
114d05d4ac4SLeon Romanovsky /*
115d05d4ac4SLeon Romanovsky  * Extraction using a tabular description like table 106. bit_offset is from
116d05d4ac4SLeon Romanovsky  * the Byte[Bit] notation.
117d05d4ac4SLeon Romanovsky  */
118d05d4ac4SLeon Romanovsky #define IBA_FIELD_BLOC(field_struct, byte_offset, bit_offset, num_bits)        \
119d05d4ac4SLeon Romanovsky 	field_struct, byte_offset,                                             \
120d05d4ac4SLeon Romanovsky 		GENMASK(7 - (bit_offset), 7 - (bit_offset) - (num_bits - 1)),  \
121d05d4ac4SLeon Romanovsky 		8
122d05d4ac4SLeon Romanovsky #define IBA_FIELD8_LOC(field_struct, byte_offset, num_bits)                    \
123d05d4ac4SLeon Romanovsky 	IBA_FIELD_BLOC(field_struct, byte_offset, 0, num_bits)
124d05d4ac4SLeon Romanovsky 
125d05d4ac4SLeon Romanovsky #define IBA_FIELD16_LOC(field_struct, byte_offset, num_bits)                   \
126d05d4ac4SLeon Romanovsky 	field_struct, (byte_offset)&0xFFFE,                                    \
127d05d4ac4SLeon Romanovsky 		GENMASK(15 - (((byte_offset) % 2) * 8),                        \
128d05d4ac4SLeon Romanovsky 			15 - (((byte_offset) % 2) * 8) - (num_bits - 1)),      \
129d05d4ac4SLeon Romanovsky 		16
130d05d4ac4SLeon Romanovsky 
131d05d4ac4SLeon Romanovsky #define IBA_FIELD32_LOC(field_struct, byte_offset, num_bits)                   \
132d05d4ac4SLeon Romanovsky 	field_struct, (byte_offset)&0xFFFC,                                    \
133d05d4ac4SLeon Romanovsky 		GENMASK(31 - (((byte_offset) % 4) * 8),                        \
134d05d4ac4SLeon Romanovsky 			31 - (((byte_offset) % 4) * 8) - (num_bits - 1)),      \
135d05d4ac4SLeon Romanovsky 		32
136d05d4ac4SLeon Romanovsky 
137d05d4ac4SLeon Romanovsky #define IBA_FIELD64_LOC(field_struct, byte_offset)                             \
138d05d4ac4SLeon Romanovsky 	field_struct, byte_offset, GENMASK_ULL(63, 0), 64
139d05d4ac4SLeon Romanovsky /*
140d05d4ac4SLeon Romanovsky  * In IBTA spec, everything that is more than 64bits is multiple
141d05d4ac4SLeon Romanovsky  * of bytes without leftover bits.
142d05d4ac4SLeon Romanovsky  */
143d05d4ac4SLeon Romanovsky #define IBA_FIELD_MLOC(field_struct, byte_offset, num_bits, type)              \
144d05d4ac4SLeon Romanovsky 	field_struct, byte_offset, type, num_bits
145d05d4ac4SLeon Romanovsky 
146d05d4ac4SLeon Romanovsky #endif /* _IBA_DEFS_H_ */
147