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 : 0 : req = mbox_alloc_msg_npc_mcam_alloc_counter(mbox_get(mbox));
15 [ # # ]: 0 : if (req == NULL)
16 : 0 : goto exit;
17 : 0 : req->count = 1;
18 : : rc = mbox_process_msg(mbox, (void *)&rsp);
19 [ # # ]: 0 : if (rc)
20 : 0 : goto exit;
21 : 0 : *ctr = rsp->cntr_list[0];
22 : 0 : exit:
23 : : mbox_put(mbox);
24 : 0 : return rc;
25 : : }
26 : :
27 : : int
28 : 0 : npc_mcam_free_counter(struct mbox *mbox, uint16_t ctr_id)
29 : : {
30 : : struct npc_mcam_oper_counter_req *req;
31 : : int rc = -ENOSPC;
32 : :
33 : 0 : req = mbox_alloc_msg_npc_mcam_free_counter(mbox_get(mbox));
34 [ # # ]: 0 : if (req == NULL)
35 : 0 : goto exit;
36 : 0 : req->cntr = ctr_id;
37 : 0 : rc = mbox_process(mbox);
38 : 0 : exit:
39 : : mbox_put(mbox);
40 : 0 : return rc;
41 : : }
42 : :
43 : : int
44 : 0 : npc_mcam_read_counter(struct mbox *mbox, uint32_t ctr_id, uint64_t *count)
45 : : {
46 : : struct npc_mcam_oper_counter_req *req;
47 : : struct npc_mcam_oper_counter_rsp *rsp;
48 : : int rc = -ENOSPC;
49 : :
50 : 0 : req = mbox_alloc_msg_npc_mcam_counter_stats(mbox_get(mbox));
51 [ # # ]: 0 : if (req == NULL)
52 : 0 : goto exit;
53 : 0 : req->cntr = ctr_id;
54 : : rc = mbox_process_msg(mbox, (void *)&rsp);
55 [ # # ]: 0 : if (rc)
56 : 0 : goto exit;
57 : 0 : *count = rsp->stat;
58 : 0 : exit:
59 : : mbox_put(mbox);
60 : 0 : return rc;
61 : : }
62 : :
63 : : int
64 : 0 : npc_mcam_clear_counter(struct mbox *mbox, uint32_t ctr_id)
65 : : {
66 : : struct npc_mcam_oper_counter_req *req;
67 : : int rc = -ENOSPC;
68 : :
69 : 0 : req = mbox_alloc_msg_npc_mcam_clear_counter(mbox_get(mbox));
70 [ # # ]: 0 : if (req == NULL)
71 : 0 : goto exit;
72 : 0 : req->cntr = ctr_id;
73 : 0 : rc = mbox_process(mbox);
74 : 0 : exit:
75 : : mbox_put(mbox);
76 : 0 : return rc;
77 : : }
78 : :
79 : : int
80 : 0 : npc_mcam_free_entry(struct mbox *mbox, uint32_t entry)
81 : : {
82 : : struct npc_mcam_free_entry_req *req;
83 : : int rc = -ENOSPC;
84 : :
85 : 0 : req = mbox_alloc_msg_npc_mcam_free_entry(mbox_get(mbox));
86 [ # # ]: 0 : if (req == NULL)
87 : 0 : goto exit;
88 : 0 : req->entry = entry;
89 : 0 : rc = mbox_process(mbox);
90 : 0 : exit:
91 : : mbox_put(mbox);
92 : 0 : return rc;
93 : : }
94 : :
95 : : int
96 : 0 : npc_mcam_free_all_entries(struct npc *npc)
97 : : {
98 : : struct npc_mcam_free_entry_req *req;
99 : 0 : struct mbox *mbox = mbox_get(npc->mbox);
100 : : int rc = -ENOSPC;
101 : :
102 : 0 : req = mbox_alloc_msg_npc_mcam_free_entry(mbox);
103 [ # # ]: 0 : if (req == NULL)
104 : 0 : goto exit;
105 : 0 : req->all = 1;
106 : 0 : rc = mbox_process(mbox);
107 : 0 : exit:
108 : : mbox_put(mbox);
109 : 0 : return rc;
110 : : }
111 : :
112 : : static int
113 : : npc_supp_key_len(uint32_t supp_mask)
114 : : {
115 : : int nib_count = 0;
116 : :
117 [ # # # # ]: 0 : while (supp_mask) {
118 : 0 : nib_count++;
119 : 0 : supp_mask &= (supp_mask - 1);
120 : : }
121 : 0 : return nib_count * 4;
122 : : }
123 : :
124 : : /**
125 : : * Returns true if any LDATA bits are extracted for specific LID+LTYPE.
126 : : *
127 : : * No LFLAG extraction is taken into account.
128 : : */
129 : : static int
130 : : npc_lid_lt_in_kex(struct npc *npc, uint8_t lid, uint8_t lt)
131 : : {
132 : : struct npc_xtract_info *x_info;
133 : : int i;
134 : :
135 [ # # ]: 0 : for (i = 0; i < NPC_MAX_LD; i++) {
136 : : x_info = &npc->prx_dxcfg[NIX_INTF_RX][lid][lt].xtract[i];
137 : : /* Check for LDATA */
138 [ # # # # ]: 0 : if (x_info->enable && x_info->len > 0)
139 : : return true;
140 : : }
141 : :
142 : : return false;
143 : : }
144 : :
145 : : static void
146 : 0 : npc_construct_ldata_mask(struct npc *npc, struct plt_bitmap *bmap, uint8_t lid, uint8_t lt,
147 : : uint8_t ld)
148 : : {
149 : : struct npc_xtract_info *x_info, *infoflag;
150 : : int hdr_off, keylen;
151 : : npc_dxcfg_t *p;
152 : : npc_fxcfg_t *q;
153 : : int i, j;
154 : :
155 : : p = &npc->prx_dxcfg;
156 : 0 : x_info = &(*p)[0][lid][lt].xtract[ld];
157 : :
158 [ # # ]: 0 : if (x_info->enable == 0)
159 : : return;
160 : :
161 : 0 : hdr_off = x_info->hdr_off * 8;
162 : 0 : keylen = x_info->len * 8;
163 [ # # ]: 0 : for (i = hdr_off; i < (hdr_off + keylen); i++)
164 : 0 : plt_bitmap_set(bmap, i);
165 : :
166 [ # # ]: 0 : if (x_info->flags_enable == 0)
167 : : return;
168 : :
169 [ # # ]: 0 : if ((npc->prx_lfcfg[0].i & 0x7) != lid)
170 : : return;
171 : :
172 : : q = &npc->prx_fxcfg;
173 [ # # ]: 0 : for (j = 0; j < NPC_MAX_LFL; j++) {
174 : : infoflag = &(*q)[0][ld][j].xtract[0];
175 [ # # ]: 0 : if (infoflag->enable) {
176 : 0 : hdr_off = infoflag->hdr_off * 8;
177 : 0 : keylen = infoflag->len * 8;
178 [ # # ]: 0 : for (i = hdr_off; i < (hdr_off + keylen); i++)
179 : 0 : plt_bitmap_set(bmap, i);
180 : : }
181 : : }
182 : : }
183 : :
184 : : /**
185 : : * Check if given LID+LTYPE combination is present in KEX
186 : : *
187 : : * len is non-zero, this function will return true if KEX extracts len bytes
188 : : * at given offset. Otherwise it'll return true if any bytes are extracted
189 : : * specifically for given LID+LTYPE combination (meaning not LFLAG based).
190 : : * The second case increases flexibility for custom frames whose extracted
191 : : * bits may change depending on KEX profile loaded.
192 : : *
193 : : * @param npc NPC context structure
194 : : * @param lid Layer ID to check for
195 : : * @param lt Layer Type to check for
196 : : * @param offset offset into the layer header to match
197 : : * @param len length of the match
198 : : */
199 : : static bool
200 : 0 : npc_is_kex_enabled(struct npc *npc, uint8_t lid, uint8_t lt, int offset, int len)
201 : : {
202 : : struct plt_bitmap *bmap;
203 : : uint32_t bmap_sz;
204 : : uint8_t *mem;
205 : : int i;
206 : :
207 [ # # ]: 0 : if (!len)
208 : 0 : return npc_lid_lt_in_kex(npc, lid, lt);
209 : :
210 : : bmap_sz = plt_bitmap_get_memory_footprint(300 * 8);
211 : 0 : mem = plt_zmalloc(bmap_sz, 0);
212 [ # # ]: 0 : if (mem == NULL) {
213 : 0 : plt_err("mem alloc failed");
214 : 0 : return false;
215 : : }
216 : 0 : bmap = plt_bitmap_init(300 * 8, mem, bmap_sz);
217 [ # # ]: 0 : if (bmap == NULL) {
218 : 0 : plt_err("mem alloc failed");
219 : 0 : plt_free(mem);
220 : 0 : return false;
221 : : }
222 : :
223 : 0 : npc_construct_ldata_mask(npc, bmap, lid, lt, 0);
224 : 0 : npc_construct_ldata_mask(npc, bmap, lid, lt, 1);
225 : :
226 [ # # ]: 0 : for (i = offset; i < (offset + len); i++) {
227 [ # # ]: 0 : if (plt_bitmap_get(bmap, i) != 0x1) {
228 : 0 : plt_free(mem);
229 : 0 : return false;
230 : : }
231 : : }
232 : :
233 : 0 : plt_free(mem);
234 : 0 : return true;
235 : : }
236 : :
237 : : uint64_t
238 : 0 : npc_get_kex_capability(struct npc *npc)
239 : : {
240 : : npc_kex_cap_terms_t kex_cap;
241 : :
242 : : memset(&kex_cap, 0, sizeof(kex_cap));
243 : :
244 : : /* Ethtype: Offset 12B, len 2B */
245 : 0 : kex_cap.bit.ethtype_0 = npc_is_kex_enabled(npc, NPC_LID_LA, NPC_LT_LA_ETHER, 12 * 8, 2 * 8);
246 : : /* QINQ VLAN Ethtype: offset 8B, len 2B */
247 : 0 : kex_cap.bit.ethtype_x =
248 : 0 : npc_is_kex_enabled(npc, NPC_LID_LB, NPC_LT_LB_STAG_QINQ, 8 * 8, 2 * 8);
249 : : /* VLAN ID0 : Outer VLAN: Offset 2B, len 2B */
250 : 0 : kex_cap.bit.vlan_id_0 = npc_is_kex_enabled(npc, NPC_LID_LB, NPC_LT_LB_CTAG, 2 * 8, 2 * 8);
251 : : /* VLAN PCP0 : Outer VLAN: Offset 2B, len 1B */
252 : 0 : kex_cap.bit.vlan_pcp_0 = npc_is_kex_enabled(npc, NPC_LID_LB, NPC_LT_LB_CTAG, 2 * 8, 2 * 1);
253 : : /* VLAN IDX : Inner VLAN: offset 6B, len 2B */
254 : 0 : kex_cap.bit.vlan_id_x =
255 : 0 : npc_is_kex_enabled(npc, NPC_LID_LB, NPC_LT_LB_STAG_QINQ, 6 * 8, 2 * 8);
256 : : /* DMCA: offset 0B, len 6B */
257 : 0 : kex_cap.bit.dmac = npc_is_kex_enabled(npc, NPC_LID_LA, NPC_LT_LA_ETHER, 0 * 8, 6 * 8);
258 : : /* IP proto: offset 9B, len 1B */
259 : 0 : kex_cap.bit.ip_proto = npc_is_kex_enabled(npc, NPC_LID_LC, NPC_LT_LC_IP, 9 * 8, 1 * 8);
260 : : /* IPv4 dscp: offset 1B, len 1B, IPv6 dscp: offset 0B, len 2B */
261 [ # # # # ]: 0 : kex_cap.bit.ip_dscp = npc_is_kex_enabled(npc, NPC_LID_LC, NPC_LT_LC_IP, 1 * 8, 1 * 8) &&
262 : 0 : npc_is_kex_enabled(npc, NPC_LID_LC, NPC_LT_LC_IP6, 0, 2 * 8);
263 : : /* UDP dport: offset 2B, len 2B */
264 : 0 : kex_cap.bit.udp_dport = npc_is_kex_enabled(npc, NPC_LID_LD, NPC_LT_LD_UDP, 2 * 8, 2 * 8);
265 : : /* UDP sport: offset 0B, len 2B */
266 : 0 : kex_cap.bit.udp_sport = npc_is_kex_enabled(npc, NPC_LID_LD, NPC_LT_LD_UDP, 0 * 8, 2 * 8);
267 : : /* TCP dport: offset 2B, len 2B */
268 : 0 : kex_cap.bit.tcp_dport = npc_is_kex_enabled(npc, NPC_LID_LD, NPC_LT_LD_TCP, 2 * 8, 2 * 8);
269 : : /* TCP sport: offset 0B, len 2B */
270 : 0 : kex_cap.bit.tcp_sport = npc_is_kex_enabled(npc, NPC_LID_LD, NPC_LT_LD_TCP, 0 * 8, 2 * 8);
271 : : /* IP SIP: offset 12B, len 4B */
272 : 0 : kex_cap.bit.sip_addr = npc_is_kex_enabled(npc, NPC_LID_LC, NPC_LT_LC_IP, 12 * 8, 4 * 8);
273 : : /* IP DIP: offset 14B, len 4B */
274 : 0 : kex_cap.bit.dip_addr = npc_is_kex_enabled(npc, NPC_LID_LC, NPC_LT_LC_IP, 14 * 8, 4 * 8);
275 : : /* IP6 SIP: offset 8B, len 16B */
276 : 0 : kex_cap.bit.sip6_addr = npc_is_kex_enabled(npc, NPC_LID_LC, NPC_LT_LC_IP6, 8 * 8, 16 * 8);
277 : : /* IP6 DIP: offset 24B, len 16B */
278 : 0 : kex_cap.bit.dip6_addr = npc_is_kex_enabled(npc, NPC_LID_LC, NPC_LT_LC_IP6, 24 * 8, 16 * 8);
279 : : /* ESP SPI: offset 0B, len 4B */
280 : 0 : kex_cap.bit.ipsec_spi = npc_is_kex_enabled(npc, NPC_LID_LE, NPC_LT_LE_ESP, 0 * 8, 4 * 8);
281 : : /* VXLAN VNI: offset 4B, len 3B */
282 : 0 : kex_cap.bit.ld_vni = npc_is_kex_enabled(npc, NPC_LID_LE, NPC_LT_LE_VXLAN, 0 * 8, 3 * 8);
283 : :
284 : : /* Custom L3 frame: varied offset and lengths */
285 : 0 : kex_cap.bit.custom_l3 = npc_is_kex_enabled(npc, NPC_LID_LC, NPC_LT_LC_CUSTOM0, 0, 0);
286 : 0 : kex_cap.bit.custom_l3 |=
287 : 0 : (uint64_t)npc_is_kex_enabled(npc, NPC_LID_LC, NPC_LT_LC_CUSTOM1, 0, 0);
288 : : /* SCTP sport : offset 0B, len 2B */
289 : 0 : kex_cap.bit.sctp_sport = npc_is_kex_enabled(npc, NPC_LID_LD, NPC_LT_LD_SCTP, 0 * 8, 2 * 8);
290 : : /* SCTP dport : offset 2B, len 2B */
291 : 0 : kex_cap.bit.sctp_dport = npc_is_kex_enabled(npc, NPC_LID_LD, NPC_LT_LD_SCTP, 2 * 8, 2 * 8);
292 : : /* ICMP type : offset 0B, len 1B */
293 : 0 : kex_cap.bit.icmp_type = npc_is_kex_enabled(npc, NPC_LID_LD, NPC_LT_LD_ICMP, 0 * 8, 1 * 8);
294 : : /* ICMP code : offset 1B, len 1B */
295 : 0 : kex_cap.bit.icmp_code = npc_is_kex_enabled(npc, NPC_LID_LD, NPC_LT_LD_ICMP, 1 * 8, 1 * 8);
296 : : /* ICMP id : offset 4B, len 2B */
297 : 0 : kex_cap.bit.icmp_id = npc_is_kex_enabled(npc, NPC_LID_LD, NPC_LT_LD_ICMP, 4 * 8, 2 * 8);
298 : : /* IGMP grp_addr : offset 4B, len 4B */
299 : 0 : kex_cap.bit.igmp_grp_addr =
300 : 0 : npc_is_kex_enabled(npc, NPC_LID_LD, NPC_LT_LD_IGMP, 4 * 8, 4 * 8);
301 : : /* GTPU teid : offset 4B, len 4B */
302 : 0 : kex_cap.bit.gtpv1_teid = npc_is_kex_enabled(npc, NPC_LID_LE, NPC_LT_LE_GTPU, 4 * 8, 4 * 8);
303 : 0 : return kex_cap.all_bits;
304 : : }
305 : :
306 : : #define BYTESM1_SHIFT 16
307 : : #define HDR_OFF_SHIFT 8
308 : : static void
309 : : npc_update_kex_info(struct npc_xtract_info *xtract_info, uint64_t val)
310 : : {
311 : 0 : xtract_info->use_hash = ((val >> 20) & 0x1);
312 : 0 : xtract_info->len = ((val >> BYTESM1_SHIFT) & 0xf) + 1;
313 : 0 : xtract_info->hdr_off = (val >> HDR_OFF_SHIFT) & 0xff;
314 : 0 : xtract_info->key_off = val & 0x3f;
315 : 0 : xtract_info->enable = ((val >> 7) & 0x1);
316 : 0 : xtract_info->flags_enable = ((val >> 6) & 0x1);
317 : : }
318 : :
319 : : int
320 : 0 : npc_mcam_alloc_entries(struct mbox *mbox, int ref_mcam, int *alloc_entry, int req_count, int prio,
321 : : int *resp_count, bool is_conti)
322 : : {
323 : : struct npc_mcam_alloc_entry_req *req;
324 : : struct npc_mcam_alloc_entry_rsp *rsp;
325 : : int rc = -ENOSPC;
326 : : int i;
327 : :
328 : 0 : req = mbox_alloc_msg_npc_mcam_alloc_entry(mbox_get(mbox));
329 [ # # ]: 0 : if (req == NULL)
330 : 0 : goto exit;
331 : 0 : req->contig = is_conti;
332 : 0 : req->count = req_count;
333 : 0 : req->priority = prio;
334 : 0 : req->ref_entry = ref_mcam;
335 : :
336 : : rc = mbox_process_msg(mbox, (void *)&rsp);
337 [ # # ]: 0 : if (rc)
338 : 0 : goto exit;
339 [ # # ]: 0 : for (i = 0; i < rsp->count; i++)
340 : 0 : alloc_entry[i] = rsp->entry_list[i];
341 : 0 : *resp_count = rsp->count;
342 [ # # ]: 0 : if (is_conti)
343 : 0 : alloc_entry[0] = rsp->entry;
344 : : rc = 0;
345 : 0 : exit:
346 : : mbox_put(mbox);
347 : 0 : return rc;
348 : : }
349 : :
350 : : int
351 : 0 : npc_mcam_alloc_entry(struct npc *npc, struct roc_npc_flow *mcam, struct roc_npc_flow *ref_mcam,
352 : : int prio, int *resp_count)
353 : : {
354 : : struct npc_mcam_alloc_entry_req *req;
355 : : struct npc_mcam_alloc_entry_rsp *rsp;
356 : 0 : struct mbox *mbox = mbox_get(npc->mbox);
357 : : int rc = -ENOSPC;
358 : :
359 : 0 : req = mbox_alloc_msg_npc_mcam_alloc_entry(mbox);
360 [ # # ]: 0 : if (req == NULL)
361 : 0 : goto exit;
362 : 0 : req->contig = 1;
363 : 0 : req->count = 1;
364 : 0 : req->priority = prio;
365 : 0 : req->ref_entry = ref_mcam->mcam_id;
366 : :
367 : : rc = mbox_process_msg(mbox, (void *)&rsp);
368 [ # # ]: 0 : if (rc)
369 : 0 : goto exit;
370 : : memset(mcam, 0, sizeof(struct roc_npc_flow));
371 : 0 : mcam->mcam_id = rsp->entry;
372 : 0 : mcam->nix_intf = ref_mcam->nix_intf;
373 : 0 : *resp_count = rsp->count;
374 : : rc = 0;
375 : 0 : exit:
376 : : mbox_put(mbox);
377 : 0 : return rc;
378 : : }
379 : :
380 : : int
381 : 0 : npc_mcam_ena_dis_entry(struct npc *npc, struct roc_npc_flow *mcam, bool enable)
382 : : {
383 : : struct npc_mcam_ena_dis_entry_req *req;
384 : 0 : struct mbox *mbox = mbox_get(npc->mbox);
385 : : int rc = -ENOSPC;
386 : :
387 [ # # ]: 0 : if (enable)
388 : 0 : req = mbox_alloc_msg_npc_mcam_ena_entry(mbox);
389 : : else
390 : 0 : req = mbox_alloc_msg_npc_mcam_dis_entry(mbox);
391 : :
392 [ # # ]: 0 : if (req == NULL)
393 : 0 : goto exit;
394 : 0 : req->entry = mcam->mcam_id;
395 : 0 : mcam->enable = enable;
396 : 0 : rc = mbox_process(mbox);
397 : 0 : exit:
398 : : mbox_put(mbox);
399 : 0 : return rc;
400 : : }
401 : :
402 : : int
403 : 0 : npc_mcam_write_entry(struct mbox *mbox, struct roc_npc_flow *mcam)
404 : : {
405 : : struct npc_mcam_write_entry_req *req;
406 : : struct mbox_msghdr *rsp;
407 : : int rc = -ENOSPC;
408 : 0 : uint16_t ctr = 0;
409 : : int i;
410 : :
411 [ # # # # ]: 0 : if (mcam->use_ctr && mcam->ctr_id == NPC_COUNTER_NONE) {
412 : 0 : rc = npc_mcam_alloc_counter(mbox, &ctr);
413 [ # # ]: 0 : if (rc)
414 : : return rc;
415 : 0 : mcam->ctr_id = ctr;
416 : :
417 : 0 : rc = npc_mcam_clear_counter(mbox, mcam->ctr_id);
418 [ # # ]: 0 : if (rc)
419 : : return rc;
420 : : }
421 : :
422 : 0 : req = mbox_alloc_msg_npc_mcam_write_entry(mbox_get(mbox));
423 [ # # ]: 0 : if (req == NULL) {
424 : : mbox_put(mbox);
425 [ # # ]: 0 : if (mcam->use_ctr)
426 : 0 : npc_mcam_free_counter(mbox, ctr);
427 : :
428 : 0 : return rc;
429 : : }
430 : 0 : req->entry = mcam->mcam_id;
431 : 0 : req->intf = mcam->nix_intf;
432 : 0 : req->enable_entry = mcam->enable;
433 : 0 : req->entry_data.action = mcam->npc_action;
434 : 0 : req->entry_data.vtag_action = mcam->vtag_action;
435 [ # # ]: 0 : if (mcam->use_ctr) {
436 : 0 : req->set_cntr = 1;
437 : 0 : req->cntr = mcam->ctr_id;
438 : : }
439 : :
440 [ # # ]: 0 : for (i = 0; i < NPC_MCAM_KEY_X4_WORDS; i++) {
441 : 0 : req->entry_data.kw[i] = mcam->mcam_data[i];
442 : 0 : req->entry_data.kw_mask[i] = mcam->mcam_mask[i];
443 : : }
444 : : rc = mbox_process_msg(mbox, (void *)&rsp);
445 : : mbox_put(mbox);
446 : 0 : return rc;
447 : : }
448 : :
449 : : static void
450 : 0 : npc_mcam_process_mkex_cfg(struct npc *npc, struct npc_get_kex_cfg_rsp *kex_rsp)
451 : : {
452 : : volatile uint64_t(*q)[NPC_MAX_INTF][NPC_MAX_LID][NPC_MAX_LT][NPC_MAX_LD];
453 : : struct npc_xtract_info *x_info = NULL;
454 : : int lid, lt, ld, fl, ix;
455 : : npc_dxcfg_t *p;
456 : : uint64_t keyw;
457 : : uint64_t val;
458 : :
459 : 0 : npc->keyx_supp_nmask[NPC_MCAM_RX] = kex_rsp->rx_keyx_cfg & 0x7fffffffULL;
460 : 0 : npc->keyx_supp_nmask[NPC_MCAM_TX] = kex_rsp->tx_keyx_cfg & 0x7fffffffULL;
461 : 0 : npc->keyx_len[NPC_MCAM_RX] = npc_supp_key_len(npc->keyx_supp_nmask[NPC_MCAM_RX]);
462 : 0 : npc->keyx_len[NPC_MCAM_TX] = npc_supp_key_len(npc->keyx_supp_nmask[NPC_MCAM_TX]);
463 : :
464 : 0 : keyw = (kex_rsp->rx_keyx_cfg >> 32) & 0x7ULL;
465 : 0 : npc->keyw[NPC_MCAM_RX] = keyw;
466 : 0 : keyw = (kex_rsp->tx_keyx_cfg >> 32) & 0x7ULL;
467 : 0 : npc->keyw[NPC_MCAM_TX] = keyw;
468 : :
469 : : /* Update KEX_LD_FLAG */
470 [ # # ]: 0 : for (ix = 0; ix < NPC_MAX_INTF; ix++) {
471 [ # # ]: 0 : for (ld = 0; ld < NPC_MAX_LD; ld++) {
472 [ # # ]: 0 : for (fl = 0; fl < NPC_MAX_LFL; fl++) {
473 : : x_info = &npc->prx_fxcfg[ix][ld][fl].xtract[0];
474 : 0 : val = kex_rsp->intf_ld_flags[ix][ld][fl];
475 : : npc_update_kex_info(x_info, val);
476 : : }
477 : : }
478 : : }
479 : :
480 : : /* Update LID, LT and LDATA cfg */
481 : : p = &npc->prx_dxcfg;
482 : : q = (volatile uint64_t(*)[][NPC_MAX_LID][NPC_MAX_LT][NPC_MAX_LD])(&kex_rsp->intf_lid_lt_ld);
483 [ # # ]: 0 : for (ix = 0; ix < NPC_MAX_INTF; ix++) {
484 [ # # ]: 0 : for (lid = 0; lid < NPC_MAX_LID; lid++) {
485 [ # # ]: 0 : for (lt = 0; lt < NPC_MAX_LT; lt++) {
486 [ # # ]: 0 : for (ld = 0; ld < NPC_MAX_LD; ld++) {
487 : : x_info = &(*p)[ix][lid][lt].xtract[ld];
488 : 0 : val = (*q)[ix][lid][lt][ld];
489 : : npc_update_kex_info(x_info, val);
490 : : }
491 : : }
492 : : }
493 : : }
494 : : /* Update LDATA Flags cfg */
495 : 0 : npc->prx_lfcfg[0].i = kex_rsp->kex_ld_flags[0];
496 : 0 : npc->prx_lfcfg[1].i = kex_rsp->kex_ld_flags[1];
497 : 0 : }
498 : :
499 : : int
500 : 0 : npc_mcam_fetch_hw_cap(struct npc *npc, uint8_t *npc_hw_cap)
501 : : {
502 : : struct get_hw_cap_rsp *hw_cap_rsp;
503 : 0 : struct mbox *mbox = mbox_get(npc->mbox);
504 : : int rc = 0;
505 : :
506 : 0 : *npc_hw_cap = 0;
507 : :
508 : 0 : mbox_alloc_msg_get_hw_cap(mbox);
509 : : rc = mbox_process_msg(mbox, (void *)&hw_cap_rsp);
510 [ # # ]: 0 : if (rc) {
511 : 0 : plt_err("Failed to fetch NPC HW capability");
512 : 0 : goto done;
513 : : }
514 : :
515 : 0 : *npc_hw_cap = hw_cap_rsp->npc_hash_extract;
516 : 0 : done:
517 : : mbox_put(mbox);
518 : 0 : return rc;
519 : : }
520 : :
521 : : int
522 : 0 : npc_mcam_fetch_kex_cfg(struct npc *npc)
523 : : {
524 : : struct npc_get_kex_cfg_rsp *kex_rsp;
525 : 0 : struct mbox *mbox = mbox_get(npc->mbox);
526 : : int rc = 0;
527 : :
528 : 0 : mbox_alloc_msg_npc_get_kex_cfg(mbox);
529 : : rc = mbox_process_msg(mbox, (void *)&kex_rsp);
530 [ # # ]: 0 : if (rc) {
531 : 0 : plt_err("Failed to fetch NPC KEX config");
532 : 0 : goto done;
533 : : }
534 : :
535 : 0 : mbox_memcpy((char *)npc->profile_name, kex_rsp->mkex_pfl_name, MKEX_NAME_LEN);
536 : :
537 : 0 : npc->exact_match_ena = (kex_rsp->rx_keyx_cfg >> 40) & 0xF;
538 : 0 : npc_mcam_process_mkex_cfg(npc, kex_rsp);
539 : :
540 : 0 : done:
541 : : mbox_put(mbox);
542 : 0 : return rc;
543 : : }
544 : :
545 : : static void
546 : 0 : npc_mcam_set_channel(struct roc_npc_flow *flow, struct npc_mcam_write_entry_req *req,
547 : : uint16_t channel, uint16_t chan_mask, bool is_second_pass)
548 : : {
549 : : uint16_t chan = 0, mask = 0;
550 : :
551 : 0 : req->entry_data.kw[0] &= ~(GENMASK(11, 0));
552 : 0 : req->entry_data.kw_mask[0] &= ~(GENMASK(11, 0));
553 : 0 : flow->mcam_data[0] &= ~(GENMASK(11, 0));
554 [ # # ]: 0 : flow->mcam_mask[0] &= ~(GENMASK(11, 0));
555 : : chan = channel;
556 : : mask = chan_mask;
557 : :
558 [ # # ]: 0 : if (roc_model_runtime_is_cn10k()) {
559 [ # # ]: 0 : if (is_second_pass) {
560 : 0 : chan = (channel | NIX_CHAN_CPT_CH_START);
561 : 0 : mask = (chan_mask | NIX_CHAN_CPT_CH_START);
562 : : } else {
563 [ # # ]: 0 : if (!(flow->npc_action & NIX_RX_ACTIONOP_UCAST_IPSEC)) {
564 : : /*
565 : : * Clear bits 10 & 11 corresponding to CPT
566 : : * channel. By default, rules should match
567 : : * both first pass packets and second pass
568 : : * packets from CPT.
569 : : */
570 : 0 : chan = (channel & NIX_CHAN_CPT_X2P_MASK);
571 : 0 : mask = (chan_mask & NIX_CHAN_CPT_X2P_MASK);
572 : : }
573 : : }
574 : : }
575 : :
576 : 0 : req->entry_data.kw[0] |= (uint64_t)chan;
577 : 0 : req->entry_data.kw_mask[0] |= (uint64_t)mask;
578 : 0 : flow->mcam_data[0] |= (uint64_t)chan;
579 : 0 : flow->mcam_mask[0] |= (uint64_t)mask;
580 : 0 : }
581 : :
582 : : static int
583 : 0 : npc_mcam_set_pf_func(struct npc *npc, struct roc_npc_flow *flow, uint16_t pf_func)
584 : : {
585 : : #define NPC_PF_FUNC_WIDTH 2
586 : : #define NPC_KEX_PF_FUNC_MASK 0xFFFF
587 : : uint16_t nr_bytes, hdr_offset, key_offset, pf_func_offset;
588 : : uint8_t *flow_mcam_data, *flow_mcam_mask;
589 : : struct npc_lid_lt_xtract_info *xinfo;
590 : : bool pffunc_found = false;
591 : 0 : uint16_t mask = 0xFFFF;
592 : : int i;
593 : :
594 : 0 : flow_mcam_data = (uint8_t *)flow->mcam_data;
595 : 0 : flow_mcam_mask = (uint8_t *)flow->mcam_mask;
596 : :
597 : : xinfo = &npc->prx_dxcfg[NIX_INTF_TX][NPC_LID_LA][NPC_LT_LA_IH_NIX_ETHER];
598 : :
599 [ # # ]: 0 : for (i = 0; i < NPC_MAX_LD; i++) {
600 : 0 : nr_bytes = xinfo->xtract[i].len;
601 : 0 : hdr_offset = xinfo->xtract[i].hdr_off;
602 : 0 : key_offset = xinfo->xtract[i].key_off;
603 : :
604 [ # # ]: 0 : if (hdr_offset > 0 || nr_bytes < NPC_PF_FUNC_WIDTH)
605 : 0 : continue;
606 : : else
607 : : pffunc_found = true;
608 : :
609 : 0 : pf_func_offset = key_offset + nr_bytes - NPC_PF_FUNC_WIDTH;
610 : 0 : memcpy((void *)&flow_mcam_data[pf_func_offset], (uint8_t *)&pf_func,
611 : : NPC_PF_FUNC_WIDTH);
612 : 0 : memcpy((void *)&flow_mcam_mask[pf_func_offset], (uint8_t *)&mask,
613 : : NPC_PF_FUNC_WIDTH);
614 : : }
615 [ # # ]: 0 : if (!pffunc_found)
616 : 0 : return -EINVAL;
617 : :
618 : : return 0;
619 : : }
620 : :
621 : : int
622 : 0 : npc_mcam_alloc_and_write(struct npc *npc, struct roc_npc_flow *flow, struct npc_parse_state *pst)
623 : : {
624 : : struct npc_mcam_write_entry_req *req;
625 : : struct nix_inl_dev *inl_dev = NULL;
626 : 0 : struct mbox *mbox = npc->mbox;
627 : : struct mbox_msghdr *rsp;
628 : : struct idev_cfg *idev;
629 : : uint16_t pf_func = 0;
630 : 0 : uint16_t ctr = ~(0);
631 : : uint32_t la_offset;
632 : : uint64_t mask;
633 : : int rc, idx;
634 : : int entry;
635 : :
636 : : PLT_SET_USED(pst);
637 : :
638 : 0 : idev = idev_get_cfg();
639 [ # # ]: 0 : if (idev)
640 : 0 : inl_dev = idev->nix_inl_dev;
641 : :
642 [ # # # # ]: 0 : if (inl_dev && inl_dev->ipsec_index) {
643 [ # # ]: 0 : if (flow->is_inline_dev)
644 : 0 : mbox = inl_dev->dev.mbox;
645 : : }
646 : :
647 [ # # ]: 0 : if (flow->use_ctr) {
648 : 0 : rc = npc_mcam_alloc_counter(mbox, &ctr);
649 [ # # ]: 0 : if (rc)
650 : : return rc;
651 : :
652 : 0 : flow->ctr_id = ctr;
653 : 0 : rc = npc_mcam_clear_counter(mbox, flow->ctr_id);
654 [ # # ]: 0 : if (rc)
655 : : return rc;
656 : : }
657 : :
658 [ # # # # : 0 : if (flow->nix_intf == NIX_INTF_RX && flow->is_inline_dev && inl_dev &&
# # ]
659 [ # # # # ]: 0 : inl_dev->ipsec_index && inl_dev->is_multi_channel) {
660 [ # # ]: 0 : if (inl_dev->curr_ipsec_idx >= inl_dev->alloc_ipsec_rules)
661 : : return NPC_ERR_MCAM_ALLOC;
662 : 0 : entry = inl_dev->ipsec_index[inl_dev->curr_ipsec_idx];
663 : 0 : inl_dev->curr_ipsec_idx++;
664 : 0 : flow->use_pre_alloc = 1;
665 : : } else {
666 : 0 : entry = npc_get_free_mcam_entry(mbox, flow, npc);
667 [ # # ]: 0 : if (entry < 0) {
668 [ # # ]: 0 : if (flow->use_ctr)
669 : 0 : npc_mcam_free_counter(mbox, ctr);
670 : 0 : return NPC_ERR_MCAM_ALLOC;
671 : : }
672 : : }
673 : :
674 [ # # ]: 0 : if (flow->nix_intf == NIX_INTF_TX) {
675 : 0 : uint16_t pf_func = flow->tx_pf_func;
676 : :
677 [ # # ]: 0 : if (flow->has_rep)
678 : 0 : pf_func = flow->rep_pf_func;
679 : :
680 [ # # ]: 0 : pf_func = plt_cpu_to_be_16(pf_func);
681 : :
682 : 0 : rc = npc_mcam_set_pf_func(npc, flow, pf_func);
683 [ # # ]: 0 : if (rc)
684 : : return rc;
685 : : }
686 : :
687 [ # # ]: 0 : if (flow->is_sampling_rule) {
688 : : /* Save and restore any mark value set */
689 : 0 : uint16_t mark = (flow->npc_action >> 40) & 0xffff;
690 : : uint16_t mce_index = 0;
691 : 0 : uint32_t rqs[2] = {};
692 : :
693 : 0 : rqs[1] = flow->recv_queue;
694 : 0 : rc = roc_nix_mcast_list_setup(npc->mbox, flow->nix_intf, 2, flow->mcast_pf_funcs,
695 : 0 : flow->mcast_channels, rqs, &flow->mcast_grp_index,
696 : : &flow->mce_start_index);
697 [ # # ]: 0 : if (rc)
698 : 0 : return rc;
699 : :
700 : : flow->npc_action = NIX_RX_ACTIONOP_MCAST;
701 : 0 : mce_index = flow->mce_start_index;
702 [ # # ]: 0 : if (flow->nix_intf == NIX_INTF_TX) {
703 : 0 : flow->npc_action |= (uint64_t)mce_index << 12;
704 : 0 : flow->npc_action |= (uint64_t)mark << 32;
705 : : } else {
706 : 0 : flow->npc_action |= (uint64_t)mce_index << 20;
707 : 0 : flow->npc_action |= (uint64_t)mark << 40;
708 : : }
709 : : }
710 : :
711 : 0 : req = mbox_alloc_msg_npc_mcam_write_entry(mbox_get(mbox));
712 [ # # ]: 0 : if (req == NULL) {
713 : : rc = -ENOSPC;
714 : 0 : goto exit;
715 : : }
716 : 0 : req->set_cntr = flow->use_ctr;
717 : 0 : req->cntr = flow->ctr_id;
718 : 0 : req->entry = entry;
719 : :
720 : 0 : req->intf = (flow->nix_intf == NIX_INTF_RX) ? NPC_MCAM_RX : NPC_MCAM_TX;
721 : 0 : req->enable_entry = 1;
722 [ # # ]: 0 : if (flow->nix_intf == NIX_INTF_RX)
723 : 0 : flow->npc_action |= (uint64_t)flow->recv_queue << 20;
724 : 0 : req->entry_data.action = flow->npc_action;
725 : :
726 : : /*
727 : : * Driver sets vtag action on per interface basis, not
728 : : * per flow basis. It is a matter of how we decide to support
729 : : * this pmd specific behavior. There are two ways:
730 : : * 1. Inherit the vtag action from the one configured
731 : : * for this interface. This can be read from the
732 : : * vtag_action configured for default mcam entry of
733 : : * this pf_func.
734 : : * 2. Do not support vtag action with npc_flow.
735 : : *
736 : : * Second approach is used now.
737 : : */
738 : 0 : req->entry_data.vtag_action = flow->vtag_action;
739 : :
740 [ # # ]: 0 : for (idx = 0; idx < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; idx++) {
741 : 0 : req->entry_data.kw[idx] = flow->mcam_data[idx];
742 : 0 : req->entry_data.kw_mask[idx] = flow->mcam_mask[idx];
743 : : }
744 : :
745 [ # # ]: 0 : if (flow->nix_intf == NIX_INTF_RX) {
746 [ # # # # ]: 0 : if (inl_dev && inl_dev->is_multi_channel &&
747 [ # # ]: 0 : (flow->npc_action & NIX_RX_ACTIONOP_UCAST_IPSEC)) {
748 : 0 : pf_func = nix_inl_dev_pffunc_get();
749 : 0 : req->entry_data.action &= ~(GENMASK(19, 4));
750 : 0 : req->entry_data.action |= (uint64_t)pf_func << 4;
751 : 0 : flow->npc_action &= ~(GENMASK(19, 4));
752 : 0 : flow->npc_action |= (uint64_t)pf_func << 4;
753 : :
754 : 0 : npc_mcam_set_channel(flow, req, inl_dev->channel, inl_dev->chan_mask,
755 : : false);
756 [ # # ]: 0 : } else if (flow->has_rep) {
757 [ # # ]: 0 : pf_func = (flow->rep_act_pf_func == 0) ? flow->rep_pf_func :
758 : : flow->rep_act_pf_func;
759 : 0 : req->entry_data.action &= ~(GENMASK(19, 4));
760 : 0 : req->entry_data.action |= (uint64_t)pf_func << 4;
761 : 0 : flow->npc_action &= ~(GENMASK(19, 4));
762 : 0 : flow->npc_action |= (uint64_t)pf_func << 4;
763 : 0 : npc_mcam_set_channel(flow, req, flow->rep_channel, (BIT_ULL(12) - 1),
764 : : false);
765 [ # # ]: 0 : } else if (npc->is_sdp_link) {
766 : 0 : npc_mcam_set_channel(flow, req, npc->sdp_channel, npc->sdp_channel_mask,
767 : 0 : pst->is_second_pass_rule);
768 : : } else {
769 : 0 : npc_mcam_set_channel(flow, req, npc->channel, (BIT_ULL(12) - 1),
770 : 0 : pst->is_second_pass_rule);
771 : : }
772 : : /*
773 : : * For second pass rule, set LA LTYPE to CPT_HDR.
774 : : * For all other rules, set LA LTYPE to match both 1st pass and 2nd pass ltypes.
775 : : */
776 [ # # # # ]: 0 : if (pst->is_second_pass_rule || (!pst->is_second_pass_rule && pst->has_eth_type)) {
777 [ # # ]: 0 : la_offset = plt_popcount32(npc->keyx_supp_nmask[flow->nix_intf] &
778 : : ((1ULL << 9 /* LA offset */) - 1));
779 : 0 : la_offset *= 4;
780 : :
781 : 0 : mask = ~((0xfULL << la_offset));
782 : 0 : req->entry_data.kw[0] &= mask;
783 : 0 : req->entry_data.kw_mask[0] &= mask;
784 : 0 : flow->mcam_data[0] &= mask;
785 : 0 : flow->mcam_mask[0] &= mask;
786 [ # # ]: 0 : if (pst->is_second_pass_rule) {
787 : 0 : req->entry_data.kw[0] |= ((uint64_t)NPC_LT_LA_CPT_HDR) << la_offset;
788 : 0 : req->entry_data.kw_mask[0] |= (0xFULL << la_offset);
789 : 0 : flow->mcam_data[0] |= ((uint64_t)NPC_LT_LA_CPT_HDR) << la_offset;
790 : 0 : flow->mcam_mask[0] |= (0xFULL << la_offset);
791 : : } else {
792 : : /* Mask ltype ETHER (0x2) and CPT_HDR (0xa) */
793 : 0 : req->entry_data.kw[0] |= (0x2ULL << la_offset);
794 : 0 : req->entry_data.kw_mask[0] |= (0x7ULL << la_offset);
795 : 0 : flow->mcam_data[0] |= (0x2ULL << la_offset);
796 : 0 : flow->mcam_mask[0] |= (0x7ULL << la_offset);
797 : : }
798 : : }
799 : : }
800 : :
801 : : rc = mbox_process_msg(mbox, (void *)&rsp);
802 [ # # ]: 0 : if (rc != 0)
803 : 0 : goto exit;
804 : :
805 : 0 : flow->mcam_id = entry;
806 : :
807 [ # # ]: 0 : if (flow->use_ctr)
808 : 0 : flow->ctr_id = ctr;
809 : : rc = 0;
810 : :
811 : 0 : exit:
812 : : mbox_put(mbox);
813 [ # # ]: 0 : if (rc)
814 : 0 : roc_nix_mcast_list_free(npc->mbox, flow->mcast_grp_index);
815 : : return rc;
816 : : }
817 : :
818 : : static void
819 : 0 : npc_set_vlan_ltype(struct npc_parse_state *pst)
820 : : {
821 : : uint64_t val, mask;
822 : : uint8_t lb_offset;
823 : :
824 : 0 : lb_offset =
825 : 0 : plt_popcount32(pst->npc->keyx_supp_nmask[pst->nix_intf] &
826 : : ((1ULL << NPC_LTYPE_LB_OFFSET) - 1));
827 : 0 : lb_offset *= 4;
828 : :
829 : 0 : mask = ~((0xfULL << lb_offset));
830 : 0 : pst->flow->mcam_data[0] &= mask;
831 : 0 : pst->flow->mcam_mask[0] &= mask;
832 : : /* NPC_LT_LB_CTAG: 0b0010, NPC_LT_LB_STAG_QINQ: 0b0011
833 : : * Set LB layertype/mask as 0b0010/0b1110 to match both.
834 : : */
835 : 0 : val = ((uint64_t)(NPC_LT_LB_CTAG & NPC_LT_LB_STAG_QINQ)) << lb_offset;
836 : 0 : pst->flow->mcam_data[0] |= val;
837 : 0 : pst->flow->mcam_mask[0] |= (0xeULL << lb_offset);
838 : 0 : }
839 : :
840 : : static void
841 : 0 : npc_set_ipv6ext_ltype_mask(struct npc_parse_state *pst)
842 : : {
843 : : uint8_t lc_offset, lcflag_offset;
844 : : uint64_t val, mask;
845 : :
846 : 0 : lc_offset =
847 [ # # ]: 0 : plt_popcount32(pst->npc->keyx_supp_nmask[pst->nix_intf] &
848 : : ((1ULL << NPC_LTYPE_LC_OFFSET) - 1));
849 : 0 : lc_offset *= 4;
850 : :
851 : 0 : mask = ~((0xfULL << lc_offset));
852 : 0 : pst->flow->mcam_data[0] &= mask;
853 : 0 : pst->flow->mcam_mask[0] &= mask;
854 : : /* NPC_LT_LC_IP6: 0b0100, NPC_LT_LC_IP6_EXT: 0b0101
855 : : * Set LC layertype/mask as 0b0100/0b1110 to match both.
856 : : */
857 : 0 : val = ((uint64_t)(NPC_LT_LC_IP6 & NPC_LT_LC_IP6_EXT)) << lc_offset;
858 : 0 : pst->flow->mcam_data[0] |= val;
859 : 0 : pst->flow->mcam_mask[0] |= (0xeULL << lc_offset);
860 : :
861 : : /* If LC LFLAG is non-zero, set the LC LFLAG mask to 0xF. In general
862 : : * case flag mask is set same as the value in data. For example, to
863 : : * match 3 VLANs, flags have to match a range of values. But, for IPv6
864 : : * extended attributes matching, we need an exact match. Hence, set the
865 : : * mask as 0xF. This is done only if LC LFLAG value is non-zero,
866 : : * because for AH and ESP, LC LFLAG is zero and we don't want to match
867 : : * zero in LFLAG.
868 : : */
869 [ # # ]: 0 : if (pst->npc->keyx_supp_nmask[pst->nix_intf] & (1ULL << NPC_LFLAG_LC_OFFSET)) {
870 [ # # ]: 0 : lcflag_offset = plt_popcount32(pst->npc->keyx_supp_nmask[pst->nix_intf] &
871 : : ((1ULL << NPC_LFLAG_LC_OFFSET) - 1));
872 : 0 : lcflag_offset *= 4;
873 : :
874 : 0 : mask = (0xfULL << lcflag_offset);
875 : 0 : val = pst->flow->mcam_data[0] & mask;
876 [ # # ]: 0 : if (val)
877 : 0 : pst->flow->mcam_mask[0] |= mask;
878 : : }
879 : 0 : }
880 : :
881 : : int
882 : 0 : npc_program_mcam(struct npc *npc, struct npc_parse_state *pst, bool mcam_alloc)
883 : : {
884 : : struct npc_mcam_read_base_rule_rsp *base_rule_rsp;
885 : : /* This is non-LDATA part in search key */
886 : 0 : uint64_t key_data[2] = {0ULL, 0ULL};
887 : 0 : uint64_t key_mask[2] = {0ULL, 0ULL};
888 : : int key_len, bit = 0, index, rc = 0;
889 : : struct nix_inl_dev *inl_dev = NULL;
890 : 0 : int intf = pst->flow->nix_intf;
891 : : struct mcam_entry *base_entry;
892 : : bool skip_base_rule = false;
893 : : int off, idx, data_off = 0;
894 : : uint8_t lid, mask, data;
895 : : struct idev_cfg *idev;
896 : : uint16_t layer_info;
897 : : uint64_t lt, flags;
898 : : struct mbox *mbox;
899 : :
900 : : /* Skip till Layer A data start */
901 [ # # ]: 0 : while (bit < NPC_PARSE_KEX_S_LA_OFFSET) {
902 [ # # ]: 0 : if (npc->keyx_supp_nmask[intf] & (1 << bit))
903 : 0 : data_off++;
904 : 0 : bit++;
905 : : }
906 : :
907 : : /* Each bit represents 1 nibble */
908 : 0 : data_off *= 4;
909 : :
910 : : index = 0;
911 [ # # ]: 0 : for (lid = 0; lid < NPC_MAX_LID; lid++) {
912 : : /* Offset in key */
913 : 0 : off = NPC_PARSE_KEX_S_LID_OFFSET(lid);
914 : 0 : lt = pst->lt[lid] & 0xf;
915 : 0 : flags = pst->flags[lid] & 0xff;
916 : :
917 : : /* NPC_LAYER_KEX_S */
918 : 0 : layer_info = ((npc->keyx_supp_nmask[intf] >> off) & 0x7);
919 : :
920 [ # # ]: 0 : if (layer_info) {
921 [ # # ]: 0 : for (idx = 0; idx <= 2; idx++) {
922 [ # # ]: 0 : if (layer_info & (1 << idx)) {
923 [ # # ]: 0 : if (idx == 2) {
924 : : data = lt;
925 : : mask = 0xf;
926 [ # # ]: 0 : } else if (idx == 1) {
927 : 0 : data = ((flags >> 4) & 0xf);
928 : : mask = ((flags >> 4) & 0xf);
929 : : } else {
930 : 0 : data = (flags & 0xf);
931 : : mask = (flags & 0xf);
932 : : }
933 : :
934 [ # # ]: 0 : if (data_off >= 64) {
935 : : data_off = 0;
936 : 0 : index++;
937 : : }
938 : 0 : key_data[index] |= ((uint64_t)data << data_off);
939 : :
940 [ # # ]: 0 : if (lt == 0)
941 : : mask = 0;
942 : 0 : key_mask[index] |= ((uint64_t)mask << data_off);
943 : 0 : data_off += 4;
944 : : }
945 : : }
946 : : }
947 : : }
948 : :
949 : : /* Copy this into mcam string */
950 : 0 : key_len = (pst->npc->keyx_len[intf] + 7) / 8;
951 [ # # ]: 0 : memcpy(pst->flow->mcam_data, key_data, key_len);
952 : 0 : memcpy(pst->flow->mcam_mask, key_mask, key_len);
953 : :
954 [ # # ]: 0 : if (pst->set_vlan_ltype_mask)
955 : 0 : npc_set_vlan_ltype(pst);
956 : :
957 [ # # ]: 0 : if (pst->set_ipv6ext_ltype_mask)
958 : 0 : npc_set_ipv6ext_ltype_mask(pst);
959 : :
960 : 0 : idev = idev_get_cfg();
961 [ # # ]: 0 : if (idev)
962 : 0 : inl_dev = idev->nix_inl_dev;
963 [ # # # # ]: 0 : if (inl_dev && inl_dev->is_multi_channel &&
964 [ # # ]: 0 : (pst->flow->npc_action & NIX_RX_ACTIONOP_UCAST_IPSEC))
965 : : skip_base_rule = true;
966 : :
967 [ # # # # : 0 : if ((pst->is_vf || pst->flow->is_rep_vf) && pst->flow->nix_intf == NIX_INTF_RX &&
# # # # ]
968 : : !skip_base_rule) {
969 [ # # ]: 0 : if (pst->flow->has_rep)
970 : 0 : mbox = mbox_get(pst->flow->rep_mbox);
971 : : else
972 : 0 : mbox = mbox_get(npc->mbox);
973 : 0 : (void)mbox_alloc_msg_npc_read_base_steer_rule(mbox);
974 : : rc = mbox_process_msg(mbox, (void *)&base_rule_rsp);
975 [ # # ]: 0 : if (rc) {
976 : : mbox_put(mbox);
977 : 0 : plt_err("Failed to fetch VF's base MCAM entry");
978 : 0 : return rc;
979 : : }
980 : : mbox_put(mbox);
981 : 0 : base_entry = &base_rule_rsp->entry_data;
982 [ # # ]: 0 : for (idx = 0; idx < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; idx++) {
983 : 0 : pst->flow->mcam_data[idx] |= base_entry->kw[idx];
984 : 0 : pst->flow->mcam_mask[idx] |= base_entry->kw_mask[idx];
985 : : }
986 : : }
987 : :
988 : : /*
989 : : * Now we have mcam data and mask formatted as
990 : : * [Key_len/4 nibbles][0 or 1 nibble hole][data]
991 : : * hole is present if key_len is odd number of nibbles.
992 : : * mcam data must be split into 64 bits + 48 bits segments
993 : : * for each back W0, W1.
994 : : */
995 : :
996 [ # # ]: 0 : if (mcam_alloc)
997 : 0 : return npc_mcam_alloc_and_write(npc, pst->flow, pst);
998 : : else
999 : : return 0;
1000 : : }
1001 : :
1002 : : int
1003 : 0 : npc_flow_enable_all_entries(struct npc *npc, bool enable)
1004 : : {
1005 : : struct nix_inl_dev *inl_dev;
1006 : : struct npc_flow_list *list;
1007 : : struct roc_npc_flow *flow;
1008 : : struct idev_cfg *idev;
1009 : : int rc = 0, idx;
1010 : :
1011 : : /* Free any MCAM counters and delete flow list */
1012 [ # # ]: 0 : for (idx = 0; idx < npc->flow_max_priority; idx++) {
1013 : 0 : list = &npc->flow_list[idx];
1014 [ # # ]: 0 : TAILQ_FOREACH(flow, list, next) {
1015 : 0 : flow->enable = enable;
1016 : 0 : rc = npc_mcam_write_entry(npc->mbox, flow);
1017 [ # # ]: 0 : if (rc)
1018 : 0 : return rc;
1019 : : }
1020 : : }
1021 : :
1022 : : list = &npc->ipsec_list;
1023 : 0 : idev = idev_get_cfg();
1024 [ # # ]: 0 : if (!idev)
1025 : : return 0;
1026 : 0 : inl_dev = idev->nix_inl_dev;
1027 : :
1028 [ # # ]: 0 : if (inl_dev) {
1029 [ # # ]: 0 : TAILQ_FOREACH(flow, list, next) {
1030 : 0 : flow->enable = enable;
1031 : 0 : rc = npc_mcam_write_entry(inl_dev->dev.mbox, flow);
1032 [ # # ]: 0 : if (rc)
1033 : 0 : return rc;
1034 : : }
1035 : : }
1036 : : return rc;
1037 : : }
1038 : :
1039 : : int
1040 : 0 : npc_flow_free_all_resources(struct npc *npc)
1041 : : {
1042 : : struct roc_npc_flow *flow;
1043 : : int rc, idx;
1044 : :
1045 : : /* Free all MCAM entries allocated */
1046 : 0 : rc = npc_mcam_free_all_entries(npc);
1047 : :
1048 : : /* Free any MCAM counters and delete flow list */
1049 [ # # ]: 0 : for (idx = 0; idx < npc->flow_max_priority; idx++) {
1050 [ # # ]: 0 : while ((flow = TAILQ_FIRST(&npc->flow_list[idx])) != NULL) {
1051 : 0 : npc_rss_group_free(npc, flow);
1052 [ # # ]: 0 : if (flow->ctr_id != NPC_COUNTER_NONE) {
1053 : 0 : rc |= npc_mcam_clear_counter(npc->mbox, flow->ctr_id);
1054 : 0 : rc |= npc_mcam_free_counter(npc->mbox, flow->ctr_id);
1055 : : }
1056 : :
1057 [ # # ]: 0 : if (flow->is_sampling_rule)
1058 : 0 : roc_nix_mcast_list_free(npc->mbox, flow->mcast_grp_index);
1059 : :
1060 : 0 : npc_delete_prio_list_entry(npc, flow);
1061 : :
1062 [ # # ]: 0 : TAILQ_REMOVE(&npc->flow_list[idx], flow, next);
1063 : 0 : plt_free(flow);
1064 : : }
1065 : : }
1066 : 0 : return rc;
1067 : : }
|