GNU Linux-libre 6.8.9-gnu
[releases.git] / drivers / net / ethernet / mellanox / mlxsw / spectrum_acl_bloom_filter.c
1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /* Copyright (c) 2018 Mellanox Technologies. All rights reserved */
3
4 #include <linux/errno.h>
5 #include <linux/gfp.h>
6 #include <linux/kernel.h>
7 #include <linux/refcount.h>
8 #include <linux/mutex.h>
9
10 #include "spectrum.h"
11 #include "spectrum_acl_tcam.h"
12
13 struct mlxsw_sp_acl_bf {
14         struct mutex lock; /* Protects Bloom Filter updates. */
15         unsigned int bank_size;
16         refcount_t refcnt[];
17 };
18
19 /* Bloom filter uses a crc-16 hash over chunks of data which contain 4 key
20  * blocks, eRP ID and region ID. In Spectrum-2 and above, region key is combined
21  * of up to 12 key blocks, so there can be up to 3 chunks in the Bloom filter
22  * key, depending on the actual number of key blocks used in the region.
23  * The layout of the Bloom filter key is as follows:
24  *
25  * +-------------------------+------------------------+------------------------+
26  * | Chunk 2 Key blocks 11-8 | Chunk 1 Key blocks 7-4 | Chunk 0 Key blocks 3-0 |
27  * +-------------------------+------------------------+------------------------+
28  */
29 #define MLXSW_BLOOM_KEY_CHUNKS 3
30
31 /* Spectrum-2 and Spectrum-3 chunks */
32 #define MLXSW_SP2_BLOOM_KEY_LEN 69
33
34 /* Each chunk size is 23 bytes. 18 bytes of it contain 4 key blocks, each is
35  * 36 bits, 2 bytes which hold eRP ID and region ID, and 3 bytes of zero
36  * padding.
37  * The layout of each chunk is as follows:
38  *
39  * +---------+----------------------+-----------------------------------+
40  * | 3 bytes |        2 bytes       |              18 bytes             |
41  * +---------+-----------+----------+-----------------------------------+
42  * | 183:158 |  157:148  | 147:144  |               143:0               |
43  * +---------+-----------+----------+-----------------------------------+
44  * |    0    | region ID |  eRP ID  |      4 Key blocks (18 Bytes)      |
45  * +---------+-----------+----------+-----------------------------------+
46  */
47 #define MLXSW_SP2_BLOOM_CHUNK_PAD_BYTES 3
48 #define MLXSW_SP2_BLOOM_CHUNK_KEY_BYTES 18
49 #define MLXSW_SP2_BLOOM_KEY_CHUNK_BYTES 23
50
51 /* The offset of the key block within a chunk is 5 bytes as it comes after
52  * 3 bytes of zero padding and 16 bits of region ID and eRP ID.
53  */
54 #define MLXSW_SP2_BLOOM_CHUNK_KEY_OFFSET 5
55
56 /* This table is just the CRC of each possible byte which is used for
57  * Spectrum-{2-3}. It is computed, Msbit first, for the Bloom filter
58  * polynomial which is 0x8529 (1 + x^3 + x^5 + x^8 + x^10 + x^15 and
59  * the implicit x^16).
60  */
61 static const u16 mlxsw_sp2_acl_bf_crc16_tab[256] = {
62 0x0000, 0x8529, 0x8f7b, 0x0a52, 0x9bdf, 0x1ef6, 0x14a4, 0x918d,
63 0xb297, 0x37be, 0x3dec, 0xb8c5, 0x2948, 0xac61, 0xa633, 0x231a,
64 0xe007, 0x652e, 0x6f7c, 0xea55, 0x7bd8, 0xfef1, 0xf4a3, 0x718a,
65 0x5290, 0xd7b9, 0xddeb, 0x58c2, 0xc94f, 0x4c66, 0x4634, 0xc31d,
66 0x4527, 0xc00e, 0xca5c, 0x4f75, 0xdef8, 0x5bd1, 0x5183, 0xd4aa,
67 0xf7b0, 0x7299, 0x78cb, 0xfde2, 0x6c6f, 0xe946, 0xe314, 0x663d,
68 0xa520, 0x2009, 0x2a5b, 0xaf72, 0x3eff, 0xbbd6, 0xb184, 0x34ad,
69 0x17b7, 0x929e, 0x98cc, 0x1de5, 0x8c68, 0x0941, 0x0313, 0x863a,
70 0x8a4e, 0x0f67, 0x0535, 0x801c, 0x1191, 0x94b8, 0x9eea, 0x1bc3,
71 0x38d9, 0xbdf0, 0xb7a2, 0x328b, 0xa306, 0x262f, 0x2c7d, 0xa954,
72 0x6a49, 0xef60, 0xe532, 0x601b, 0xf196, 0x74bf, 0x7eed, 0xfbc4,
73 0xd8de, 0x5df7, 0x57a5, 0xd28c, 0x4301, 0xc628, 0xcc7a, 0x4953,
74 0xcf69, 0x4a40, 0x4012, 0xc53b, 0x54b6, 0xd19f, 0xdbcd, 0x5ee4,
75 0x7dfe, 0xf8d7, 0xf285, 0x77ac, 0xe621, 0x6308, 0x695a, 0xec73,
76 0x2f6e, 0xaa47, 0xa015, 0x253c, 0xb4b1, 0x3198, 0x3bca, 0xbee3,
77 0x9df9, 0x18d0, 0x1282, 0x97ab, 0x0626, 0x830f, 0x895d, 0x0c74,
78 0x91b5, 0x149c, 0x1ece, 0x9be7, 0x0a6a, 0x8f43, 0x8511, 0x0038,
79 0x2322, 0xa60b, 0xac59, 0x2970, 0xb8fd, 0x3dd4, 0x3786, 0xb2af,
80 0x71b2, 0xf49b, 0xfec9, 0x7be0, 0xea6d, 0x6f44, 0x6516, 0xe03f,
81 0xc325, 0x460c, 0x4c5e, 0xc977, 0x58fa, 0xddd3, 0xd781, 0x52a8,
82 0xd492, 0x51bb, 0x5be9, 0xdec0, 0x4f4d, 0xca64, 0xc036, 0x451f,
83 0x6605, 0xe32c, 0xe97e, 0x6c57, 0xfdda, 0x78f3, 0x72a1, 0xf788,
84 0x3495, 0xb1bc, 0xbbee, 0x3ec7, 0xaf4a, 0x2a63, 0x2031, 0xa518,
85 0x8602, 0x032b, 0x0979, 0x8c50, 0x1ddd, 0x98f4, 0x92a6, 0x178f,
86 0x1bfb, 0x9ed2, 0x9480, 0x11a9, 0x8024, 0x050d, 0x0f5f, 0x8a76,
87 0xa96c, 0x2c45, 0x2617, 0xa33e, 0x32b3, 0xb79a, 0xbdc8, 0x38e1,
88 0xfbfc, 0x7ed5, 0x7487, 0xf1ae, 0x6023, 0xe50a, 0xef58, 0x6a71,
89 0x496b, 0xcc42, 0xc610, 0x4339, 0xd2b4, 0x579d, 0x5dcf, 0xd8e6,
90 0x5edc, 0xdbf5, 0xd1a7, 0x548e, 0xc503, 0x402a, 0x4a78, 0xcf51,
91 0xec4b, 0x6962, 0x6330, 0xe619, 0x7794, 0xf2bd, 0xf8ef, 0x7dc6,
92 0xbedb, 0x3bf2, 0x31a0, 0xb489, 0x2504, 0xa02d, 0xaa7f, 0x2f56,
93 0x0c4c, 0x8965, 0x8337, 0x061e, 0x9793, 0x12ba, 0x18e8, 0x9dc1,
94 };
95
96 /* Spectrum-4 chunks */
97 #define MLXSW_SP4_BLOOM_KEY_LEN 60
98
99 /* In Spectrum-4, there is no padding. Each chunk size is 20 bytes.
100  * 18 bytes of it contain 4 key blocks, each is 36 bits, and 2 bytes which hold
101  * eRP ID and region ID.
102  * The layout of each chunk is as follows:
103  *
104  * +----------------------+-----------------------------------+
105  * |        2 bytes       |              18 bytes             |
106  * +-----------+----------+-----------------------------------+
107  * |  157:148  | 147:144  |               143:0               |
108  * +---------+-----------+----------+-------------------------+
109  * | region ID |  eRP ID  |      4 Key blocks (18 Bytes)      |
110  * +-----------+----------+-----------------------------------+
111  */
112
113 #define MLXSW_SP4_BLOOM_CHUNK_PAD_BYTES 0
114 #define MLXSW_SP4_BLOOM_CHUNK_KEY_BYTES 18
115 #define MLXSW_SP4_BLOOM_KEY_CHUNK_BYTES 20
116
117 /* The offset of the key block within a chunk is 2 bytes as it comes after
118  * 16 bits of region ID and eRP ID.
119  */
120 #define MLXSW_SP4_BLOOM_CHUNK_KEY_OFFSET 2
121
122 /* For Spectrum-4, two hash functions are used, CRC-10 and CRC-6 based.
123  * The result is combination of the two calculations -
124  * 6 bit column are MSB (result of CRC-6),
125  * 10 bit row are LSB (result of CRC-10).
126  */
127
128 /* This table is just the CRC of each possible byte which is used for
129  * Spectrum-4. It is computed, Msbit first, for the Bloom filter
130  * polynomial which is 0x1b (1 + x^1 + x^3 + x^4 and the implicit x^10).
131  */
132 static const u16 mlxsw_sp4_acl_bf_crc10_tab[256] = {
133 0x0000, 0x001b, 0x0036, 0x002d, 0x006c, 0x0077, 0x005a, 0x0041,
134 0x00d8, 0x00c3, 0x00ee, 0x00f5, 0x00b4, 0x00af, 0x0082, 0x0099,
135 0x01b0, 0x01ab, 0x0186, 0x019d, 0x01dc, 0x01c7, 0x01ea, 0x01f1,
136 0x0168, 0x0173, 0x015e, 0x0145, 0x0104, 0x011f, 0x0132, 0x0129,
137 0x0360, 0x037b, 0x0356, 0x034d, 0x030c, 0x0317, 0x033a, 0x0321,
138 0x03b8, 0x03a3, 0x038e, 0x0395, 0x03d4, 0x03cf, 0x03e2, 0x03f9,
139 0x02d0, 0x02cb, 0x02e6, 0x02fd, 0x02bc, 0x02a7, 0x028a, 0x0291,
140 0x0208, 0x0213, 0x023e, 0x0225, 0x0264, 0x027f, 0x0252, 0x0249,
141 0x02db, 0x02c0, 0x02ed, 0x02f6, 0x02b7, 0x02ac, 0x0281, 0x029a,
142 0x0203, 0x0218, 0x0235, 0x022e, 0x026f, 0x0274, 0x0259, 0x0242,
143 0x036b, 0x0370, 0x035d, 0x0346, 0x0307, 0x031c, 0x0331, 0x032a,
144 0x03b3, 0x03a8, 0x0385, 0x039e, 0x03df, 0x03c4, 0x03e9, 0x03f2,
145 0x01bb, 0x01a0, 0x018d, 0x0196, 0x01d7, 0x01cc, 0x01e1, 0x01fa,
146 0x0163, 0x0178, 0x0155, 0x014e, 0x010f, 0x0114, 0x0139, 0x0122,
147 0x000b, 0x0010, 0x003d, 0x0026, 0x0067, 0x007c, 0x0051, 0x004a,
148 0x00d3, 0x00c8, 0x00e5, 0x00fe, 0x00bf, 0x00a4, 0x0089, 0x0092,
149 0x01ad, 0x01b6, 0x019b, 0x0180, 0x01c1, 0x01da, 0x01f7, 0x01ec,
150 0x0175, 0x016e, 0x0143, 0x0158, 0x0119, 0x0102, 0x012f, 0x0134,
151 0x001d, 0x0006, 0x002b, 0x0030, 0x0071, 0x006a, 0x0047, 0x005c,
152 0x00c5, 0x00de, 0x00f3, 0x00e8, 0x00a9, 0x00b2, 0x009f, 0x0084,
153 0x02cd, 0x02d6, 0x02fb, 0x02e0, 0x02a1, 0x02ba, 0x0297, 0x028c,
154 0x0215, 0x020e, 0x0223, 0x0238, 0x0279, 0x0262, 0x024f, 0x0254,
155 0x037d, 0x0366, 0x034b, 0x0350, 0x0311, 0x030a, 0x0327, 0x033c,
156 0x03a5, 0x03be, 0x0393, 0x0388, 0x03c9, 0x03d2, 0x03ff, 0x03e4,
157 0x0376, 0x036d, 0x0340, 0x035b, 0x031a, 0x0301, 0x032c, 0x0337,
158 0x03ae, 0x03b5, 0x0398, 0x0383, 0x03c2, 0x03d9, 0x03f4, 0x03ef,
159 0x02c6, 0x02dd, 0x02f0, 0x02eb, 0x02aa, 0x02b1, 0x029c, 0x0287,
160 0x021e, 0x0205, 0x0228, 0x0233, 0x0272, 0x0269, 0x0244, 0x025f,
161 0x0016, 0x000d, 0x0020, 0x003b, 0x007a, 0x0061, 0x004c, 0x0057,
162 0x00ce, 0x00d5, 0x00f8, 0x00e3, 0x00a2, 0x00b9, 0x0094, 0x008f,
163 0x01a6, 0x01bd, 0x0190, 0x018b, 0x01ca, 0x01d1, 0x01fc, 0x01e7,
164 0x017e, 0x0165, 0x0148, 0x0153, 0x0112, 0x0109, 0x0124, 0x013f,
165 };
166
167 /* This table is just the CRC of each possible byte which is used for
168  * Spectrum-4. It is computed, Msbit first, for the Bloom filter
169  * polynomial which is 0x2d (1 + x^2+ x^3 + x^5 and the implicit x^6).
170  */
171 static const u8 mlxsw_sp4_acl_bf_crc6_tab[256] = {
172 0x00, 0x2d, 0x37, 0x1a, 0x03, 0x2e, 0x34, 0x19,
173 0x06, 0x2b, 0x31, 0x1c, 0x05, 0x28, 0x32, 0x1f,
174 0x0c, 0x21, 0x3b, 0x16, 0x0f, 0x22, 0x38, 0x15,
175 0x0a, 0x27, 0x3d, 0x10, 0x09, 0x24, 0x3e, 0x13,
176 0x18, 0x35, 0x2f, 0x02, 0x1b, 0x36, 0x2c, 0x01,
177 0x1e, 0x33, 0x29, 0x04, 0x1d, 0x30, 0x2a, 0x07,
178 0x14, 0x39, 0x23, 0x0e, 0x17, 0x3a, 0x20, 0x0d,
179 0x12, 0x3f, 0x25, 0x08, 0x11, 0x3c, 0x26, 0x0b,
180 0x30, 0x1d, 0x07, 0x2a, 0x33, 0x1e, 0x04, 0x29,
181 0x36, 0x1b, 0x01, 0x2c, 0x35, 0x18, 0x02, 0x2f,
182 0x3c, 0x11, 0x0b, 0x26, 0x3f, 0x12, 0x08, 0x25,
183 0x3a, 0x17, 0x0d, 0x20, 0x39, 0x14, 0x0e, 0x23,
184 0x28, 0x05, 0x1f, 0x32, 0x2b, 0x06, 0x1c, 0x31,
185 0x2e, 0x03, 0x19, 0x34, 0x2d, 0x00, 0x1a, 0x37,
186 0x24, 0x09, 0x13, 0x3e, 0x27, 0x0a, 0x10, 0x3d,
187 0x22, 0x0f, 0x15, 0x38, 0x21, 0x0c, 0x16, 0x3b,
188 0x0d, 0x20, 0x3a, 0x17, 0x0e, 0x23, 0x39, 0x14,
189 0x0b, 0x26, 0x3c, 0x11, 0x08, 0x25, 0x3f, 0x12,
190 0x01, 0x2c, 0x36, 0x1b, 0x02, 0x2f, 0x35, 0x18,
191 0x07, 0x2a, 0x30, 0x1d, 0x04, 0x29, 0x33, 0x1e,
192 0x15, 0x38, 0x22, 0x0f, 0x16, 0x3b, 0x21, 0x0c,
193 0x13, 0x3e, 0x24, 0x09, 0x10, 0x3d, 0x27, 0x0a,
194 0x19, 0x34, 0x2e, 0x03, 0x1a, 0x37, 0x2d, 0x00,
195 0x1f, 0x32, 0x28, 0x05, 0x1c, 0x31, 0x2b, 0x06,
196 0x3d, 0x10, 0x0a, 0x27, 0x3e, 0x13, 0x09, 0x24,
197 0x3b, 0x16, 0x0c, 0x21, 0x38, 0x15, 0x0f, 0x22,
198 0x31, 0x1c, 0x06, 0x2b, 0x32, 0x1f, 0x05, 0x28,
199 0x37, 0x1a, 0x00, 0x2d, 0x34, 0x19, 0x03, 0x2e,
200 0x25, 0x08, 0x12, 0x3f, 0x26, 0x0b, 0x11, 0x3c,
201 0x23, 0x0e, 0x14, 0x39, 0x20, 0x0d, 0x17, 0x3a,
202 0x29, 0x04, 0x1e, 0x33, 0x2a, 0x07, 0x1d, 0x30,
203 0x2f, 0x02, 0x18, 0x35, 0x2c, 0x01, 0x1b, 0x36,
204 };
205
206 /* Each chunk contains 4 key blocks. Chunk 2 uses key blocks 11-8,
207  * and we need to populate it with 4 key blocks copied from the entry encoded
208  * key. The original keys layout is same for Spectrum-{2,3,4}.
209  * Since the encoded key contains a 2 bytes padding, key block 11 starts at
210  * offset 2. block 7 that is used in chunk 1 starts at offset 20 as 4 key blocks
211  * take 18 bytes. See 'MLXSW_SP2_AFK_BLOCK_LAYOUT' for more details.
212  * This array defines key offsets for easy access when copying key blocks from
213  * entry key to Bloom filter chunk.
214  */
215 static const u8 chunk_key_offsets[MLXSW_BLOOM_KEY_CHUNKS] = {2, 20, 38};
216
217 static u16 mlxsw_sp2_acl_bf_crc16_byte(u16 crc, u8 c)
218 {
219         return (crc << 8) ^ mlxsw_sp2_acl_bf_crc16_tab[(crc >> 8) ^ c];
220 }
221
222 static u16 mlxsw_sp2_acl_bf_crc(const u8 *buffer, size_t len)
223 {
224         u16 crc = 0;
225
226         while (len--)
227                 crc = mlxsw_sp2_acl_bf_crc16_byte(crc, *buffer++);
228         return crc;
229 }
230
231 static void
232 __mlxsw_sp_acl_bf_key_encode(struct mlxsw_sp_acl_atcam_region *aregion,
233                              struct mlxsw_sp_acl_atcam_entry *aentry,
234                              char *output, u8 *len, u8 max_chunks, u8 pad_bytes,
235                              u8 key_offset, u8 chunk_key_len, u8 chunk_len)
236 {
237         struct mlxsw_afk_key_info *key_info = aregion->region->key_info;
238         u8 chunk_index, chunk_count, block_count;
239         char *chunk = output;
240         __be16 erp_region_id;
241
242         block_count = mlxsw_afk_key_info_blocks_count_get(key_info);
243         chunk_count = 1 + ((block_count - 1) >> 2);
244         erp_region_id = cpu_to_be16(aentry->ht_key.erp_id |
245                                    (aregion->region->id << 4));
246         for (chunk_index = max_chunks - chunk_count; chunk_index < max_chunks;
247              chunk_index++) {
248                 memset(chunk, 0, pad_bytes);
249                 memcpy(chunk + pad_bytes, &erp_region_id,
250                        sizeof(erp_region_id));
251                 memcpy(chunk + key_offset,
252                        &aentry->enc_key[chunk_key_offsets[chunk_index]],
253                        chunk_key_len);
254                 chunk += chunk_len;
255         }
256         *len = chunk_count * chunk_len;
257 }
258
259 static void
260 mlxsw_sp2_acl_bf_key_encode(struct mlxsw_sp_acl_atcam_region *aregion,
261                             struct mlxsw_sp_acl_atcam_entry *aentry,
262                             char *output, u8 *len)
263 {
264         __mlxsw_sp_acl_bf_key_encode(aregion, aentry, output, len,
265                                      MLXSW_BLOOM_KEY_CHUNKS,
266                                      MLXSW_SP2_BLOOM_CHUNK_PAD_BYTES,
267                                      MLXSW_SP2_BLOOM_CHUNK_KEY_OFFSET,
268                                      MLXSW_SP2_BLOOM_CHUNK_KEY_BYTES,
269                                      MLXSW_SP2_BLOOM_KEY_CHUNK_BYTES);
270 }
271
272 static unsigned int
273 mlxsw_sp2_acl_bf_index_get(struct mlxsw_sp_acl_bf *bf,
274                            struct mlxsw_sp_acl_atcam_region *aregion,
275                            struct mlxsw_sp_acl_atcam_entry *aentry)
276 {
277         char bf_key[MLXSW_SP2_BLOOM_KEY_LEN];
278         u8 bf_size;
279
280         mlxsw_sp2_acl_bf_key_encode(aregion, aentry, bf_key, &bf_size);
281         return mlxsw_sp2_acl_bf_crc(bf_key, bf_size);
282 }
283
284 static u16 mlxsw_sp4_acl_bf_crc10_byte(u16 crc, u8 c)
285 {
286         u8 index = ((crc >> 2) ^ c) & 0xff;
287
288         return ((crc << 8) ^ mlxsw_sp4_acl_bf_crc10_tab[index]) & 0x3ff;
289 }
290
291 static u16 mlxsw_sp4_acl_bf_crc6_byte(u16 crc, u8 c)
292 {
293         u8 index = (crc ^ c) & 0xff;
294
295         return ((crc << 6) ^ (mlxsw_sp4_acl_bf_crc6_tab[index] << 2)) & 0xfc;
296 }
297
298 static u16 mlxsw_sp4_acl_bf_crc(const u8 *buffer, size_t len)
299 {
300         u16 crc_row = 0, crc_col = 0;
301
302         while (len--) {
303                 crc_row = mlxsw_sp4_acl_bf_crc10_byte(crc_row, *buffer);
304                 crc_col = mlxsw_sp4_acl_bf_crc6_byte(crc_col, *buffer);
305                 buffer++;
306         }
307
308         crc_col >>= 2;
309
310         /* 6 bit column are MSB, 10 bit row are LSB */
311         return (crc_col << 10) | crc_row;
312 }
313
314 static void right_shift_array(char *arr, u8 len, u8 shift_bits)
315 {
316         u8 byte_mask = 0xff >> shift_bits;
317         int i;
318
319         if (WARN_ON(!shift_bits || shift_bits >= 8))
320                 return;
321
322         for (i = len - 1; i >= 0; i--) {
323                 /* The first iteration looks like out-of-bounds access,
324                  * but actually references a buffer that the array is shifted
325                  * into. This move is legal as we never send the last chunk to
326                  * this function.
327                  */
328                 arr[i + 1] &= byte_mask;
329                 arr[i + 1] |= arr[i] << (8 - shift_bits);
330                 arr[i] = arr[i] >> shift_bits;
331         }
332 }
333
334 static void mlxsw_sp4_bf_key_shift_chunks(u8 chunk_count, char *output)
335 {
336         /* The chunks are suppoosed to be continuous, with no padding.
337          * Since region ID and eRP ID use 14 bits, and not fully 2 bytes,
338          * and in Spectrum-4 there is no padding, it is necessary to shift some
339          * chunks 2 bits right.
340          */
341         switch (chunk_count) {
342         case 2:
343                 /* The chunks are copied as follow:
344                  * +-------------+-----------------+
345                  * | Chunk 0     |   Chunk 1       |
346                  * | IDs  | keys |(**) IDs  | keys |
347                  * +-------------+-----------------+
348                  * In (**), there are two unused bits, therefore, chunk 0 needs
349                  * to be shifted two bits right.
350                  */
351                 right_shift_array(output, MLXSW_SP4_BLOOM_KEY_CHUNK_BYTES, 2);
352                 break;
353         case 3:
354                 /* The chunks are copied as follow:
355                  * +-------------+-----------------+-----------------+
356                  * | Chunk 0     |   Chunk 1       |   Chunk 2       |
357                  * | IDs  | keys |(**) IDs  | keys |(**) IDs  | keys |
358                  * +-------------+-----------------+-----------------+
359                  * In (**), there are two unused bits, therefore, chunk 1 needs
360                  * to be shifted two bits right and chunk 0 needs to be shifted
361                  * four bits right.
362                  */
363                 right_shift_array(output + MLXSW_SP4_BLOOM_KEY_CHUNK_BYTES,
364                                   MLXSW_SP4_BLOOM_KEY_CHUNK_BYTES, 2);
365                 right_shift_array(output, MLXSW_SP4_BLOOM_KEY_CHUNK_BYTES, 4);
366                 break;
367         default:
368                 WARN_ON(chunk_count > MLXSW_BLOOM_KEY_CHUNKS);
369         }
370 }
371
372 static void
373 mlxsw_sp4_acl_bf_key_encode(struct mlxsw_sp_acl_atcam_region *aregion,
374                             struct mlxsw_sp_acl_atcam_entry *aentry,
375                             char *output, u8 *len)
376 {
377         struct mlxsw_afk_key_info *key_info = aregion->region->key_info;
378         u8 block_count = mlxsw_afk_key_info_blocks_count_get(key_info);
379         u8 chunk_count = 1 + ((block_count - 1) >> 2);
380
381         __mlxsw_sp_acl_bf_key_encode(aregion, aentry, output, len,
382                                      MLXSW_BLOOM_KEY_CHUNKS,
383                                      MLXSW_SP4_BLOOM_CHUNK_PAD_BYTES,
384                                      MLXSW_SP4_BLOOM_CHUNK_KEY_OFFSET,
385                                      MLXSW_SP4_BLOOM_CHUNK_KEY_BYTES,
386                                      MLXSW_SP4_BLOOM_KEY_CHUNK_BYTES);
387         mlxsw_sp4_bf_key_shift_chunks(chunk_count, output);
388 }
389
390 static unsigned int
391 mlxsw_sp4_acl_bf_index_get(struct mlxsw_sp_acl_bf *bf,
392                            struct mlxsw_sp_acl_atcam_region *aregion,
393                            struct mlxsw_sp_acl_atcam_entry *aentry)
394 {
395         char bf_key[MLXSW_SP4_BLOOM_KEY_LEN] = {};
396         u8 bf_size;
397
398         mlxsw_sp4_acl_bf_key_encode(aregion, aentry, bf_key, &bf_size);
399         return mlxsw_sp4_acl_bf_crc(bf_key, bf_size);
400 }
401
402 static unsigned int
403 mlxsw_sp_acl_bf_rule_count_index_get(struct mlxsw_sp_acl_bf *bf,
404                                      unsigned int erp_bank,
405                                      unsigned int bf_index)
406 {
407         return erp_bank * bf->bank_size + bf_index;
408 }
409
410 int
411 mlxsw_sp_acl_bf_entry_add(struct mlxsw_sp *mlxsw_sp,
412                           struct mlxsw_sp_acl_bf *bf,
413                           struct mlxsw_sp_acl_atcam_region *aregion,
414                           unsigned int erp_bank,
415                           struct mlxsw_sp_acl_atcam_entry *aentry)
416 {
417         unsigned int rule_index;
418         char *peabfe_pl;
419         u16 bf_index;
420         int err;
421
422         mutex_lock(&bf->lock);
423
424         bf_index = mlxsw_sp->acl_bf_ops->index_get(bf, aregion, aentry);
425         rule_index = mlxsw_sp_acl_bf_rule_count_index_get(bf, erp_bank,
426                                                           bf_index);
427
428         if (refcount_inc_not_zero(&bf->refcnt[rule_index])) {
429                 err = 0;
430                 goto unlock;
431         }
432
433         peabfe_pl = kmalloc(MLXSW_REG_PEABFE_LEN, GFP_KERNEL);
434         if (!peabfe_pl) {
435                 err = -ENOMEM;
436                 goto unlock;
437         }
438
439         mlxsw_reg_peabfe_pack(peabfe_pl);
440         mlxsw_reg_peabfe_rec_pack(peabfe_pl, 0, 1, erp_bank, bf_index);
441         err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(peabfe), peabfe_pl);
442         kfree(peabfe_pl);
443         if (err)
444                 goto unlock;
445
446         refcount_set(&bf->refcnt[rule_index], 1);
447         err = 0;
448
449 unlock:
450         mutex_unlock(&bf->lock);
451         return err;
452 }
453
454 void
455 mlxsw_sp_acl_bf_entry_del(struct mlxsw_sp *mlxsw_sp,
456                           struct mlxsw_sp_acl_bf *bf,
457                           struct mlxsw_sp_acl_atcam_region *aregion,
458                           unsigned int erp_bank,
459                           struct mlxsw_sp_acl_atcam_entry *aentry)
460 {
461         unsigned int rule_index;
462         char *peabfe_pl;
463         u16 bf_index;
464
465         mutex_lock(&bf->lock);
466
467         bf_index = mlxsw_sp->acl_bf_ops->index_get(bf, aregion, aentry);
468         rule_index = mlxsw_sp_acl_bf_rule_count_index_get(bf, erp_bank,
469                                                           bf_index);
470
471         if (refcount_dec_and_test(&bf->refcnt[rule_index])) {
472                 peabfe_pl = kmalloc(MLXSW_REG_PEABFE_LEN, GFP_KERNEL);
473                 if (!peabfe_pl)
474                         goto unlock;
475
476                 mlxsw_reg_peabfe_pack(peabfe_pl);
477                 mlxsw_reg_peabfe_rec_pack(peabfe_pl, 0, 0, erp_bank, bf_index);
478                 mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(peabfe), peabfe_pl);
479                 kfree(peabfe_pl);
480         }
481
482 unlock:
483         mutex_unlock(&bf->lock);
484 }
485
486 struct mlxsw_sp_acl_bf *
487 mlxsw_sp_acl_bf_init(struct mlxsw_sp *mlxsw_sp, unsigned int num_erp_banks)
488 {
489         struct mlxsw_sp_acl_bf *bf;
490         unsigned int bf_bank_size;
491
492         if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, ACL_MAX_BF_LOG))
493                 return ERR_PTR(-EIO);
494
495         /* Bloom filter size per erp_table_bank
496          * is 2^ACL_MAX_BF_LOG
497          */
498         bf_bank_size = 1 << MLXSW_CORE_RES_GET(mlxsw_sp->core, ACL_MAX_BF_LOG);
499         bf = kzalloc(struct_size(bf, refcnt, size_mul(bf_bank_size, num_erp_banks)),
500                      GFP_KERNEL);
501         if (!bf)
502                 return ERR_PTR(-ENOMEM);
503
504         bf->bank_size = bf_bank_size;
505         mutex_init(&bf->lock);
506
507         return bf;
508 }
509
510 void mlxsw_sp_acl_bf_fini(struct mlxsw_sp_acl_bf *bf)
511 {
512         mutex_destroy(&bf->lock);
513         kfree(bf);
514 }
515
516 const struct mlxsw_sp_acl_bf_ops mlxsw_sp2_acl_bf_ops = {
517         .index_get = mlxsw_sp2_acl_bf_index_get,
518 };
519
520 const struct mlxsw_sp_acl_bf_ops mlxsw_sp4_acl_bf_ops = {
521         .index_get = mlxsw_sp4_acl_bf_index_get,
522 };