Merge tag 'regmap-fix-v5.0-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git...
[sfrench/cifs-2.6.git] / drivers / net / ethernet / mellanox / mlxsw / spectrum_acl_flex_keys.c
1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /* Copyright (c) 2017-2018 Mellanox Technologies. All rights reserved */
3
4 #include <linux/kernel.h>
5 #include <linux/module.h>
6 #include "spectrum.h"
7 #include "item.h"
8 #include "core_acl_flex_keys.h"
9
10 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_l2_dmac[] = {
11         MLXSW_AFK_ELEMENT_INST_BUF(DMAC_32_47, 0x00, 2),
12         MLXSW_AFK_ELEMENT_INST_BUF(DMAC_0_31, 0x02, 4),
13         MLXSW_AFK_ELEMENT_INST_U32(PCP, 0x08, 13, 3),
14         MLXSW_AFK_ELEMENT_INST_U32(VID, 0x08, 0, 12),
15         MLXSW_AFK_ELEMENT_INST_U32(SRC_SYS_PORT, 0x0C, 0, 8),
16 };
17
18 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_l2_smac[] = {
19         MLXSW_AFK_ELEMENT_INST_BUF(SMAC_32_47, 0x00, 2),
20         MLXSW_AFK_ELEMENT_INST_BUF(SMAC_0_31, 0x02, 4),
21         MLXSW_AFK_ELEMENT_INST_U32(PCP, 0x08, 13, 3),
22         MLXSW_AFK_ELEMENT_INST_U32(VID, 0x08, 0, 12),
23         MLXSW_AFK_ELEMENT_INST_U32(SRC_SYS_PORT, 0x0C, 0, 8),
24 };
25
26 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_l2_smac_ex[] = {
27         MLXSW_AFK_ELEMENT_INST_BUF(SMAC_32_47, 0x02, 2),
28         MLXSW_AFK_ELEMENT_INST_BUF(SMAC_0_31, 0x04, 4),
29         MLXSW_AFK_ELEMENT_INST_U32(ETHERTYPE, 0x0C, 0, 16),
30 };
31
32 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_sip[] = {
33         MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_0_31, 0x00, 4),
34         MLXSW_AFK_ELEMENT_INST_U32(IP_PROTO, 0x08, 0, 8),
35         MLXSW_AFK_ELEMENT_INST_U32(SRC_SYS_PORT, 0x0C, 0, 8),
36 };
37
38 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_dip[] = {
39         MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_0_31, 0x00, 4),
40         MLXSW_AFK_ELEMENT_INST_U32(IP_PROTO, 0x08, 0, 8),
41         MLXSW_AFK_ELEMENT_INST_U32(SRC_SYS_PORT, 0x0C, 0, 8),
42 };
43
44 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4[] = {
45         MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_0_31, 0x00, 4),
46         MLXSW_AFK_ELEMENT_INST_U32(IP_ECN, 0x04, 4, 2),
47         MLXSW_AFK_ELEMENT_INST_U32(IP_TTL_, 0x04, 24, 8),
48         MLXSW_AFK_ELEMENT_INST_U32(IP_DSCP, 0x08, 0, 6),
49         MLXSW_AFK_ELEMENT_INST_U32(TCP_FLAGS, 0x08, 8, 9), /* TCP_CONTROL+TCP_ECN */
50 };
51
52 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_ex[] = {
53         MLXSW_AFK_ELEMENT_INST_U32(VID, 0x00, 0, 12),
54         MLXSW_AFK_ELEMENT_INST_U32(PCP, 0x08, 29, 3),
55         MLXSW_AFK_ELEMENT_INST_U32(SRC_L4_PORT, 0x08, 0, 16),
56         MLXSW_AFK_ELEMENT_INST_U32(DST_L4_PORT, 0x0C, 0, 16),
57 };
58
59 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_dip[] = {
60         MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_32_63, 0x00, 4),
61         MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_0_31, 0x04, 4),
62 };
63
64 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_ex1[] = {
65         MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_96_127, 0x00, 4),
66         MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_64_95, 0x04, 4),
67         MLXSW_AFK_ELEMENT_INST_U32(IP_PROTO, 0x08, 0, 8),
68 };
69
70 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_sip[] = {
71         MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_32_63, 0x00, 4),
72         MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_0_31, 0x04, 4),
73 };
74
75 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_sip_ex[] = {
76         MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_96_127, 0x00, 4),
77         MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_64_95, 0x04, 4),
78 };
79
80 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_packet_type[] = {
81         MLXSW_AFK_ELEMENT_INST_U32(ETHERTYPE, 0x00, 0, 16),
82 };
83
84 static const struct mlxsw_afk_block mlxsw_sp1_afk_blocks[] = {
85         MLXSW_AFK_BLOCK(0x10, mlxsw_sp_afk_element_info_l2_dmac),
86         MLXSW_AFK_BLOCK(0x11, mlxsw_sp_afk_element_info_l2_smac),
87         MLXSW_AFK_BLOCK(0x12, mlxsw_sp_afk_element_info_l2_smac_ex),
88         MLXSW_AFK_BLOCK(0x30, mlxsw_sp_afk_element_info_ipv4_sip),
89         MLXSW_AFK_BLOCK(0x31, mlxsw_sp_afk_element_info_ipv4_dip),
90         MLXSW_AFK_BLOCK(0x32, mlxsw_sp_afk_element_info_ipv4),
91         MLXSW_AFK_BLOCK(0x33, mlxsw_sp_afk_element_info_ipv4_ex),
92         MLXSW_AFK_BLOCK(0x60, mlxsw_sp_afk_element_info_ipv6_dip),
93         MLXSW_AFK_BLOCK(0x65, mlxsw_sp_afk_element_info_ipv6_ex1),
94         MLXSW_AFK_BLOCK(0x62, mlxsw_sp_afk_element_info_ipv6_sip),
95         MLXSW_AFK_BLOCK(0x63, mlxsw_sp_afk_element_info_ipv6_sip_ex),
96         MLXSW_AFK_BLOCK(0xB0, mlxsw_sp_afk_element_info_packet_type),
97 };
98
99 #define MLXSW_SP1_AFK_KEY_BLOCK_SIZE 16
100
101 static void mlxsw_sp1_afk_encode_block(char *output, int block_index,
102                                        char *block)
103 {
104         unsigned int offset = block_index * MLXSW_SP1_AFK_KEY_BLOCK_SIZE;
105         char *output_indexed = output + offset;
106
107         memcpy(output_indexed, block, MLXSW_SP1_AFK_KEY_BLOCK_SIZE);
108 }
109
110 static void mlxsw_sp1_afk_clear_block(char *output, int block_index)
111 {
112         unsigned int offset = block_index * MLXSW_SP1_AFK_KEY_BLOCK_SIZE;
113         char *output_indexed = output + offset;
114
115         memset(output_indexed, 0, MLXSW_SP1_AFK_KEY_BLOCK_SIZE);
116 }
117
118 const struct mlxsw_afk_ops mlxsw_sp1_afk_ops = {
119         .blocks         = mlxsw_sp1_afk_blocks,
120         .blocks_count   = ARRAY_SIZE(mlxsw_sp1_afk_blocks),
121         .encode_block   = mlxsw_sp1_afk_encode_block,
122         .clear_block    = mlxsw_sp1_afk_clear_block,
123 };
124
125 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_0[] = {
126         MLXSW_AFK_ELEMENT_INST_BUF(DMAC_0_31, 0x04, 4),
127 };
128
129 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_1[] = {
130         MLXSW_AFK_ELEMENT_INST_BUF(SMAC_0_31, 0x04, 4),
131 };
132
133 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_2[] = {
134         MLXSW_AFK_ELEMENT_INST_BUF(SMAC_32_47, 0x04, 2),
135         MLXSW_AFK_ELEMENT_INST_BUF(DMAC_32_47, 0x06, 2),
136 };
137
138 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_3[] = {
139         MLXSW_AFK_ELEMENT_INST_U32(PCP, 0x00, 0, 3),
140         MLXSW_AFK_ELEMENT_INST_U32(VID, 0x04, 16, 12),
141         MLXSW_AFK_ELEMENT_INST_BUF(DMAC_32_47, 0x06, 2),
142 };
143
144 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_4[] = {
145         MLXSW_AFK_ELEMENT_INST_U32(PCP, 0x00, 0, 3),
146         MLXSW_AFK_ELEMENT_INST_U32(VID, 0x04, 16, 12),
147         MLXSW_AFK_ELEMENT_INST_U32(ETHERTYPE, 0x04, 0, 16),
148 };
149
150 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_5[] = {
151         MLXSW_AFK_ELEMENT_INST_U32(VID, 0x04, 16, 12),
152         MLXSW_AFK_ELEMENT_INST_U32(SRC_SYS_PORT, 0x04, 0, 8), /* RX_ACL_SYSTEM_PORT */
153 };
154
155 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_0[] = {
156         MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_0_31, 0x04, 4),
157 };
158
159 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_1[] = {
160         MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_0_31, 0x04, 4),
161 };
162
163 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_2[] = {
164         MLXSW_AFK_ELEMENT_INST_U32(IP_DSCP, 0x04, 0, 6),
165         MLXSW_AFK_ELEMENT_INST_U32(IP_ECN, 0x04, 6, 2),
166         MLXSW_AFK_ELEMENT_INST_U32(IP_TTL_, 0x04, 8, 8),
167         MLXSW_AFK_ELEMENT_INST_U32(IP_PROTO, 0x04, 16, 8),
168 };
169
170 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_4[] = {
171         MLXSW_AFK_ELEMENT_INST_U32(VIRT_ROUTER_0_7, 0x04, 24, 8),
172         MLXSW_AFK_ELEMENT_INST_U32(VIRT_ROUTER_8_10, 0x00, 0, 3),
173 };
174
175 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_0[] = {
176         MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_32_63, 0x04, 4),
177 };
178
179 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_1[] = {
180         MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_64_95, 0x04, 4),
181 };
182
183 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_2[] = {
184         MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_96_127, 0x04, 4),
185 };
186
187 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_3[] = {
188         MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_32_63, 0x04, 4),
189 };
190
191 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_4[] = {
192         MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_64_95, 0x04, 4),
193 };
194
195 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_5[] = {
196         MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_96_127, 0x04, 4),
197 };
198
199 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_l4_0[] = {
200         MLXSW_AFK_ELEMENT_INST_U32(SRC_L4_PORT, 0x04, 16, 16),
201         MLXSW_AFK_ELEMENT_INST_U32(DST_L4_PORT, 0x04, 0, 16),
202 };
203
204 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_l4_2[] = {
205         MLXSW_AFK_ELEMENT_INST_U32(TCP_FLAGS, 0x04, 16, 9), /* TCP_CONTROL + TCP_ECN */
206 };
207
208 static const struct mlxsw_afk_block mlxsw_sp2_afk_blocks[] = {
209         MLXSW_AFK_BLOCK(0x10, mlxsw_sp_afk_element_info_mac_0),
210         MLXSW_AFK_BLOCK(0x11, mlxsw_sp_afk_element_info_mac_1),
211         MLXSW_AFK_BLOCK(0x12, mlxsw_sp_afk_element_info_mac_2),
212         MLXSW_AFK_BLOCK(0x13, mlxsw_sp_afk_element_info_mac_3),
213         MLXSW_AFK_BLOCK(0x14, mlxsw_sp_afk_element_info_mac_4),
214         MLXSW_AFK_BLOCK(0x15, mlxsw_sp_afk_element_info_mac_5),
215         MLXSW_AFK_BLOCK(0x38, mlxsw_sp_afk_element_info_ipv4_0),
216         MLXSW_AFK_BLOCK(0x39, mlxsw_sp_afk_element_info_ipv4_1),
217         MLXSW_AFK_BLOCK(0x3A, mlxsw_sp_afk_element_info_ipv4_2),
218         MLXSW_AFK_BLOCK(0x3C, mlxsw_sp_afk_element_info_ipv4_4),
219         MLXSW_AFK_BLOCK(0x40, mlxsw_sp_afk_element_info_ipv6_0),
220         MLXSW_AFK_BLOCK(0x41, mlxsw_sp_afk_element_info_ipv6_1),
221         MLXSW_AFK_BLOCK(0x42, mlxsw_sp_afk_element_info_ipv6_2),
222         MLXSW_AFK_BLOCK(0x43, mlxsw_sp_afk_element_info_ipv6_3),
223         MLXSW_AFK_BLOCK(0x44, mlxsw_sp_afk_element_info_ipv6_4),
224         MLXSW_AFK_BLOCK(0x45, mlxsw_sp_afk_element_info_ipv6_5),
225         MLXSW_AFK_BLOCK(0x90, mlxsw_sp_afk_element_info_l4_0),
226         MLXSW_AFK_BLOCK(0x92, mlxsw_sp_afk_element_info_l4_2),
227 };
228
229 #define MLXSW_SP2_AFK_BITS_PER_BLOCK 36
230
231 /* A block in Spectrum-2 is of the following form:
232  *
233  * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
234  * |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |35|34|33|32|
235  * +-----------------------------------------------------------------------------------------------+
236  * |31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|15|14|13|12|11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0|
237  * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
238  */
239 MLXSW_ITEM64(sp2_afk, block, value, 0x00, 0, MLXSW_SP2_AFK_BITS_PER_BLOCK);
240
241 /* The key / mask block layout in Spectrum-2 is of the following form:
242  *
243  * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
244  * |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |                block11_high                   |
245  * +-----------------------------------------------------------------------------------------------+
246  * |                    block11_low                               |         block10_high           |
247  * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
248  * ...
249  */
250
251 struct mlxsw_sp2_afk_block_layout {
252         unsigned short offset;
253         struct mlxsw_item item;
254 };
255
256 #define MLXSW_SP2_AFK_BLOCK_LAYOUT(_block, _offset, _shift)                     \
257         {                                                                       \
258                 .offset = _offset,                                              \
259                 {                                                               \
260                         .shift = _shift,                                        \
261                         .size = {.bits = MLXSW_SP2_AFK_BITS_PER_BLOCK},         \
262                         .name = #_block,                                        \
263                 }                                                               \
264         }                                                                       \
265
266 static const struct mlxsw_sp2_afk_block_layout mlxsw_sp2_afk_blocks_layout[] = {
267         MLXSW_SP2_AFK_BLOCK_LAYOUT(block0, 0x30, 0),
268         MLXSW_SP2_AFK_BLOCK_LAYOUT(block1, 0x2C, 4),
269         MLXSW_SP2_AFK_BLOCK_LAYOUT(block2, 0x28, 8),
270         MLXSW_SP2_AFK_BLOCK_LAYOUT(block3, 0x24, 12),
271         MLXSW_SP2_AFK_BLOCK_LAYOUT(block4, 0x20, 16),
272         MLXSW_SP2_AFK_BLOCK_LAYOUT(block5, 0x1C, 20),
273         MLXSW_SP2_AFK_BLOCK_LAYOUT(block6, 0x18, 24),
274         MLXSW_SP2_AFK_BLOCK_LAYOUT(block7, 0x14, 28),
275         MLXSW_SP2_AFK_BLOCK_LAYOUT(block8, 0x0C, 0),
276         MLXSW_SP2_AFK_BLOCK_LAYOUT(block9, 0x08, 4),
277         MLXSW_SP2_AFK_BLOCK_LAYOUT(block10, 0x04, 8),
278         MLXSW_SP2_AFK_BLOCK_LAYOUT(block11, 0x00, 12),
279 };
280
281 static void __mlxsw_sp2_afk_block_value_set(char *output, int block_index,
282                                             u64 block_value)
283 {
284         const struct mlxsw_sp2_afk_block_layout *block_layout;
285
286         if (WARN_ON(block_index < 0 ||
287                     block_index >= ARRAY_SIZE(mlxsw_sp2_afk_blocks_layout)))
288                 return;
289
290         block_layout = &mlxsw_sp2_afk_blocks_layout[block_index];
291         __mlxsw_item_set64(output + block_layout->offset,
292                            &block_layout->item, 0, block_value);
293 }
294
295 static void mlxsw_sp2_afk_encode_block(char *output, int block_index,
296                                        char *block)
297 {
298         u64 block_value = mlxsw_sp2_afk_block_value_get(block);
299
300         __mlxsw_sp2_afk_block_value_set(output, block_index, block_value);
301 }
302
303 static void mlxsw_sp2_afk_clear_block(char *output, int block_index)
304 {
305         __mlxsw_sp2_afk_block_value_set(output, block_index, 0);
306 }
307
308 const struct mlxsw_afk_ops mlxsw_sp2_afk_ops = {
309         .blocks         = mlxsw_sp2_afk_blocks,
310         .blocks_count   = ARRAY_SIZE(mlxsw_sp2_afk_blocks),
311         .encode_block   = mlxsw_sp2_afk_encode_block,
312         .clear_block    = mlxsw_sp2_afk_clear_block,
313 };