Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(C) 2021 Marvell.
3 : : */
4 : : #include "roc_api.h"
5 : : #include "roc_priv.h"
6 : :
7 : : int
8 [ # # ]: 0 : npc_mcam_alloc_counter(struct mbox *mbox, uint16_t *ctr)
9 : : {
10 : : struct npc_mcam_alloc_counter_req *req;
11 : : struct npc_mcam_alloc_counter_rsp *rsp;
12 : : int rc = -ENOSPC;
13 : :
14 : : /* For CN20K, counters are enabled by default */
15 [ # # ]: 0 : if (roc_model_is_cn20k())
16 : : return 0;
17 : :
18 : 0 : req = mbox_alloc_msg_npc_mcam_alloc_counter(mbox_get(mbox));
19 [ # # ]: 0 : if (req == NULL)
20 : 0 : goto exit;
21 : 0 : req->count = 1;
22 : : rc = mbox_process_msg(mbox, (void *)&rsp);
23 [ # # ]: 0 : if (rc)
24 : 0 : goto exit;
25 : 0 : *ctr = rsp->cntr_list[0];
26 : 0 : exit:
27 : : mbox_put(mbox);
28 : 0 : return rc;
29 : : }
30 : :
31 : : int
32 [ # # ]: 0 : npc_mcam_free_counter(struct mbox *mbox, uint16_t ctr_id)
33 : : {
34 : : struct npc_mcam_oper_counter_req *req;
35 : : int rc = -ENOSPC;
36 : :
37 [ # # ]: 0 : if (roc_model_is_cn20k())
38 : : return 0;
39 : :
40 : 0 : req = mbox_alloc_msg_npc_mcam_free_counter(mbox_get(mbox));
41 [ # # ]: 0 : if (req == NULL)
42 : 0 : goto exit;
43 : 0 : req->cntr = ctr_id;
44 : 0 : rc = mbox_process(mbox);
45 : 0 : exit:
46 : : mbox_put(mbox);
47 : 0 : return rc;
48 : : }
49 : :
50 : : int
51 [ # # ]: 0 : npc_mcam_get_stats(struct mbox *mbox, struct roc_npc_flow *flow, uint64_t *count)
52 : : {
53 : : struct npc_mcam_get_stats_req *req;
54 : : struct npc_mcam_get_stats_rsp *rsp;
55 : : int rc = -ENOSPC;
56 : :
57 : : /* valid only for cn20k */
58 [ # # ]: 0 : if (!roc_model_is_cn20k())
59 : : return 0;
60 : :
61 : 0 : req = mbox_alloc_msg_npc_mcam_entry_stats(mbox_get(mbox));
62 [ # # ]: 0 : if (req == NULL)
63 : 0 : goto exit;
64 : 0 : req->entry = flow->mcam_id;
65 : : rc = mbox_process_msg(mbox, (void *)&rsp);
66 [ # # ]: 0 : if (rc)
67 : 0 : goto exit;
68 : 0 : *count = rsp->stat;
69 : 0 : exit:
70 : : mbox_put(mbox);
71 : 0 : return rc;
72 : : }
73 : :
74 : : int
75 [ # # ]: 0 : npc_mcam_read_counter(struct mbox *mbox, uint32_t ctr_id, uint64_t *count)
76 : : {
77 : : struct npc_mcam_oper_counter_req *req;
78 : : struct npc_mcam_oper_counter_rsp *rsp;
79 : : int rc = -ENOSPC;
80 : :
81 [ # # ]: 0 : if (roc_model_is_cn20k())
82 : : return 0;
83 : :
84 : 0 : req = mbox_alloc_msg_npc_mcam_counter_stats(mbox_get(mbox));
85 [ # # ]: 0 : if (req == NULL)
86 : 0 : goto exit;
87 : 0 : req->cntr = ctr_id;
88 : : rc = mbox_process_msg(mbox, (void *)&rsp);
89 [ # # ]: 0 : if (rc)
90 : 0 : goto exit;
91 : 0 : *count = rsp->stat;
92 : 0 : exit:
93 : : mbox_put(mbox);
94 : 0 : return rc;
95 : : }
96 : :
97 : : int
98 [ # # # # ]: 0 : npc_mcam_clear_counter(struct mbox *mbox, uint32_t ctr_id)
99 : : {
100 : : struct npc_mcam_oper_counter_req *req;
101 : : int rc = -ENOSPC;
102 : :
103 [ # # ]: 0 : if (roc_model_is_cn20k())
104 : : return 0;
105 : :
106 : 0 : req = mbox_alloc_msg_npc_mcam_clear_counter(mbox_get(mbox));
107 [ # # ]: 0 : if (req == NULL)
108 : 0 : goto exit;
109 : 0 : req->cntr = ctr_id;
110 : 0 : rc = mbox_process(mbox);
111 : 0 : exit:
112 : : mbox_put(mbox);
113 : 0 : return rc;
114 : : }
115 : :
116 : : int
117 : 0 : npc_mcam_free_entry(struct mbox *mbox, uint32_t entry)
118 : : {
119 : : struct npc_mcam_free_entry_req *req;
120 : : int rc = -ENOSPC;
121 : :
122 : 0 : req = mbox_alloc_msg_npc_mcam_free_entry(mbox_get(mbox));
123 [ # # ]: 0 : if (req == NULL)
124 : 0 : goto exit;
125 : 0 : req->entry = entry;
126 : 0 : rc = mbox_process(mbox);
127 : 0 : exit:
128 : : mbox_put(mbox);
129 : 0 : return rc;
130 : : }
131 : :
132 : : int
133 : 0 : npc_mcam_free_all_entries(struct npc *npc)
134 : : {
135 : : struct npc_mcam_free_entry_req *req;
136 : 0 : struct mbox *mbox = mbox_get(npc->mbox);
137 : : int rc = -ENOSPC;
138 : :
139 : 0 : req = mbox_alloc_msg_npc_mcam_free_entry(mbox);
140 [ # # ]: 0 : if (req == NULL)
141 : 0 : goto exit;
142 : 0 : req->all = 1;
143 : 0 : rc = mbox_process(mbox);
144 : 0 : exit:
145 : : mbox_put(mbox);
146 : 0 : return rc;
147 : : }
148 : :
149 : : static int
150 : : npc_supp_key_len(uint32_t supp_mask)
151 : : {
152 : : int nib_count = 0;
153 : :
154 [ # # # # : 0 : while (supp_mask) {
# # # # ]
155 : 0 : nib_count++;
156 : 0 : supp_mask &= (supp_mask - 1);
157 : : }
158 : 0 : return nib_count * 4;
159 : : }
160 : :
161 : : /**
162 : : * Returns true if any LDATA bits are extracted for specific LID+LTYPE.
163 : : *
164 : : * No LFLAG extraction is taken into account.
165 : : */
166 : : static int
167 [ # # ]: 0 : npc_lid_lt_in_kex(struct npc *npc, uint8_t lid, uint8_t lt)
168 : : {
169 : : struct npc_xtract_info *x_info;
170 : : int i;
171 : :
172 [ # # ]: 0 : if (!roc_model_is_cn20k()) {
173 [ # # ]: 0 : for (i = 0; i < NPC_MAX_LD; i++) {
174 : 0 : x_info = &npc->prx_dxcfg[NIX_INTF_RX][lid][lt].xtract[i];
175 : : /* Check for LDATA */
176 [ # # # # ]: 0 : if (x_info->enable && x_info->len > 0)
177 : : return true;
178 : : }
179 : : } else {
180 [ # # ]: 0 : for (i = 0; i < NPC_MAX_EXTRACTOR; i++) {
181 : : union npc_kex_ldata_flags_cfg *lid_info = &npc->lid_cfg[NIX_INTF_RX][i];
182 : :
183 [ # # ]: 0 : if (lid_info->s.lid != lid)
184 : 0 : continue;
185 : 0 : x_info = &npc->prx_dxcfg_cn20k[NIX_INTF_RX][i][lt].xtract;
186 : : /* Check for LDATA */
187 [ # # # # ]: 0 : if (x_info->enable && x_info->len > 0)
188 : : return true;
189 : : }
190 : : }
191 : :
192 : : return false;
193 : : }
194 : :
195 : : static void
196 : 0 : npc_construct_ldata_mask_cn20k(struct npc *npc, struct plt_bitmap *bmap, uint8_t lid, uint8_t lt)
197 : : {
198 : : struct npc_xtract_info *x_info;
199 : : int hdr_off, keylen;
200 : : int i, j;
201 : :
202 [ # # ]: 0 : for (i = 0; i < NPC_MAX_EXTRACTOR; i++) {
203 : : union npc_kex_ldata_flags_cfg *lid_conf = &npc->lid_cfg[NIX_INTF_RX][i];
204 : :
205 [ # # ]: 0 : if (lid_conf->s.lid != lid)
206 : 0 : continue;
207 : :
208 : 0 : x_info = &npc->prx_dxcfg_cn20k[NIX_INTF_RX][i][lt].xtract;
209 [ # # ]: 0 : if (x_info->enable == 0)
210 : 0 : continue;
211 : :
212 : 0 : hdr_off = x_info->hdr_off * 8;
213 : 0 : keylen = x_info->len * 8;
214 [ # # ]: 0 : for (j = hdr_off; j < (hdr_off + keylen); j++)
215 : 0 : plt_bitmap_set(bmap, j);
216 : : }
217 : 0 : }
218 : :
219 : : static void
220 : 0 : npc_construct_ldata_mask(struct npc *npc, struct plt_bitmap *bmap, uint8_t lid, uint8_t lt,
221 : : uint8_t ld)
222 : : {
223 : : struct npc_xtract_info *x_info, *infoflag;
224 : : int hdr_off, keylen;
225 : : npc_dxcfg_t *p;
226 : : npc_fxcfg_t *q;
227 : : int i, j;
228 : :
229 : : p = &npc->prx_dxcfg;
230 : 0 : x_info = &(*p)[0][lid][lt].xtract[ld];
231 : :
232 [ # # ]: 0 : if (x_info->enable == 0)
233 : : return;
234 : :
235 : 0 : hdr_off = x_info->hdr_off * 8;
236 : 0 : keylen = x_info->len * 8;
237 [ # # ]: 0 : for (i = hdr_off; i < (hdr_off + keylen); i++)
238 : 0 : plt_bitmap_set(bmap, i);
239 : :
240 [ # # ]: 0 : if (x_info->flags_enable == 0)
241 : : return;
242 : :
243 [ # # ]: 0 : if ((npc->prx_lfcfg[0].i & 0x7) != lid)
244 : : return;
245 : :
246 : : q = &npc->prx_fxcfg;
247 [ # # ]: 0 : for (j = 0; j < NPC_MAX_LFL; j++) {
248 : : infoflag = &(*q)[0][ld][j].xtract[0];
249 [ # # ]: 0 : if (infoflag->enable) {
250 : 0 : hdr_off = infoflag->hdr_off * 8;
251 : 0 : keylen = infoflag->len * 8;
252 [ # # ]: 0 : for (i = hdr_off; i < (hdr_off + keylen); i++)
253 : 0 : plt_bitmap_set(bmap, i);
254 : : }
255 : : }
256 : : }
257 : :
258 : : /**
259 : : * Check if given LID+LTYPE combination is present in KEX
260 : : *
261 : : * len is non-zero, this function will return true if KEX extracts len bytes
262 : : * at given offset. Otherwise it'll return true if any bytes are extracted
263 : : * specifically for given LID+LTYPE combination (meaning not LFLAG based).
264 : : * The second case increases flexibility for custom frames whose extracted
265 : : * bits may change depending on KEX profile loaded.
266 : : *
267 : : * @param npc NPC context structure
268 : : * @param lid Layer ID to check for
269 : : * @param lt Layer Type to check for
270 : : * @param offset offset into the layer header to match
271 : : * @param len length of the match
272 : : */
273 : : static bool
274 : 0 : npc_is_kex_enabled(struct npc *npc, uint8_t lid, uint8_t lt, int offset, int len)
275 : : {
276 : : struct plt_bitmap *bmap;
277 : : uint32_t bmap_sz;
278 : : uint8_t *mem;
279 : : int i;
280 : :
281 [ # # ]: 0 : if (!len)
282 : 0 : return npc_lid_lt_in_kex(npc, lid, lt);
283 : :
284 : : bmap_sz = plt_bitmap_get_memory_footprint(300 * 8);
285 : 0 : mem = plt_zmalloc(bmap_sz, 0);
286 [ # # ]: 0 : if (mem == NULL) {
287 : 0 : plt_err("mem alloc failed");
288 : 0 : return false;
289 : : }
290 : 0 : bmap = plt_bitmap_init(300 * 8, mem, bmap_sz);
291 [ # # ]: 0 : if (bmap == NULL) {
292 : 0 : plt_err("mem alloc failed");
293 : 0 : plt_free(mem);
294 : 0 : return false;
295 : : }
296 : :
297 [ # # ]: 0 : if (!roc_model_is_cn20k()) {
298 : 0 : npc_construct_ldata_mask(npc, bmap, lid, lt, 0);
299 : 0 : npc_construct_ldata_mask(npc, bmap, lid, lt, 1);
300 : : } else {
301 : 0 : npc_construct_ldata_mask_cn20k(npc, bmap, lid, lt);
302 : : }
303 : :
304 [ # # ]: 0 : for (i = offset; i < (offset + len); i++) {
305 [ # # ]: 0 : if (plt_bitmap_get(bmap, i) != 0x1) {
306 : 0 : plt_free(mem);
307 : 0 : return false;
308 : : }
309 : : }
310 : :
311 : 0 : plt_free(mem);
312 : 0 : return true;
313 : : }
314 : :
315 : : uint64_t
316 : 0 : npc_get_kex_capability(struct npc *npc)
317 : : {
318 : : npc_kex_cap_terms_t kex_cap;
319 : :
320 : : memset(&kex_cap, 0, sizeof(kex_cap));
321 : :
322 : : /* Ethtype: Offset 12B, len 2B */
323 : 0 : kex_cap.bit.ethtype_0 = npc_is_kex_enabled(npc, NPC_LID_LA, NPC_LT_LA_ETHER, 12 * 8, 2 * 8);
324 : : /* QINQ VLAN Ethtype: offset 8B, len 2B */
325 : 0 : kex_cap.bit.ethtype_x =
326 : 0 : npc_is_kex_enabled(npc, NPC_LID_LB, NPC_LT_LB_STAG_QINQ, 8 * 8, 2 * 8);
327 : : /* VLAN ID0 : Outer VLAN: Offset 2B, len 2B */
328 : 0 : kex_cap.bit.vlan_id_0 = npc_is_kex_enabled(npc, NPC_LID_LB, NPC_LT_LB_CTAG, 2 * 8, 2 * 8);
329 : : /* VLAN PCP0 : Outer VLAN: Offset 2B, len 1B */
330 : 0 : kex_cap.bit.vlan_pcp_0 = npc_is_kex_enabled(npc, NPC_LID_LB, NPC_LT_LB_CTAG, 2 * 8, 2 * 1);
331 : : /* VLAN IDX : Inner VLAN: offset 6B, len 2B */
332 : 0 : kex_cap.bit.vlan_id_x =
333 : 0 : npc_is_kex_enabled(npc, NPC_LID_LB, NPC_LT_LB_STAG_QINQ, 6 * 8, 2 * 8);
334 : : /* DMCA: offset 0B, len 6B */
335 : 0 : kex_cap.bit.dmac = npc_is_kex_enabled(npc, NPC_LID_LA, NPC_LT_LA_ETHER, 0 * 8, 6 * 8);
336 : : /* IP proto: offset 9B, len 1B */
337 : 0 : kex_cap.bit.ip_proto = npc_is_kex_enabled(npc, NPC_LID_LC, NPC_LT_LC_IP, 9 * 8, 1 * 8);
338 : : /* IPv4 dscp: offset 1B, len 1B, IPv6 dscp: offset 0B, len 2B */
339 [ # # # # ]: 0 : kex_cap.bit.ip_dscp = npc_is_kex_enabled(npc, NPC_LID_LC, NPC_LT_LC_IP, 1 * 8, 1 * 8) &&
340 : 0 : npc_is_kex_enabled(npc, NPC_LID_LC, NPC_LT_LC_IP6, 0, 2 * 8);
341 : : /* UDP dport: offset 2B, len 2B */
342 : 0 : kex_cap.bit.udp_dport = npc_is_kex_enabled(npc, NPC_LID_LD, NPC_LT_LD_UDP, 2 * 8, 2 * 8);
343 : : /* UDP sport: offset 0B, len 2B */
344 : 0 : kex_cap.bit.udp_sport = npc_is_kex_enabled(npc, NPC_LID_LD, NPC_LT_LD_UDP, 0 * 8, 2 * 8);
345 : : /* TCP dport: offset 2B, len 2B */
346 : 0 : kex_cap.bit.tcp_dport = npc_is_kex_enabled(npc, NPC_LID_LD, NPC_LT_LD_TCP, 2 * 8, 2 * 8);
347 : : /* TCP sport: offset 0B, len 2B */
348 : 0 : kex_cap.bit.tcp_sport = npc_is_kex_enabled(npc, NPC_LID_LD, NPC_LT_LD_TCP, 0 * 8, 2 * 8);
349 : : /* IP SIP: offset 12B, len 4B */
350 : 0 : kex_cap.bit.sip_addr = npc_is_kex_enabled(npc, NPC_LID_LC, NPC_LT_LC_IP, 12 * 8, 4 * 8);
351 : : /* IP DIP: offset 14B, len 4B */
352 : 0 : kex_cap.bit.dip_addr = npc_is_kex_enabled(npc, NPC_LID_LC, NPC_LT_LC_IP, 14 * 8, 4 * 8);
353 : : /* IP6 SIP: offset 8B, len 16B */
354 : 0 : kex_cap.bit.sip6_addr = npc_is_kex_enabled(npc, NPC_LID_LC, NPC_LT_LC_IP6, 8 * 8, 16 * 8);
355 : : /* IP6 DIP: offset 24B, len 16B */
356 : 0 : kex_cap.bit.dip6_addr = npc_is_kex_enabled(npc, NPC_LID_LC, NPC_LT_LC_IP6, 24 * 8, 16 * 8);
357 : : /* ESP SPI: offset 0B, len 4B */
358 : 0 : kex_cap.bit.ipsec_spi = npc_is_kex_enabled(npc, NPC_LID_LE, NPC_LT_LE_ESP, 0 * 8, 4 * 8);
359 : : /* VXLAN VNI: offset 4B, len 3B */
360 : 0 : kex_cap.bit.ld_vni = npc_is_kex_enabled(npc, NPC_LID_LE, NPC_LT_LE_VXLAN, 0 * 8, 3 * 8);
361 : :
362 : : /* Custom L3 frame: varied offset and lengths */
363 : : kex_cap.bit.custom_l3 = npc_is_kex_enabled(npc, NPC_LID_LC, NPC_LT_LC_CUSTOM0, 0, 0);
364 : 0 : kex_cap.bit.custom_l3 |=
365 : : (uint64_t)npc_is_kex_enabled(npc, NPC_LID_LC, NPC_LT_LC_CUSTOM1, 0, 0);
366 : : /* SCTP sport : offset 0B, len 2B */
367 : 0 : kex_cap.bit.sctp_sport = npc_is_kex_enabled(npc, NPC_LID_LD, NPC_LT_LD_SCTP, 0 * 8, 2 * 8);
368 : : /* SCTP dport : offset 2B, len 2B */
369 : 0 : kex_cap.bit.sctp_dport = npc_is_kex_enabled(npc, NPC_LID_LD, NPC_LT_LD_SCTP, 2 * 8, 2 * 8);
370 : : /* ICMP type : offset 0B, len 1B */
371 : 0 : kex_cap.bit.icmp_type = npc_is_kex_enabled(npc, NPC_LID_LD, NPC_LT_LD_ICMP, 0 * 8, 1 * 8);
372 : : /* ICMP code : offset 1B, len 1B */
373 : 0 : kex_cap.bit.icmp_code = npc_is_kex_enabled(npc, NPC_LID_LD, NPC_LT_LD_ICMP, 1 * 8, 1 * 8);
374 : : /* ICMP id : offset 4B, len 2B */
375 : 0 : kex_cap.bit.icmp_id = npc_is_kex_enabled(npc, NPC_LID_LD, NPC_LT_LD_ICMP, 4 * 8, 2 * 8);
376 : : /* IGMP grp_addr : offset 4B, len 4B */
377 : 0 : kex_cap.bit.igmp_grp_addr =
378 : 0 : npc_is_kex_enabled(npc, NPC_LID_LD, NPC_LT_LD_IGMP, 4 * 8, 4 * 8);
379 : : /* GTPU teid : offset 4B, len 4B */
380 : 0 : kex_cap.bit.gtpv1_teid = npc_is_kex_enabled(npc, NPC_LID_LE, NPC_LT_LE_GTPU, 4 * 8, 4 * 8);
381 : 0 : return kex_cap.all_bits;
382 : : }
383 : :
384 : : #define BYTESM1_SHIFT 16
385 : : #define HDR_OFF_SHIFT 8
386 : : static void
387 : : npc_update_kex_info(struct npc_xtract_info *xtract_info, uint64_t val)
388 : : {
389 : 0 : xtract_info->use_hash = ((val >> 20) & 0x1);
390 : 0 : xtract_info->len = ((val >> BYTESM1_SHIFT) & 0xf) + 1;
391 : 0 : xtract_info->hdr_off = (val >> HDR_OFF_SHIFT) & 0xff;
392 : 0 : xtract_info->key_off = val & 0x3f;
393 : 0 : xtract_info->enable = ((val >> 7) & 0x1);
394 : 0 : xtract_info->flags_enable = ((val >> 6) & 0x1);
395 : : }
396 : :
397 : : int
398 : 0 : npc_mcam_alloc_entries(struct mbox *mbox, int ref_mcam, int *alloc_entry, int req_count, int prio,
399 : : int *resp_count, bool is_conti)
400 : : {
401 : : struct npc_mcam_alloc_entry_req *req;
402 : : struct npc_mcam_alloc_entry_rsp *rsp;
403 : : int rc = -ENOSPC;
404 : : int i;
405 : :
406 : 0 : req = mbox_alloc_msg_npc_mcam_alloc_entry(mbox_get(mbox));
407 [ # # ]: 0 : if (req == NULL)
408 : 0 : goto exit;
409 : 0 : req->contig = is_conti;
410 : 0 : req->count = req_count;
411 : 0 : req->ref_priority = prio;
412 : 0 : req->ref_entry = ref_mcam;
413 : :
414 : : rc = mbox_process_msg(mbox, (void *)&rsp);
415 [ # # ]: 0 : if (rc)
416 : 0 : goto exit;
417 [ # # ]: 0 : for (i = 0; i < rsp->count; i++)
418 : 0 : alloc_entry[i] = rsp->entry_list[i];
419 : 0 : *resp_count = rsp->count;
420 [ # # ]: 0 : if (is_conti)
421 : 0 : alloc_entry[0] = rsp->entry;
422 : : rc = 0;
423 : 0 : exit:
424 : : mbox_put(mbox);
425 : 0 : return rc;
426 : : }
427 : :
428 : : uint8_t
429 : 0 : npc_kex_key_type_config_get(struct npc *npc)
430 : : {
431 : : /* KEX is configured just for X2 */
432 [ # # ]: 0 : if (npc->keyw[ROC_NPC_INTF_RX] == 1)
433 : : return NPC_CN20K_MCAM_KEY_X2;
434 : :
435 : : /* KEX is configured just for X4 */
436 [ # # ]: 0 : if (npc->keyw[ROC_NPC_INTF_RX] == 2)
437 : 0 : return NPC_CN20K_MCAM_KEY_X4;
438 : :
439 : : /* KEX is configured for both X2 and X4 */
440 : : return NPC_CN20K_MCAM_KEY_DYN;
441 : : }
442 : :
443 : : int
444 : 0 : npc_mcam_alloc_entry(struct npc *npc, struct roc_npc_flow *mcam, struct roc_npc_flow *ref_mcam,
445 : : uint8_t prio, int *resp_count)
446 : : {
447 : 0 : struct mbox *mbox = mbox_get(npc->mbox);
448 : : struct npc_mcam_alloc_entry_req *req;
449 : : struct npc_mcam_alloc_entry_rsp *rsp;
450 : : int rc = -ENOSPC;
451 : :
452 : 0 : req = mbox_alloc_msg_npc_mcam_alloc_entry(mbox);
453 [ # # ]: 0 : if (req == NULL)
454 : 0 : goto exit;
455 : :
456 : 0 : req->count = 1;
457 : 0 : req->ref_priority = prio;
458 [ # # ]: 0 : req->ref_entry = ref_mcam ? ref_mcam->mcam_id : 0;
459 : 0 : req->kw_type = mcam->key_type;
460 : :
461 [ # # ]: 0 : if (npc_kex_key_type_config_get(npc) == NPC_CN20K_MCAM_KEY_DYN)
462 : 0 : req->virt = 1;
463 : :
464 : : rc = mbox_process_msg(mbox, (void *)&rsp);
465 [ # # ]: 0 : if (rc)
466 : 0 : goto exit;
467 : :
468 : 0 : mcam->mcam_id = rsp->entry_list[0];
469 [ # # ]: 0 : mcam->nix_intf = ref_mcam ? ref_mcam->nix_intf : 0;
470 : 0 : *resp_count = rsp->count;
471 : :
472 : : rc = 0;
473 : 0 : exit:
474 : : mbox_put(mbox);
475 : 0 : return rc;
476 : : }
477 : :
478 : : int
479 : 0 : npc_mcam_ena_dis_entry(struct npc *npc, struct roc_npc_flow *mcam, bool enable)
480 : : {
481 : : struct npc_mcam_ena_dis_entry_req *req;
482 : 0 : struct mbox *mbox = mbox_get(npc->mbox);
483 : : int rc = -ENOSPC;
484 : :
485 [ # # ]: 0 : if (enable)
486 : 0 : req = mbox_alloc_msg_npc_mcam_ena_entry(mbox);
487 : : else
488 : 0 : req = mbox_alloc_msg_npc_mcam_dis_entry(mbox);
489 : :
490 [ # # ]: 0 : if (req == NULL)
491 : 0 : goto exit;
492 : 0 : req->entry = mcam->mcam_id;
493 : 0 : mcam->enable = enable;
494 : 0 : rc = mbox_process(mbox);
495 : 0 : exit:
496 : : mbox_put(mbox);
497 : 0 : return rc;
498 : : }
499 : :
500 : : int
501 : 0 : npc_mcam_write_entry(struct mbox *mbox, struct roc_npc_flow *mcam)
502 : : {
503 : : struct npc_mcam_write_entry_req *req;
504 : : struct npc_cn20k_mcam_write_entry_req *cn20k_req;
505 : : struct mbox_msghdr *rsp;
506 : : int rc = -ENOSPC;
507 : 0 : uint16_t ctr = 0;
508 : : int i;
509 : :
510 [ # # # # ]: 0 : if (mcam->use_ctr && mcam->ctr_id == NPC_COUNTER_NONE) {
511 : 0 : rc = npc_mcam_alloc_counter(mbox, &ctr);
512 [ # # ]: 0 : if (rc)
513 : : return rc;
514 : 0 : mcam->ctr_id = ctr;
515 : :
516 : 0 : rc = npc_mcam_clear_counter(mbox, mcam->ctr_id);
517 [ # # ]: 0 : if (rc)
518 : : return rc;
519 : : }
520 : :
521 [ # # ]: 0 : if (roc_model_is_cn20k()) {
522 : 0 : cn20k_req = mbox_alloc_msg_npc_cn20k_mcam_write_entry(mbox_get(mbox));
523 [ # # ]: 0 : if (cn20k_req == NULL) {
524 : : mbox_put(mbox);
525 [ # # ]: 0 : if (mcam->use_ctr)
526 : 0 : npc_mcam_free_counter(mbox, ctr);
527 : :
528 : 0 : return rc;
529 : : }
530 : 0 : cn20k_req->entry = mcam->mcam_id;
531 : 0 : cn20k_req->intf = mcam->nix_intf;
532 : 0 : cn20k_req->enable_entry = mcam->enable;
533 : 0 : cn20k_req->entry_data.action = mcam->npc_action;
534 : 0 : cn20k_req->entry_data.action2 = mcam->npc_action2;
535 : 0 : cn20k_req->entry_data.vtag_action = mcam->vtag_action;
536 : 0 : cn20k_req->hw_prio = mcam->priority;
537 [ # # ]: 0 : if (mcam->use_ctr)
538 : 0 : cn20k_req->cntr = mcam->ctr_id;
539 : :
540 [ # # ]: 0 : for (i = 0; i < NPC_MCAM_KEY_X4_WORDS; i++) {
541 : 0 : cn20k_req->entry_data.kw[i] = mcam->mcam_data[i];
542 : 0 : cn20k_req->entry_data.kw_mask[i] = mcam->mcam_mask[i];
543 : : }
544 : : } else {
545 : 0 : req = mbox_alloc_msg_npc_mcam_write_entry(mbox_get(mbox));
546 [ # # ]: 0 : if (req == NULL) {
547 : : mbox_put(mbox);
548 [ # # ]: 0 : if (mcam->use_ctr)
549 : 0 : npc_mcam_free_counter(mbox, ctr);
550 : :
551 : 0 : return rc;
552 : : }
553 : 0 : req->entry = mcam->mcam_id;
554 : 0 : req->intf = mcam->nix_intf;
555 : 0 : req->enable_entry = mcam->enable;
556 : 0 : req->entry_data.action = mcam->npc_action;
557 : 0 : req->entry_data.vtag_action = mcam->vtag_action;
558 [ # # ]: 0 : if (mcam->use_ctr) {
559 : 0 : req->set_cntr = 1;
560 : 0 : req->cntr = mcam->ctr_id;
561 : : }
562 : :
563 [ # # ]: 0 : for (i = 0; i < NPC_MCAM_KEY_X4_WORDS; i++) {
564 : 0 : req->entry_data.kw[i] = mcam->mcam_data[i];
565 : 0 : req->entry_data.kw_mask[i] = mcam->mcam_mask[i];
566 : : }
567 : : }
568 : : rc = mbox_process_msg(mbox, (void *)&rsp);
569 : : mbox_put(mbox);
570 : 0 : return rc;
571 : : }
572 : :
573 : : static void
574 : 0 : npc_mcam_kex_cfg_dump(struct npc_cn20k_get_kex_cfg_rsp *kex_rsp)
575 : : {
576 [ # # ]: 0 : for (int i = 0; i < NPC_MAX_INTF; i++) {
577 [ # # ]: 0 : for (int j = 0; j < NPC_MAX_EXTRACTOR; j++) {
578 [ # # ]: 0 : if (kex_rsp->intf_extr[i][j] == 0)
579 : 0 : continue;
580 : 0 : plt_info("Intf %d, Extr %d: 0x%" PRIx64, i, j, kex_rsp->intf_extr[i][j]);
581 : : }
582 : : }
583 : :
584 [ # # ]: 0 : for (int i = 0; i < NPC_MAX_INTF; i++) {
585 [ # # ]: 0 : for (int j = 0; j < NPC_MAX_EXTRACTOR; j++) {
586 [ # # ]: 0 : for (int k = 0; k < NPC_MAX_LT; k++) {
587 [ # # ]: 0 : if (kex_rsp->intf_extr_lt[i][j][k] == 0)
588 : 0 : continue;
589 : 0 : plt_info("Intf %d, Extr %d, LT %d: 0x%" PRIx64, i, j, k,
590 : : kex_rsp->intf_extr_lt[i][j][k]);
591 : : }
592 : : }
593 : : }
594 : 0 : }
595 : :
596 : : static void
597 : 0 : npc_mcam_process_mkex_cfg_cn20k(struct npc *npc, struct npc_cn20k_get_kex_cfg_rsp *kex_rsp)
598 : : {
599 : : volatile uint64_t(*q)[NPC_MAX_INTF][NPC_MAX_EXTRACTOR][NPC_MAX_LT];
600 : : volatile uint64_t(*d)[NPC_MAX_INTF][NPC_MAX_EXTRACTOR];
601 : : struct npc_xtract_info *x_info = NULL;
602 : : union npc_kex_ldata_flags_cfg *ld_info = NULL;
603 : : int ex, lt, ix;
604 : : npc_dxcfg_cn20k_t *p;
605 : : npc_lid_cn20k_t *l;
606 : : uint64_t keyw;
607 : : uint64_t val;
608 : :
609 : 0 : npc->keyx_supp_nmask[NPC_MCAM_RX] = kex_rsp->rx_keyx_cfg & 0x7fffffffULL;
610 : 0 : npc->keyx_supp_nmask[NPC_MCAM_TX] = kex_rsp->tx_keyx_cfg & 0x7fffffffULL;
611 : 0 : npc->keyx_len[NPC_MCAM_RX] = npc_supp_key_len(npc->keyx_supp_nmask[NPC_MCAM_RX]);
612 : 0 : npc->keyx_len[NPC_MCAM_TX] = npc_supp_key_len(npc->keyx_supp_nmask[NPC_MCAM_TX]);
613 : :
614 : 0 : keyw = (kex_rsp->rx_keyx_cfg >> 32) & 0x7ULL;
615 : 0 : npc->keyw[NPC_MCAM_RX] = keyw;
616 : 0 : keyw = (kex_rsp->tx_keyx_cfg >> 32) & 0x7ULL;
617 : 0 : npc->keyw[NPC_MCAM_TX] = keyw;
618 : :
619 : : p = &npc->prx_dxcfg_cn20k;
620 : : l = &npc->lid_cfg;
621 : : q = (volatile uint64_t(*)[][NPC_MAX_EXTRACTOR][NPC_MAX_LT])(&kex_rsp->intf_extr_lt);
622 : : d = (volatile uint64_t(*)[][NPC_MAX_EXTRACTOR])(&kex_rsp->intf_extr);
623 [ # # ]: 0 : for (ix = 0; ix < NPC_MAX_INTF; ix++) {
624 [ # # ]: 0 : for (ex = 0; ex < NPC_MAX_EXTRACTOR; ex++) {
625 : 0 : val = (*d)[ix][ex];
626 : : ld_info = &(*l)[ix][ex];
627 : 0 : ld_info->s.lid = (val & 0x7);
628 [ # # ]: 0 : for (lt = 0; lt < NPC_MAX_LT; lt++) {
629 : : x_info = &(*p)[ix][ex][lt].xtract;
630 : 0 : val = (*q)[ix][ex][lt];
631 : : npc_update_kex_info(x_info, val);
632 : : }
633 : : }
634 : : }
635 : 0 : }
636 : :
637 : : static void
638 : 0 : npc_mcam_process_mkex_cfg(struct npc *npc, struct npc_get_kex_cfg_rsp *kex_rsp)
639 : : {
640 : : volatile uint64_t(*q)[NPC_MAX_INTF][NPC_MAX_LID][NPC_MAX_LT][NPC_MAX_LD];
641 : : struct npc_xtract_info *x_info = NULL;
642 : : int lid, lt, ld, fl, ix;
643 : : npc_dxcfg_t *p;
644 : : uint64_t keyw;
645 : : uint64_t val;
646 : :
647 : 0 : npc->keyx_supp_nmask[NPC_MCAM_RX] = kex_rsp->rx_keyx_cfg & 0x7fffffffULL;
648 : 0 : npc->keyx_supp_nmask[NPC_MCAM_TX] = kex_rsp->tx_keyx_cfg & 0x7fffffffULL;
649 : 0 : npc->keyx_len[NPC_MCAM_RX] = npc_supp_key_len(npc->keyx_supp_nmask[NPC_MCAM_RX]);
650 : 0 : npc->keyx_len[NPC_MCAM_TX] = npc_supp_key_len(npc->keyx_supp_nmask[NPC_MCAM_TX]);
651 : :
652 : 0 : keyw = (kex_rsp->rx_keyx_cfg >> 32) & 0x7ULL;
653 : 0 : npc->keyw[NPC_MCAM_RX] = keyw;
654 : 0 : keyw = (kex_rsp->tx_keyx_cfg >> 32) & 0x7ULL;
655 : 0 : npc->keyw[NPC_MCAM_TX] = keyw;
656 : :
657 : : /* Update KEX_LD_FLAG */
658 [ # # ]: 0 : for (ix = 0; ix < NPC_MAX_INTF; ix++) {
659 [ # # ]: 0 : for (ld = 0; ld < NPC_MAX_LD; ld++) {
660 [ # # ]: 0 : for (fl = 0; fl < NPC_MAX_LFL; fl++) {
661 : : x_info = &npc->prx_fxcfg[ix][ld][fl].xtract[0];
662 : 0 : val = kex_rsp->intf_ld_flags[ix][ld][fl];
663 : : npc_update_kex_info(x_info, val);
664 : : }
665 : : }
666 : : }
667 : :
668 : : /* Update LID, LT and LDATA cfg */
669 : : p = &npc->prx_dxcfg;
670 : : q = (volatile uint64_t(*)[][NPC_MAX_LID][NPC_MAX_LT][NPC_MAX_LD])(&kex_rsp->intf_lid_lt_ld);
671 [ # # ]: 0 : for (ix = 0; ix < NPC_MAX_INTF; ix++) {
672 [ # # ]: 0 : for (lid = 0; lid < NPC_MAX_LID; lid++) {
673 [ # # ]: 0 : for (lt = 0; lt < NPC_MAX_LT; lt++) {
674 [ # # ]: 0 : for (ld = 0; ld < NPC_MAX_LD; ld++) {
675 : : x_info = &(*p)[ix][lid][lt].xtract[ld];
676 : 0 : val = (*q)[ix][lid][lt][ld];
677 : : npc_update_kex_info(x_info, val);
678 : : }
679 : : }
680 : : }
681 : : }
682 : : /* Update LDATA Flags cfg */
683 : 0 : npc->prx_lfcfg[0].i = kex_rsp->kex_ld_flags[0];
684 : 0 : npc->prx_lfcfg[1].i = kex_rsp->kex_ld_flags[1];
685 : 0 : }
686 : :
687 : : int
688 : 0 : npc_mcam_fetch_hw_cap(struct npc *npc, uint8_t *npc_hw_cap)
689 : : {
690 : : struct get_hw_cap_rsp *hw_cap_rsp;
691 : 0 : struct mbox *mbox = mbox_get(npc->mbox);
692 : : int rc = 0;
693 : :
694 : 0 : *npc_hw_cap = 0;
695 : :
696 : 0 : mbox_alloc_msg_get_hw_cap(mbox);
697 : : rc = mbox_process_msg(mbox, (void *)&hw_cap_rsp);
698 [ # # ]: 0 : if (rc) {
699 : 0 : plt_err("Failed to fetch NPC HW capability");
700 : 0 : goto done;
701 : : }
702 : :
703 : 0 : *npc_hw_cap = hw_cap_rsp->npc_hash_extract;
704 : 0 : done:
705 : : mbox_put(mbox);
706 : 0 : return rc;
707 : : }
708 : :
709 : : int
710 : 0 : npc_mcam_fetch_kex_cfg(struct npc *npc)
711 : : {
712 : : struct npc_get_kex_cfg_rsp *kex_rsp;
713 : : struct npc_cn20k_get_kex_cfg_rsp *kex_rsp_20k;
714 : 0 : struct mbox *mbox = mbox_get(npc->mbox);
715 : : int rc = 0;
716 : :
717 [ # # ]: 0 : if (!roc_model_is_cn20k()) {
718 : 0 : mbox_alloc_msg_npc_get_kex_cfg(mbox);
719 : : rc = mbox_process_msg(mbox, (void *)&kex_rsp);
720 [ # # ]: 0 : if (rc) {
721 : 0 : plt_err("Failed to fetch NPC KEX config");
722 : 0 : goto done;
723 : : }
724 : :
725 : 0 : mbox_memcpy((char *)npc->profile_name, kex_rsp->mkex_pfl_name, MKEX_NAME_LEN);
726 : :
727 : 0 : npc->exact_match_ena = (kex_rsp->rx_keyx_cfg >> 40) & 0xF;
728 : 0 : npc_mcam_process_mkex_cfg(npc, kex_rsp);
729 : : } else {
730 : 0 : mbox_alloc_msg_npc_cn20k_get_kex_cfg(mbox);
731 : : rc = mbox_process_msg(mbox, (void *)&kex_rsp_20k);
732 [ # # ]: 0 : if (rc) {
733 : 0 : plt_err("Failed to fetch NPC KEX config");
734 : 0 : goto done;
735 : : }
736 : :
737 : 0 : mbox_memcpy((char *)npc->profile_name, kex_rsp_20k->mkex_pfl_name, MKEX_NAME_LEN);
738 : :
739 : 0 : npc->exact_match_ena = (kex_rsp_20k->rx_keyx_cfg >> 40) & 0xF;
740 : 0 : npc_mcam_process_mkex_cfg_cn20k(npc, kex_rsp_20k);
741 [ # # ]: 0 : if (npc->enable_debug)
742 : 0 : npc_mcam_kex_cfg_dump(kex_rsp_20k);
743 : : }
744 : :
745 : 0 : done:
746 : : mbox_put(mbox);
747 : 0 : return rc;
748 : : }
749 : :
750 : : static void
751 : 0 : npc_mcam_set_channel(struct roc_npc_flow *flow, struct npc_cn20k_mcam_write_entry_req *req,
752 : : uint16_t channel, uint16_t chan_mask, bool is_second_pass)
753 : : {
754 : : uint16_t chan = 0, mask = 0;
755 : :
756 : 0 : req->entry_data.kw[0] &= ~(GENMASK(11, 0));
757 : 0 : req->entry_data.kw_mask[0] &= ~(GENMASK(11, 0));
758 : 0 : flow->mcam_data[0] &= ~(GENMASK(11, 0));
759 [ # # ]: 0 : flow->mcam_mask[0] &= ~(GENMASK(11, 0));
760 : :
761 : : chan = channel;
762 : : mask = chan_mask;
763 : :
764 [ # # ]: 0 : if (roc_model_runtime_is_cn10k()) {
765 [ # # ]: 0 : if (is_second_pass) {
766 : 0 : chan = (channel | NIX_CHAN_CPT_CH_START);
767 : 0 : mask = (chan_mask | NIX_CHAN_CPT_CH_START);
768 : : } else {
769 [ # # ]: 0 : if (!roc_npc_action_is_rx_inline(flow->npc_action)) {
770 : : /*
771 : : * Clear bits 10 & 11 corresponding to CPT
772 : : * channel. By default, rules should match
773 : : * both first pass packets and second pass
774 : : * packets from CPT.
775 : : */
776 : 0 : chan = (channel & NIX_CHAN_CPT_X2P_MASK);
777 : 0 : mask = (chan_mask & NIX_CHAN_CPT_X2P_MASK);
778 : : }
779 : : }
780 : : }
781 : :
782 : 0 : req->entry_data.kw[0] |= (uint64_t)chan;
783 : 0 : req->entry_data.kw_mask[0] |= (uint64_t)mask;
784 : 0 : flow->mcam_data[0] |= (uint64_t)chan;
785 : 0 : flow->mcam_mask[0] |= (uint64_t)mask;
786 : 0 : }
787 : :
788 : : /* Fold RQ into the action word and program the RX channel into kw[0],
789 : : * matching the RX steps the sync path does in npc_mcam_alloc_and_write().
790 : : */
791 : : void
792 : 0 : roc_npc_mcam_write_rx_finalize(struct roc_npc *roc_npc, struct roc_npc_flow *flow)
793 : : {
794 : : struct npc *npc = roc_npc_to_npc_priv(roc_npc);
795 : : uint16_t chan, mask;
796 : : uint64_t op;
797 : :
798 [ # # ]: 0 : if (flow->nix_intf != NIX_INTF_RX)
799 : : return;
800 : :
801 : : /* Set the RQ in the action index field, but only for UCAST* ops that
802 : : * use it as a receive queue. Clear then set so a re-finalize on an
803 : : * async QUEUE update leaves no stale bits.
804 : : */
805 : 0 : op = flow->npc_action & 0xFULL;
806 : 0 : if (op == NIX_RX_ACTIONOP_UCAST || op == NIX_RX_ACTIONOP_UCAST_IPSEC ||
807 [ # # ]: 0 : op == NIX_RX_ACTIONOP_UCAST_CPT) {
808 : 0 : flow->npc_action &= ~GENMASK_ULL(39, 20);
809 : 0 : flow->npc_action |= ((uint64_t)flow->recv_queue << 20) & GENMASK_ULL(39, 20);
810 : : }
811 : :
812 : : /* Program the RX channel into kw[0]. */
813 : 0 : chan = npc->channel;
814 : : mask = BIT_ULL(12) - 1;
815 : :
816 : 0 : flow->mcam_data[0] &= ~(GENMASK(11, 0));
817 [ # # ]: 0 : flow->mcam_mask[0] &= ~(GENMASK(11, 0));
818 : :
819 [ # # # # ]: 0 : if (roc_model_runtime_is_cn10k() && !roc_npc_action_is_rx_inline(flow->npc_action)) {
820 : 0 : chan = (chan & NIX_CHAN_CPT_X2P_MASK);
821 : : mask = (mask & NIX_CHAN_CPT_X2P_MASK);
822 : : }
823 : :
824 : 0 : flow->mcam_data[0] |= (uint64_t)chan;
825 : 0 : flow->mcam_mask[0] |= (uint64_t)mask;
826 : : }
827 : :
828 : : #define NPC_PF_FUNC_WIDTH 2
829 : : #define NPC_KEX_PF_FUNC_MASK 0xFFFF
830 : :
831 : : static int
832 : 0 : npc_mcam_set_pf_func(struct npc *npc, struct roc_npc_flow *flow, uint16_t pf_func)
833 : : {
834 : : uint16_t nr_bytes, hdr_offset, key_offset, pf_func_offset;
835 : : uint8_t *flow_mcam_data, *flow_mcam_mask;
836 : : struct npc_lid_lt_xtract_info *xinfo;
837 : : bool pffunc_found = false;
838 : 0 : uint16_t mask = 0xFFFF;
839 : : int i;
840 : :
841 : 0 : flow_mcam_data = (uint8_t *)flow->mcam_data;
842 : 0 : flow_mcam_mask = (uint8_t *)flow->mcam_mask;
843 : :
844 : : xinfo = &npc->prx_dxcfg[NIX_INTF_TX][NPC_LID_LA][NPC_LT_LA_IH_NIX_ETHER];
845 : :
846 [ # # ]: 0 : for (i = 0; i < NPC_MAX_LD; i++) {
847 : 0 : nr_bytes = xinfo->xtract[i].len;
848 : 0 : hdr_offset = xinfo->xtract[i].hdr_off;
849 : 0 : key_offset = xinfo->xtract[i].key_off;
850 : :
851 [ # # ]: 0 : if (hdr_offset > 0 || nr_bytes < NPC_PF_FUNC_WIDTH)
852 : 0 : continue;
853 : : else
854 : : pffunc_found = true;
855 : :
856 : 0 : pf_func_offset = key_offset + nr_bytes - NPC_PF_FUNC_WIDTH;
857 : 0 : memcpy((void *)&flow_mcam_data[pf_func_offset], (uint8_t *)&pf_func,
858 : : NPC_PF_FUNC_WIDTH);
859 : 0 : memcpy((void *)&flow_mcam_mask[pf_func_offset], (uint8_t *)&mask,
860 : : NPC_PF_FUNC_WIDTH);
861 : : }
862 [ # # ]: 0 : if (!pffunc_found)
863 : 0 : return -EINVAL;
864 : :
865 : : return 0;
866 : : }
867 : :
868 : : static int
869 : 0 : npc_mcam_set_pf_func_cn20k(struct npc *npc, struct roc_npc_flow *flow, uint16_t pf_func)
870 : : {
871 : : uint16_t nr_bytes, hdr_offset, key_offset, pf_func_offset;
872 : : struct npc_lid_lt_xtract_info_cn20k *xinfo;
873 : : uint8_t *flow_mcam_data, *flow_mcam_mask;
874 : : bool pffunc_found = false;
875 : 0 : uint16_t mask = 0xFFFF;
876 : : int i;
877 : :
878 : 0 : flow_mcam_data = (uint8_t *)flow->mcam_data;
879 : 0 : flow_mcam_mask = (uint8_t *)flow->mcam_mask;
880 : :
881 : 0 : xinfo = npc->prx_dxcfg_cn20k[NIX_INTF_TX][NPC_LID_LA];
882 : :
883 [ # # ]: 0 : for (i = 0; i < NPC_MAX_LT; i++) {
884 : 0 : nr_bytes = xinfo[i].xtract.len;
885 : 0 : hdr_offset = xinfo[i].xtract.hdr_off;
886 : 0 : key_offset = xinfo[i].xtract.key_off;
887 : :
888 [ # # ]: 0 : if (hdr_offset > 0 || nr_bytes < NPC_PF_FUNC_WIDTH)
889 : 0 : continue;
890 : : else
891 : : pffunc_found = true;
892 : :
893 : 0 : pf_func_offset = key_offset + nr_bytes - NPC_PF_FUNC_WIDTH;
894 : 0 : memcpy((void *)&flow_mcam_data[pf_func_offset], (uint8_t *)&pf_func,
895 : : NPC_PF_FUNC_WIDTH);
896 : 0 : memcpy((void *)&flow_mcam_mask[pf_func_offset], (uint8_t *)&mask,
897 : : NPC_PF_FUNC_WIDTH);
898 : : }
899 [ # # ]: 0 : if (!pffunc_found)
900 : 0 : return -EINVAL;
901 : :
902 : : return 0;
903 : : }
904 : :
905 : : int
906 : 0 : npc_mcam_alloc_and_write(struct npc *npc, struct roc_npc_flow *flow, struct npc_parse_state *pst)
907 : : {
908 : : struct npc_cn20k_mcam_write_entry_req *cn20k_req;
909 : : struct npc_cn20k_mcam_write_entry_req req;
910 : : struct nix_inl_dev *inl_dev = NULL;
911 : 0 : struct mbox *mbox = npc->mbox;
912 : : struct mbox_msghdr *rsp;
913 : : struct idev_cfg *idev;
914 : : uint16_t pf_func = 0;
915 : 0 : uint16_t ctr = ~(0);
916 : : uint32_t la_offset;
917 : : uint64_t mask;
918 : : int rc, idx;
919 : : int entry;
920 : :
921 : : PLT_SET_USED(pst);
922 : :
923 : 0 : idev = idev_get_cfg();
924 [ # # ]: 0 : if (idev)
925 : 0 : inl_dev = idev->nix_inl_dev;
926 : :
927 [ # # # # ]: 0 : if (inl_dev && inl_dev->ipsec_index) {
928 [ # # ]: 0 : if (flow->is_inline_dev)
929 : 0 : mbox = inl_dev->dev.mbox;
930 : : }
931 : :
932 [ # # ]: 0 : if (flow->use_ctr) {
933 : 0 : rc = npc_mcam_alloc_counter(mbox, &ctr);
934 [ # # ]: 0 : if (rc)
935 : : return rc;
936 : :
937 : 0 : flow->ctr_id = ctr;
938 : 0 : rc = npc_mcam_clear_counter(mbox, flow->ctr_id);
939 [ # # ]: 0 : if (rc)
940 : : return rc;
941 : : }
942 : :
943 [ # # ]: 0 : if (roc_model_is_cn20k()) {
944 : 0 : req.hw_prio = flow->priority;
945 : 0 : flow->key_type = npc_get_key_type(npc, flow);
946 : 0 : req.req_kw_type = flow->key_type;
947 : : }
948 : :
949 [ # # # # : 0 : if (flow->nix_intf == NIX_INTF_RX && flow->is_inline_dev && inl_dev &&
# # ]
950 [ # # # # ]: 0 : inl_dev->ipsec_index && inl_dev->is_multi_channel) {
951 [ # # ]: 0 : if (inl_dev->curr_ipsec_idx >= inl_dev->alloc_ipsec_rules)
952 : : return NPC_ERR_MCAM_ALLOC;
953 : 0 : entry = inl_dev->ipsec_index[inl_dev->curr_ipsec_idx];
954 : 0 : inl_dev->curr_ipsec_idx++;
955 : 0 : flow->use_pre_alloc = 1;
956 : : } else {
957 : 0 : entry = npc_get_free_mcam_entry(mbox, flow, npc);
958 [ # # ]: 0 : if (entry < 0) {
959 [ # # ]: 0 : if (flow->use_ctr)
960 : 0 : npc_mcam_free_counter(mbox, ctr);
961 : 0 : return NPC_ERR_MCAM_ALLOC;
962 : : }
963 : : }
964 : :
965 [ # # ]: 0 : if (flow->nix_intf == NIX_INTF_TX) {
966 : 0 : uint16_t pffunc = flow->tx_pf_func;
967 : :
968 [ # # ]: 0 : if (flow->has_rep)
969 : 0 : pffunc = flow->rep_pf_func;
970 : :
971 [ # # ]: 0 : pffunc = plt_cpu_to_be_16(pffunc);
972 : :
973 [ # # ]: 0 : if (roc_model_is_cn20k())
974 : 0 : rc = npc_mcam_set_pf_func_cn20k(npc, flow, pffunc);
975 : : else
976 : 0 : rc = npc_mcam_set_pf_func(npc, flow, pffunc);
977 [ # # ]: 0 : if (rc)
978 : : return rc;
979 : : }
980 : :
981 [ # # ]: 0 : if (flow->is_sampling_rule) {
982 : : /* Save and restore any mark value set */
983 : 0 : uint16_t mark = (flow->npc_action >> 40) & 0xffff;
984 : : uint16_t mce_index = 0;
985 : 0 : uint32_t rqs[2] = {};
986 : :
987 : 0 : rqs[1] = flow->recv_queue;
988 : 0 : rc = roc_nix_mcast_list_setup(npc->mbox, flow->nix_intf, 2, flow->mcast_pf_funcs,
989 : 0 : flow->mcast_channels, rqs, &flow->mcast_grp_index,
990 : : &flow->mce_start_index);
991 [ # # ]: 0 : if (rc)
992 : 0 : return rc;
993 : :
994 : : flow->npc_action = NIX_RX_ACTIONOP_MCAST;
995 : 0 : mce_index = flow->mce_start_index;
996 [ # # ]: 0 : if (flow->nix_intf == NIX_INTF_TX) {
997 : 0 : flow->npc_action |= (uint64_t)mce_index << 12;
998 : 0 : flow->npc_action |= (uint64_t)mark << 32;
999 : : } else {
1000 : 0 : flow->npc_action |= (uint64_t)mce_index << 20;
1001 : 0 : flow->npc_action |= (uint64_t)mark << 40;
1002 : : }
1003 : : }
1004 : :
1005 : 0 : req.cntr = flow->ctr_id;
1006 : 0 : req.entry = entry;
1007 : :
1008 : 0 : req.intf = (flow->nix_intf == NIX_INTF_RX) ? NPC_MCAM_RX : NPC_MCAM_TX;
1009 : 0 : req.enable_entry = 1;
1010 [ # # ]: 0 : if (flow->nix_intf == NIX_INTF_RX)
1011 : 0 : flow->npc_action |= (uint64_t)flow->recv_queue << 20;
1012 : 0 : req.entry_data.action = flow->npc_action;
1013 : 0 : req.entry_data.action2 = flow->npc_action2;
1014 : :
1015 : : /*
1016 : : * Driver sets vtag action on per interface basis, not
1017 : : * per flow basis. It is a matter of how we decide to support
1018 : : * this pmd specific behavior. There are two ways:
1019 : : * 1. Inherit the vtag action from the one configured
1020 : : * for this interface. This can be read from the
1021 : : * vtag_action configured for default mcam entry of
1022 : : * this pf_func.
1023 : : * 2. Do not support vtag action with npc_flow.
1024 : : *
1025 : : * Second approach is used now.
1026 : : */
1027 : 0 : req.entry_data.vtag_action = flow->vtag_action;
1028 : :
1029 [ # # ]: 0 : for (idx = 0; idx < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; idx++) {
1030 : 0 : req.entry_data.kw[idx] = flow->mcam_data[idx];
1031 : 0 : req.entry_data.kw_mask[idx] = flow->mcam_mask[idx];
1032 : : }
1033 : :
1034 [ # # ]: 0 : if (flow->nix_intf == NIX_INTF_RX) {
1035 [ # # # # : 0 : if (inl_dev && inl_dev->is_multi_channel &&
# # ]
1036 : : roc_npc_action_is_rx_inline(flow->npc_action)) {
1037 : 0 : pf_func = nix_inl_dev_pffunc_get();
1038 : 0 : req.entry_data.action &= ~(GENMASK(19, 4));
1039 : 0 : req.entry_data.action |= (uint64_t)pf_func << 4;
1040 : 0 : flow->npc_action &= ~(GENMASK(19, 4));
1041 : 0 : flow->npc_action |= (uint64_t)pf_func << 4;
1042 : :
1043 : 0 : npc_mcam_set_channel(flow, &req, inl_dev->channel, inl_dev->chan_mask,
1044 : : false);
1045 [ # # ]: 0 : } else if (flow->has_rep) {
1046 [ # # ]: 0 : pf_func = (flow->rep_act_pf_func == 0) ? flow->rep_pf_func :
1047 : : flow->rep_act_pf_func;
1048 : 0 : req.entry_data.action &= ~(GENMASK(19, 4));
1049 : 0 : req.entry_data.action |= (uint64_t)pf_func << 4;
1050 : 0 : flow->npc_action &= ~(GENMASK(19, 4));
1051 : 0 : flow->npc_action |= (uint64_t)pf_func << 4;
1052 : 0 : npc_mcam_set_channel(flow, &req, flow->rep_channel, (BIT_ULL(12) - 1),
1053 : : false);
1054 [ # # ]: 0 : } else if (npc->is_sdp_link) {
1055 : 0 : npc_mcam_set_channel(flow, &req, npc->sdp_channel, npc->sdp_channel_mask,
1056 : 0 : pst->is_second_pass_rule);
1057 : : } else {
1058 : 0 : npc_mcam_set_channel(flow, &req, npc->channel, (BIT_ULL(12) - 1),
1059 : 0 : pst->is_second_pass_rule);
1060 : : }
1061 : : /*
1062 : : * For second pass rule, set LA LTYPE to CPT_HDR.
1063 : : * For all other rules, set LA LTYPE to match both 1st pass and 2nd pass ltypes.
1064 : : */
1065 [ # # # # ]: 0 : if (pst->is_second_pass_rule || (!pst->is_second_pass_rule && pst->has_eth_type)) {
1066 [ # # ]: 0 : la_offset = plt_popcount32(npc->keyx_supp_nmask[flow->nix_intf] &
1067 : : ((1ULL << 9 /* LA offset */) - 1));
1068 : 0 : la_offset *= 4;
1069 : :
1070 : 0 : mask = ~((0xfULL << la_offset));
1071 : 0 : req.entry_data.kw[0] &= mask;
1072 : 0 : req.entry_data.kw_mask[0] &= mask;
1073 : 0 : flow->mcam_data[0] &= mask;
1074 : 0 : flow->mcam_mask[0] &= mask;
1075 [ # # ]: 0 : if (pst->is_second_pass_rule) {
1076 : 0 : req.entry_data.kw[0] |= ((uint64_t)NPC_LT_LA_CPT_HDR) << la_offset;
1077 : 0 : req.entry_data.kw_mask[0] |= (0xFULL << la_offset);
1078 : 0 : flow->mcam_data[0] |= ((uint64_t)NPC_LT_LA_CPT_HDR) << la_offset;
1079 : 0 : flow->mcam_mask[0] |= (0xFULL << la_offset);
1080 : : } else {
1081 : : /* Mask ltype ETHER (0x2) and CPT_HDR (0xa) */
1082 : 0 : req.entry_data.kw[0] |= (0x2ULL << la_offset);
1083 : 0 : req.entry_data.kw_mask[0] |= (0x7ULL << la_offset);
1084 : 0 : flow->mcam_data[0] |= (0x2ULL << la_offset);
1085 : 0 : flow->mcam_mask[0] |= (0x7ULL << la_offset);
1086 : : }
1087 : : }
1088 : : }
1089 : :
1090 [ # # ]: 0 : if (roc_model_is_cn20k()) {
1091 : 0 : cn20k_req = mbox_alloc_msg_npc_cn20k_mcam_write_entry(mbox_get(mbox));
1092 [ # # ]: 0 : if (cn20k_req == NULL) {
1093 : : mbox_put(mbox);
1094 [ # # ]: 0 : if (flow->use_ctr)
1095 : 0 : npc_mcam_free_counter(mbox, ctr);
1096 : :
1097 : 0 : return rc;
1098 : : }
1099 : 0 : cn20k_req->entry = req.entry;
1100 : 0 : cn20k_req->intf = req.intf;
1101 : 0 : cn20k_req->enable_entry = req.enable_entry;
1102 : 0 : cn20k_req->entry_data.action = req.entry_data.action;
1103 : 0 : cn20k_req->entry_data.vtag_action = req.entry_data.vtag_action;
1104 : 0 : cn20k_req->hw_prio = req.hw_prio;
1105 : 0 : cn20k_req->req_kw_type = req.req_kw_type;
1106 [ # # ]: 0 : if (flow->use_ctr)
1107 : 0 : cn20k_req->cntr = req.cntr;
1108 : :
1109 : 0 : mbox_memcpy(&cn20k_req->entry_data, &req.entry_data,
1110 : : sizeof(struct cn20k_mcam_entry));
1111 : : } else {
1112 : : struct npc_mcam_write_entry_req *req_leg;
1113 : :
1114 : 0 : req_leg = mbox_alloc_msg_npc_mcam_write_entry(mbox_get(mbox));
1115 [ # # ]: 0 : if (req_leg == NULL) {
1116 : : rc = -ENOSPC;
1117 : 0 : goto exit;
1118 : : }
1119 [ # # ]: 0 : for (idx = 0; idx < NPC_MAX_KWS_IN_KEY; idx++) {
1120 : 0 : req_leg->entry_data.kw[idx] = req.entry_data.kw[idx];
1121 : 0 : req_leg->entry_data.kw_mask[idx] = req.entry_data.kw_mask[idx];
1122 : : }
1123 : 0 : req_leg->entry = req.entry;
1124 : 0 : req_leg->intf = req.intf;
1125 : 0 : req_leg->enable_entry = req.enable_entry;
1126 : 0 : req_leg->cntr = req.cntr;
1127 : 0 : req_leg->entry_data.action = req.entry_data.action;
1128 : 0 : req_leg->entry_data.vtag_action = req.entry_data.vtag_action;
1129 : 0 : req_leg->set_cntr = flow->use_ctr;
1130 : : }
1131 : : rc = mbox_process_msg(mbox, (void *)&rsp);
1132 [ # # ]: 0 : if (rc != 0)
1133 : 0 : goto exit;
1134 : :
1135 : 0 : flow->mcam_id = entry;
1136 : :
1137 [ # # ]: 0 : if (flow->use_ctr)
1138 : 0 : flow->ctr_id = ctr;
1139 : : rc = 0;
1140 : :
1141 : 0 : exit:
1142 : : mbox_put(mbox);
1143 [ # # # # ]: 0 : if (rc && flow->is_sampling_rule)
1144 : 0 : roc_nix_mcast_list_free(npc->mbox, flow->mcast_grp_index);
1145 : : return rc;
1146 : : }
1147 : :
1148 : : static void
1149 [ # # ]: 0 : npc_set_vlan_ltype(struct npc_parse_state *pst)
1150 : : {
1151 : : uint64_t val, mask;
1152 : : uint8_t lb_offset;
1153 : :
1154 [ # # ]: 0 : if (roc_model_is_cn20k()) {
1155 : 0 : lb_offset = plt_popcount32(pst->npc->keyx_supp_nmask[pst->nix_intf] &
1156 : : ((1ULL << NPC_CN20K_LTYPE_LB_OFFSET) - 1));
1157 : :
1158 : : } else {
1159 : 0 : lb_offset = plt_popcount32(pst->npc->keyx_supp_nmask[pst->nix_intf] &
1160 : : ((1ULL << NPC_LTYPE_LB_OFFSET) - 1));
1161 : : }
1162 : 0 : lb_offset *= 4;
1163 : :
1164 : 0 : mask = ~((0xfULL << lb_offset));
1165 : 0 : pst->flow->mcam_data[0] &= mask;
1166 : 0 : pst->flow->mcam_mask[0] &= mask;
1167 : : /* NPC_LT_LB_CTAG: 0b0010, NPC_LT_LB_STAG_QINQ: 0b0011
1168 : : * Set LB layertype/mask as 0b0010/0b1110 to match both.
1169 : : */
1170 : 0 : val = ((uint64_t)(NPC_LT_LB_CTAG & NPC_LT_LB_STAG_QINQ)) << lb_offset;
1171 : 0 : pst->flow->mcam_data[0] |= val;
1172 : 0 : pst->flow->mcam_mask[0] |= (0xeULL << lb_offset);
1173 : 0 : }
1174 : :
1175 : : static void
1176 [ # # ]: 0 : npc_set_ipv6ext_ltype_mask(struct npc_parse_state *pst)
1177 : : {
1178 : : uint8_t lc_offset, lcflag_offset;
1179 : : uint64_t val, mask;
1180 : :
1181 [ # # ]: 0 : if (roc_model_is_cn20k()) {
1182 : 0 : lc_offset = plt_popcount32(pst->npc->keyx_supp_nmask[pst->nix_intf] &
1183 : : ((1ULL << NPC_CN20K_LTYPE_LC_OFFSET) - 1));
1184 : :
1185 : : } else {
1186 : 0 : lc_offset = plt_popcount32(pst->npc->keyx_supp_nmask[pst->nix_intf] &
1187 : : ((1ULL << NPC_LTYPE_LC_OFFSET) - 1));
1188 : : }
1189 : 0 : lc_offset *= 4;
1190 : :
1191 : 0 : mask = ~((0xfULL << lc_offset));
1192 : 0 : pst->flow->mcam_data[0] &= mask;
1193 : 0 : pst->flow->mcam_mask[0] &= mask;
1194 : : /* NPC_LT_LC_IP6: 0b0100, NPC_LT_LC_IP6_EXT: 0b0101
1195 : : * Set LC layertype/mask as 0b0100/0b1110 to match both.
1196 : : */
1197 : 0 : val = ((uint64_t)(NPC_LT_LC_IP6 & NPC_LT_LC_IP6_EXT)) << lc_offset;
1198 : 0 : pst->flow->mcam_data[0] |= val;
1199 : 0 : pst->flow->mcam_mask[0] |= (0xeULL << lc_offset);
1200 : :
1201 : : /* If LC LFLAG is non-zero, set the LC LFLAG mask to 0xF. In general
1202 : : * case flag mask is set same as the value in data. For example, to
1203 : : * match 3 VLANs, flags have to match a range of values. But, for IPv6
1204 : : * extended attributes matching, we need an exact match. Hence, set the
1205 : : * mask as 0xF. This is done only if LC LFLAG value is non-zero,
1206 : : * because for AH and ESP, LC LFLAG is zero and we don't want to match
1207 : : * zero in LFLAG.
1208 : : */
1209 [ # # ]: 0 : if (pst->npc->keyx_supp_nmask[pst->nix_intf] & (1ULL << NPC_LFLAG_LC_OFFSET)) {
1210 [ # # ]: 0 : if (roc_model_is_cn20k()) {
1211 : 0 : lcflag_offset = plt_popcount32(pst->npc->keyx_supp_nmask[pst->nix_intf] &
1212 : : ((1ULL << NPC_CN20K_LFLAG_LC_OFFSET) - 1));
1213 : :
1214 : : } else {
1215 : 0 : lcflag_offset = plt_popcount32(pst->npc->keyx_supp_nmask[pst->nix_intf] &
1216 : : ((1ULL << NPC_LFLAG_LC_OFFSET) - 1));
1217 : : }
1218 : 0 : lcflag_offset *= 4;
1219 : :
1220 : 0 : mask = (0xfULL << lcflag_offset);
1221 : 0 : val = pst->flow->mcam_data[0] & mask;
1222 [ # # ]: 0 : if (val)
1223 : 0 : pst->flow->mcam_mask[0] |= mask;
1224 : : }
1225 : 0 : }
1226 : :
1227 : : int
1228 : 0 : npc_program_mcam(struct npc *npc, struct npc_parse_state *pst, bool mcam_alloc)
1229 : : {
1230 : : /* This is non-LDATA part in search key */
1231 : 0 : uint64_t key_data[2] = {0ULL, 0ULL};
1232 : 0 : uint64_t key_mask[2] = {0ULL, 0ULL};
1233 : : int key_len, bit = 0, index, rc = 0;
1234 : : struct nix_inl_dev *inl_dev = NULL;
1235 : 0 : int intf = pst->flow->nix_intf;
1236 : : bool skip_base_rule = false;
1237 : : int off, idx, data_off = 0;
1238 : : uint8_t lid, mask, data;
1239 : : struct idev_cfg *idev;
1240 : : uint16_t layer_info;
1241 : : uint64_t lt, flags;
1242 : : struct mbox *mbox;
1243 : :
1244 : : /* Skip till Layer A data start */
1245 [ # # ]: 0 : while (bit < NPC_PARSE_KEX_S_LA_OFFSET) {
1246 [ # # ]: 0 : if (npc->keyx_supp_nmask[intf] & (1 << bit))
1247 : 0 : data_off++;
1248 : 0 : bit++;
1249 : : }
1250 : :
1251 : : /* Each bit represents 1 nibble */
1252 [ # # ]: 0 : data_off *= 4;
1253 : :
1254 : : index = 0;
1255 [ # # ]: 0 : if (!roc_model_is_cn20k()) {
1256 [ # # ]: 0 : for (lid = 0; lid < NPC_MAX_LID; lid++) {
1257 : : /* Offset in key */
1258 : 0 : off = NPC_PARSE_KEX_S_LID_OFFSET(lid);
1259 : 0 : lt = pst->lt[lid] & 0xf;
1260 : 0 : flags = pst->flags[lid] & 0xff;
1261 : :
1262 : : /* NPC_LAYER_KEX_S */
1263 : 0 : layer_info = ((npc->keyx_supp_nmask[intf] >> off) & 0x7);
1264 [ # # ]: 0 : if (!layer_info)
1265 : 0 : continue;
1266 : :
1267 [ # # ]: 0 : for (idx = 0; idx <= 2; idx++) {
1268 [ # # ]: 0 : if (!(layer_info & (1 << idx)))
1269 : 0 : continue;
1270 : :
1271 [ # # ]: 0 : if (idx == 2) {
1272 : : data = lt;
1273 : : mask = 0xf;
1274 [ # # ]: 0 : } else if (idx == 1) {
1275 : 0 : data = ((flags >> 4) & 0xf);
1276 : : mask = ((flags >> 4) & 0xf);
1277 : : } else {
1278 : 0 : data = (flags & 0xf);
1279 : : mask = (flags & 0xf);
1280 : : }
1281 : :
1282 [ # # ]: 0 : if (data_off >= 64) {
1283 : : data_off = 0;
1284 : 0 : index++;
1285 : : }
1286 : 0 : key_data[index] |= ((uint64_t)data << data_off);
1287 : :
1288 [ # # ]: 0 : if (lt == 0)
1289 : : mask = 0;
1290 : 0 : key_mask[index] |= ((uint64_t)mask << data_off);
1291 : 0 : data_off += 4;
1292 : : }
1293 : : }
1294 : : } else {
1295 [ # # ]: 0 : for (lid = 0; lid < NPC_MAX_LID; lid++) {
1296 : : /* Offset in key */
1297 : 0 : off = NPC_PARSE_KEX_S_LID_OFFSET_CN20K(lid);
1298 : 0 : lt = pst->lt[lid] & 0xf;
1299 : 0 : flags = pst->flags[lid] & 0xf;
1300 : :
1301 : : /* NPC_LAYER_KEX_S */
1302 : 0 : layer_info = ((npc->keyx_supp_nmask[intf] >> off) & 0x3);
1303 [ # # ]: 0 : if (!layer_info)
1304 : 0 : continue;
1305 : :
1306 [ # # ]: 0 : for (idx = 0; idx <= 1; idx++) {
1307 [ # # ]: 0 : if (!(layer_info & (1 << idx)))
1308 : 0 : continue;
1309 : :
1310 [ # # ]: 0 : if (idx == 1) {
1311 : : data = lt;
1312 : : mask = 0xf;
1313 : : } else {
1314 : : data = (flags & 0xf);
1315 : : mask = (flags & 0xf);
1316 : : }
1317 : :
1318 [ # # ]: 0 : if (data_off >= 64) {
1319 : : data_off = 0;
1320 : 0 : index++;
1321 : : }
1322 : 0 : key_data[index] |= ((uint64_t)data << data_off);
1323 : :
1324 [ # # ]: 0 : if (lt == 0)
1325 : : mask = 0;
1326 : 0 : key_mask[index] |= ((uint64_t)mask << data_off);
1327 : 0 : data_off += 4;
1328 : : }
1329 : : }
1330 : : }
1331 : :
1332 : : /* Copy this into mcam string */
1333 : 0 : key_len = (pst->npc->keyx_len[intf] + 7) / 8;
1334 [ # # ]: 0 : memcpy(pst->flow->mcam_data, key_data, key_len);
1335 : 0 : memcpy(pst->flow->mcam_mask, key_mask, key_len);
1336 : :
1337 [ # # ]: 0 : if (pst->set_vlan_ltype_mask)
1338 : 0 : npc_set_vlan_ltype(pst);
1339 : :
1340 [ # # ]: 0 : if (pst->set_ipv6ext_ltype_mask)
1341 : 0 : npc_set_ipv6ext_ltype_mask(pst);
1342 : :
1343 : 0 : idev = idev_get_cfg();
1344 [ # # ]: 0 : if (idev)
1345 : 0 : inl_dev = idev->nix_inl_dev;
1346 [ # # # # : 0 : if (inl_dev && inl_dev->is_multi_channel &&
# # ]
1347 [ # # ]: 0 : roc_npc_action_is_rx_inline(pst->flow->npc_action))
1348 : : skip_base_rule = true;
1349 : :
1350 [ # # # # : 0 : if ((pst->is_vf || pst->flow->is_rep_vf) && pst->flow->nix_intf == NIX_INTF_RX &&
# # # # ]
1351 : : !skip_base_rule) {
1352 [ # # ]: 0 : if (pst->flow->has_rep)
1353 : 0 : mbox = mbox_get(pst->flow->rep_mbox);
1354 : : else
1355 : 0 : mbox = mbox_get(npc->mbox);
1356 [ # # ]: 0 : if (roc_model_is_cn20k()) {
1357 : : struct npc_cn20k_mcam_read_base_rule_rsp *base_rule_rsp;
1358 : : struct cn20k_mcam_entry *base_entry;
1359 : :
1360 : 0 : (void)mbox_alloc_msg_npc_cn20k_read_base_steer_rule(mbox);
1361 : : rc = mbox_process_msg(mbox, (void *)&base_rule_rsp);
1362 [ # # ]: 0 : if (rc) {
1363 : : mbox_put(mbox);
1364 : 0 : plt_err("Failed to fetch VF's base MCAM entry");
1365 : 0 : return rc;
1366 : : }
1367 : : mbox_put(mbox);
1368 : 0 : base_entry = &base_rule_rsp->entry;
1369 [ # # ]: 0 : for (idx = 0; idx < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; idx++) {
1370 : 0 : pst->flow->mcam_data[idx] |= base_entry->kw[idx];
1371 : 0 : pst->flow->mcam_mask[idx] |= base_entry->kw_mask[idx];
1372 : : }
1373 : :
1374 : : } else {
1375 : : struct npc_mcam_read_base_rule_rsp *base_rule_rsp;
1376 : : struct mcam_entry *base_entry;
1377 : :
1378 : 0 : (void)mbox_alloc_msg_npc_read_base_steer_rule(mbox);
1379 : : rc = mbox_process_msg(mbox, (void *)&base_rule_rsp);
1380 [ # # ]: 0 : if (rc) {
1381 : : mbox_put(mbox);
1382 : 0 : plt_err("Failed to fetch VF's base MCAM entry");
1383 : 0 : return rc;
1384 : : }
1385 : : mbox_put(mbox);
1386 : 0 : base_entry = &base_rule_rsp->entry_data;
1387 [ # # ]: 0 : for (idx = 0; idx < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; idx++) {
1388 : 0 : pst->flow->mcam_data[idx] |= base_entry->kw[idx];
1389 : 0 : pst->flow->mcam_mask[idx] |= base_entry->kw_mask[idx];
1390 : : }
1391 : : }
1392 : : }
1393 : :
1394 : : /*
1395 : : * Now we have mcam data and mask formatted as
1396 : : * [Key_len/4 nibbles][0 or 1 nibble hole][data]
1397 : : * hole is present if key_len is odd number of nibbles.
1398 : : * mcam data must be split into 64 bits + 48 bits segments
1399 : : * for each back W0, W1.
1400 : : */
1401 : :
1402 [ # # ]: 0 : if (mcam_alloc)
1403 : 0 : return npc_mcam_alloc_and_write(npc, pst->flow, pst);
1404 : : else
1405 : : return 0;
1406 : : }
1407 : :
1408 : : int
1409 : 0 : npc_flow_enable_all_entries(struct npc *npc, bool enable)
1410 : : {
1411 : : struct nix_inl_dev *inl_dev;
1412 : : struct npc_flow_list *list;
1413 : : struct roc_npc_flow *flow;
1414 : : struct idev_cfg *idev;
1415 : : int rc = 0, idx;
1416 : :
1417 : : /* Free any MCAM counters and delete flow list */
1418 [ # # ]: 0 : for (idx = 0; idx < npc->flow_max_priority; idx++) {
1419 : 0 : list = &npc->flow_list[idx];
1420 [ # # ]: 0 : TAILQ_FOREACH(flow, list, next) {
1421 : 0 : flow->enable = enable;
1422 : 0 : rc = npc_mcam_write_entry(npc->mbox, flow);
1423 [ # # ]: 0 : if (rc)
1424 : 0 : return rc;
1425 : : }
1426 : : }
1427 : :
1428 : : list = &npc->ipsec_list;
1429 : 0 : idev = idev_get_cfg();
1430 [ # # ]: 0 : if (!idev)
1431 : : return 0;
1432 : 0 : inl_dev = idev->nix_inl_dev;
1433 : :
1434 [ # # ]: 0 : if (inl_dev) {
1435 [ # # ]: 0 : TAILQ_FOREACH(flow, list, next) {
1436 : 0 : flow->enable = enable;
1437 : 0 : rc = npc_mcam_write_entry(inl_dev->dev.mbox, flow);
1438 [ # # ]: 0 : if (rc)
1439 : 0 : return rc;
1440 : : }
1441 : : }
1442 : : return rc;
1443 : : }
1444 : :
1445 : : int
1446 : 0 : npc_flow_free_all_resources(struct npc *npc)
1447 : : {
1448 : : struct roc_npc_flow *flow;
1449 : : int rc, idx;
1450 : :
1451 : : /* Free all MCAM entries allocated */
1452 : 0 : rc = npc_mcam_free_all_entries(npc);
1453 : :
1454 : : /* Free any MCAM counters and delete flow list */
1455 [ # # ]: 0 : for (idx = 0; idx < npc->flow_max_priority; idx++) {
1456 [ # # ]: 0 : while ((flow = TAILQ_FIRST(&npc->flow_list[idx])) != NULL) {
1457 : 0 : npc_rss_group_free(npc, flow);
1458 [ # # ]: 0 : if (flow->ctr_id != NPC_COUNTER_NONE) {
1459 : 0 : rc |= npc_mcam_clear_counter(npc->mbox, flow->ctr_id);
1460 : 0 : rc |= npc_mcam_free_counter(npc->mbox, flow->ctr_id);
1461 : : }
1462 : :
1463 [ # # ]: 0 : if (flow->is_sampling_rule)
1464 : 0 : roc_nix_mcast_list_free(npc->mbox, flow->mcast_grp_index);
1465 : :
1466 : 0 : npc_delete_prio_list_entry(npc, flow);
1467 : :
1468 [ # # ]: 0 : TAILQ_REMOVE(&npc->flow_list[idx], flow, next);
1469 : 0 : plt_free(flow);
1470 : : }
1471 : : }
1472 : :
1473 : : /* Reconcile template-table bookkeeping for all teardown paths. */
1474 : 0 : npc_template_tables_flush_reconcile(npc);
1475 : :
1476 : 0 : return rc;
1477 : : }
|