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, 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 }; 523