xref: /linux-6.15/include/net/libeth/cache.h (revision 62c88425)
1*62c88425SAlexander Lobakin /* SPDX-License-Identifier: GPL-2.0-only */
2*62c88425SAlexander Lobakin /* Copyright (C) 2024 Intel Corporation */
3*62c88425SAlexander Lobakin 
4*62c88425SAlexander Lobakin #ifndef __LIBETH_CACHE_H
5*62c88425SAlexander Lobakin #define __LIBETH_CACHE_H
6*62c88425SAlexander Lobakin 
7*62c88425SAlexander Lobakin #include <linux/cache.h>
8*62c88425SAlexander Lobakin 
9*62c88425SAlexander Lobakin /**
10*62c88425SAlexander Lobakin  * libeth_cacheline_group_assert - make sure cacheline group size is expected
11*62c88425SAlexander Lobakin  * @type: type of the structure containing the group
12*62c88425SAlexander Lobakin  * @grp: group name inside the struct
13*62c88425SAlexander Lobakin  * @sz: expected group size
14*62c88425SAlexander Lobakin  */
15*62c88425SAlexander Lobakin #if defined(CONFIG_64BIT) && SMP_CACHE_BYTES == 64
16*62c88425SAlexander Lobakin #define libeth_cacheline_group_assert(type, grp, sz)			      \
17*62c88425SAlexander Lobakin 	static_assert(offsetof(type, __cacheline_group_end__##grp) -	      \
18*62c88425SAlexander Lobakin 		      offsetofend(type, __cacheline_group_begin__##grp) ==    \
19*62c88425SAlexander Lobakin 		      (sz))
20*62c88425SAlexander Lobakin #define __libeth_cacheline_struct_assert(type, sz)			      \
21*62c88425SAlexander Lobakin 	static_assert(sizeof(type) == (sz))
22*62c88425SAlexander Lobakin #else /* !CONFIG_64BIT || SMP_CACHE_BYTES != 64 */
23*62c88425SAlexander Lobakin #define libeth_cacheline_group_assert(type, grp, sz)			      \
24*62c88425SAlexander Lobakin 	static_assert(offsetof(type, __cacheline_group_end__##grp) -	      \
25*62c88425SAlexander Lobakin 		      offsetofend(type, __cacheline_group_begin__##grp) <=    \
26*62c88425SAlexander Lobakin 		      (sz))
27*62c88425SAlexander Lobakin #define __libeth_cacheline_struct_assert(type, sz)			      \
28*62c88425SAlexander Lobakin 	static_assert(sizeof(type) <= (sz))
29*62c88425SAlexander Lobakin #endif /* !CONFIG_64BIT || SMP_CACHE_BYTES != 64 */
30*62c88425SAlexander Lobakin 
31*62c88425SAlexander Lobakin #define __libeth_cls1(sz1)	SMP_CACHE_ALIGN(sz1)
32*62c88425SAlexander Lobakin #define __libeth_cls2(sz1, sz2)	(SMP_CACHE_ALIGN(sz1) + SMP_CACHE_ALIGN(sz2))
33*62c88425SAlexander Lobakin #define __libeth_cls3(sz1, sz2, sz3)					      \
34*62c88425SAlexander Lobakin 	(SMP_CACHE_ALIGN(sz1) + SMP_CACHE_ALIGN(sz2) + SMP_CACHE_ALIGN(sz3))
35*62c88425SAlexander Lobakin #define __libeth_cls(...)						      \
36*62c88425SAlexander Lobakin 	CONCATENATE(__libeth_cls, COUNT_ARGS(__VA_ARGS__))(__VA_ARGS__)
37*62c88425SAlexander Lobakin 
38*62c88425SAlexander Lobakin /**
39*62c88425SAlexander Lobakin  * libeth_cacheline_struct_assert - make sure CL-based struct size is expected
40*62c88425SAlexander Lobakin  * @type: type of the struct
41*62c88425SAlexander Lobakin  * @...: from 1 to 3 CL group sizes (read-mostly, read-write, cold)
42*62c88425SAlexander Lobakin  *
43*62c88425SAlexander Lobakin  * When a struct contains several CL groups, it's difficult to predict its size
44*62c88425SAlexander Lobakin  * on different architectures. The macro instead takes sizes of all of the
45*62c88425SAlexander Lobakin  * groups the structure contains and generates the final struct size.
46*62c88425SAlexander Lobakin  */
47*62c88425SAlexander Lobakin #define libeth_cacheline_struct_assert(type, ...)			      \
48*62c88425SAlexander Lobakin 	__libeth_cacheline_struct_assert(type, __libeth_cls(__VA_ARGS__));    \
49*62c88425SAlexander Lobakin 	static_assert(__alignof(type) >= SMP_CACHE_BYTES)
50*62c88425SAlexander Lobakin 
51*62c88425SAlexander Lobakin /**
52*62c88425SAlexander Lobakin  * libeth_cacheline_set_assert - make sure CL-based struct layout is expected
53*62c88425SAlexander Lobakin  * @type: type of the struct
54*62c88425SAlexander Lobakin  * @ro: expected size of the read-mostly group
55*62c88425SAlexander Lobakin  * @rw: expected size of the read-write group
56*62c88425SAlexander Lobakin  * @c: expected size of the cold group
57*62c88425SAlexander Lobakin  *
58*62c88425SAlexander Lobakin  * Check that each group size is expected and then do final struct size check.
59*62c88425SAlexander Lobakin  */
60*62c88425SAlexander Lobakin #define libeth_cacheline_set_assert(type, ro, rw, c)			      \
61*62c88425SAlexander Lobakin 	libeth_cacheline_group_assert(type, read_mostly, ro);		      \
62*62c88425SAlexander Lobakin 	libeth_cacheline_group_assert(type, read_write, rw);		      \
63*62c88425SAlexander Lobakin 	libeth_cacheline_group_assert(type, cold, c);			      \
64*62c88425SAlexander Lobakin 	libeth_cacheline_struct_assert(type, ro, rw, c)
65*62c88425SAlexander Lobakin 
66*62c88425SAlexander Lobakin #endif /* __LIBETH_CACHE_H */
67