xref: /linux/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_bloom_filter.c (revision 32a92f8c89326985e05dce8b22d3f0aa07a3e1bd)
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 char *
mlxsw_sp_acl_bf_enc_key_get(struct mlxsw_sp_acl_atcam_entry * aentry,u8 chunk_index)216 mlxsw_sp_acl_bf_enc_key_get(struct mlxsw_sp_acl_atcam_entry *aentry,
217 			    u8 chunk_index)
218 {
219 	switch (chunk_index) {
220 	case 0:
221 		return &aentry->ht_key.enc_key[2];
222 	case 1:
223 		return &aentry->ht_key.enc_key[20];
224 	case 2:
225 		return &aentry->ht_key.enc_key[38];
226 	default:
227 		WARN_ON_ONCE(1);
228 		return &aentry->ht_key.enc_key[0];
229 	}
230 }
231 
mlxsw_sp2_acl_bf_crc16_byte(u16 crc,u8 c)232 static u16 mlxsw_sp2_acl_bf_crc16_byte(u16 crc, u8 c)
233 {
234 	return (crc << 8) ^ mlxsw_sp2_acl_bf_crc16_tab[(crc >> 8) ^ c];
235 }
236 
mlxsw_sp2_acl_bf_crc(const u8 * buffer,size_t len)237 static u16 mlxsw_sp2_acl_bf_crc(const u8 *buffer, size_t len)
238 {
239 	u16 crc = 0;
240 
241 	while (len--)
242 		crc = mlxsw_sp2_acl_bf_crc16_byte(crc, *buffer++);
243 	return crc;
244 }
245 
246 static void
__mlxsw_sp_acl_bf_key_encode(struct mlxsw_sp_acl_atcam_region * aregion,struct mlxsw_sp_acl_atcam_entry * aentry,char * output,u8 * len,u8 max_chunks,u8 pad_bytes,u8 key_offset,u8 chunk_key_len,u8 chunk_len)247 __mlxsw_sp_acl_bf_key_encode(struct mlxsw_sp_acl_atcam_region *aregion,
248 			     struct mlxsw_sp_acl_atcam_entry *aentry,
249 			     char *output, u8 *len, u8 max_chunks, u8 pad_bytes,
250 			     u8 key_offset, u8 chunk_key_len, u8 chunk_len)
251 {
252 	struct mlxsw_afk_key_info *key_info = aregion->region->key_info;
253 	u8 chunk_index, chunk_count;
254 	char *chunk = output;
255 	__be16 erp_region_id;
256 	u32 block_count;
257 
258 	block_count = mlxsw_afk_key_info_blocks_count_get(key_info);
259 	chunk_count = 1 + ((block_count - 1) >> 2);
260 	erp_region_id = cpu_to_be16(aentry->ht_key.erp_id |
261 				   (aregion->region->id << 4));
262 	for (chunk_index = max_chunks - chunk_count; chunk_index < max_chunks;
263 	     chunk_index++) {
264 		char *enc_key;
265 
266 		memset(chunk, 0, pad_bytes);
267 		memcpy(chunk + pad_bytes, &erp_region_id,
268 		       sizeof(erp_region_id));
269 		enc_key = mlxsw_sp_acl_bf_enc_key_get(aentry, chunk_index);
270 		memcpy(chunk + key_offset, enc_key, chunk_key_len);
271 		chunk += chunk_len;
272 	}
273 	*len = chunk_count * chunk_len;
274 }
275 
276 static void
mlxsw_sp2_acl_bf_key_encode(struct mlxsw_sp_acl_atcam_region * aregion,struct mlxsw_sp_acl_atcam_entry * aentry,char * output,u8 * len)277 mlxsw_sp2_acl_bf_key_encode(struct mlxsw_sp_acl_atcam_region *aregion,
278 			    struct mlxsw_sp_acl_atcam_entry *aentry,
279 			    char *output, u8 *len)
280 {
281 	__mlxsw_sp_acl_bf_key_encode(aregion, aentry, output, len,
282 				     MLXSW_BLOOM_KEY_CHUNKS,
283 				     MLXSW_SP2_BLOOM_CHUNK_PAD_BYTES,
284 				     MLXSW_SP2_BLOOM_CHUNK_KEY_OFFSET,
285 				     MLXSW_SP2_BLOOM_CHUNK_KEY_BYTES,
286 				     MLXSW_SP2_BLOOM_KEY_CHUNK_BYTES);
287 }
288 
289 static unsigned int
mlxsw_sp2_acl_bf_index_get(struct mlxsw_sp_acl_bf * bf,struct mlxsw_sp_acl_atcam_region * aregion,struct mlxsw_sp_acl_atcam_entry * aentry)290 mlxsw_sp2_acl_bf_index_get(struct mlxsw_sp_acl_bf *bf,
291 			   struct mlxsw_sp_acl_atcam_region *aregion,
292 			   struct mlxsw_sp_acl_atcam_entry *aentry)
293 {
294 	char bf_key[MLXSW_SP2_BLOOM_KEY_LEN];
295 	u8 bf_size;
296 
297 	mlxsw_sp2_acl_bf_key_encode(aregion, aentry, bf_key, &bf_size);
298 	return mlxsw_sp2_acl_bf_crc(bf_key, bf_size);
299 }
300 
mlxsw_sp4_acl_bf_crc10_byte(u16 crc,u8 c)301 static u16 mlxsw_sp4_acl_bf_crc10_byte(u16 crc, u8 c)
302 {
303 	u8 index = ((crc >> 2) ^ c) & 0xff;
304 
305 	return ((crc << 8) ^ mlxsw_sp4_acl_bf_crc10_tab[index]) & 0x3ff;
306 }
307 
mlxsw_sp4_acl_bf_crc6_byte(u16 crc,u8 c)308 static u16 mlxsw_sp4_acl_bf_crc6_byte(u16 crc, u8 c)
309 {
310 	u8 index = (crc ^ c) & 0xff;
311 
312 	return ((crc << 6) ^ (mlxsw_sp4_acl_bf_crc6_tab[index] << 2)) & 0xfc;
313 }
314 
mlxsw_sp4_acl_bf_crc(const u8 * buffer,size_t len)315 static u16 mlxsw_sp4_acl_bf_crc(const u8 *buffer, size_t len)
316 {
317 	u16 crc_row = 0, crc_col = 0;
318 
319 	while (len--) {
320 		crc_row = mlxsw_sp4_acl_bf_crc10_byte(crc_row, *buffer);
321 		crc_col = mlxsw_sp4_acl_bf_crc6_byte(crc_col, *buffer);
322 		buffer++;
323 	}
324 
325 	crc_col >>= 2;
326 
327 	/* 6 bit column are MSB, 10 bit row are LSB */
328 	return (crc_col << 10) | crc_row;
329 }
330 
right_shift_array(char * arr,u8 len,u8 shift_bits)331 static void right_shift_array(char *arr, u8 len, u8 shift_bits)
332 {
333 	u8 byte_mask = 0xff >> shift_bits;
334 	int i;
335 
336 	if (WARN_ON(!shift_bits || shift_bits >= 8))
337 		return;
338 
339 	for (i = len - 1; i >= 0; i--) {
340 		/* The first iteration looks like out-of-bounds access,
341 		 * but actually references a buffer that the array is shifted
342 		 * into. This move is legal as we never send the last chunk to
343 		 * this function.
344 		 */
345 		arr[i + 1] &= byte_mask;
346 		arr[i + 1] |= arr[i] << (8 - shift_bits);
347 		arr[i] = arr[i] >> shift_bits;
348 	}
349 }
350 
mlxsw_sp4_bf_key_shift_chunks(u8 chunk_count,char * output)351 static void mlxsw_sp4_bf_key_shift_chunks(u8 chunk_count, char *output)
352 {
353 	/* The chunks are suppoosed to be continuous, with no padding.
354 	 * Since region ID and eRP ID use 14 bits, and not fully 2 bytes,
355 	 * and in Spectrum-4 there is no padding, it is necessary to shift some
356 	 * chunks 2 bits right.
357 	 */
358 	switch (chunk_count) {
359 	case 2:
360 		/* The chunks are copied as follow:
361 		 * +-------------+-----------------+
362 		 * | Chunk 0     |   Chunk 1       |
363 		 * | IDs  | keys |(**) IDs  | keys |
364 		 * +-------------+-----------------+
365 		 * In (**), there are two unused bits, therefore, chunk 0 needs
366 		 * to be shifted two bits right.
367 		 */
368 		right_shift_array(output, MLXSW_SP4_BLOOM_KEY_CHUNK_BYTES, 2);
369 		break;
370 	case 3:
371 		/* The chunks are copied as follow:
372 		 * +-------------+-----------------+-----------------+
373 		 * | Chunk 0     |   Chunk 1       |   Chunk 2       |
374 		 * | IDs  | keys |(**) IDs  | keys |(**) IDs  | keys |
375 		 * +-------------+-----------------+-----------------+
376 		 * In (**), there are two unused bits, therefore, chunk 1 needs
377 		 * to be shifted two bits right and chunk 0 needs to be shifted
378 		 * four bits right.
379 		 */
380 		right_shift_array(output + MLXSW_SP4_BLOOM_KEY_CHUNK_BYTES,
381 				  MLXSW_SP4_BLOOM_KEY_CHUNK_BYTES, 2);
382 		right_shift_array(output, MLXSW_SP4_BLOOM_KEY_CHUNK_BYTES, 4);
383 		break;
384 	default:
385 		WARN_ON(chunk_count > MLXSW_BLOOM_KEY_CHUNKS);
386 	}
387 }
388 
389 static void
mlxsw_sp4_acl_bf_key_encode(struct mlxsw_sp_acl_atcam_region * aregion,struct mlxsw_sp_acl_atcam_entry * aentry,char * output,u8 * len)390 mlxsw_sp4_acl_bf_key_encode(struct mlxsw_sp_acl_atcam_region *aregion,
391 			    struct mlxsw_sp_acl_atcam_entry *aentry,
392 			    char *output, u8 *len)
393 {
394 	struct mlxsw_afk_key_info *key_info = aregion->region->key_info;
395 	u8 block_count = mlxsw_afk_key_info_blocks_count_get(key_info);
396 	u8 chunk_count = 1 + ((block_count - 1) >> 2);
397 
398 	__mlxsw_sp_acl_bf_key_encode(aregion, aentry, output, len,
399 				     MLXSW_BLOOM_KEY_CHUNKS,
400 				     MLXSW_SP4_BLOOM_CHUNK_PAD_BYTES,
401 				     MLXSW_SP4_BLOOM_CHUNK_KEY_OFFSET,
402 				     MLXSW_SP4_BLOOM_CHUNK_KEY_BYTES,
403 				     MLXSW_SP4_BLOOM_KEY_CHUNK_BYTES);
404 	mlxsw_sp4_bf_key_shift_chunks(chunk_count, output);
405 }
406 
407 static unsigned int
mlxsw_sp4_acl_bf_index_get(struct mlxsw_sp_acl_bf * bf,struct mlxsw_sp_acl_atcam_region * aregion,struct mlxsw_sp_acl_atcam_entry * aentry)408 mlxsw_sp4_acl_bf_index_get(struct mlxsw_sp_acl_bf *bf,
409 			   struct mlxsw_sp_acl_atcam_region *aregion,
410 			   struct mlxsw_sp_acl_atcam_entry *aentry)
411 {
412 	char bf_key[MLXSW_SP4_BLOOM_KEY_LEN] = {};
413 	u8 bf_size;
414 
415 	mlxsw_sp4_acl_bf_key_encode(aregion, aentry, bf_key, &bf_size);
416 	return mlxsw_sp4_acl_bf_crc(bf_key, bf_size);
417 }
418 
419 static unsigned int
mlxsw_sp_acl_bf_rule_count_index_get(struct mlxsw_sp_acl_bf * bf,unsigned int erp_bank,unsigned int bf_index)420 mlxsw_sp_acl_bf_rule_count_index_get(struct mlxsw_sp_acl_bf *bf,
421 				     unsigned int erp_bank,
422 				     unsigned int bf_index)
423 {
424 	return erp_bank * bf->bank_size + bf_index;
425 }
426 
427 int
mlxsw_sp_acl_bf_entry_add(struct mlxsw_sp * mlxsw_sp,struct mlxsw_sp_acl_bf * bf,struct mlxsw_sp_acl_atcam_region * aregion,unsigned int erp_bank,struct mlxsw_sp_acl_atcam_entry * aentry)428 mlxsw_sp_acl_bf_entry_add(struct mlxsw_sp *mlxsw_sp,
429 			  struct mlxsw_sp_acl_bf *bf,
430 			  struct mlxsw_sp_acl_atcam_region *aregion,
431 			  unsigned int erp_bank,
432 			  struct mlxsw_sp_acl_atcam_entry *aentry)
433 {
434 	unsigned int rule_index;
435 	char *peabfe_pl;
436 	u16 bf_index;
437 	int err;
438 
439 	mutex_lock(&bf->lock);
440 
441 	bf_index = mlxsw_sp->acl_bf_ops->index_get(bf, aregion, aentry);
442 	rule_index = mlxsw_sp_acl_bf_rule_count_index_get(bf, erp_bank,
443 							  bf_index);
444 
445 	if (refcount_inc_not_zero(&bf->refcnt[rule_index])) {
446 		err = 0;
447 		goto unlock;
448 	}
449 
450 	peabfe_pl = kmalloc(MLXSW_REG_PEABFE_LEN, GFP_KERNEL);
451 	if (!peabfe_pl) {
452 		err = -ENOMEM;
453 		goto unlock;
454 	}
455 
456 	mlxsw_reg_peabfe_pack(peabfe_pl);
457 	mlxsw_reg_peabfe_rec_pack(peabfe_pl, 0, 1, erp_bank, bf_index);
458 	err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(peabfe), peabfe_pl);
459 	kfree(peabfe_pl);
460 	if (err)
461 		goto unlock;
462 
463 	refcount_set(&bf->refcnt[rule_index], 1);
464 	err = 0;
465 
466 unlock:
467 	mutex_unlock(&bf->lock);
468 	return err;
469 }
470 
471 void
mlxsw_sp_acl_bf_entry_del(struct mlxsw_sp * mlxsw_sp,struct mlxsw_sp_acl_bf * bf,struct mlxsw_sp_acl_atcam_region * aregion,unsigned int erp_bank,struct mlxsw_sp_acl_atcam_entry * aentry)472 mlxsw_sp_acl_bf_entry_del(struct mlxsw_sp *mlxsw_sp,
473 			  struct mlxsw_sp_acl_bf *bf,
474 			  struct mlxsw_sp_acl_atcam_region *aregion,
475 			  unsigned int erp_bank,
476 			  struct mlxsw_sp_acl_atcam_entry *aentry)
477 {
478 	unsigned int rule_index;
479 	char *peabfe_pl;
480 	u16 bf_index;
481 
482 	mutex_lock(&bf->lock);
483 
484 	bf_index = mlxsw_sp->acl_bf_ops->index_get(bf, aregion, aentry);
485 	rule_index = mlxsw_sp_acl_bf_rule_count_index_get(bf, erp_bank,
486 							  bf_index);
487 
488 	if (refcount_dec_and_test(&bf->refcnt[rule_index])) {
489 		peabfe_pl = kmalloc(MLXSW_REG_PEABFE_LEN, GFP_KERNEL);
490 		if (!peabfe_pl)
491 			goto unlock;
492 
493 		mlxsw_reg_peabfe_pack(peabfe_pl);
494 		mlxsw_reg_peabfe_rec_pack(peabfe_pl, 0, 0, erp_bank, bf_index);
495 		mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(peabfe), peabfe_pl);
496 		kfree(peabfe_pl);
497 	}
498 
499 unlock:
500 	mutex_unlock(&bf->lock);
501 }
502 
503 struct mlxsw_sp_acl_bf *
mlxsw_sp_acl_bf_init(struct mlxsw_sp * mlxsw_sp,unsigned int num_erp_banks)504 mlxsw_sp_acl_bf_init(struct mlxsw_sp *mlxsw_sp, unsigned int num_erp_banks)
505 {
506 	struct mlxsw_sp_acl_bf *bf;
507 	unsigned int bf_bank_size;
508 
509 	if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, ACL_MAX_BF_LOG))
510 		return ERR_PTR(-EIO);
511 
512 	/* Bloom filter size per erp_table_bank
513 	 * is 2^ACL_MAX_BF_LOG
514 	 */
515 	bf_bank_size = 1 << MLXSW_CORE_RES_GET(mlxsw_sp->core, ACL_MAX_BF_LOG);
516 	bf = kzalloc_flex(*bf, refcnt, size_mul(bf_bank_size, num_erp_banks));
517 	if (!bf)
518 		return ERR_PTR(-ENOMEM);
519 
520 	bf->bank_size = bf_bank_size;
521 	mutex_init(&bf->lock);
522 
523 	return bf;
524 }
525 
mlxsw_sp_acl_bf_fini(struct mlxsw_sp_acl_bf * bf)526 void mlxsw_sp_acl_bf_fini(struct mlxsw_sp_acl_bf *bf)
527 {
528 	mutex_destroy(&bf->lock);
529 	kfree(bf);
530 }
531 
532 const struct mlxsw_sp_acl_bf_ops mlxsw_sp2_acl_bf_ops = {
533 	.index_get = mlxsw_sp2_acl_bf_index_get,
534 };
535 
536 const struct mlxsw_sp_acl_bf_ops mlxsw_sp4_acl_bf_ops = {
537 	.index_get = mlxsw_sp4_acl_bf_index_get,
538 };
539