1 /*
2 * Copyright 2008-2012 Freescale Semiconductor Inc.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above copyright
9 * notice, this list of conditions and the following disclaimer in the
10 * documentation and/or other materials provided with the distribution.
11 * * Neither the name of Freescale Semiconductor nor the
12 * names of its contributors may be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 *
16 * ALTERNATIVELY, this software may be distributed under the terms of the
17 * GNU General Public License ("GPL") as published by the Free Software
18 * Foundation, either version 2 of that License or (at your option) any
19 * later version.
20 *
21 * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
22 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
25 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33
34 /******************************************************************************
35 @File fm_kg.c
36
37 @Description FM PCD ...
38 *//***************************************************************************/
39 #include "std_ext.h"
40 #include "error_ext.h"
41 #include "string_ext.h"
42 #include "debug_ext.h"
43 #include "net_ext.h"
44 #include "fm_port_ext.h"
45
46 #include "fm_common.h"
47 #include "fm_pcd.h"
48 #include "fm_hc.h"
49 #include "fm_pcd_ipc.h"
50 #include "fm_kg.h"
51 #include "fsl_fman_kg.h"
52
53
54 /****************************************/
55 /* static functions */
56 /****************************************/
57
KgHwLock(t_Handle h_FmPcdKg)58 static uint32_t KgHwLock(t_Handle h_FmPcdKg)
59 {
60 ASSERT_COND(h_FmPcdKg);
61 return XX_LockIntrSpinlock(((t_FmPcdKg *)h_FmPcdKg)->h_HwSpinlock);
62 }
63
KgHwUnlock(t_Handle h_FmPcdKg,uint32_t intFlags)64 static void KgHwUnlock(t_Handle h_FmPcdKg, uint32_t intFlags)
65 {
66 ASSERT_COND(h_FmPcdKg);
67 XX_UnlockIntrSpinlock(((t_FmPcdKg *)h_FmPcdKg)->h_HwSpinlock, intFlags);
68 }
69
KgSchemeLock(t_Handle h_Scheme)70 static uint32_t KgSchemeLock(t_Handle h_Scheme)
71 {
72 ASSERT_COND(h_Scheme);
73 return FmPcdLockSpinlock(((t_FmPcdKgScheme *)h_Scheme)->p_Lock);
74 }
75
KgSchemeUnlock(t_Handle h_Scheme,uint32_t intFlags)76 static void KgSchemeUnlock(t_Handle h_Scheme, uint32_t intFlags)
77 {
78 ASSERT_COND(h_Scheme);
79 FmPcdUnlockSpinlock(((t_FmPcdKgScheme *)h_Scheme)->p_Lock, intFlags);
80 }
81
KgSchemeFlagTryLock(t_Handle h_Scheme)82 static bool KgSchemeFlagTryLock(t_Handle h_Scheme)
83 {
84 ASSERT_COND(h_Scheme);
85 return FmPcdLockTryLock(((t_FmPcdKgScheme *)h_Scheme)->p_Lock);
86 }
87
KgSchemeFlagUnlock(t_Handle h_Scheme)88 static void KgSchemeFlagUnlock(t_Handle h_Scheme)
89 {
90 ASSERT_COND(h_Scheme);
91 FmPcdLockUnlock(((t_FmPcdKgScheme *)h_Scheme)->p_Lock);
92 }
93
WriteKgarWait(t_FmPcd * p_FmPcd,uint32_t fmkg_ar)94 static t_Error WriteKgarWait(t_FmPcd *p_FmPcd, uint32_t fmkg_ar)
95 {
96
97 struct fman_kg_regs *regs = p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs;
98
99 if (fman_kg_write_ar_wait(regs, fmkg_ar))
100 RETURN_ERROR(MINOR, E_INVALID_STATE, ("Keygen scheme access violation"));
101
102 return E_OK;
103 }
104
GetGenericSwDefault(t_FmPcdKgExtractDflt swDefaults[],uint8_t numOfSwDefaults,uint8_t code)105 static e_FmPcdKgExtractDfltSelect GetGenericSwDefault(t_FmPcdKgExtractDflt swDefaults[], uint8_t numOfSwDefaults, uint8_t code)
106 {
107 int i;
108
109 switch (code)
110 {
111 case (KG_SCH_GEN_PARSE_RESULT_N_FQID):
112 case (KG_SCH_GEN_DEFAULT):
113 case (KG_SCH_GEN_NEXTHDR):
114 for (i=0 ; i<numOfSwDefaults ; i++)
115 if (swDefaults[i].type == e_FM_PCD_KG_GENERIC_NOT_FROM_DATA)
116 return swDefaults[i].dfltSelect;
117 break;
118 case (KG_SCH_GEN_SHIM1):
119 case (KG_SCH_GEN_SHIM2):
120 case (KG_SCH_GEN_IP_PID_NO_V):
121 case (KG_SCH_GEN_ETH_NO_V):
122 case (KG_SCH_GEN_SNAP_NO_V):
123 case (KG_SCH_GEN_VLAN1_NO_V):
124 case (KG_SCH_GEN_VLAN2_NO_V):
125 case (KG_SCH_GEN_ETH_TYPE_NO_V):
126 case (KG_SCH_GEN_PPP_NO_V):
127 case (KG_SCH_GEN_MPLS1_NO_V):
128 case (KG_SCH_GEN_MPLS_LAST_NO_V):
129 case (KG_SCH_GEN_L3_NO_V):
130 case (KG_SCH_GEN_IP2_NO_V):
131 case (KG_SCH_GEN_GRE_NO_V):
132 case (KG_SCH_GEN_L4_NO_V):
133 for (i=0 ; i<numOfSwDefaults ; i++)
134 if (swDefaults[i].type == e_FM_PCD_KG_GENERIC_FROM_DATA_NO_V)
135 return swDefaults[i].dfltSelect;
136 break;
137 case (KG_SCH_GEN_START_OF_FRM):
138 case (KG_SCH_GEN_ETH):
139 case (KG_SCH_GEN_SNAP):
140 case (KG_SCH_GEN_VLAN1):
141 case (KG_SCH_GEN_VLAN2):
142 case (KG_SCH_GEN_ETH_TYPE):
143 case (KG_SCH_GEN_PPP):
144 case (KG_SCH_GEN_MPLS1):
145 case (KG_SCH_GEN_MPLS2):
146 case (KG_SCH_GEN_MPLS3):
147 case (KG_SCH_GEN_MPLS_LAST):
148 case (KG_SCH_GEN_IPV4):
149 case (KG_SCH_GEN_IPV6):
150 case (KG_SCH_GEN_IPV4_TUNNELED):
151 case (KG_SCH_GEN_IPV6_TUNNELED):
152 case (KG_SCH_GEN_MIN_ENCAP):
153 case (KG_SCH_GEN_GRE):
154 case (KG_SCH_GEN_TCP):
155 case (KG_SCH_GEN_UDP):
156 case (KG_SCH_GEN_IPSEC_AH):
157 case (KG_SCH_GEN_SCTP):
158 case (KG_SCH_GEN_DCCP):
159 case (KG_SCH_GEN_IPSEC_ESP):
160 for (i=0 ; i<numOfSwDefaults ; i++)
161 if (swDefaults[i].type == e_FM_PCD_KG_GENERIC_FROM_DATA)
162 return swDefaults[i].dfltSelect;
163 break;
164 default:
165 break;
166 }
167
168 return e_FM_PCD_KG_DFLT_ILLEGAL;
169 }
170
GetGenCode(e_FmPcdExtractFrom src,uint8_t * p_Offset)171 static uint8_t GetGenCode(e_FmPcdExtractFrom src, uint8_t *p_Offset)
172 {
173 *p_Offset = 0;
174
175 switch (src)
176 {
177 case (e_FM_PCD_EXTRACT_FROM_FRAME_START):
178 return KG_SCH_GEN_START_OF_FRM;
179 case (e_FM_PCD_EXTRACT_FROM_DFLT_VALUE):
180 return KG_SCH_GEN_DEFAULT;
181 case (e_FM_PCD_EXTRACT_FROM_PARSE_RESULT):
182 return KG_SCH_GEN_PARSE_RESULT_N_FQID;
183 case (e_FM_PCD_EXTRACT_FROM_ENQ_FQID):
184 *p_Offset = 32;
185 return KG_SCH_GEN_PARSE_RESULT_N_FQID;
186 case (e_FM_PCD_EXTRACT_FROM_CURR_END_OF_PARSE):
187 return KG_SCH_GEN_NEXTHDR;
188 default:
189 REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal 'extract from' src"));
190 return 0;
191 }
192 }
193
GetGenHdrCode(e_NetHeaderType hdr,e_FmPcdHdrIndex hdrIndex,bool ignoreProtocolValidation)194 static uint8_t GetGenHdrCode(e_NetHeaderType hdr, e_FmPcdHdrIndex hdrIndex, bool ignoreProtocolValidation)
195 {
196 if (!ignoreProtocolValidation)
197 switch (hdr)
198 {
199 case (HEADER_TYPE_NONE):
200 ASSERT_COND(FALSE);
201 case (HEADER_TYPE_ETH):
202 return KG_SCH_GEN_ETH;
203 case (HEADER_TYPE_LLC_SNAP):
204 return KG_SCH_GEN_SNAP;
205 case (HEADER_TYPE_PPPoE):
206 return KG_SCH_GEN_PPP;
207 case (HEADER_TYPE_MPLS):
208 if ((hdrIndex == e_FM_PCD_HDR_INDEX_NONE) || (hdrIndex == e_FM_PCD_HDR_INDEX_1))
209 return KG_SCH_GEN_MPLS1;
210 if (hdrIndex == e_FM_PCD_HDR_INDEX_2)
211 return KG_SCH_GEN_MPLS2;
212 if (hdrIndex == e_FM_PCD_HDR_INDEX_3)
213 return KG_SCH_GEN_MPLS3;
214 if (hdrIndex == e_FM_PCD_HDR_INDEX_LAST)
215 return KG_SCH_GEN_MPLS_LAST;
216 REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal MPLS header index"));
217 return 0;
218 case (HEADER_TYPE_IPv4):
219 if ((hdrIndex == e_FM_PCD_HDR_INDEX_NONE) || (hdrIndex == e_FM_PCD_HDR_INDEX_1))
220 return KG_SCH_GEN_IPV4;
221 if ((hdrIndex == e_FM_PCD_HDR_INDEX_2) || (hdrIndex == e_FM_PCD_HDR_INDEX_LAST))
222 return KG_SCH_GEN_IPV4_TUNNELED;
223 REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv4 header index"));
224 return 0;
225 case (HEADER_TYPE_IPv6):
226 if ((hdrIndex == e_FM_PCD_HDR_INDEX_NONE) || (hdrIndex == e_FM_PCD_HDR_INDEX_1))
227 return KG_SCH_GEN_IPV6;
228 if ((hdrIndex == e_FM_PCD_HDR_INDEX_2) || (hdrIndex == e_FM_PCD_HDR_INDEX_LAST))
229 return KG_SCH_GEN_IPV6_TUNNELED;
230 REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv6 header index"));
231 return 0;
232 case (HEADER_TYPE_GRE):
233 return KG_SCH_GEN_GRE;
234 case (HEADER_TYPE_TCP):
235 return KG_SCH_GEN_TCP;
236 case (HEADER_TYPE_UDP):
237 return KG_SCH_GEN_UDP;
238 case (HEADER_TYPE_IPSEC_AH):
239 return KG_SCH_GEN_IPSEC_AH;
240 case (HEADER_TYPE_IPSEC_ESP):
241 return KG_SCH_GEN_IPSEC_ESP;
242 case (HEADER_TYPE_SCTP):
243 return KG_SCH_GEN_SCTP;
244 case (HEADER_TYPE_DCCP):
245 return KG_SCH_GEN_DCCP;
246 default:
247 REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
248 return 0;
249 }
250 else
251 switch (hdr)
252 {
253 case (HEADER_TYPE_NONE):
254 ASSERT_COND(FALSE);
255 case (HEADER_TYPE_ETH):
256 return KG_SCH_GEN_ETH_NO_V;
257 case (HEADER_TYPE_LLC_SNAP):
258 return KG_SCH_GEN_SNAP_NO_V;
259 case (HEADER_TYPE_PPPoE):
260 return KG_SCH_GEN_PPP_NO_V;
261 case (HEADER_TYPE_MPLS):
262 if ((hdrIndex == e_FM_PCD_HDR_INDEX_NONE) || (hdrIndex == e_FM_PCD_HDR_INDEX_1))
263 return KG_SCH_GEN_MPLS1_NO_V;
264 if (hdrIndex == e_FM_PCD_HDR_INDEX_LAST)
265 return KG_SCH_GEN_MPLS_LAST_NO_V;
266 if ((hdrIndex == e_FM_PCD_HDR_INDEX_2) || (hdrIndex == e_FM_PCD_HDR_INDEX_3) )
267 REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Indexed MPLS Extraction not supported"));
268 else
269 REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal MPLS header index"));
270 return 0;
271 case (HEADER_TYPE_IPv4):
272 case (HEADER_TYPE_IPv6):
273 if ((hdrIndex == e_FM_PCD_HDR_INDEX_NONE) || (hdrIndex == e_FM_PCD_HDR_INDEX_1))
274 return KG_SCH_GEN_L3_NO_V;
275 if ((hdrIndex == e_FM_PCD_HDR_INDEX_2) || (hdrIndex == e_FM_PCD_HDR_INDEX_LAST))
276 return KG_SCH_GEN_IP2_NO_V;
277 REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IP header index"));
278 case (HEADER_TYPE_MINENCAP):
279 return KG_SCH_GEN_IP2_NO_V;
280 case (HEADER_TYPE_USER_DEFINED_L3):
281 return KG_SCH_GEN_L3_NO_V;
282 case (HEADER_TYPE_GRE):
283 return KG_SCH_GEN_GRE_NO_V;
284 case (HEADER_TYPE_TCP):
285 case (HEADER_TYPE_UDP):
286 case (HEADER_TYPE_IPSEC_AH):
287 case (HEADER_TYPE_IPSEC_ESP):
288 case (HEADER_TYPE_SCTP):
289 case (HEADER_TYPE_DCCP):
290 return KG_SCH_GEN_L4_NO_V;
291 case (HEADER_TYPE_USER_DEFINED_SHIM1):
292 return KG_SCH_GEN_SHIM1;
293 case (HEADER_TYPE_USER_DEFINED_SHIM2):
294 return KG_SCH_GEN_SHIM2;
295 default:
296 REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
297 return 0;
298 }
299 }
GetGenFieldCode(e_NetHeaderType hdr,t_FmPcdFields field,bool ignoreProtocolValidation,e_FmPcdHdrIndex hdrIndex)300 static t_GenericCodes GetGenFieldCode(e_NetHeaderType hdr, t_FmPcdFields field, bool ignoreProtocolValidation, e_FmPcdHdrIndex hdrIndex)
301 {
302 if (!ignoreProtocolValidation)
303 switch (hdr)
304 {
305 case (HEADER_TYPE_NONE):
306 ASSERT_COND(FALSE);
307 break;
308 case (HEADER_TYPE_ETH):
309 switch (field.eth)
310 {
311 case (NET_HEADER_FIELD_ETH_TYPE):
312 return KG_SCH_GEN_ETH_TYPE;
313 default:
314 REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
315 return 0;
316 }
317 break;
318 case (HEADER_TYPE_VLAN):
319 switch (field.vlan)
320 {
321 case (NET_HEADER_FIELD_VLAN_TCI):
322 if ((hdrIndex == e_FM_PCD_HDR_INDEX_NONE) || (hdrIndex == e_FM_PCD_HDR_INDEX_1))
323 return KG_SCH_GEN_VLAN1;
324 if (hdrIndex == e_FM_PCD_HDR_INDEX_LAST)
325 return KG_SCH_GEN_VLAN2;
326 REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal VLAN header index"));
327 return 0;
328 }
329 break;
330 case (HEADER_TYPE_MPLS):
331 case (HEADER_TYPE_IPSEC_AH):
332 case (HEADER_TYPE_IPSEC_ESP):
333 case (HEADER_TYPE_LLC_SNAP):
334 case (HEADER_TYPE_PPPoE):
335 case (HEADER_TYPE_IPv4):
336 case (HEADER_TYPE_IPv6):
337 case (HEADER_TYPE_GRE):
338 case (HEADER_TYPE_MINENCAP):
339 case (HEADER_TYPE_USER_DEFINED_L3):
340 case (HEADER_TYPE_TCP):
341 case (HEADER_TYPE_UDP):
342 case (HEADER_TYPE_SCTP):
343 case (HEADER_TYPE_DCCP):
344 case (HEADER_TYPE_USER_DEFINED_L4):
345 REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
346 return 0;
347 default:
348 break;
349
350 }
351 else
352 switch (hdr)
353 {
354 case (HEADER_TYPE_NONE):
355 ASSERT_COND(FALSE);
356 break;
357 case (HEADER_TYPE_ETH):
358 switch (field.eth)
359 {
360 case (NET_HEADER_FIELD_ETH_TYPE):
361 return KG_SCH_GEN_ETH_TYPE_NO_V;
362 default:
363 REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
364 return 0;
365 }
366 break;
367 case (HEADER_TYPE_VLAN):
368 switch (field.vlan)
369 {
370 case (NET_HEADER_FIELD_VLAN_TCI) :
371 if ((hdrIndex == e_FM_PCD_HDR_INDEX_NONE) || (hdrIndex == e_FM_PCD_HDR_INDEX_1))
372 return KG_SCH_GEN_VLAN1_NO_V;
373 if (hdrIndex == e_FM_PCD_HDR_INDEX_LAST)
374 return KG_SCH_GEN_VLAN2_NO_V;
375 REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal VLAN header index"));
376 return 0;
377 }
378 break;
379 case (HEADER_TYPE_IPv4):
380 switch (field.ipv4)
381 {
382 case (NET_HEADER_FIELD_IPv4_PROTO):
383 return KG_SCH_GEN_IP_PID_NO_V;
384 default:
385 REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
386 return 0;
387 }
388 break;
389 case (HEADER_TYPE_IPv6):
390 switch (field.ipv6)
391 {
392 case (NET_HEADER_FIELD_IPv6_NEXT_HDR):
393 return KG_SCH_GEN_IP_PID_NO_V;
394 default:
395 REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
396 return 0;
397 }
398 break;
399 case (HEADER_TYPE_MPLS):
400 case (HEADER_TYPE_LLC_SNAP):
401 case (HEADER_TYPE_PPPoE):
402 case (HEADER_TYPE_GRE):
403 case (HEADER_TYPE_MINENCAP):
404 case (HEADER_TYPE_USER_DEFINED_L3):
405 case (HEADER_TYPE_TCP):
406 case (HEADER_TYPE_UDP):
407 case (HEADER_TYPE_IPSEC_AH):
408 case (HEADER_TYPE_IPSEC_ESP):
409 case (HEADER_TYPE_SCTP):
410 case (HEADER_TYPE_DCCP):
411 case (HEADER_TYPE_USER_DEFINED_L4):
412 REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
413 return 0;
414 default:
415 break;
416 }
417 REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Header not supported"));
418 return 0;
419 }
420
GetKnownProtMask(t_FmPcd * p_FmPcd,e_NetHeaderType hdr,e_FmPcdHdrIndex index,t_FmPcdFields field)421 static t_KnownFieldsMasks GetKnownProtMask(t_FmPcd *p_FmPcd, e_NetHeaderType hdr, e_FmPcdHdrIndex index, t_FmPcdFields field)
422 {
423 UNUSED(p_FmPcd);
424
425 switch (hdr)
426 {
427 case (HEADER_TYPE_NONE):
428 ASSERT_COND(FALSE);
429 break;
430 case (HEADER_TYPE_ETH):
431 switch (field.eth)
432 {
433 case (NET_HEADER_FIELD_ETH_DA):
434 return KG_SCH_KN_MACDST;
435 case (NET_HEADER_FIELD_ETH_SA):
436 return KG_SCH_KN_MACSRC;
437 case (NET_HEADER_FIELD_ETH_TYPE):
438 return KG_SCH_KN_ETYPE;
439 default:
440 REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
441 return 0;
442 }
443 case (HEADER_TYPE_LLC_SNAP):
444 switch (field.llcSnap)
445 {
446 case (NET_HEADER_FIELD_LLC_SNAP_TYPE):
447 return KG_SCH_KN_ETYPE;
448 default:
449 REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
450 return 0;
451 }
452 case (HEADER_TYPE_VLAN):
453 switch (field.vlan)
454 {
455 case (NET_HEADER_FIELD_VLAN_TCI):
456 if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
457 return KG_SCH_KN_TCI1;
458 if (index == e_FM_PCD_HDR_INDEX_LAST)
459 return KG_SCH_KN_TCI2;
460 else
461 {
462 REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
463 return 0;
464 }
465 default:
466 REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
467 return 0;
468 }
469 case (HEADER_TYPE_MPLS):
470 switch (field.mpls)
471 {
472 case (NET_HEADER_FIELD_MPLS_LABEL_STACK):
473 if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
474 return KG_SCH_KN_MPLS1;
475 if (index == e_FM_PCD_HDR_INDEX_2)
476 return KG_SCH_KN_MPLS2;
477 if (index == e_FM_PCD_HDR_INDEX_LAST)
478 return KG_SCH_KN_MPLS_LAST;
479 REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal MPLS index"));
480 return 0;
481 default:
482 REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
483 return 0;
484 }
485 case (HEADER_TYPE_IPv4):
486 switch (field.ipv4)
487 {
488 case (NET_HEADER_FIELD_IPv4_SRC_IP):
489 if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
490 return KG_SCH_KN_IPSRC1;
491 if ((index == e_FM_PCD_HDR_INDEX_2) || (index == e_FM_PCD_HDR_INDEX_LAST))
492 return KG_SCH_KN_IPSRC2;
493 REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv4 index"));
494 return 0;
495 case (NET_HEADER_FIELD_IPv4_DST_IP):
496 if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
497 return KG_SCH_KN_IPDST1;
498 if ((index == e_FM_PCD_HDR_INDEX_2) || (index == e_FM_PCD_HDR_INDEX_LAST))
499 return KG_SCH_KN_IPDST2;
500 REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv4 index"));
501 return 0;
502 case (NET_HEADER_FIELD_IPv4_PROTO):
503 if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
504 return KG_SCH_KN_PTYPE1;
505 if ((index == e_FM_PCD_HDR_INDEX_2) || (index == e_FM_PCD_HDR_INDEX_LAST))
506 return KG_SCH_KN_PTYPE2;
507 REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv4 index"));
508 return 0;
509 case (NET_HEADER_FIELD_IPv4_TOS):
510 if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
511 return KG_SCH_KN_IPTOS_TC1;
512 if ((index == e_FM_PCD_HDR_INDEX_2) || (index == e_FM_PCD_HDR_INDEX_LAST))
513 return KG_SCH_KN_IPTOS_TC2;
514 REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv4 index"));
515 return 0;
516 default:
517 REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
518 return 0;
519 }
520 case (HEADER_TYPE_IPv6):
521 switch (field.ipv6)
522 {
523 case (NET_HEADER_FIELD_IPv6_SRC_IP):
524 if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
525 return KG_SCH_KN_IPSRC1;
526 if ((index == e_FM_PCD_HDR_INDEX_2) || (index == e_FM_PCD_HDR_INDEX_LAST))
527 return KG_SCH_KN_IPSRC2;
528 REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv6 index"));
529 return 0;
530 case (NET_HEADER_FIELD_IPv6_DST_IP):
531 if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
532 return KG_SCH_KN_IPDST1;
533 if ((index == e_FM_PCD_HDR_INDEX_2) || (index == e_FM_PCD_HDR_INDEX_LAST))
534 return KG_SCH_KN_IPDST2;
535 REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv6 index"));
536 return 0;
537 case (NET_HEADER_FIELD_IPv6_NEXT_HDR):
538 if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
539 return KG_SCH_KN_PTYPE1;
540 if (index == e_FM_PCD_HDR_INDEX_2)
541 return KG_SCH_KN_PTYPE2;
542 if (index == e_FM_PCD_HDR_INDEX_LAST)
543 #ifdef FM_KG_NO_IPPID_SUPPORT
544 if (p_FmPcd->fmRevInfo.majorRev < 6)
545 return KG_SCH_KN_PTYPE2;
546 #endif /* FM_KG_NO_IPPID_SUPPORT */
547 return KG_SCH_KN_IPPID;
548 REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv6 index"));
549 return 0;
550 case (NET_HEADER_FIELD_IPv6_VER | NET_HEADER_FIELD_IPv6_FL | NET_HEADER_FIELD_IPv6_TC):
551 if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
552 return (KG_SCH_KN_IPV6FL1 | KG_SCH_KN_IPTOS_TC1);
553 if ((index == e_FM_PCD_HDR_INDEX_2) || (index == e_FM_PCD_HDR_INDEX_LAST))
554 return (KG_SCH_KN_IPV6FL2 | KG_SCH_KN_IPTOS_TC2);
555 REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv6 index"));
556 return 0;
557 case (NET_HEADER_FIELD_IPv6_VER | NET_HEADER_FIELD_IPv6_TC):
558 if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
559 return KG_SCH_KN_IPTOS_TC1;
560 if ((index == e_FM_PCD_HDR_INDEX_2) || (index == e_FM_PCD_HDR_INDEX_LAST))
561 return KG_SCH_KN_IPTOS_TC2;
562 REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv6 index"));
563 return 0;
564 case (NET_HEADER_FIELD_IPv6_FL):
565 if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
566 return KG_SCH_KN_IPV6FL1;
567 if ((index == e_FM_PCD_HDR_INDEX_2) || (index == e_FM_PCD_HDR_INDEX_LAST))
568 return KG_SCH_KN_IPV6FL2;
569 REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv6 index"));
570 return 0;
571 default:
572 REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
573 return 0;
574 }
575 case (HEADER_TYPE_GRE):
576 switch (field.gre)
577 {
578 case (NET_HEADER_FIELD_GRE_TYPE):
579 return KG_SCH_KN_GREPTYPE;
580 default:
581 REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
582 return 0;
583 }
584 case (HEADER_TYPE_MINENCAP):
585 switch (field.minencap)
586 {
587 case (NET_HEADER_FIELD_MINENCAP_SRC_IP):
588 return KG_SCH_KN_IPSRC2;
589 case (NET_HEADER_FIELD_MINENCAP_DST_IP):
590 return KG_SCH_KN_IPDST2;
591 case (NET_HEADER_FIELD_MINENCAP_TYPE):
592 return KG_SCH_KN_PTYPE2;
593 default:
594 REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
595 return 0;
596 }
597 case (HEADER_TYPE_TCP):
598 switch (field.tcp)
599 {
600 case (NET_HEADER_FIELD_TCP_PORT_SRC):
601 return KG_SCH_KN_L4PSRC;
602 case (NET_HEADER_FIELD_TCP_PORT_DST):
603 return KG_SCH_KN_L4PDST;
604 case (NET_HEADER_FIELD_TCP_FLAGS):
605 return KG_SCH_KN_TFLG;
606 default:
607 REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
608 return 0;
609 }
610 case (HEADER_TYPE_UDP):
611 switch (field.udp)
612 {
613 case (NET_HEADER_FIELD_UDP_PORT_SRC):
614 return KG_SCH_KN_L4PSRC;
615 case (NET_HEADER_FIELD_UDP_PORT_DST):
616 return KG_SCH_KN_L4PDST;
617 default:
618 REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
619 return 0;
620 }
621 case (HEADER_TYPE_IPSEC_AH):
622 switch (field.ipsecAh)
623 {
624 case (NET_HEADER_FIELD_IPSEC_AH_SPI):
625 return KG_SCH_KN_IPSEC_SPI;
626 case (NET_HEADER_FIELD_IPSEC_AH_NH):
627 return KG_SCH_KN_IPSEC_NH;
628 default:
629 REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
630 return 0;
631 }
632 case (HEADER_TYPE_IPSEC_ESP):
633 switch (field.ipsecEsp)
634 {
635 case (NET_HEADER_FIELD_IPSEC_ESP_SPI):
636 return KG_SCH_KN_IPSEC_SPI;
637 default:
638 REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
639 return 0;
640 }
641 case (HEADER_TYPE_SCTP):
642 switch (field.sctp)
643 {
644 case (NET_HEADER_FIELD_SCTP_PORT_SRC):
645 return KG_SCH_KN_L4PSRC;
646 case (NET_HEADER_FIELD_SCTP_PORT_DST):
647 return KG_SCH_KN_L4PDST;
648 default:
649 REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
650 return 0;
651 }
652 case (HEADER_TYPE_DCCP):
653 switch (field.dccp)
654 {
655 case (NET_HEADER_FIELD_DCCP_PORT_SRC):
656 return KG_SCH_KN_L4PSRC;
657 case (NET_HEADER_FIELD_DCCP_PORT_DST):
658 return KG_SCH_KN_L4PDST;
659 default:
660 REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
661 return 0;
662 }
663 case (HEADER_TYPE_PPPoE):
664 switch (field.pppoe)
665 {
666 case (NET_HEADER_FIELD_PPPoE_PID):
667 return KG_SCH_KN_PPPID;
668 case (NET_HEADER_FIELD_PPPoE_SID):
669 return KG_SCH_KN_PPPSID;
670 default:
671 REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
672 return 0;
673 }
674 default:
675 break;
676
677 }
678
679 REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
680 return 0;
681 }
682
683
GetKnownFieldId(uint32_t bitMask)684 static uint8_t GetKnownFieldId(uint32_t bitMask)
685 {
686 uint8_t cnt = 0;
687
688 while (bitMask)
689 if (bitMask & 0x80000000)
690 break;
691 else
692 {
693 cnt++;
694 bitMask <<= 1;
695 }
696 return cnt;
697
698 }
699
GetExtractedOrMask(uint8_t bitOffset,bool fqid)700 static uint8_t GetExtractedOrMask(uint8_t bitOffset, bool fqid)
701 {
702 uint8_t i, mask, numOfOnesToClear, walking1Mask = 1;
703
704 /* bitOffset 1-7 --> mask 0x1-0x7F */
705 if (bitOffset<8)
706 {
707 mask = 0;
708 for (i = 0 ; i < bitOffset ; i++, walking1Mask <<= 1)
709 mask |= walking1Mask;
710 }
711 else
712 {
713 mask = 0xFF;
714 numOfOnesToClear = 0;
715 if (fqid && bitOffset>24)
716 /* bitOffset 25-31 --> mask 0xFE-0x80 */
717 numOfOnesToClear = (uint8_t)(bitOffset-24);
718 else
719 /* bitOffset 9-15 --> mask 0xFE-0x80 */
720 if (!fqid && bitOffset>8)
721 numOfOnesToClear = (uint8_t)(bitOffset-8);
722 for (i = 0 ; i < numOfOnesToClear ; i++, walking1Mask <<= 1)
723 mask &= ~walking1Mask;
724 /* bitOffset 8-24 for FQID, 8 for PP --> no mask (0xFF)*/
725 }
726 return mask;
727 }
728
IncSchemeOwners(t_FmPcd * p_FmPcd,t_FmPcdKgInterModuleBindPortToSchemes * p_BindPort)729 static void IncSchemeOwners(t_FmPcd *p_FmPcd, t_FmPcdKgInterModuleBindPortToSchemes *p_BindPort)
730 {
731 t_FmPcdKg *p_FmPcdKg;
732 t_FmPcdKgScheme *p_Scheme;
733 uint32_t intFlags;
734 uint8_t relativeSchemeId;
735 int i;
736
737 p_FmPcdKg = p_FmPcd->p_FmPcdKg;
738
739 /* for each scheme - update owners counters */
740 for (i = 0; i < p_BindPort->numOfSchemes; i++)
741 {
742 relativeSchemeId = FmPcdKgGetRelativeSchemeId(p_FmPcd, p_BindPort->schemesIds[i]);
743 ASSERT_COND(relativeSchemeId < FM_PCD_KG_NUM_OF_SCHEMES);
744
745 p_Scheme = &p_FmPcdKg->schemes[relativeSchemeId];
746
747 /* increment owners number */
748 intFlags = KgSchemeLock(p_Scheme);
749 p_Scheme->owners++;
750 KgSchemeUnlock(p_Scheme, intFlags);
751 }
752 }
753
DecSchemeOwners(t_FmPcd * p_FmPcd,t_FmPcdKgInterModuleBindPortToSchemes * p_BindPort)754 static void DecSchemeOwners(t_FmPcd *p_FmPcd, t_FmPcdKgInterModuleBindPortToSchemes *p_BindPort)
755 {
756 t_FmPcdKg *p_FmPcdKg;
757 t_FmPcdKgScheme *p_Scheme;
758 uint32_t intFlags;
759 uint8_t relativeSchemeId;
760 int i;
761
762 p_FmPcdKg = p_FmPcd->p_FmPcdKg;
763
764 /* for each scheme - update owners counters */
765 for (i = 0; i < p_BindPort->numOfSchemes; i++)
766 {
767 relativeSchemeId = FmPcdKgGetRelativeSchemeId(p_FmPcd, p_BindPort->schemesIds[i]);
768 ASSERT_COND(relativeSchemeId < FM_PCD_KG_NUM_OF_SCHEMES);
769
770 p_Scheme = &p_FmPcdKg->schemes[relativeSchemeId];
771
772 /* increment owners number */
773 ASSERT_COND(p_Scheme->owners);
774 intFlags = KgSchemeLock(p_Scheme);
775 p_Scheme->owners--;
776 KgSchemeUnlock(p_Scheme, intFlags);
777 }
778 }
779
UpdateRequiredActionFlag(t_FmPcdKgScheme * p_Scheme,bool set)780 static void UpdateRequiredActionFlag(t_FmPcdKgScheme *p_Scheme, bool set)
781 {
782 /* this routine is locked by the calling routine */
783 ASSERT_COND(p_Scheme);
784 ASSERT_COND(p_Scheme->valid);
785
786 if (set)
787 p_Scheme->requiredActionFlag = TRUE;
788 else
789 {
790 p_Scheme->requiredAction = 0;
791 p_Scheme->requiredActionFlag = FALSE;
792 }
793 }
794
KgWriteSp(t_FmPcd * p_FmPcd,uint8_t hardwarePortId,uint32_t spReg,bool add)795 static t_Error KgWriteSp(t_FmPcd *p_FmPcd, uint8_t hardwarePortId, uint32_t spReg, bool add)
796 {
797 struct fman_kg_regs *p_KgRegs;
798
799 uint32_t tmpKgarReg = 0, intFlags;
800 t_Error err = E_OK;
801
802 /* The calling routine had locked the port, so for each port only one core can access
803 * (so we don't need a lock here) */
804
805 if (p_FmPcd->h_Hc)
806 return FmHcKgWriteSp(p_FmPcd->h_Hc, hardwarePortId, spReg, add);
807
808 p_KgRegs = p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs;
809
810 tmpKgarReg = FmPcdKgBuildReadPortSchemeBindActionReg(hardwarePortId);
811 /* lock a common KG reg */
812 intFlags = KgHwLock(p_FmPcd->p_FmPcdKg);
813 err = WriteKgarWait(p_FmPcd, tmpKgarReg);
814 if (err)
815 {
816 KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags);
817 RETURN_ERROR(MINOR, err, NO_MSG);
818 }
819
820 fman_kg_write_sp(p_KgRegs, spReg, add);
821
822 tmpKgarReg = FmPcdKgBuildWritePortSchemeBindActionReg(hardwarePortId);
823
824 err = WriteKgarWait(p_FmPcd, tmpKgarReg);
825 KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags);
826 return err;
827 }
828
KgWriteCpp(t_FmPcd * p_FmPcd,uint8_t hardwarePortId,uint32_t cppReg)829 static t_Error KgWriteCpp(t_FmPcd *p_FmPcd, uint8_t hardwarePortId, uint32_t cppReg)
830 {
831 struct fman_kg_regs *p_KgRegs;
832 uint32_t tmpKgarReg, intFlags;
833 t_Error err;
834
835 p_KgRegs = p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs;
836
837 if (p_FmPcd->h_Hc)
838 {
839 err = FmHcKgWriteCpp(p_FmPcd->h_Hc, hardwarePortId, cppReg);
840 return err;
841 }
842
843 intFlags = KgHwLock(p_FmPcd->p_FmPcdKg);
844 fman_kg_write_cpp(p_KgRegs, cppReg);
845 tmpKgarReg = FmPcdKgBuildWritePortClsPlanBindActionReg(hardwarePortId);
846 err = WriteKgarWait(p_FmPcd, tmpKgarReg);
847 KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags);
848
849 return err;
850 }
851
BuildCppReg(t_FmPcd * p_FmPcd,uint8_t clsPlanGrpId)852 static uint32_t BuildCppReg(t_FmPcd *p_FmPcd, uint8_t clsPlanGrpId)
853 {
854 uint32_t tmpKgpeCpp;
855
856 tmpKgpeCpp = (uint32_t)(p_FmPcd->p_FmPcdKg->clsPlanGrps[clsPlanGrpId].baseEntry / 8);
857 tmpKgpeCpp |= (uint32_t)(((p_FmPcd->p_FmPcdKg->clsPlanGrps[clsPlanGrpId].sizeOfGrp / 8) - 1) << FM_KG_PE_CPP_MASK_SHIFT);
858
859 return tmpKgpeCpp;
860 }
861
BindPortToClsPlanGrp(t_FmPcd * p_FmPcd,uint8_t hardwarePortId,uint8_t clsPlanGrpId)862 static t_Error BindPortToClsPlanGrp(t_FmPcd *p_FmPcd, uint8_t hardwarePortId, uint8_t clsPlanGrpId)
863 {
864 uint32_t tmpKgpeCpp = 0;
865
866 tmpKgpeCpp = BuildCppReg(p_FmPcd, clsPlanGrpId);
867 return KgWriteCpp(p_FmPcd, hardwarePortId, tmpKgpeCpp);
868 }
869
UnbindPortToClsPlanGrp(t_FmPcd * p_FmPcd,uint8_t hardwarePortId)870 static void UnbindPortToClsPlanGrp(t_FmPcd *p_FmPcd, uint8_t hardwarePortId)
871 {
872 KgWriteCpp(p_FmPcd, hardwarePortId, 0);
873 }
874
875 #if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
ReadClsPlanBlockActionReg(uint8_t grpId)876 static uint32_t __attribute__((unused)) ReadClsPlanBlockActionReg(uint8_t grpId)
877 {
878 return (uint32_t)(FM_KG_KGAR_GO |
879 FM_KG_KGAR_READ |
880 FM_PCD_KG_KGAR_SEL_CLS_PLAN_ENTRY |
881 DUMMY_PORT_ID |
882 ((uint32_t)grpId << FM_PCD_KG_KGAR_NUM_SHIFT) |
883 FM_PCD_KG_KGAR_WSEL_MASK);
884
885 /* if we ever want to write 1 by 1, use:
886 sel = (uint8_t)(0x01 << (7- (entryId % CLS_PLAN_NUM_PER_GRP)));
887 */
888 }
889 #endif /* (defined(DEBUG_ERRORS) && ... */
890
PcdKgErrorException(t_Handle h_FmPcd)891 static void PcdKgErrorException(t_Handle h_FmPcd)
892 {
893 t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;
894 uint32_t event,schemeIndexes = 0, index = 0;
895 struct fman_kg_regs *p_KgRegs;
896
897 ASSERT_COND(FmIsMaster(p_FmPcd->h_Fm));
898 p_KgRegs = p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs;
899 fman_kg_get_event(p_KgRegs, &event, &schemeIndexes);
900
901 if (event & FM_EX_KG_DOUBLE_ECC)
902 p_FmPcd->f_Exception(p_FmPcd->h_App,e_FM_PCD_KG_EXCEPTION_DOUBLE_ECC);
903 if (event & FM_EX_KG_KEYSIZE_OVERFLOW)
904 {
905 if (schemeIndexes)
906 {
907 while (schemeIndexes)
908 {
909 if (schemeIndexes & 0x1)
910 p_FmPcd->f_FmPcdIndexedException(p_FmPcd->h_App,e_FM_PCD_KG_EXCEPTION_KEYSIZE_OVERFLOW, (uint16_t)(31 - index));
911 schemeIndexes >>= 1;
912 index+=1;
913 }
914 }
915 else /* this should happen only when interrupt is forced. */
916 p_FmPcd->f_Exception(p_FmPcd->h_App,e_FM_PCD_KG_EXCEPTION_KEYSIZE_OVERFLOW);
917 }
918 }
919
KgInitGuest(t_FmPcd * p_FmPcd)920 static t_Error KgInitGuest(t_FmPcd *p_FmPcd)
921 {
922 t_Error err = E_OK;
923 t_FmPcdIpcKgSchemesParams kgAlloc;
924 uint32_t replyLength;
925 t_FmPcdIpcReply reply;
926 t_FmPcdIpcMsg msg;
927
928 ASSERT_COND(p_FmPcd->guestId != NCSW_MASTER_ID);
929
930 /* in GUEST_PARTITION, we use the IPC */
931 memset(&reply, 0, sizeof(reply));
932 memset(&msg, 0, sizeof(msg));
933 memset(&kgAlloc, 0, sizeof(t_FmPcdIpcKgSchemesParams));
934 kgAlloc.numOfSchemes = p_FmPcd->p_FmPcdKg->numOfSchemes;
935 kgAlloc.guestId = p_FmPcd->guestId;
936 msg.msgId = FM_PCD_ALLOC_KG_SCHEMES;
937 memcpy(msg.msgBody, &kgAlloc, sizeof(kgAlloc));
938 replyLength = sizeof(uint32_t) + p_FmPcd->p_FmPcdKg->numOfSchemes*sizeof(uint8_t);
939 if ((err = XX_IpcSendMessage(p_FmPcd->h_IpcSession,
940 (uint8_t*)&msg,
941 sizeof(msg.msgId) + sizeof(kgAlloc),
942 (uint8_t*)&reply,
943 &replyLength,
944 NULL,
945 NULL)) != E_OK)
946 RETURN_ERROR(MAJOR, err, NO_MSG);
947 if (replyLength != (sizeof(uint32_t) + p_FmPcd->p_FmPcdKg->numOfSchemes*sizeof(uint8_t)))
948 RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
949 memcpy(p_FmPcd->p_FmPcdKg->schemesIds, (uint8_t*)(reply.replyBody),p_FmPcd->p_FmPcdKg->numOfSchemes*sizeof(uint8_t));
950
951 return (t_Error)reply.error;
952 }
953
KgInitMaster(t_FmPcd * p_FmPcd)954 static t_Error KgInitMaster(t_FmPcd *p_FmPcd)
955 {
956 t_Error err = E_OK;
957 struct fman_kg_regs *p_Regs = p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs;
958
959 ASSERT_COND(p_FmPcd->guestId == NCSW_MASTER_ID);
960
961 if (p_FmPcd->exceptions & FM_EX_KG_DOUBLE_ECC)
962 FmEnableRamsEcc(p_FmPcd->h_Fm);
963
964 fman_kg_init(p_Regs, p_FmPcd->exceptions, GET_NIA_BMI_AC_ENQ_FRAME(p_FmPcd));
965
966 /* register even if no interrupts enabled, to allow future enablement */
967 FmRegisterIntr(p_FmPcd->h_Fm,
968 e_FM_MOD_KG,
969 0,
970 e_FM_INTR_TYPE_ERR,
971 PcdKgErrorException,
972 p_FmPcd);
973
974 fman_kg_enable_scheme_interrupts(p_Regs);
975
976 if (p_FmPcd->p_FmPcdKg->numOfSchemes)
977 {
978 err = FmPcdKgAllocSchemes(p_FmPcd,
979 p_FmPcd->p_FmPcdKg->numOfSchemes,
980 p_FmPcd->guestId,
981 p_FmPcd->p_FmPcdKg->schemesIds);
982 if (err)
983 RETURN_ERROR(MINOR, err, NO_MSG);
984 }
985
986 return E_OK;
987 }
988
ValidateSchemeSw(t_FmPcdKgScheme * p_Scheme)989 static void ValidateSchemeSw(t_FmPcdKgScheme *p_Scheme)
990 {
991 ASSERT_COND(!p_Scheme->valid);
992 if (p_Scheme->netEnvId != ILLEGAL_NETENV)
993 FmPcdIncNetEnvOwners(p_Scheme->h_FmPcd, p_Scheme->netEnvId);
994 p_Scheme->valid = TRUE;
995 }
996
InvalidateSchemeSw(t_FmPcdKgScheme * p_Scheme)997 static t_Error InvalidateSchemeSw(t_FmPcdKgScheme *p_Scheme)
998 {
999 if (p_Scheme->owners)
1000 RETURN_ERROR(MINOR, E_INVALID_STATE, ("Trying to delete a scheme that has ports bound to"));
1001
1002 if (p_Scheme->netEnvId != ILLEGAL_NETENV)
1003 FmPcdDecNetEnvOwners(p_Scheme->h_FmPcd, p_Scheme->netEnvId);
1004 p_Scheme->valid = FALSE;
1005
1006 return E_OK;
1007 }
1008
BuildSchemeRegs(t_FmPcdKgScheme * p_Scheme,t_FmPcdKgSchemeParams * p_SchemeParams,struct fman_kg_scheme_regs * p_SchemeRegs)1009 static t_Error BuildSchemeRegs(t_FmPcdKgScheme *p_Scheme,
1010 t_FmPcdKgSchemeParams *p_SchemeParams,
1011 struct fman_kg_scheme_regs *p_SchemeRegs)
1012 {
1013 t_FmPcd *p_FmPcd = (t_FmPcd *)(p_Scheme->h_FmPcd);
1014 uint32_t grpBits = 0;
1015 uint8_t grpBase;
1016 bool direct=TRUE, absolute=FALSE;
1017 uint16_t profileId=0, numOfProfiles=0, relativeProfileId;
1018 t_Error err = E_OK;
1019 int i = 0;
1020 t_NetEnvParams netEnvParams;
1021 uint32_t tmpReg, fqbTmp = 0, ppcTmp = 0, selectTmp, maskTmp, knownTmp, genTmp;
1022 t_FmPcdKgKeyExtractAndHashParams *p_KeyAndHash = NULL;
1023 uint8_t j, curr, idx;
1024 uint8_t id, shift=0, code=0, offset=0, size=0;
1025 t_FmPcdExtractEntry *p_Extract = NULL;
1026 t_FmPcdKgExtractedOrParams *p_ExtractOr;
1027 bool generic = FALSE;
1028 t_KnownFieldsMasks bitMask;
1029 e_FmPcdKgExtractDfltSelect swDefault = (e_FmPcdKgExtractDfltSelect)0;
1030 t_FmPcdKgSchemesExtracts *p_LocalExtractsArray;
1031 uint8_t numOfSwDefaults = 0;
1032 t_FmPcdKgExtractDflt swDefaults[NUM_OF_SW_DEFAULTS];
1033 uint8_t currGenId = 0;
1034
1035 memset(swDefaults, 0, NUM_OF_SW_DEFAULTS*sizeof(t_FmPcdKgExtractDflt));
1036 memset(p_SchemeRegs, 0, sizeof(struct fman_kg_scheme_regs));
1037
1038 if (p_SchemeParams->netEnvParams.numOfDistinctionUnits > FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS)
1039 RETURN_ERROR(MAJOR, E_INVALID_VALUE,
1040 ("numOfDistinctionUnits should not exceed %d", FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS));
1041
1042 /* by netEnv parameters, get match vector */
1043 if (!p_SchemeParams->alwaysDirect)
1044 {
1045 p_Scheme->netEnvId = FmPcdGetNetEnvId(p_SchemeParams->netEnvParams.h_NetEnv);
1046 netEnvParams.netEnvId = p_Scheme->netEnvId;
1047 netEnvParams.numOfDistinctionUnits = p_SchemeParams->netEnvParams.numOfDistinctionUnits;
1048 memcpy(netEnvParams.unitIds, p_SchemeParams->netEnvParams.unitIds, (sizeof(uint8_t))*p_SchemeParams->netEnvParams.numOfDistinctionUnits);
1049 err = PcdGetUnitsVector(p_FmPcd, &netEnvParams);
1050 if (err)
1051 RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
1052 p_Scheme->matchVector = netEnvParams.vector;
1053 }
1054 else
1055 {
1056 p_Scheme->matchVector = SCHEME_ALWAYS_DIRECT;
1057 p_Scheme->netEnvId = ILLEGAL_NETENV;
1058 }
1059
1060 if (p_SchemeParams->nextEngine == e_FM_PCD_INVALID)
1061 RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Next Engine of the scheme is not Valid"));
1062
1063 if (p_SchemeParams->bypassFqidGeneration)
1064 {
1065 #ifdef FM_KG_NO_BYPASS_FQID_GEN
1066 if ((p_FmPcd->fmRevInfo.majorRev != 4) && (p_FmPcd->fmRevInfo.majorRev < 6))
1067 RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("bypassFqidGeneration."));
1068 #endif /* FM_KG_NO_BYPASS_FQID_GEN */
1069 if (p_SchemeParams->baseFqid)
1070 RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("baseFqid set for a scheme that does not generate an FQID"));
1071 }
1072 else
1073 if (!p_SchemeParams->baseFqid)
1074 DBG(WARNING, ("baseFqid is 0."));
1075
1076 if (p_SchemeParams->nextEngine == e_FM_PCD_PLCR)
1077 {
1078 direct = p_SchemeParams->kgNextEngineParams.plcrProfile.direct;
1079 p_Scheme->directPlcr = direct;
1080 absolute = (bool)(p_SchemeParams->kgNextEngineParams.plcrProfile.sharedProfile ? TRUE : FALSE);
1081 if (!direct && absolute)
1082 RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Indirect policing is not available when profile is shared."));
1083
1084 if (direct)
1085 {
1086 profileId = p_SchemeParams->kgNextEngineParams.plcrProfile.profileSelect.directRelativeProfileId;
1087 numOfProfiles = 1;
1088 }
1089 else
1090 {
1091 profileId = p_SchemeParams->kgNextEngineParams.plcrProfile.profileSelect.indirectProfile.fqidOffsetRelativeProfileIdBase;
1092 shift = p_SchemeParams->kgNextEngineParams.plcrProfile.profileSelect.indirectProfile.fqidOffsetShift;
1093 numOfProfiles = p_SchemeParams->kgNextEngineParams.plcrProfile.profileSelect.indirectProfile.numOfProfiles;
1094 }
1095 }
1096
1097 if (p_SchemeParams->nextEngine == e_FM_PCD_CC)
1098 {
1099 #ifdef FM_KG_NO_BYPASS_PLCR_PROFILE_GEN
1100 if ((p_SchemeParams->kgNextEngineParams.cc.plcrNext) && (p_SchemeParams->kgNextEngineParams.cc.bypassPlcrProfileGeneration))
1101 {
1102 if ((p_FmPcd->fmRevInfo.majorRev != 4) && (p_FmPcd->fmRevInfo.majorRev < 6))
1103 RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("bypassPlcrProfileGeneration."));
1104 }
1105 #endif /* FM_KG_NO_BYPASS_PLCR_PROFILE_GEN */
1106
1107 err = FmPcdCcGetGrpParams(p_SchemeParams->kgNextEngineParams.cc.h_CcTree,
1108 p_SchemeParams->kgNextEngineParams.cc.grpId,
1109 &grpBits,
1110 &grpBase);
1111 if (err)
1112 RETURN_ERROR(MAJOR, err, NO_MSG);
1113 p_Scheme->ccUnits = grpBits;
1114
1115 if ((p_SchemeParams->kgNextEngineParams.cc.plcrNext) &&
1116 (!p_SchemeParams->kgNextEngineParams.cc.bypassPlcrProfileGeneration))
1117 {
1118 if (p_SchemeParams->kgNextEngineParams.cc.plcrProfile.sharedProfile)
1119 RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Shared profile may not be used after Coarse classification."));
1120 absolute = FALSE;
1121 direct = p_SchemeParams->kgNextEngineParams.cc.plcrProfile.direct;
1122 if (direct)
1123 {
1124 profileId = p_SchemeParams->kgNextEngineParams.cc.plcrProfile.profileSelect.directRelativeProfileId;
1125 numOfProfiles = 1;
1126 }
1127 else
1128 {
1129 profileId = p_SchemeParams->kgNextEngineParams.cc.plcrProfile.profileSelect.indirectProfile.fqidOffsetRelativeProfileIdBase;
1130 shift = p_SchemeParams->kgNextEngineParams.cc.plcrProfile.profileSelect.indirectProfile.fqidOffsetShift;
1131 numOfProfiles = p_SchemeParams->kgNextEngineParams.cc.plcrProfile.profileSelect.indirectProfile.numOfProfiles;
1132 }
1133 }
1134 }
1135
1136 /* if policer is used directly after KG, or after CC */
1137 if ((p_SchemeParams->nextEngine == e_FM_PCD_PLCR) ||
1138 ((p_SchemeParams->nextEngine == e_FM_PCD_CC) &&
1139 (p_SchemeParams->kgNextEngineParams.cc.plcrNext) &&
1140 (!p_SchemeParams->kgNextEngineParams.cc.bypassPlcrProfileGeneration)))
1141 {
1142 /* if private policer profile, it may be uninitialized yet, therefore no checks are done at this stage */
1143 if (absolute)
1144 {
1145 /* for absolute direct policy only, */
1146 relativeProfileId = profileId;
1147 err = FmPcdPlcrGetAbsoluteIdByProfileParams((t_Handle)p_FmPcd,e_FM_PCD_PLCR_SHARED,NULL, relativeProfileId, &profileId);
1148 if (err)
1149 RETURN_ERROR(MAJOR, err, ("Shared profile not valid offset"));
1150 if (!FmPcdPlcrIsProfileValid(p_FmPcd, profileId))
1151 RETURN_ERROR(MINOR, E_INVALID_STATE, ("Shared profile not valid."));
1152 p_Scheme->relativeProfileId = profileId;
1153 }
1154 else
1155 {
1156 /* save relative profile id's for later check */
1157 p_Scheme->nextRelativePlcrProfile = TRUE;
1158 p_Scheme->relativeProfileId = profileId;
1159 p_Scheme->numOfProfiles = numOfProfiles;
1160 }
1161 }
1162 else
1163 {
1164 /* if policer is NOT going to be used after KG at all than if bypassFqidGeneration
1165 is set, we do not need numOfUsedExtractedOrs and hashDistributionNumOfFqids */
1166 if (p_SchemeParams->bypassFqidGeneration && p_SchemeParams->numOfUsedExtractedOrs)
1167 RETURN_ERROR(MAJOR, E_INVALID_STATE,
1168 ("numOfUsedExtractedOrs is set in a scheme that does not generate FQID or policer profile ID"));
1169 if (p_SchemeParams->bypassFqidGeneration &&
1170 p_SchemeParams->useHash &&
1171 p_SchemeParams->keyExtractAndHashParams.hashDistributionNumOfFqids)
1172 RETURN_ERROR(MAJOR, E_INVALID_STATE,
1173 ("hashDistributionNumOfFqids is set in a scheme that does not generate FQID or policer profile ID"));
1174 }
1175
1176 /* configure all 21 scheme registers */
1177 tmpReg = KG_SCH_MODE_EN;
1178 switch (p_SchemeParams->nextEngine)
1179 {
1180 case (e_FM_PCD_PLCR):
1181 /* add to mode register - NIA */
1182 tmpReg |= KG_SCH_MODE_NIA_PLCR;
1183 tmpReg |= NIA_ENG_PLCR;
1184 tmpReg |= (uint32_t)(p_SchemeParams->kgNextEngineParams.plcrProfile.sharedProfile ? NIA_PLCR_ABSOLUTE:0);
1185 /* initialize policer profile command - */
1186 /* configure kgse_ppc */
1187 if (direct)
1188 /* use profileId as base, other fields are 0 */
1189 p_SchemeRegs->kgse_ppc = (uint32_t)profileId;
1190 else
1191 {
1192 if (shift > MAX_PP_SHIFT)
1193 RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fqidOffsetShift may not be larger than %d", MAX_PP_SHIFT));
1194
1195 if (!numOfProfiles || !POWER_OF_2(numOfProfiles))
1196 RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("numOfProfiles must not be 0 and must be a power of 2"));
1197
1198 ppcTmp = ((uint32_t)shift << KG_SCH_PP_SHIFT_HIGH_SHIFT) & KG_SCH_PP_SHIFT_HIGH;
1199 ppcTmp |= ((uint32_t)shift << KG_SCH_PP_SHIFT_LOW_SHIFT) & KG_SCH_PP_SHIFT_LOW;
1200 ppcTmp |= ((uint32_t)(numOfProfiles-1) << KG_SCH_PP_MASK_SHIFT);
1201 ppcTmp |= (uint32_t)profileId;
1202
1203 p_SchemeRegs->kgse_ppc = ppcTmp;
1204 }
1205 break;
1206 case (e_FM_PCD_CC):
1207 /* mode reg - define NIA */
1208 tmpReg |= (NIA_ENG_FM_CTL | NIA_FM_CTL_AC_CC);
1209
1210 p_SchemeRegs->kgse_ccbs = grpBits;
1211 tmpReg |= (uint32_t)(grpBase << KG_SCH_MODE_CCOBASE_SHIFT);
1212
1213 if (p_SchemeParams->kgNextEngineParams.cc.plcrNext)
1214 {
1215 if (!p_SchemeParams->kgNextEngineParams.cc.bypassPlcrProfileGeneration)
1216 {
1217 /* find out if absolute or relative */
1218 if (absolute)
1219 RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("It is illegal to request a shared profile in a scheme that is in a KG->CC->PLCR flow"));
1220 if (direct)
1221 {
1222 /* mask = 0, base = directProfileId */
1223 p_SchemeRegs->kgse_ppc = (uint32_t)profileId;
1224 }
1225 else
1226 {
1227 if (shift > MAX_PP_SHIFT)
1228 RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fqidOffsetShift may not be larger than %d", MAX_PP_SHIFT));
1229 if (!numOfProfiles || !POWER_OF_2(numOfProfiles))
1230 RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("numOfProfiles must not be 0 and must be a power of 2"));
1231
1232 ppcTmp = ((uint32_t)shift << KG_SCH_PP_SHIFT_HIGH_SHIFT) & KG_SCH_PP_SHIFT_HIGH;
1233 ppcTmp |= ((uint32_t)shift << KG_SCH_PP_SHIFT_LOW_SHIFT) & KG_SCH_PP_SHIFT_LOW;
1234 ppcTmp |= ((uint32_t)(numOfProfiles-1) << KG_SCH_PP_MASK_SHIFT);
1235 ppcTmp |= (uint32_t)profileId;
1236
1237 p_SchemeRegs->kgse_ppc = ppcTmp;
1238 }
1239 }
1240 }
1241 break;
1242 case (e_FM_PCD_DONE):
1243 if (p_SchemeParams->kgNextEngineParams.doneAction == e_FM_PCD_DROP_FRAME)
1244 tmpReg |= GET_NIA_BMI_AC_DISCARD_FRAME(p_FmPcd);
1245 else
1246 tmpReg |= GET_NIA_BMI_AC_ENQ_FRAME(p_FmPcd);
1247 break;
1248 default:
1249 RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Next engine not supported"));
1250 }
1251 p_SchemeRegs->kgse_mode = tmpReg;
1252
1253 p_SchemeRegs->kgse_mv = p_Scheme->matchVector;
1254
1255 #if (DPAA_VERSION >= 11)
1256 if (p_SchemeParams->overrideStorageProfile)
1257 {
1258 p_SchemeRegs->kgse_om |= KG_SCH_OM_VSPE;
1259
1260 if (p_SchemeParams->storageProfile.direct)
1261 {
1262 profileId = p_SchemeParams->storageProfile.profileSelect.directRelativeProfileId;
1263 shift = 0;
1264 numOfProfiles = 1;
1265 }
1266 else
1267 {
1268 profileId = p_SchemeParams->storageProfile.profileSelect.indirectProfile.fqidOffsetRelativeProfileIdBase;
1269 shift = p_SchemeParams->storageProfile.profileSelect.indirectProfile.fqidOffsetShift;
1270 numOfProfiles = p_SchemeParams->storageProfile.profileSelect.indirectProfile.numOfProfiles;
1271 }
1272 if (shift > MAX_SP_SHIFT)
1273 RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fqidOffsetShift may not be larger than %d", MAX_SP_SHIFT));
1274
1275 if (!numOfProfiles || !POWER_OF_2(numOfProfiles))
1276 RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("numOfProfiles must not be 0 and must be a power of 2"));
1277
1278 tmpReg = (uint32_t)shift << KG_SCH_VSP_SHIFT;
1279 tmpReg |= ((uint32_t)(numOfProfiles-1) << KG_SCH_VSP_MASK_SHIFT);
1280 tmpReg |= (uint32_t)profileId;
1281
1282
1283 p_SchemeRegs->kgse_vsp = tmpReg;
1284
1285 p_Scheme->vspe = TRUE;
1286
1287 }
1288 else
1289 p_SchemeRegs->kgse_vsp = KG_SCH_VSP_NO_KSP_EN;
1290 #endif /* (DPAA_VERSION >= 11) */
1291
1292 if (p_SchemeParams->useHash)
1293 {
1294 p_KeyAndHash = &p_SchemeParams->keyExtractAndHashParams;
1295
1296 if (p_KeyAndHash->numOfUsedExtracts >= FM_PCD_KG_MAX_NUM_OF_EXTRACTS_PER_KEY)
1297 RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("numOfUsedExtracts out of range"));
1298
1299 /* configure kgse_dv0 */
1300 p_SchemeRegs->kgse_dv0 = p_KeyAndHash->privateDflt0;
1301
1302 /* configure kgse_dv1 */
1303 p_SchemeRegs->kgse_dv1 = p_KeyAndHash->privateDflt1;
1304
1305 if (!p_SchemeParams->bypassFqidGeneration)
1306 {
1307 if (!p_KeyAndHash->hashDistributionNumOfFqids || !POWER_OF_2(p_KeyAndHash->hashDistributionNumOfFqids))
1308 RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("hashDistributionNumOfFqids must not be 0 and must be a power of 2"));
1309 if ((p_KeyAndHash->hashDistributionNumOfFqids-1) & p_SchemeParams->baseFqid)
1310 DBG(WARNING, ("baseFqid unaligned. Distribution may result in less than hashDistributionNumOfFqids queues."));
1311 }
1312
1313 /* configure kgse_ekdv */
1314 tmpReg = 0;
1315 for ( i=0 ;i<p_KeyAndHash->numOfUsedDflts ; i++)
1316 {
1317 switch (p_KeyAndHash->dflts[i].type)
1318 {
1319 case (e_FM_PCD_KG_MAC_ADDR):
1320 tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_MAC_ADDR_SHIFT);
1321 break;
1322 case (e_FM_PCD_KG_TCI):
1323 tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_TCI_SHIFT);
1324 break;
1325 case (e_FM_PCD_KG_ENET_TYPE):
1326 tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_ENET_TYPE_SHIFT);
1327 break;
1328 case (e_FM_PCD_KG_PPP_SESSION_ID):
1329 tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_PPP_SESSION_ID_SHIFT);
1330 break;
1331 case (e_FM_PCD_KG_PPP_PROTOCOL_ID):
1332 tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_PPP_PROTOCOL_ID_SHIFT);
1333 break;
1334 case (e_FM_PCD_KG_MPLS_LABEL):
1335 tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_MPLS_LABEL_SHIFT);
1336 break;
1337 case (e_FM_PCD_KG_IP_ADDR):
1338 tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_IP_ADDR_SHIFT);
1339 break;
1340 case (e_FM_PCD_KG_PROTOCOL_TYPE):
1341 tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_PROTOCOL_TYPE_SHIFT);
1342 break;
1343 case (e_FM_PCD_KG_IP_TOS_TC):
1344 tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_IP_TOS_TC_SHIFT);
1345 break;
1346 case (e_FM_PCD_KG_IPV6_FLOW_LABEL):
1347 tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_L4_PORT_SHIFT);
1348 break;
1349 case (e_FM_PCD_KG_IPSEC_SPI):
1350 tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_IPSEC_SPI_SHIFT);
1351 break;
1352 case (e_FM_PCD_KG_L4_PORT):
1353 tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_L4_PORT_SHIFT);
1354 break;
1355 case (e_FM_PCD_KG_TCP_FLAG):
1356 tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_TCP_FLAG_SHIFT);
1357 break;
1358 case (e_FM_PCD_KG_GENERIC_FROM_DATA):
1359 swDefaults[numOfSwDefaults].type = e_FM_PCD_KG_GENERIC_FROM_DATA;
1360 swDefaults[numOfSwDefaults].dfltSelect = p_KeyAndHash->dflts[i].dfltSelect;
1361 numOfSwDefaults ++;
1362 break;
1363 case (e_FM_PCD_KG_GENERIC_FROM_DATA_NO_V):
1364 swDefaults[numOfSwDefaults].type = e_FM_PCD_KG_GENERIC_FROM_DATA_NO_V;
1365 swDefaults[numOfSwDefaults].dfltSelect = p_KeyAndHash->dflts[i].dfltSelect;
1366 numOfSwDefaults ++;
1367 break;
1368 case (e_FM_PCD_KG_GENERIC_NOT_FROM_DATA):
1369 swDefaults[numOfSwDefaults].type = e_FM_PCD_KG_GENERIC_NOT_FROM_DATA;
1370 swDefaults[numOfSwDefaults].dfltSelect = p_KeyAndHash->dflts[i].dfltSelect;
1371 numOfSwDefaults ++;
1372 break;
1373 default:
1374 RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);
1375 }
1376 }
1377 p_SchemeRegs->kgse_ekdv = tmpReg;
1378
1379 p_LocalExtractsArray = (t_FmPcdKgSchemesExtracts *)XX_Malloc(sizeof(t_FmPcdKgSchemesExtracts));
1380 if (!p_LocalExtractsArray)
1381 RETURN_ERROR(MAJOR, E_NO_MEMORY, ("No memory"));
1382
1383 /* configure kgse_ekfc and kgse_gec */
1384 knownTmp = 0;
1385 for ( i=0 ;i<p_KeyAndHash->numOfUsedExtracts ; i++)
1386 {
1387 p_Extract = &p_KeyAndHash->extractArray[i];
1388 switch (p_Extract->type)
1389 {
1390 case (e_FM_PCD_KG_EXTRACT_PORT_PRIVATE_INFO):
1391 knownTmp |= KG_SCH_KN_PORT_ID;
1392 /* save in driver structure */
1393 p_LocalExtractsArray->extractsArray[i].id = GetKnownFieldId(KG_SCH_KN_PORT_ID);
1394 p_LocalExtractsArray->extractsArray[i].known = TRUE;
1395 break;
1396 case (e_FM_PCD_EXTRACT_BY_HDR):
1397 switch (p_Extract->extractByHdr.hdr)
1398 {
1399 #if (DPAA_VERSION >= 11) || ((DPAA_VERSION == 10) && defined(FM_CAPWAP_SUPPORT))
1400 case (HEADER_TYPE_UDP_LITE):
1401 p_Extract->extractByHdr.hdr = HEADER_TYPE_UDP;
1402 break;
1403 #endif /* (DPAA_VERSION >= 11) || ((DPAA_VERSION == 10) && defined(FM_CAPWAP_SUPPORT)) */
1404 case (HEADER_TYPE_UDP_ENCAP_ESP):
1405 switch (p_Extract->extractByHdr.type)
1406 {
1407 case (e_FM_PCD_EXTRACT_FROM_HDR):
1408 /* case where extraction from ESP only */
1409 if (p_Extract->extractByHdr.extractByHdrType.fromHdr.offset >= UDP_HEADER_SIZE)
1410 {
1411 p_Extract->extractByHdr.hdr = FmPcdGetAliasHdr(p_FmPcd, p_Scheme->netEnvId, HEADER_TYPE_UDP_ENCAP_ESP);
1412 p_Extract->extractByHdr.extractByHdrType.fromHdr.offset -= UDP_HEADER_SIZE;
1413 p_Extract->extractByHdr.ignoreProtocolValidation = TRUE;
1414 }
1415 else
1416 {
1417 p_Extract->extractByHdr.hdr = HEADER_TYPE_UDP;
1418 p_Extract->extractByHdr.ignoreProtocolValidation = FALSE;
1419 }
1420 break;
1421 case (e_FM_PCD_EXTRACT_FROM_FIELD):
1422 switch (p_Extract->extractByHdr.extractByHdrType.fromField.field.udpEncapEsp)
1423 {
1424 case (NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_SRC):
1425 case (NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_DST):
1426 case (NET_HEADER_FIELD_UDP_ENCAP_ESP_LEN):
1427 case (NET_HEADER_FIELD_UDP_ENCAP_ESP_CKSUM):
1428 p_Extract->extractByHdr.hdr = HEADER_TYPE_UDP;
1429 break;
1430 case (NET_HEADER_FIELD_UDP_ENCAP_ESP_SPI):
1431 p_Extract->extractByHdr.type = e_FM_PCD_EXTRACT_FROM_HDR;
1432 p_Extract->extractByHdr.hdr = FmPcdGetAliasHdr(p_FmPcd, p_Scheme->netEnvId, HEADER_TYPE_UDP_ENCAP_ESP);
1433 /*p_Extract->extractByHdr.extractByHdrType.fromField.offset += ESP_SPI_OFFSET;*/
1434 p_Extract->extractByHdr.ignoreProtocolValidation = TRUE;
1435 break;
1436 case (NET_HEADER_FIELD_UDP_ENCAP_ESP_SEQUENCE_NUM):
1437 p_Extract->extractByHdr.type = e_FM_PCD_EXTRACT_FROM_HDR;
1438 p_Extract->extractByHdr.hdr = FmPcdGetAliasHdr(p_FmPcd, p_Scheme->netEnvId, HEADER_TYPE_UDP_ENCAP_ESP);
1439 p_Extract->extractByHdr.extractByHdrType.fromField.offset += ESP_SEQ_NUM_OFFSET;
1440 p_Extract->extractByHdr.ignoreProtocolValidation = TRUE;
1441 break;
1442 }
1443 break;
1444 case (e_FM_PCD_EXTRACT_FULL_FIELD):
1445 switch (p_Extract->extractByHdr.extractByHdrType.fullField.udpEncapEsp)
1446 {
1447 case (NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_SRC):
1448 case (NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_DST):
1449 case (NET_HEADER_FIELD_UDP_ENCAP_ESP_LEN):
1450 case (NET_HEADER_FIELD_UDP_ENCAP_ESP_CKSUM):
1451 p_Extract->extractByHdr.hdr = HEADER_TYPE_UDP;
1452 break;
1453 case (NET_HEADER_FIELD_UDP_ENCAP_ESP_SPI):
1454 p_Extract->extractByHdr.type = e_FM_PCD_EXTRACT_FROM_HDR;
1455 p_Extract->extractByHdr.hdr = FmPcdGetAliasHdr(p_FmPcd, p_Scheme->netEnvId, HEADER_TYPE_UDP_ENCAP_ESP);
1456 p_Extract->extractByHdr.extractByHdrType.fromHdr.size = ESP_SPI_SIZE;
1457 p_Extract->extractByHdr.extractByHdrType.fromHdr.offset = ESP_SPI_OFFSET;
1458 p_Extract->extractByHdr.ignoreProtocolValidation = TRUE;
1459 break;
1460 case (NET_HEADER_FIELD_UDP_ENCAP_ESP_SEQUENCE_NUM):
1461 p_Extract->extractByHdr.type = e_FM_PCD_EXTRACT_FROM_HDR;
1462 p_Extract->extractByHdr.hdr = FmPcdGetAliasHdr(p_FmPcd, p_Scheme->netEnvId, HEADER_TYPE_UDP_ENCAP_ESP);
1463 p_Extract->extractByHdr.extractByHdrType.fromHdr.size = ESP_SEQ_NUM_SIZE;
1464 p_Extract->extractByHdr.extractByHdrType.fromHdr.offset = ESP_SEQ_NUM_OFFSET;
1465 p_Extract->extractByHdr.ignoreProtocolValidation = TRUE;
1466 break;
1467 }
1468 break;
1469 }
1470 break;
1471 default:
1472 break;
1473 }
1474 switch (p_Extract->extractByHdr.type)
1475 {
1476 case (e_FM_PCD_EXTRACT_FROM_HDR):
1477 generic = TRUE;
1478 /* get the header code for the generic extract */
1479 code = GetGenHdrCode(p_Extract->extractByHdr.hdr, p_Extract->extractByHdr.hdrIndex, p_Extract->extractByHdr.ignoreProtocolValidation);
1480 /* set generic register fields */
1481 offset = p_Extract->extractByHdr.extractByHdrType.fromHdr.offset;
1482 size = p_Extract->extractByHdr.extractByHdrType.fromHdr.size;
1483 break;
1484 case (e_FM_PCD_EXTRACT_FROM_FIELD):
1485 generic = TRUE;
1486 /* get the field code for the generic extract */
1487 code = GetGenFieldCode(p_Extract->extractByHdr.hdr,
1488 p_Extract->extractByHdr.extractByHdrType.fromField.field, p_Extract->extractByHdr.ignoreProtocolValidation,p_Extract->extractByHdr.hdrIndex);
1489 offset = p_Extract->extractByHdr.extractByHdrType.fromField.offset;
1490 size = p_Extract->extractByHdr.extractByHdrType.fromField.size;
1491 break;
1492 case (e_FM_PCD_EXTRACT_FULL_FIELD):
1493 if (!p_Extract->extractByHdr.ignoreProtocolValidation)
1494 {
1495 /* if we have a known field for it - use it, otherwise use generic */
1496 bitMask = GetKnownProtMask(p_FmPcd, p_Extract->extractByHdr.hdr, p_Extract->extractByHdr.hdrIndex,
1497 p_Extract->extractByHdr.extractByHdrType.fullField);
1498 if (bitMask)
1499 {
1500 knownTmp |= bitMask;
1501 /* save in driver structure */
1502 p_LocalExtractsArray->extractsArray[i].id = GetKnownFieldId(bitMask);
1503 p_LocalExtractsArray->extractsArray[i].known = TRUE;
1504 }
1505 else
1506 generic = TRUE;
1507 }
1508 else
1509 generic = TRUE;
1510 if (generic)
1511 {
1512 /* tmp - till we cover more headers under generic */
1513 XX_Free(p_LocalExtractsArray);
1514 RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Full header selection not supported"));
1515 }
1516 break;
1517 default:
1518 XX_Free(p_LocalExtractsArray);
1519 RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);
1520 }
1521 break;
1522 case (e_FM_PCD_EXTRACT_NON_HDR):
1523 /* use generic */
1524 generic = TRUE;
1525 offset = 0;
1526 /* get the field code for the generic extract */
1527 code = GetGenCode(p_Extract->extractNonHdr.src, &offset);
1528 offset += p_Extract->extractNonHdr.offset;
1529 size = p_Extract->extractNonHdr.size;
1530 break;
1531 default:
1532 RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);
1533 }
1534
1535 if (generic)
1536 {
1537 /* set generic register fields */
1538 if (currGenId >= FM_KG_NUM_OF_GENERIC_REGS)
1539 {
1540 XX_Free(p_LocalExtractsArray);
1541 RETURN_ERROR(MAJOR, E_FULL, ("Generic registers are fully used"));
1542 }
1543 if (!code)
1544 {
1545 XX_Free(p_LocalExtractsArray);
1546 RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, NO_MSG);
1547 }
1548
1549 genTmp = KG_SCH_GEN_VALID;
1550 genTmp |= (uint32_t)(code << KG_SCH_GEN_HT_SHIFT);
1551 genTmp |= offset;
1552 if ((size > MAX_KG_SCH_SIZE) || (size < 1))
1553 {
1554 XX_Free(p_LocalExtractsArray);
1555 RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal extraction (size out of range)"));
1556 }
1557 genTmp |= (uint32_t)((size - 1) << KG_SCH_GEN_SIZE_SHIFT);
1558 swDefault = GetGenericSwDefault(swDefaults, numOfSwDefaults, code);
1559 if (swDefault == e_FM_PCD_KG_DFLT_ILLEGAL)
1560 DBG(WARNING, ("No sw default configured"));
1561 else
1562 genTmp |= swDefault << KG_SCH_GEN_DEF_SHIFT;
1563
1564 genTmp |= KG_SCH_GEN_MASK;
1565 p_SchemeRegs->kgse_gec[currGenId] = genTmp;
1566 /* save in driver structure */
1567 p_LocalExtractsArray->extractsArray[i].id = currGenId++;
1568 p_LocalExtractsArray->extractsArray[i].known = FALSE;
1569 generic = FALSE;
1570 }
1571 }
1572 p_SchemeRegs->kgse_ekfc = knownTmp;
1573
1574 selectTmp = 0;
1575 maskTmp = 0xFFFFFFFF;
1576 /* configure kgse_bmch, kgse_bmcl and kgse_fqb */
1577
1578 if (p_KeyAndHash->numOfUsedMasks > FM_PCD_KG_NUM_OF_EXTRACT_MASKS)
1579 {
1580 XX_Free(p_LocalExtractsArray);
1581 RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Only %d masks supported", FM_PCD_KG_NUM_OF_EXTRACT_MASKS));
1582 }
1583 for ( i=0 ;i<p_KeyAndHash->numOfUsedMasks ; i++)
1584 {
1585 /* Get the relative id of the extract (for known 0-0x1f, for generic 0-7) */
1586 id = p_LocalExtractsArray->extractsArray[p_KeyAndHash->masks[i].extractArrayIndex].id;
1587 /* Get the shift of the select field (depending on i) */
1588 GET_MASK_SEL_SHIFT(shift,i);
1589 if (p_LocalExtractsArray->extractsArray[p_KeyAndHash->masks[i].extractArrayIndex].known)
1590 selectTmp |= id << shift;
1591 else
1592 selectTmp |= (id + MASK_FOR_GENERIC_BASE_ID) << shift;
1593
1594 /* Get the shift of the offset field (depending on i) - may
1595 be in kgse_bmch or in kgse_fqb (depending on i) */
1596 GET_MASK_OFFSET_SHIFT(shift,i);
1597 if (i<=1)
1598 selectTmp |= p_KeyAndHash->masks[i].offset << shift;
1599 else
1600 fqbTmp |= p_KeyAndHash->masks[i].offset << shift;
1601
1602 /* Get the shift of the mask field (depending on i) */
1603 GET_MASK_SHIFT(shift,i);
1604 /* pass all bits */
1605 maskTmp |= KG_SCH_BITMASK_MASK << shift;
1606 /* clear bits that need masking */
1607 maskTmp &= ~(0xFF << shift) ;
1608 /* set mask bits */
1609 maskTmp |= (p_KeyAndHash->masks[i].mask << shift) ;
1610 }
1611 p_SchemeRegs->kgse_bmch = selectTmp;
1612 p_SchemeRegs->kgse_bmcl = maskTmp;
1613 /* kgse_fqb will be written t the end of the routine */
1614
1615 /* configure kgse_hc */
1616 if (p_KeyAndHash->hashShift > MAX_HASH_SHIFT)
1617 {
1618 XX_Free(p_LocalExtractsArray);
1619 RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("hashShift must not be larger than %d", MAX_HASH_SHIFT));
1620 }
1621 if (p_KeyAndHash->hashDistributionFqidsShift > MAX_DIST_FQID_SHIFT)
1622 {
1623 XX_Free(p_LocalExtractsArray);
1624 RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("hashDistributionFqidsShift must not be larger than %d", MAX_DIST_FQID_SHIFT));
1625 }
1626
1627 tmpReg = 0;
1628
1629 tmpReg |= ((p_KeyAndHash->hashDistributionNumOfFqids - 1) << p_KeyAndHash->hashDistributionFqidsShift);
1630 tmpReg |= p_KeyAndHash->hashShift << KG_SCH_HASH_CONFIG_SHIFT_SHIFT;
1631
1632 if (p_KeyAndHash->symmetricHash)
1633 {
1634 if ((!!(p_SchemeRegs->kgse_ekfc & KG_SCH_KN_MACSRC) != !!(p_SchemeRegs->kgse_ekfc & KG_SCH_KN_MACDST)) ||
1635 (!!(p_SchemeRegs->kgse_ekfc & KG_SCH_KN_IPSRC1) != !!(p_SchemeRegs->kgse_ekfc & KG_SCH_KN_IPDST1)) ||
1636 (!!(p_SchemeRegs->kgse_ekfc & KG_SCH_KN_IPSRC2) != !!(p_SchemeRegs->kgse_ekfc & KG_SCH_KN_IPDST2)) ||
1637 (!!(p_SchemeRegs->kgse_ekfc & KG_SCH_KN_L4PSRC) != !!(p_SchemeRegs->kgse_ekfc & KG_SCH_KN_L4PDST)))
1638 {
1639 XX_Free(p_LocalExtractsArray);
1640 RETURN_ERROR(MAJOR, E_INVALID_STATE, ("symmetricHash set but src/dest extractions missing"));
1641 }
1642 tmpReg |= KG_SCH_HASH_CONFIG_SYM;
1643 }
1644 p_SchemeRegs->kgse_hc = tmpReg;
1645
1646 /* build the return array describing the order of the extractions */
1647
1648 /* the last currGenId places of the array
1649 are for generic extracts that are always last.
1650 We now sort for the calculation of the order of the known
1651 extractions we sort the known extracts between orderedArray[0] and
1652 orderedArray[p_KeyAndHash->numOfUsedExtracts - currGenId - 1].
1653 for the calculation of the order of the generic extractions we use:
1654 num_of_generic - currGenId
1655 num_of_known - p_KeyAndHash->numOfUsedExtracts - currGenId
1656 first_generic_index = num_of_known */
1657 curr = 0;
1658 for (i=0;i<p_KeyAndHash->numOfUsedExtracts ; i++)
1659 {
1660 if (p_LocalExtractsArray->extractsArray[i].known)
1661 {
1662 ASSERT_COND(curr<(p_KeyAndHash->numOfUsedExtracts - currGenId));
1663 j = curr;
1664 /* id is the extract id (port id = 0, mac src = 1 etc.). the value in the array is the original
1665 index in the user's extractions array */
1666 /* we compare the id of the current extract with the id of the extract in the orderedArray[j-1]
1667 location */
1668 while ((j > 0) && (p_LocalExtractsArray->extractsArray[i].id <
1669 p_LocalExtractsArray->extractsArray[p_Scheme->orderedArray[j-1]].id))
1670 {
1671 p_Scheme->orderedArray[j] =
1672 p_Scheme->orderedArray[j-1];
1673 j--;
1674 }
1675 p_Scheme->orderedArray[j] = (uint8_t)i;
1676 curr++;
1677 }
1678 else
1679 {
1680 /* index is first_generic_index + generic index (id) */
1681 idx = (uint8_t)(p_KeyAndHash->numOfUsedExtracts - currGenId + p_LocalExtractsArray->extractsArray[i].id);
1682 ASSERT_COND(idx < FM_PCD_KG_MAX_NUM_OF_EXTRACTS_PER_KEY);
1683 p_Scheme->orderedArray[idx]= (uint8_t)i;
1684 }
1685 }
1686 XX_Free(p_LocalExtractsArray);
1687 }
1688 else
1689 {
1690 /* clear all unused registers: */
1691 p_SchemeRegs->kgse_ekfc = 0;
1692 p_SchemeRegs->kgse_ekdv = 0;
1693 p_SchemeRegs->kgse_bmch = 0;
1694 p_SchemeRegs->kgse_bmcl = 0;
1695 p_SchemeRegs->kgse_hc = 0;
1696 p_SchemeRegs->kgse_dv0 = 0;
1697 p_SchemeRegs->kgse_dv1 = 0;
1698 }
1699
1700 if (p_SchemeParams->bypassFqidGeneration)
1701 p_SchemeRegs->kgse_hc |= KG_SCH_HASH_CONFIG_NO_FQID;
1702
1703 /* configure kgse_spc */
1704 if ( p_SchemeParams->schemeCounter.update)
1705 p_SchemeRegs->kgse_spc = p_SchemeParams->schemeCounter.value;
1706
1707
1708 /* check that are enough generic registers */
1709 if (p_SchemeParams->numOfUsedExtractedOrs + currGenId > FM_KG_NUM_OF_GENERIC_REGS)
1710 RETURN_ERROR(MAJOR, E_FULL, ("Generic registers are fully used"));
1711
1712 /* extracted OR mask on Qid */
1713 for ( i=0 ;i<p_SchemeParams->numOfUsedExtractedOrs ; i++)
1714 {
1715
1716 p_Scheme->extractedOrs = TRUE;
1717 /* configure kgse_gec[i] */
1718 p_ExtractOr = &p_SchemeParams->extractedOrs[i];
1719 switch (p_ExtractOr->type)
1720 {
1721 case (e_FM_PCD_KG_EXTRACT_PORT_PRIVATE_INFO):
1722 code = KG_SCH_GEN_PARSE_RESULT_N_FQID;
1723 offset = 0;
1724 break;
1725 case (e_FM_PCD_EXTRACT_BY_HDR):
1726 /* get the header code for the generic extract */
1727 code = GetGenHdrCode(p_ExtractOr->extractByHdr.hdr, p_ExtractOr->extractByHdr.hdrIndex, p_ExtractOr->extractByHdr.ignoreProtocolValidation);
1728 /* set generic register fields */
1729 offset = p_ExtractOr->extractionOffset;
1730 break;
1731 case (e_FM_PCD_EXTRACT_NON_HDR):
1732 /* get the field code for the generic extract */
1733 offset = 0;
1734 code = GetGenCode(p_ExtractOr->src, &offset);
1735 offset += p_ExtractOr->extractionOffset;
1736 break;
1737 default:
1738 RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);
1739 }
1740
1741 /* set generic register fields */
1742 if (!code)
1743 RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, NO_MSG);
1744 genTmp = KG_SCH_GEN_EXTRACT_TYPE | KG_SCH_GEN_VALID;
1745 genTmp |= (uint32_t)(code << KG_SCH_GEN_HT_SHIFT);
1746 genTmp |= offset;
1747 if (!!p_ExtractOr->bitOffsetInFqid == !!p_ExtractOr->bitOffsetInPlcrProfile)
1748 RETURN_ERROR(MAJOR, E_INVALID_VALUE, (" extracted byte must effect either FQID or Policer profile"));
1749
1750 /************************************************************************************
1751 bitOffsetInFqid and bitOffsetInPolicerProfile are translated to rotate parameter
1752 in the following way:
1753
1754 Driver API and implementation:
1755 ==============================
1756 FQID: extracted OR byte may be shifted right 1-31 bits to effect parts of the FQID.
1757 if shifted less than 8 bits, or more than 24 bits a mask is set on the bits that
1758 are not overlapping FQID.
1759 ------------------------
1760 | FQID (24) |
1761 ------------------------
1762 --------
1763 | | extracted OR byte
1764 --------
1765
1766 Policer Profile: extracted OR byte may be shifted right 1-15 bits to effect parts of the
1767 PP id. Unless shifted exactly 8 bits to overlap the PP id, a mask is set on the bits that
1768 are not overlapping PP id.
1769
1770 --------
1771 | PP (8) |
1772 --------
1773 --------
1774 | | extracted OR byte
1775 --------
1776
1777 HW implementation
1778 =================
1779 FQID and PP construct a 32 bit word in the way describe below. Extracted byte is located
1780 as the highest byte of that word and may be rotated to effect any part os the FQID or
1781 the PP.
1782 ------------------------ --------
1783 | FQID (24) || PP (8) |
1784 ------------------------ --------
1785 --------
1786 | | extracted OR byte
1787 --------
1788
1789 ************************************************************************************/
1790
1791 if (p_ExtractOr->bitOffsetInFqid)
1792 {
1793 if (p_ExtractOr->bitOffsetInFqid > MAX_KG_SCH_FQID_BIT_OFFSET )
1794 RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal extraction (bitOffsetInFqid out of range)"));
1795 if (p_ExtractOr->bitOffsetInFqid<8)
1796 genTmp |= (uint32_t)((p_ExtractOr->bitOffsetInFqid+24) << KG_SCH_GEN_SIZE_SHIFT);
1797 else
1798 genTmp |= (uint32_t)((p_ExtractOr->bitOffsetInFqid-8) << KG_SCH_GEN_SIZE_SHIFT);
1799 p_ExtractOr->mask &= GetExtractedOrMask(p_ExtractOr->bitOffsetInFqid, TRUE);
1800 }
1801 else /* effect policer profile */
1802 {
1803 if (p_ExtractOr->bitOffsetInPlcrProfile > MAX_KG_SCH_PP_BIT_OFFSET )
1804 RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal extraction (bitOffsetInPlcrProfile out of range)"));
1805 p_Scheme->bitOffsetInPlcrProfile = p_ExtractOr->bitOffsetInPlcrProfile;
1806 genTmp |= (uint32_t)((p_ExtractOr->bitOffsetInPlcrProfile+16) << KG_SCH_GEN_SIZE_SHIFT);
1807 p_ExtractOr->mask &= GetExtractedOrMask(p_ExtractOr->bitOffsetInPlcrProfile, FALSE);
1808 }
1809
1810 genTmp |= (uint32_t)(p_ExtractOr->extractionOffset << KG_SCH_GEN_DEF_SHIFT);
1811 /* clear bits that need masking */
1812 genTmp &= ~KG_SCH_GEN_MASK ;
1813 /* set mask bits */
1814 genTmp |= (uint32_t)(p_ExtractOr->mask << KG_SCH_GEN_MASK_SHIFT);
1815 p_SchemeRegs->kgse_gec[currGenId++] = genTmp;
1816
1817 }
1818 /* clear all unused GEC registers */
1819 for ( i=currGenId ;i<FM_KG_NUM_OF_GENERIC_REGS ; i++)
1820 p_SchemeRegs->kgse_gec[i] = 0;
1821
1822 /* add base Qid for this scheme */
1823 /* add configuration for kgse_fqb */
1824 if (p_SchemeParams->baseFqid & ~0x00FFFFFF)
1825 RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("baseFqid must be between 1 and 2^24-1"));
1826
1827 fqbTmp |= p_SchemeParams->baseFqid;
1828 p_SchemeRegs->kgse_fqb = fqbTmp;
1829
1830 p_Scheme->nextEngine = p_SchemeParams->nextEngine;
1831 p_Scheme->doneAction = p_SchemeParams->kgNextEngineParams.doneAction;
1832
1833 return E_OK;
1834 }
1835
1836
1837 /*****************************************************************************/
1838 /* Inter-module API routines */
1839 /*****************************************************************************/
1840
FmPcdKgBuildClsPlanGrp(t_Handle h_FmPcd,t_FmPcdKgInterModuleClsPlanGrpParams * p_Grp,t_FmPcdKgInterModuleClsPlanSet * p_ClsPlanSet)1841 t_Error FmPcdKgBuildClsPlanGrp(t_Handle h_FmPcd, t_FmPcdKgInterModuleClsPlanGrpParams *p_Grp, t_FmPcdKgInterModuleClsPlanSet *p_ClsPlanSet)
1842 {
1843 t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
1844 t_FmPcdKgClsPlanGrp *p_ClsPlanGrp;
1845 t_FmPcdIpcKgClsPlanParams kgAlloc;
1846 t_Error err = E_OK;
1847 uint32_t oredVectors = 0;
1848 int i, j;
1849
1850 /* this routine is protected by the calling routine ! */
1851 if (p_Grp->numOfOptions >= FM_PCD_MAX_NUM_OF_OPTIONS(FM_PCD_MAX_NUM_OF_CLS_PLANS))
1852 RETURN_ERROR(MAJOR, E_INVALID_VALUE,("Too many classification plan basic options selected."));
1853
1854 /* find a new clsPlan group */
1855 for (i = 0; i < FM_MAX_NUM_OF_PORTS; i++)
1856 if (!p_FmPcd->p_FmPcdKg->clsPlanGrps[i].used)
1857 break;
1858 if (i == FM_MAX_NUM_OF_PORTS)
1859 RETURN_ERROR(MAJOR, E_FULL,("No classification plan groups available."));
1860
1861 p_FmPcd->p_FmPcdKg->clsPlanGrps[i].used = TRUE;
1862
1863 p_Grp->clsPlanGrpId = (uint8_t)i;
1864
1865 if (p_Grp->numOfOptions == 0)
1866 p_FmPcd->p_FmPcdKg->emptyClsPlanGrpId = (uint8_t)i;
1867
1868 p_ClsPlanGrp = &p_FmPcd->p_FmPcdKg->clsPlanGrps[i];
1869 p_ClsPlanGrp->netEnvId = p_Grp->netEnvId;
1870 p_ClsPlanGrp->owners = 0;
1871 FmPcdSetClsPlanGrpId(p_FmPcd, p_Grp->netEnvId, p_Grp->clsPlanGrpId);
1872 if (p_Grp->numOfOptions != 0)
1873 FmPcdIncNetEnvOwners(p_FmPcd, p_Grp->netEnvId);
1874
1875 p_ClsPlanGrp->sizeOfGrp = (uint16_t)(1 << p_Grp->numOfOptions);
1876 /* a minimal group of 8 is required */
1877 if (p_ClsPlanGrp->sizeOfGrp < CLS_PLAN_NUM_PER_GRP)
1878 p_ClsPlanGrp->sizeOfGrp = CLS_PLAN_NUM_PER_GRP;
1879 if (p_FmPcd->guestId == NCSW_MASTER_ID)
1880 {
1881 err = KgAllocClsPlanEntries(h_FmPcd, p_ClsPlanGrp->sizeOfGrp, p_FmPcd->guestId, &p_ClsPlanGrp->baseEntry);
1882
1883 if (err)
1884 RETURN_ERROR(MINOR, E_INVALID_STATE, NO_MSG);
1885 }
1886 else
1887 {
1888 t_FmPcdIpcMsg msg;
1889 uint32_t replyLength;
1890 t_FmPcdIpcReply reply;
1891
1892 /* in GUEST_PARTITION, we use the IPC, to also set a private driver group if required */
1893 memset(&reply, 0, sizeof(reply));
1894 memset(&msg, 0, sizeof(msg));
1895 memset(&kgAlloc, 0, sizeof(kgAlloc));
1896 kgAlloc.guestId = p_FmPcd->guestId;
1897 kgAlloc.numOfClsPlanEntries = p_ClsPlanGrp->sizeOfGrp;
1898 msg.msgId = FM_PCD_ALLOC_KG_CLSPLAN;
1899 memcpy(msg.msgBody, &kgAlloc, sizeof(kgAlloc));
1900 replyLength = (sizeof(uint32_t) + sizeof(p_ClsPlanGrp->baseEntry));
1901 if ((err = XX_IpcSendMessage(p_FmPcd->h_IpcSession,
1902 (uint8_t*)&msg,
1903 sizeof(msg.msgId) + sizeof(kgAlloc),
1904 (uint8_t*)&reply,
1905 &replyLength,
1906 NULL,
1907 NULL)) != E_OK)
1908 RETURN_ERROR(MAJOR, err, NO_MSG);
1909
1910 if (replyLength != (sizeof(uint32_t) + sizeof(p_ClsPlanGrp->baseEntry)))
1911 RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
1912 if ((t_Error)reply.error != E_OK)
1913 RETURN_ERROR(MINOR, (t_Error)reply.error, NO_MSG);
1914
1915 p_ClsPlanGrp->baseEntry = *(uint8_t*)(reply.replyBody);
1916 }
1917
1918 /* build classification plan entries parameters */
1919 p_ClsPlanSet->baseEntry = p_ClsPlanGrp->baseEntry;
1920 p_ClsPlanSet->numOfClsPlanEntries = p_ClsPlanGrp->sizeOfGrp;
1921
1922 oredVectors = 0;
1923 for (i = 0; i<p_Grp->numOfOptions; i++)
1924 {
1925 oredVectors |= p_Grp->optVectors[i];
1926 /* save an array of used options - the indexes represent the power of 2 index */
1927 p_ClsPlanGrp->optArray[i] = p_Grp->options[i];
1928 }
1929 /* set the classification plan relevant entries so that all bits
1930 * relevant to the list of options is cleared
1931 */
1932 for (j = 0; j<p_ClsPlanGrp->sizeOfGrp; j++)
1933 p_ClsPlanSet->vectors[j] = ~oredVectors;
1934
1935 for (i = 0; i<p_Grp->numOfOptions; i++)
1936 {
1937 /* option i got the place 2^i in the clsPlan array. all entries that
1938 * have bit i set, should have the vector bit cleared. So each option
1939 * has one location that it is exclusive (1,2,4,8...) and represent the
1940 * presence of that option only, and other locations that represent a
1941 * combination of options.
1942 * e.g:
1943 * If ethernet-BC is option 1 it gets entry 2 in the table. Entry 2
1944 * now represents a frame with ethernet-BC header - so the bit
1945 * representing ethernet-BC should be set and all other option bits
1946 * should be cleared.
1947 * Entries 2,3,6,7,10... also have ethernet-BC and therefore have bit
1948 * vector[1] set, but they also have other bits set:
1949 * 3=1+2, options 0 and 1
1950 * 6=2+4, options 1 and 2
1951 * 7=1+2+4, options 0,1,and 2
1952 * 10=2+8, options 1 and 3
1953 * etc.
1954 * */
1955
1956 /* now for each option (i), we set their bits in all entries (j)
1957 * that contain bit 2^i.
1958 */
1959 for (j = 0; j<p_ClsPlanGrp->sizeOfGrp; j++)
1960 {
1961 if (j & (1<<i))
1962 p_ClsPlanSet->vectors[j] |= p_Grp->optVectors[i];
1963 }
1964 }
1965
1966 return E_OK;
1967 }
1968
FmPcdKgDestroyClsPlanGrp(t_Handle h_FmPcd,uint8_t grpId)1969 void FmPcdKgDestroyClsPlanGrp(t_Handle h_FmPcd, uint8_t grpId)
1970 {
1971 t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
1972 t_FmPcdIpcKgClsPlanParams kgAlloc;
1973 t_Error err;
1974 t_FmPcdIpcMsg msg;
1975 uint32_t replyLength;
1976 t_FmPcdIpcReply reply;
1977
1978 /* check that no port is bound to this clsPlan */
1979 if (p_FmPcd->p_FmPcdKg->clsPlanGrps[grpId].owners)
1980 {
1981 REPORT_ERROR(MINOR, E_INVALID_STATE, ("Trying to delete a clsPlan grp that has ports bound to"));
1982 return;
1983 }
1984
1985 FmPcdSetClsPlanGrpId(p_FmPcd, p_FmPcd->p_FmPcdKg->clsPlanGrps[grpId].netEnvId, ILLEGAL_CLS_PLAN);
1986
1987 if (grpId == p_FmPcd->p_FmPcdKg->emptyClsPlanGrpId)
1988 p_FmPcd->p_FmPcdKg->emptyClsPlanGrpId = ILLEGAL_CLS_PLAN;
1989 else
1990 FmPcdDecNetEnvOwners(p_FmPcd, p_FmPcd->p_FmPcdKg->clsPlanGrps[grpId].netEnvId);
1991
1992 /* free blocks */
1993 if (p_FmPcd->guestId == NCSW_MASTER_ID)
1994 KgFreeClsPlanEntries(h_FmPcd,
1995 p_FmPcd->p_FmPcdKg->clsPlanGrps[grpId].sizeOfGrp,
1996 p_FmPcd->guestId,
1997 p_FmPcd->p_FmPcdKg->clsPlanGrps[grpId].baseEntry);
1998 else /* in GUEST_PARTITION, we use the IPC, to also set a private driver group if required */
1999 {
2000 memset(&reply, 0, sizeof(reply));
2001 memset(&msg, 0, sizeof(msg));
2002 kgAlloc.guestId = p_FmPcd->guestId;
2003 kgAlloc.numOfClsPlanEntries = p_FmPcd->p_FmPcdKg->clsPlanGrps[grpId].sizeOfGrp;
2004 kgAlloc.clsPlanBase = p_FmPcd->p_FmPcdKg->clsPlanGrps[grpId].baseEntry;
2005 msg.msgId = FM_PCD_FREE_KG_CLSPLAN;
2006 memcpy(msg.msgBody, &kgAlloc, sizeof(kgAlloc));
2007 replyLength = sizeof(uint32_t);
2008 err = XX_IpcSendMessage(p_FmPcd->h_IpcSession,
2009 (uint8_t*)&msg,
2010 sizeof(msg.msgId) + sizeof(kgAlloc),
2011 (uint8_t*)&reply,
2012 &replyLength,
2013 NULL,
2014 NULL);
2015 if (err != E_OK)
2016 {
2017 REPORT_ERROR(MINOR, err, NO_MSG);
2018 return;
2019 }
2020 if (replyLength != sizeof(uint32_t))
2021 {
2022 REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
2023 return;
2024 }
2025 if ((t_Error)reply.error != E_OK)
2026 {
2027 REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Free KG clsPlan failed"));
2028 return;
2029 }
2030 }
2031
2032 /* clear clsPlan driver structure */
2033 memset(&p_FmPcd->p_FmPcdKg->clsPlanGrps[grpId], 0, sizeof(t_FmPcdKgClsPlanGrp));
2034 }
2035
FmPcdKgBuildBindPortToSchemes(t_Handle h_FmPcd,t_FmPcdKgInterModuleBindPortToSchemes * p_BindPort,uint32_t * p_SpReg,bool add)2036 t_Error FmPcdKgBuildBindPortToSchemes(t_Handle h_FmPcd, t_FmPcdKgInterModuleBindPortToSchemes *p_BindPort, uint32_t *p_SpReg, bool add)
2037 {
2038 t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
2039 uint32_t j, schemesPerPortVector = 0;
2040 t_FmPcdKgScheme *p_Scheme;
2041 uint8_t i, relativeSchemeId;
2042 uint32_t tmp, walking1Mask;
2043 uint8_t swPortIndex = 0;
2044
2045 SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
2046 SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdKg, E_INVALID_HANDLE);
2047 SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE);
2048
2049 /* for each scheme */
2050 for (i = 0; i<p_BindPort->numOfSchemes; i++)
2051 {
2052 relativeSchemeId = FmPcdKgGetRelativeSchemeId(p_FmPcd, p_BindPort->schemesIds[i]);
2053 if (relativeSchemeId >= FM_PCD_KG_NUM_OF_SCHEMES)
2054 RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, NO_MSG);
2055
2056 if (add)
2057 {
2058 p_Scheme = &p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId];
2059 if (!FmPcdKgIsSchemeValidSw(p_Scheme))
2060 RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Requested scheme is invalid."));
2061 /* check netEnvId of the port against the scheme netEnvId */
2062 if ((p_Scheme->netEnvId != p_BindPort->netEnvId) && (p_Scheme->netEnvId != ILLEGAL_NETENV))
2063 RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Port may not be bound to requested scheme - differ in netEnvId"));
2064
2065 /* if next engine is private port policer profile, we need to check that it is valid */
2066 HW_PORT_ID_TO_SW_PORT_INDX(swPortIndex, p_BindPort->hardwarePortId);
2067 if (p_Scheme->nextRelativePlcrProfile)
2068 {
2069 for (j = 0;j<p_Scheme->numOfProfiles;j++)
2070 {
2071 ASSERT_COND(p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].h_FmPort);
2072 if (p_Scheme->relativeProfileId+j >= p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].numOfProfiles)
2073 RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Relative profile not in range"));
2074 if (!FmPcdPlcrIsProfileValid(p_FmPcd, (uint16_t)(p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].profilesBase + p_Scheme->relativeProfileId + j)))
2075 RETURN_ERROR(MINOR, E_INVALID_STATE, ("Relative profile not valid."));
2076 }
2077 }
2078 if (!p_BindPort->useClsPlan)
2079 {
2080 /* This check may be redundant as port is a assigned to the whole NetEnv */
2081
2082 /* if this port does not use clsPlan, it may not be bound to schemes with units that contain
2083 cls plan options. Schemes that are used only directly, should not be checked.
2084 it also may not be bound to schemes that go to CC with units that are options - so we OR
2085 the match vector and the grpBits (= ccUnits) */
2086 if ((p_Scheme->matchVector != SCHEME_ALWAYS_DIRECT) || p_Scheme->ccUnits)
2087 {
2088 uint8_t netEnvId;
2089 walking1Mask = 0x80000000;
2090 netEnvId = (p_Scheme->netEnvId == ILLEGAL_NETENV)? p_BindPort->netEnvId:p_Scheme->netEnvId;
2091 tmp = (p_Scheme->matchVector == SCHEME_ALWAYS_DIRECT)? 0:p_Scheme->matchVector;
2092 tmp |= p_Scheme->ccUnits;
2093 while (tmp)
2094 {
2095 if (tmp & walking1Mask)
2096 {
2097 tmp &= ~walking1Mask;
2098 if (!PcdNetEnvIsUnitWithoutOpts(p_FmPcd, netEnvId, walking1Mask))
2099 RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Port (without clsPlan) may not be bound to requested scheme - uses clsPlan options"));
2100 }
2101 walking1Mask >>= 1;
2102 }
2103 }
2104 }
2105 }
2106 /* build vector */
2107 schemesPerPortVector |= 1 << (31 - p_BindPort->schemesIds[i]);
2108 }
2109
2110 *p_SpReg = schemesPerPortVector;
2111
2112 return E_OK;
2113 }
2114
FmPcdKgBindPortToSchemes(t_Handle h_FmPcd,t_FmPcdKgInterModuleBindPortToSchemes * p_SchemeBind)2115 t_Error FmPcdKgBindPortToSchemes(t_Handle h_FmPcd , t_FmPcdKgInterModuleBindPortToSchemes *p_SchemeBind)
2116 {
2117 t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
2118 uint32_t spReg;
2119 t_Error err = E_OK;
2120
2121 err = FmPcdKgBuildBindPortToSchemes(h_FmPcd, p_SchemeBind, &spReg, TRUE);
2122 if (err)
2123 RETURN_ERROR(MAJOR, err, NO_MSG);
2124
2125 err = KgWriteSp(p_FmPcd, p_SchemeBind->hardwarePortId, spReg, TRUE);
2126 if (err)
2127 RETURN_ERROR(MAJOR, err, NO_MSG);
2128
2129 IncSchemeOwners(p_FmPcd, p_SchemeBind);
2130
2131 return E_OK;
2132 }
2133
FmPcdKgUnbindPortToSchemes(t_Handle h_FmPcd,t_FmPcdKgInterModuleBindPortToSchemes * p_SchemeBind)2134 t_Error FmPcdKgUnbindPortToSchemes(t_Handle h_FmPcd, t_FmPcdKgInterModuleBindPortToSchemes *p_SchemeBind)
2135 {
2136 t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
2137 uint32_t spReg;
2138 t_Error err = E_OK;
2139
2140 err = FmPcdKgBuildBindPortToSchemes(p_FmPcd, p_SchemeBind, &spReg, FALSE);
2141 if (err)
2142 RETURN_ERROR(MAJOR, err, NO_MSG);
2143
2144 err = KgWriteSp(p_FmPcd, p_SchemeBind->hardwarePortId, spReg, FALSE);
2145 if (err)
2146 RETURN_ERROR(MAJOR, err, NO_MSG);
2147
2148 DecSchemeOwners(p_FmPcd, p_SchemeBind);
2149
2150 return E_OK;
2151 }
2152
FmPcdKgIsSchemeValidSw(t_Handle h_Scheme)2153 bool FmPcdKgIsSchemeValidSw(t_Handle h_Scheme)
2154 {
2155 t_FmPcdKgScheme *p_Scheme = (t_FmPcdKgScheme*)h_Scheme;
2156
2157 return p_Scheme->valid;
2158 }
2159
KgIsSchemeAlwaysDirect(t_Handle h_FmPcd,uint8_t schemeId)2160 bool KgIsSchemeAlwaysDirect(t_Handle h_FmPcd, uint8_t schemeId)
2161 {
2162 t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
2163
2164 if (p_FmPcd->p_FmPcdKg->schemes[schemeId].matchVector == SCHEME_ALWAYS_DIRECT)
2165 return TRUE;
2166 else
2167 return FALSE;
2168 }
2169
FmPcdKgAllocSchemes(t_Handle h_FmPcd,uint8_t numOfSchemes,uint8_t guestId,uint8_t * p_SchemesIds)2170 t_Error FmPcdKgAllocSchemes(t_Handle h_FmPcd, uint8_t numOfSchemes, uint8_t guestId, uint8_t *p_SchemesIds)
2171 {
2172 t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;
2173 uint8_t i, j;
2174
2175 SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
2176 SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdKg, E_INVALID_HANDLE);
2177
2178 /* This routine is issued only on master core of master partition -
2179 either directly or through IPC, so no need for lock */
2180
2181 for (j = 0, i = 0; i < FM_PCD_KG_NUM_OF_SCHEMES && j < numOfSchemes; i++)
2182 {
2183 if (!p_FmPcd->p_FmPcdKg->schemesMng[i].allocated)
2184 {
2185 p_FmPcd->p_FmPcdKg->schemesMng[i].allocated = TRUE;
2186 p_FmPcd->p_FmPcdKg->schemesMng[i].ownerId = guestId;
2187 p_SchemesIds[j] = i;
2188 j++;
2189 }
2190 }
2191
2192 if (j != numOfSchemes)
2193 {
2194 /* roll back */
2195 for (j--; j; j--)
2196 {
2197 p_FmPcd->p_FmPcdKg->schemesMng[p_SchemesIds[j]].allocated = FALSE;
2198 p_FmPcd->p_FmPcdKg->schemesMng[p_SchemesIds[j]].ownerId = 0;
2199 p_SchemesIds[j] = 0;
2200 }
2201
2202 RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ("No schemes found"));
2203 }
2204
2205 return E_OK;
2206 }
2207
FmPcdKgFreeSchemes(t_Handle h_FmPcd,uint8_t numOfSchemes,uint8_t guestId,uint8_t * p_SchemesIds)2208 t_Error FmPcdKgFreeSchemes(t_Handle h_FmPcd, uint8_t numOfSchemes, uint8_t guestId, uint8_t *p_SchemesIds)
2209 {
2210 t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;
2211 uint8_t i;
2212
2213 SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
2214 SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdKg, E_INVALID_HANDLE);
2215
2216 /* This routine is issued only on master core of master partition -
2217 either directly or through IPC */
2218
2219 for (i = 0; i < numOfSchemes; i++)
2220 {
2221 if (!p_FmPcd->p_FmPcdKg->schemesMng[p_SchemesIds[i]].allocated)
2222 {
2223 RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Scheme was not previously allocated"));
2224 }
2225 if (p_FmPcd->p_FmPcdKg->schemesMng[p_SchemesIds[i]].ownerId != guestId)
2226 {
2227 RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Scheme is not owned by caller. "));
2228 }
2229 p_FmPcd->p_FmPcdKg->schemesMng[p_SchemesIds[i]].allocated = FALSE;
2230 p_FmPcd->p_FmPcdKg->schemesMng[p_SchemesIds[i]].ownerId = 0;
2231 }
2232
2233 return E_OK;
2234 }
2235
KgAllocClsPlanEntries(t_Handle h_FmPcd,uint16_t numOfClsPlanEntries,uint8_t guestId,uint8_t * p_First)2236 t_Error KgAllocClsPlanEntries(t_Handle h_FmPcd, uint16_t numOfClsPlanEntries, uint8_t guestId, uint8_t *p_First)
2237 {
2238 t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;
2239 uint8_t numOfBlocks, blocksFound=0, first=0;
2240 uint8_t i, j;
2241
2242 /* This routine is issued only on master core of master partition -
2243 either directly or through IPC, so no need for lock */
2244
2245 if (!numOfClsPlanEntries)
2246 return E_OK;
2247
2248 if ((numOfClsPlanEntries % CLS_PLAN_NUM_PER_GRP) || (!POWER_OF_2(numOfClsPlanEntries)))
2249 RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("numOfClsPlanEntries must be a power of 2 and divisible by 8"));
2250
2251 numOfBlocks = (uint8_t)(numOfClsPlanEntries/CLS_PLAN_NUM_PER_GRP);
2252
2253 /* try to find consequent blocks */
2254 first = 0;
2255 for (i = 0; i < FM_PCD_MAX_NUM_OF_CLS_PLANS/CLS_PLAN_NUM_PER_GRP;)
2256 {
2257 if (!p_FmPcd->p_FmPcdKg->clsPlanBlocksMng[i].allocated)
2258 {
2259 blocksFound++;
2260 i++;
2261 if (blocksFound == numOfBlocks)
2262 break;
2263 }
2264 else
2265 {
2266 blocksFound = 0;
2267 /* advance i to the next aligned address */
2268 first = i = (uint8_t)(first + numOfBlocks);
2269 }
2270 }
2271
2272 if (blocksFound == numOfBlocks)
2273 {
2274 *p_First = (uint8_t)(first * CLS_PLAN_NUM_PER_GRP);
2275 for (j = first; j < (first + numOfBlocks); j++)
2276 {
2277 p_FmPcd->p_FmPcdKg->clsPlanBlocksMng[j].allocated = TRUE;
2278 p_FmPcd->p_FmPcdKg->clsPlanBlocksMng[j].ownerId = guestId;
2279 }
2280 return E_OK;
2281 }
2282 else
2283 RETURN_ERROR(MINOR, E_FULL, ("No resources for clsPlan"));
2284 }
2285
KgFreeClsPlanEntries(t_Handle h_FmPcd,uint16_t numOfClsPlanEntries,uint8_t guestId,uint8_t base)2286 void KgFreeClsPlanEntries(t_Handle h_FmPcd, uint16_t numOfClsPlanEntries, uint8_t guestId, uint8_t base)
2287 {
2288 t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
2289 uint8_t numOfBlocks;
2290 uint8_t i, baseBlock;
2291
2292 #ifdef DISABLE_ASSERTIONS
2293 UNUSED(guestId);
2294 #endif /* DISABLE_ASSERTIONS */
2295
2296 /* This routine is issued only on master core of master partition -
2297 either directly or through IPC, so no need for lock */
2298
2299 numOfBlocks = (uint8_t)(numOfClsPlanEntries/CLS_PLAN_NUM_PER_GRP);
2300 ASSERT_COND(!(base%CLS_PLAN_NUM_PER_GRP));
2301
2302 baseBlock = (uint8_t)(base/CLS_PLAN_NUM_PER_GRP);
2303 for (i=baseBlock;i<baseBlock+numOfBlocks;i++)
2304 {
2305 ASSERT_COND(p_FmPcd->p_FmPcdKg->clsPlanBlocksMng[i].allocated);
2306 ASSERT_COND(guestId == p_FmPcd->p_FmPcdKg->clsPlanBlocksMng[i].ownerId);
2307 p_FmPcd->p_FmPcdKg->clsPlanBlocksMng[i].allocated = FALSE;
2308 p_FmPcd->p_FmPcdKg->clsPlanBlocksMng[i].ownerId = 0;
2309 }
2310 }
2311
KgEnable(t_FmPcd * p_FmPcd)2312 void KgEnable(t_FmPcd *p_FmPcd)
2313 {
2314 struct fman_kg_regs *p_Regs = p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs;
2315
2316 ASSERT_COND(FmIsMaster(p_FmPcd->h_Fm));
2317 fman_kg_enable(p_Regs);
2318 }
2319
KgDisable(t_FmPcd * p_FmPcd)2320 void KgDisable(t_FmPcd *p_FmPcd)
2321 {
2322 struct fman_kg_regs *p_Regs = p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs;
2323
2324 ASSERT_COND(FmIsMaster(p_FmPcd->h_Fm));
2325 fman_kg_disable(p_Regs);
2326 }
2327
KgSetClsPlan(t_Handle h_FmPcd,t_FmPcdKgInterModuleClsPlanSet * p_Set)2328 void KgSetClsPlan(t_Handle h_FmPcd, t_FmPcdKgInterModuleClsPlanSet *p_Set)
2329 {
2330 t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;
2331 struct fman_kg_cp_regs *p_FmPcdKgPortRegs;
2332 uint32_t tmpKgarReg = 0, intFlags;
2333 uint16_t i, j;
2334
2335 /* This routine is protected by the calling routine ! */
2336 ASSERT_COND(FmIsMaster(p_FmPcd->h_Fm));
2337 p_FmPcdKgPortRegs = &p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->clsPlanRegs;
2338
2339 intFlags = KgHwLock(p_FmPcd->p_FmPcdKg);
2340 for (i=p_Set->baseEntry;i<p_Set->baseEntry+p_Set->numOfClsPlanEntries;i+=8)
2341 {
2342 tmpKgarReg = FmPcdKgBuildWriteClsPlanBlockActionReg((uint8_t)(i / CLS_PLAN_NUM_PER_GRP));
2343
2344 for (j = i; j < i+8; j++)
2345 {
2346 ASSERT_COND(IN_RANGE(0, (j - p_Set->baseEntry), FM_PCD_MAX_NUM_OF_CLS_PLANS-1));
2347 WRITE_UINT32(p_FmPcdKgPortRegs->kgcpe[j % CLS_PLAN_NUM_PER_GRP],p_Set->vectors[j - p_Set->baseEntry]);
2348 }
2349
2350 if (WriteKgarWait(p_FmPcd, tmpKgarReg) != E_OK)
2351 {
2352 REPORT_ERROR(MAJOR, E_INVALID_STATE, ("WriteKgarWait FAILED"));
2353 KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags);
2354 return;
2355 }
2356 }
2357 KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags);
2358 }
2359
KgConfig(t_FmPcd * p_FmPcd,t_FmPcdParams * p_FmPcdParams)2360 t_Handle KgConfig( t_FmPcd *p_FmPcd, t_FmPcdParams *p_FmPcdParams)
2361 {
2362 t_FmPcdKg *p_FmPcdKg;
2363
2364 UNUSED(p_FmPcd);
2365
2366 if (p_FmPcdParams->numOfSchemes > FM_PCD_KG_NUM_OF_SCHEMES)
2367 {
2368 REPORT_ERROR(MAJOR, E_INVALID_VALUE,
2369 ("numOfSchemes should not exceed %d", FM_PCD_KG_NUM_OF_SCHEMES));
2370 return NULL;
2371 }
2372
2373 p_FmPcdKg = (t_FmPcdKg *)XX_Malloc(sizeof(t_FmPcdKg));
2374 if (!p_FmPcdKg)
2375 {
2376 REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM Keygen allocation FAILED"));
2377 return NULL;
2378 }
2379 memset(p_FmPcdKg, 0, sizeof(t_FmPcdKg));
2380
2381
2382 if (FmIsMaster(p_FmPcd->h_Fm))
2383 {
2384 p_FmPcdKg->p_FmPcdKgRegs = (struct fman_kg_regs *)UINT_TO_PTR(FmGetPcdKgBaseAddr(p_FmPcdParams->h_Fm));
2385 p_FmPcd->exceptions |= DEFAULT_fmPcdKgErrorExceptions;
2386 p_FmPcdKg->p_IndirectAccessRegs = (u_FmPcdKgIndirectAccessRegs *)&p_FmPcdKg->p_FmPcdKgRegs->fmkg_indirect[0];
2387 }
2388
2389 p_FmPcdKg->numOfSchemes = p_FmPcdParams->numOfSchemes;
2390 if ((p_FmPcd->guestId == NCSW_MASTER_ID) && !p_FmPcdKg->numOfSchemes)
2391 {
2392 p_FmPcdKg->numOfSchemes = FM_PCD_KG_NUM_OF_SCHEMES;
2393 DBG(WARNING, ("numOfSchemes was defined 0 by user, re-defined by driver to FM_PCD_KG_NUM_OF_SCHEMES"));
2394 }
2395
2396 p_FmPcdKg->emptyClsPlanGrpId = ILLEGAL_CLS_PLAN;
2397
2398 return p_FmPcdKg;
2399 }
2400
KgInit(t_FmPcd * p_FmPcd)2401 t_Error KgInit(t_FmPcd *p_FmPcd)
2402 {
2403 t_Error err = E_OK;
2404
2405 p_FmPcd->p_FmPcdKg->h_HwSpinlock = XX_InitSpinlock();
2406 if (!p_FmPcd->p_FmPcdKg->h_HwSpinlock)
2407 RETURN_ERROR(MAJOR, E_NO_MEMORY, ("FM KG HW spinlock"));
2408
2409 if (p_FmPcd->guestId == NCSW_MASTER_ID)
2410 err = KgInitMaster(p_FmPcd);
2411 else
2412 err = KgInitGuest(p_FmPcd);
2413
2414 if (err != E_OK)
2415 {
2416 if (p_FmPcd->p_FmPcdKg->h_HwSpinlock)
2417 XX_FreeSpinlock(p_FmPcd->p_FmPcdKg->h_HwSpinlock);
2418 }
2419
2420 return err;
2421 }
2422
KgFree(t_FmPcd * p_FmPcd)2423 t_Error KgFree(t_FmPcd *p_FmPcd)
2424 {
2425 t_FmPcdIpcKgSchemesParams kgAlloc;
2426 t_Error err = E_OK;
2427 t_FmPcdIpcMsg msg;
2428 uint32_t replyLength;
2429 t_FmPcdIpcReply reply;
2430
2431 FmUnregisterIntr(p_FmPcd->h_Fm, e_FM_MOD_KG, 0, e_FM_INTR_TYPE_ERR);
2432
2433 if (p_FmPcd->guestId == NCSW_MASTER_ID)
2434 {
2435 err = FmPcdKgFreeSchemes(p_FmPcd,
2436 p_FmPcd->p_FmPcdKg->numOfSchemes,
2437 p_FmPcd->guestId,
2438 p_FmPcd->p_FmPcdKg->schemesIds);
2439 if (err)
2440 RETURN_ERROR(MAJOR, err, NO_MSG);
2441
2442 if (p_FmPcd->p_FmPcdKg->h_HwSpinlock)
2443 XX_FreeSpinlock(p_FmPcd->p_FmPcdKg->h_HwSpinlock);
2444
2445 return E_OK;
2446 }
2447
2448 /* guest */
2449 memset(&reply, 0, sizeof(reply));
2450 memset(&msg, 0, sizeof(msg));
2451 kgAlloc.numOfSchemes = p_FmPcd->p_FmPcdKg->numOfSchemes;
2452 kgAlloc.guestId = p_FmPcd->guestId;
2453 ASSERT_COND(kgAlloc.numOfSchemes < FM_PCD_KG_NUM_OF_SCHEMES);
2454 memcpy(kgAlloc.schemesIds, p_FmPcd->p_FmPcdKg->schemesIds, (sizeof(uint8_t))*kgAlloc.numOfSchemes);
2455 msg.msgId = FM_PCD_FREE_KG_SCHEMES;
2456 memcpy(msg.msgBody, &kgAlloc, sizeof(kgAlloc));
2457 replyLength = sizeof(uint32_t);
2458 if ((err = XX_IpcSendMessage(p_FmPcd->h_IpcSession,
2459 (uint8_t*)&msg,
2460 sizeof(msg.msgId) + sizeof(kgAlloc),
2461 (uint8_t*)&reply,
2462 &replyLength,
2463 NULL,
2464 NULL)) != E_OK)
2465 RETURN_ERROR(MAJOR, err, NO_MSG);
2466 if (replyLength != sizeof(uint32_t))
2467 RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
2468
2469 if (p_FmPcd->p_FmPcdKg->h_HwSpinlock)
2470 XX_FreeSpinlock(p_FmPcd->p_FmPcdKg->h_HwSpinlock);
2471
2472 return (t_Error)reply.error;
2473 }
2474
FmPcdKgSetOrBindToClsPlanGrp(t_Handle h_FmPcd,uint8_t hardwarePortId,uint8_t netEnvId,protocolOpt_t * p_OptArray,uint8_t * p_ClsPlanGrpId,bool * p_IsEmptyClsPlanGrp)2475 t_Error FmPcdKgSetOrBindToClsPlanGrp(t_Handle h_FmPcd, uint8_t hardwarePortId, uint8_t netEnvId, protocolOpt_t *p_OptArray, uint8_t *p_ClsPlanGrpId, bool *p_IsEmptyClsPlanGrp)
2476 {
2477 t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;
2478 t_FmPcdKgInterModuleClsPlanGrpParams grpParams, *p_GrpParams;
2479 t_FmPcdKgClsPlanGrp *p_ClsPlanGrp;
2480 t_FmPcdKgInterModuleClsPlanSet *p_ClsPlanSet;
2481 t_Error err;
2482
2483 /* This function is issued only from FM_PORT_SetPcd which locked all PCD modules,
2484 so no need for lock here */
2485
2486 memset(&grpParams, 0, sizeof(grpParams));
2487 grpParams.clsPlanGrpId = ILLEGAL_CLS_PLAN;
2488 p_GrpParams = &grpParams;
2489
2490 p_GrpParams->netEnvId = netEnvId;
2491
2492 /* Get from the NetEnv the information of the clsPlan (can be already created,
2493 * or needs to build) */
2494 err = PcdGetClsPlanGrpParams(h_FmPcd, p_GrpParams);
2495 if (err)
2496 RETURN_ERROR(MINOR,err,NO_MSG);
2497
2498 if (p_GrpParams->grpExists)
2499 {
2500 /* this group was already updated (at least) in SW */
2501 *p_ClsPlanGrpId = p_GrpParams->clsPlanGrpId;
2502 }
2503 else
2504 {
2505 p_ClsPlanSet = (t_FmPcdKgInterModuleClsPlanSet *)XX_Malloc(sizeof(t_FmPcdKgInterModuleClsPlanSet));
2506 if (!p_ClsPlanSet)
2507 RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Classification plan set"));
2508 memset(p_ClsPlanSet, 0, sizeof(t_FmPcdKgInterModuleClsPlanSet));
2509 /* Build (in SW) the clsPlan parameters, including the vectors to be written to HW */
2510 err = FmPcdKgBuildClsPlanGrp(h_FmPcd, p_GrpParams, p_ClsPlanSet);
2511 if (err)
2512 {
2513 XX_Free(p_ClsPlanSet);
2514 RETURN_ERROR(MINOR, err, NO_MSG);
2515 }
2516 *p_ClsPlanGrpId = p_GrpParams->clsPlanGrpId;
2517
2518 if (p_FmPcd->h_Hc)
2519 {
2520 /* write clsPlan entries to memory */
2521 err = FmHcPcdKgSetClsPlan(p_FmPcd->h_Hc, p_ClsPlanSet);
2522 if (err)
2523 {
2524 XX_Free(p_ClsPlanSet);
2525 RETURN_ERROR(MAJOR, err, NO_MSG);
2526 }
2527 }
2528 else
2529 /* write clsPlan entries to memory */
2530 KgSetClsPlan(p_FmPcd, p_ClsPlanSet);
2531
2532 XX_Free(p_ClsPlanSet);
2533 }
2534
2535 /* Set caller parameters */
2536
2537 /* mark if this is an empty classification group */
2538 if (*p_ClsPlanGrpId == p_FmPcd->p_FmPcdKg->emptyClsPlanGrpId)
2539 *p_IsEmptyClsPlanGrp = TRUE;
2540 else
2541 *p_IsEmptyClsPlanGrp = FALSE;
2542
2543 p_ClsPlanGrp = &p_FmPcd->p_FmPcdKg->clsPlanGrps[*p_ClsPlanGrpId];
2544
2545 /* increment owners number */
2546 p_ClsPlanGrp->owners++;
2547
2548 /* copy options array for port */
2549 memcpy(p_OptArray, &p_FmPcd->p_FmPcdKg->clsPlanGrps[*p_ClsPlanGrpId].optArray, FM_PCD_MAX_NUM_OF_OPTIONS(FM_PCD_MAX_NUM_OF_CLS_PLANS)*sizeof(protocolOpt_t));
2550
2551 /* bind port to the new or existing group */
2552 err = BindPortToClsPlanGrp(p_FmPcd, hardwarePortId, p_GrpParams->clsPlanGrpId);
2553 if (err)
2554 RETURN_ERROR(MINOR, err, NO_MSG);
2555
2556 return E_OK;
2557 }
2558
FmPcdKgDeleteOrUnbindPortToClsPlanGrp(t_Handle h_FmPcd,uint8_t hardwarePortId,uint8_t clsPlanGrpId)2559 t_Error FmPcdKgDeleteOrUnbindPortToClsPlanGrp(t_Handle h_FmPcd, uint8_t hardwarePortId, uint8_t clsPlanGrpId)
2560 {
2561 t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;
2562 t_FmPcdKgClsPlanGrp *p_ClsPlanGrp = &p_FmPcd->p_FmPcdKg->clsPlanGrps[clsPlanGrpId];
2563 t_FmPcdKgInterModuleClsPlanSet *p_ClsPlanSet;
2564 t_Error err;
2565
2566 /* This function is issued only from FM_PORT_DeletePcd which locked all PCD modules,
2567 so no need for lock here */
2568
2569 UnbindPortToClsPlanGrp(p_FmPcd, hardwarePortId);
2570
2571 /* decrement owners number */
2572 ASSERT_COND(p_ClsPlanGrp->owners);
2573 p_ClsPlanGrp->owners--;
2574
2575 if (!p_ClsPlanGrp->owners)
2576 {
2577 if (p_FmPcd->h_Hc)
2578 {
2579 err = FmHcPcdKgDeleteClsPlan(p_FmPcd->h_Hc, clsPlanGrpId);
2580 return err;
2581 }
2582 else
2583 {
2584 /* clear clsPlan entries in memory */
2585 p_ClsPlanSet = (t_FmPcdKgInterModuleClsPlanSet *)XX_Malloc(sizeof(t_FmPcdKgInterModuleClsPlanSet));
2586 if (!p_ClsPlanSet)
2587 {
2588 RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Classification plan set"));
2589 }
2590 memset(p_ClsPlanSet, 0, sizeof(t_FmPcdKgInterModuleClsPlanSet));
2591
2592 p_ClsPlanSet->baseEntry = p_FmPcd->p_FmPcdKg->clsPlanGrps[clsPlanGrpId].baseEntry;
2593 p_ClsPlanSet->numOfClsPlanEntries = p_FmPcd->p_FmPcdKg->clsPlanGrps[clsPlanGrpId].sizeOfGrp;
2594 KgSetClsPlan(p_FmPcd, p_ClsPlanSet);
2595 XX_Free(p_ClsPlanSet);
2596
2597 FmPcdKgDestroyClsPlanGrp(h_FmPcd, clsPlanGrpId);
2598 }
2599 }
2600 return E_OK;
2601 }
2602
FmPcdKgGetRequiredAction(t_Handle h_FmPcd,uint8_t schemeId)2603 uint32_t FmPcdKgGetRequiredAction(t_Handle h_FmPcd, uint8_t schemeId)
2604 {
2605 t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
2606 ASSERT_COND(p_FmPcd->p_FmPcdKg->schemes[schemeId].valid);
2607
2608 return p_FmPcd->p_FmPcdKg->schemes[schemeId].requiredAction;
2609 }
2610
FmPcdKgGetRequiredActionFlag(t_Handle h_FmPcd,uint8_t schemeId)2611 uint32_t FmPcdKgGetRequiredActionFlag(t_Handle h_FmPcd, uint8_t schemeId)
2612 {
2613 t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
2614
2615 ASSERT_COND(p_FmPcd->p_FmPcdKg->schemes[schemeId].valid);
2616
2617 return p_FmPcd->p_FmPcdKg->schemes[schemeId].requiredActionFlag;
2618 }
2619
FmPcdKgIsDirectPlcr(t_Handle h_FmPcd,uint8_t schemeId)2620 bool FmPcdKgIsDirectPlcr(t_Handle h_FmPcd, uint8_t schemeId)
2621 {
2622 t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
2623
2624 ASSERT_COND(p_FmPcd->p_FmPcdKg->schemes[schemeId].valid);
2625
2626 return p_FmPcd->p_FmPcdKg->schemes[schemeId].directPlcr;
2627 }
2628
2629
FmPcdKgGetRelativeProfileId(t_Handle h_FmPcd,uint8_t schemeId)2630 uint16_t FmPcdKgGetRelativeProfileId(t_Handle h_FmPcd, uint8_t schemeId)
2631 {
2632 t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
2633
2634 ASSERT_COND(p_FmPcd->p_FmPcdKg->schemes[schemeId].valid);
2635
2636 return p_FmPcd->p_FmPcdKg->schemes[schemeId].relativeProfileId;
2637 }
2638
FmPcdKgIsDistrOnPlcrProfile(t_Handle h_FmPcd,uint8_t schemeId)2639 bool FmPcdKgIsDistrOnPlcrProfile(t_Handle h_FmPcd, uint8_t schemeId)
2640 {
2641 t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
2642
2643 ASSERT_COND(p_FmPcd->p_FmPcdKg->schemes[schemeId].valid);
2644
2645 if ((p_FmPcd->p_FmPcdKg->schemes[schemeId].extractedOrs &&
2646 p_FmPcd->p_FmPcdKg->schemes[schemeId].bitOffsetInPlcrProfile) ||
2647 p_FmPcd->p_FmPcdKg->schemes[schemeId].nextRelativePlcrProfile)
2648 return TRUE;
2649 else
2650 return FALSE;
2651
2652 }
2653
FmPcdKgGetNextEngine(t_Handle h_FmPcd,uint8_t relativeSchemeId)2654 e_FmPcdEngine FmPcdKgGetNextEngine(t_Handle h_FmPcd, uint8_t relativeSchemeId)
2655 {
2656 t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
2657
2658 ASSERT_COND(p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].valid);
2659
2660 return p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].nextEngine;
2661 }
2662
FmPcdKgGetDoneAction(t_Handle h_FmPcd,uint8_t schemeId)2663 e_FmPcdDoneAction FmPcdKgGetDoneAction(t_Handle h_FmPcd, uint8_t schemeId)
2664 {
2665 t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
2666
2667 ASSERT_COND(p_FmPcd->p_FmPcdKg->schemes[schemeId].valid);
2668
2669 return p_FmPcd->p_FmPcdKg->schemes[schemeId].doneAction;
2670 }
2671
FmPcdKgUpdateRequiredAction(t_Handle h_Scheme,uint32_t requiredAction)2672 void FmPcdKgUpdateRequiredAction(t_Handle h_Scheme, uint32_t requiredAction)
2673 {
2674 t_FmPcdKgScheme *p_Scheme = (t_FmPcdKgScheme *)h_Scheme;
2675
2676 /* this routine is protected by calling routine */
2677
2678 ASSERT_COND(p_Scheme->valid);
2679
2680 p_Scheme->requiredAction |= requiredAction;
2681 }
2682
FmPcdKgHwSchemeIsValid(uint32_t schemeModeReg)2683 bool FmPcdKgHwSchemeIsValid(uint32_t schemeModeReg)
2684 {
2685 return (bool)!!(schemeModeReg & KG_SCH_MODE_EN);
2686 }
2687
FmPcdKgBuildWriteSchemeActionReg(uint8_t schemeId,bool updateCounter)2688 uint32_t FmPcdKgBuildWriteSchemeActionReg(uint8_t schemeId, bool updateCounter)
2689 {
2690 return (uint32_t)(((uint32_t)schemeId << FM_PCD_KG_KGAR_NUM_SHIFT) |
2691 FM_KG_KGAR_GO |
2692 FM_KG_KGAR_WRITE |
2693 FM_KG_KGAR_SEL_SCHEME_ENTRY |
2694 DUMMY_PORT_ID |
2695 (updateCounter ? FM_KG_KGAR_SCM_WSEL_UPDATE_CNT:0));
2696 }
2697
FmPcdKgBuildReadSchemeActionReg(uint8_t schemeId)2698 uint32_t FmPcdKgBuildReadSchemeActionReg(uint8_t schemeId)
2699 {
2700 return (uint32_t)(((uint32_t)schemeId << FM_PCD_KG_KGAR_NUM_SHIFT) |
2701 FM_KG_KGAR_GO |
2702 FM_KG_KGAR_READ |
2703 FM_KG_KGAR_SEL_SCHEME_ENTRY |
2704 DUMMY_PORT_ID |
2705 FM_KG_KGAR_SCM_WSEL_UPDATE_CNT);
2706
2707 }
2708
FmPcdKgBuildWriteClsPlanBlockActionReg(uint8_t grpId)2709 uint32_t FmPcdKgBuildWriteClsPlanBlockActionReg(uint8_t grpId)
2710 {
2711 return (uint32_t)(FM_KG_KGAR_GO |
2712 FM_KG_KGAR_WRITE |
2713 FM_PCD_KG_KGAR_SEL_CLS_PLAN_ENTRY |
2714 DUMMY_PORT_ID |
2715 ((uint32_t)grpId << FM_PCD_KG_KGAR_NUM_SHIFT) |
2716 FM_PCD_KG_KGAR_WSEL_MASK);
2717
2718 /* if we ever want to write 1 by 1, use:
2719 sel = (uint8_t)(0x01 << (7- (entryId % CLS_PLAN_NUM_PER_GRP)));
2720 */
2721 }
2722
FmPcdKgBuildWritePortSchemeBindActionReg(uint8_t hardwarePortId)2723 uint32_t FmPcdKgBuildWritePortSchemeBindActionReg(uint8_t hardwarePortId)
2724 {
2725
2726 return (uint32_t)(FM_KG_KGAR_GO |
2727 FM_KG_KGAR_WRITE |
2728 FM_PCD_KG_KGAR_SEL_PORT_ENTRY |
2729 hardwarePortId |
2730 FM_PCD_KG_KGAR_SEL_PORT_WSEL_SP);
2731 }
2732
FmPcdKgBuildReadPortSchemeBindActionReg(uint8_t hardwarePortId)2733 uint32_t FmPcdKgBuildReadPortSchemeBindActionReg(uint8_t hardwarePortId)
2734 {
2735
2736 return (uint32_t)(FM_KG_KGAR_GO |
2737 FM_KG_KGAR_READ |
2738 FM_PCD_KG_KGAR_SEL_PORT_ENTRY |
2739 hardwarePortId |
2740 FM_PCD_KG_KGAR_SEL_PORT_WSEL_SP);
2741 }
2742
FmPcdKgBuildWritePortClsPlanBindActionReg(uint8_t hardwarePortId)2743 uint32_t FmPcdKgBuildWritePortClsPlanBindActionReg(uint8_t hardwarePortId)
2744 {
2745
2746 return (uint32_t)(FM_KG_KGAR_GO |
2747 FM_KG_KGAR_WRITE |
2748 FM_PCD_KG_KGAR_SEL_PORT_ENTRY |
2749 hardwarePortId |
2750 FM_PCD_KG_KGAR_SEL_PORT_WSEL_CPP);
2751 }
2752
FmPcdKgGetClsPlanGrpBase(t_Handle h_FmPcd,uint8_t clsPlanGrp)2753 uint8_t FmPcdKgGetClsPlanGrpBase(t_Handle h_FmPcd, uint8_t clsPlanGrp)
2754 {
2755 t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
2756
2757 return p_FmPcd->p_FmPcdKg->clsPlanGrps[clsPlanGrp].baseEntry;
2758 }
2759
FmPcdKgGetClsPlanGrpSize(t_Handle h_FmPcd,uint8_t clsPlanGrp)2760 uint16_t FmPcdKgGetClsPlanGrpSize(t_Handle h_FmPcd, uint8_t clsPlanGrp)
2761 {
2762 t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
2763
2764 return p_FmPcd->p_FmPcdKg->clsPlanGrps[clsPlanGrp].sizeOfGrp;
2765 }
2766
2767
FmPcdKgGetSchemeId(t_Handle h_Scheme)2768 uint8_t FmPcdKgGetSchemeId(t_Handle h_Scheme)
2769 {
2770 return ((t_FmPcdKgScheme*)h_Scheme)->schemeId;
2771
2772 }
2773
2774 #if (DPAA_VERSION >= 11)
FmPcdKgGetVspe(t_Handle h_Scheme)2775 bool FmPcdKgGetVspe(t_Handle h_Scheme)
2776 {
2777 return ((t_FmPcdKgScheme*)h_Scheme)->vspe;
2778
2779 }
2780 #endif /* (DPAA_VERSION >= 11) */
2781
FmPcdKgGetRelativeSchemeId(t_Handle h_FmPcd,uint8_t schemeId)2782 uint8_t FmPcdKgGetRelativeSchemeId(t_Handle h_FmPcd, uint8_t schemeId)
2783 {
2784 t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
2785 uint8_t i;
2786
2787 for (i = 0;i<p_FmPcd->p_FmPcdKg->numOfSchemes;i++)
2788 if (p_FmPcd->p_FmPcdKg->schemesIds[i] == schemeId)
2789 return i;
2790
2791 if (i == p_FmPcd->p_FmPcdKg->numOfSchemes)
2792 REPORT_ERROR(MAJOR, E_NOT_IN_RANGE, ("Scheme is out of partition range"));
2793
2794 return FM_PCD_KG_NUM_OF_SCHEMES;
2795 }
2796
FmPcdKgGetSchemeHandle(t_Handle h_FmPcd,uint8_t relativeSchemeId)2797 t_Handle FmPcdKgGetSchemeHandle(t_Handle h_FmPcd, uint8_t relativeSchemeId)
2798 {
2799 t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
2800
2801 ASSERT_COND(p_FmPcd);
2802
2803 /* check that schemeId is in range */
2804 if (relativeSchemeId >= p_FmPcd->p_FmPcdKg->numOfSchemes)
2805 {
2806 REPORT_ERROR(MAJOR, E_NOT_IN_RANGE, ("relative-scheme-id %d!", relativeSchemeId));
2807 return NULL;
2808 }
2809
2810 if (!FmPcdKgIsSchemeValidSw(&p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId]))
2811 return NULL;
2812
2813 return &p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId];
2814 }
2815
FmPcdKgIsSchemeHasOwners(t_Handle h_Scheme)2816 bool FmPcdKgIsSchemeHasOwners(t_Handle h_Scheme)
2817 {
2818 return (((t_FmPcdKgScheme*)h_Scheme)->owners == 0)?FALSE:TRUE;
2819 }
2820
FmPcdKgCcGetSetParams(t_Handle h_FmPcd,t_Handle h_Scheme,uint32_t requiredAction,uint32_t value)2821 t_Error FmPcdKgCcGetSetParams(t_Handle h_FmPcd, t_Handle h_Scheme, uint32_t requiredAction, uint32_t value)
2822 {
2823 t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
2824 uint8_t relativeSchemeId, physicalSchemeId;
2825 uint32_t tmpKgarReg, tmpReg32 = 0, intFlags;
2826 t_Error err;
2827 t_FmPcdKgScheme *p_Scheme = (t_FmPcdKgScheme*)h_Scheme;
2828
2829 SANITY_CHECK_RETURN_VALUE(h_FmPcd, E_INVALID_HANDLE, 0);
2830 SANITY_CHECK_RETURN_VALUE(p_FmPcd->p_FmPcdKg, E_INVALID_HANDLE, 0);
2831 SANITY_CHECK_RETURN_VALUE(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE, 0);
2832
2833 /* Calling function locked all PCD modules, so no need to lock here */
2834
2835 if (!FmPcdKgIsSchemeValidSw(h_Scheme))
2836 RETURN_ERROR(MAJOR, E_ALREADY_EXISTS, ("Scheme is Invalid"));
2837
2838 if (p_FmPcd->h_Hc)
2839 {
2840 err = FmHcPcdKgCcGetSetParams(p_FmPcd->h_Hc, h_Scheme, requiredAction, value);
2841
2842 UpdateRequiredActionFlag(h_Scheme,TRUE);
2843 FmPcdKgUpdateRequiredAction(h_Scheme,requiredAction);
2844 return err;
2845 }
2846
2847 physicalSchemeId = p_Scheme->schemeId;
2848
2849 relativeSchemeId = FmPcdKgGetRelativeSchemeId(p_FmPcd, physicalSchemeId);
2850 if (relativeSchemeId >= FM_PCD_KG_NUM_OF_SCHEMES)
2851 RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, NO_MSG);
2852
2853 if (!p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].requiredActionFlag ||
2854 !(p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].requiredAction & requiredAction))
2855 {
2856 if (requiredAction & UPDATE_NIA_ENQ_WITHOUT_DMA)
2857 {
2858 switch (p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].nextEngine)
2859 {
2860 case (e_FM_PCD_DONE):
2861 if (p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].doneAction == e_FM_PCD_ENQ_FRAME)
2862 {
2863 tmpKgarReg = FmPcdKgBuildReadSchemeActionReg(physicalSchemeId);
2864 intFlags = KgHwLock(p_FmPcd->p_FmPcdKg);
2865 WriteKgarWait(p_FmPcd, tmpKgarReg);
2866 tmpReg32 = GET_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_mode);
2867 ASSERT_COND(tmpReg32 & (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME));
2868 WRITE_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_mode, tmpReg32 | NIA_BMI_AC_ENQ_FRAME_WITHOUT_DMA);
2869 /* call indirect command for scheme write */
2870 tmpKgarReg = FmPcdKgBuildWriteSchemeActionReg(physicalSchemeId, FALSE);
2871 WriteKgarWait(p_FmPcd, tmpKgarReg);
2872 KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags);
2873 }
2874 break;
2875 case (e_FM_PCD_PLCR):
2876 if (!p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].directPlcr ||
2877 (p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].extractedOrs &&
2878 p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].bitOffsetInPlcrProfile) ||
2879 p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].nextRelativePlcrProfile)
2880 {
2881 RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("In this situation PP can not be with distribution and has to be shared"));
2882 }
2883 err = FmPcdPlcrCcGetSetParams(h_FmPcd, p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].relativeProfileId, requiredAction);
2884 if (err)
2885 {
2886 RETURN_ERROR(MAJOR, err, NO_MSG);
2887 }
2888 break;
2889 default:
2890 RETURN_ERROR(MAJOR, E_INVALID_VALUE,("in this situation the next engine after scheme can be or PLCR or ENQ_FRAME"));
2891 }
2892 }
2893 if (requiredAction & UPDATE_KG_NIA_CC_WA)
2894 {
2895 if (p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].nextEngine == e_FM_PCD_CC)
2896 {
2897 tmpKgarReg = FmPcdKgBuildReadSchemeActionReg(physicalSchemeId);
2898 intFlags = KgHwLock(p_FmPcd->p_FmPcdKg);
2899 WriteKgarWait(p_FmPcd, tmpKgarReg);
2900 tmpReg32 = GET_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_mode);
2901 ASSERT_COND(tmpReg32 & (NIA_ENG_FM_CTL | NIA_FM_CTL_AC_CC));
2902 tmpReg32 &= ~NIA_FM_CTL_AC_CC;
2903 WRITE_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_mode, tmpReg32 | NIA_FM_CTL_AC_PRE_CC);
2904 /* call indirect command for scheme write */
2905 tmpKgarReg = FmPcdKgBuildWriteSchemeActionReg(physicalSchemeId, FALSE);
2906 WriteKgarWait(p_FmPcd, tmpKgarReg);
2907 KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags);
2908 }
2909 }
2910 if (requiredAction & UPDATE_KG_OPT_MODE)
2911 {
2912 tmpKgarReg = FmPcdKgBuildReadSchemeActionReg(physicalSchemeId);
2913 intFlags = KgHwLock(p_FmPcd->p_FmPcdKg);
2914 WriteKgarWait(p_FmPcd, tmpKgarReg);
2915 WRITE_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_om, value);
2916 /* call indirect command for scheme write */
2917 tmpKgarReg = FmPcdKgBuildWriteSchemeActionReg(physicalSchemeId, FALSE);
2918 WriteKgarWait(p_FmPcd, tmpKgarReg);
2919 KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags);
2920 }
2921 if (requiredAction & UPDATE_KG_NIA)
2922 {
2923 tmpKgarReg = FmPcdKgBuildReadSchemeActionReg(physicalSchemeId);
2924 intFlags = KgHwLock(p_FmPcd->p_FmPcdKg);
2925 WriteKgarWait(p_FmPcd, tmpKgarReg);
2926 tmpReg32 = GET_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_mode);
2927 tmpReg32 &= ~(NIA_ENG_MASK | NIA_AC_MASK);
2928 tmpReg32 |= value;
2929 WRITE_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_mode, tmpReg32);
2930 /* call indirect command for scheme write */
2931 tmpKgarReg = FmPcdKgBuildWriteSchemeActionReg(physicalSchemeId, FALSE);
2932 WriteKgarWait(p_FmPcd, tmpKgarReg);
2933 KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags);
2934 }
2935 }
2936
2937 UpdateRequiredActionFlag(h_Scheme, TRUE);
2938 FmPcdKgUpdateRequiredAction(h_Scheme, requiredAction);
2939
2940 return E_OK;
2941 }
2942 /*********************** End of inter-module routines ************************/
2943
2944
2945 /****************************************/
2946 /* API routines */
2947 /****************************************/
2948
FM_PCD_KgSchemeSet(t_Handle h_FmPcd,t_FmPcdKgSchemeParams * p_SchemeParams)2949 t_Handle FM_PCD_KgSchemeSet(t_Handle h_FmPcd, t_FmPcdKgSchemeParams *p_SchemeParams)
2950 {
2951 t_FmPcd *p_FmPcd;
2952 struct fman_kg_scheme_regs schemeRegs;
2953 struct fman_kg_scheme_regs *p_MemRegs;
2954 uint8_t i;
2955 t_Error err = E_OK;
2956 uint32_t tmpKgarReg;
2957 uint32_t intFlags;
2958 uint8_t physicalSchemeId, relativeSchemeId = 0;
2959 t_FmPcdKgScheme *p_Scheme;
2960
2961 if (p_SchemeParams->modify)
2962 {
2963 p_Scheme = (t_FmPcdKgScheme *)p_SchemeParams->id.h_Scheme;
2964 p_FmPcd = p_Scheme->h_FmPcd;
2965
2966 SANITY_CHECK_RETURN_VALUE(p_FmPcd, E_INVALID_HANDLE, NULL);
2967 SANITY_CHECK_RETURN_VALUE(p_FmPcd->p_FmPcdKg, E_INVALID_HANDLE, NULL);
2968
2969 if (!FmPcdKgIsSchemeValidSw(p_Scheme))
2970 {
2971 REPORT_ERROR(MAJOR, E_ALREADY_EXISTS,
2972 ("Scheme is invalid"));
2973 return NULL;
2974 }
2975
2976 if (!KgSchemeFlagTryLock(p_Scheme))
2977 {
2978 DBG(TRACE, ("Scheme Try Lock - BUSY"));
2979 /* Signal to caller BUSY condition */
2980 p_SchemeParams->id.h_Scheme = NULL;
2981 return NULL;
2982 }
2983 }
2984 else
2985 {
2986 p_FmPcd = (t_FmPcd*)h_FmPcd;
2987
2988 SANITY_CHECK_RETURN_VALUE(p_FmPcd, E_INVALID_HANDLE, NULL);
2989 SANITY_CHECK_RETURN_VALUE(p_FmPcd->p_FmPcdKg, E_INVALID_HANDLE, NULL);
2990
2991 relativeSchemeId = p_SchemeParams->id.relativeSchemeId;
2992 /* check that schemeId is in range */
2993 if (relativeSchemeId >= p_FmPcd->p_FmPcdKg->numOfSchemes)
2994 {
2995 REPORT_ERROR(MAJOR, E_NOT_IN_RANGE, ("relative-scheme-id %d!", relativeSchemeId));
2996 return NULL;
2997 }
2998
2999 p_Scheme = &p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId];
3000 if (FmPcdKgIsSchemeValidSw(p_Scheme))
3001 {
3002 REPORT_ERROR(MAJOR, E_ALREADY_EXISTS,
3003 ("Scheme id (%d)!", relativeSchemeId));
3004 return NULL;
3005 }
3006 /* Clear all fields, scheme may have beed previously used */
3007 memset(p_Scheme, 0, sizeof(t_FmPcdKgScheme));
3008
3009 p_Scheme->schemeId = p_FmPcd->p_FmPcdKg->schemesIds[relativeSchemeId];
3010 p_Scheme->h_FmPcd = p_FmPcd;
3011
3012 p_Scheme->p_Lock = FmPcdAcquireLock(p_FmPcd);
3013 if (!p_Scheme->p_Lock)
3014 REPORT_ERROR(MAJOR, E_NOT_AVAILABLE, ("FM KG Scheme lock obj!"));
3015 }
3016
3017 err = BuildSchemeRegs((t_Handle)p_Scheme, p_SchemeParams, &schemeRegs);
3018 if (err)
3019 {
3020 REPORT_ERROR(MAJOR, err, NO_MSG);
3021 if (p_SchemeParams->modify)
3022 KgSchemeFlagUnlock(p_Scheme);
3023 if (!p_SchemeParams->modify &&
3024 p_Scheme->p_Lock)
3025 FmPcdReleaseLock(p_FmPcd, p_Scheme->p_Lock);
3026 return NULL;
3027 }
3028
3029 if (p_FmPcd->h_Hc)
3030 {
3031 err = FmHcPcdKgSetScheme(p_FmPcd->h_Hc,
3032 (t_Handle)p_Scheme,
3033 &schemeRegs,
3034 p_SchemeParams->schemeCounter.update);
3035 if (p_SchemeParams->modify)
3036 KgSchemeFlagUnlock(p_Scheme);
3037 if (err)
3038 {
3039 if (!p_SchemeParams->modify &&
3040 p_Scheme->p_Lock)
3041 FmPcdReleaseLock(p_FmPcd, p_Scheme->p_Lock);
3042 return NULL;
3043 }
3044 if (!p_SchemeParams->modify)
3045 ValidateSchemeSw(p_Scheme);
3046 return (t_Handle)p_Scheme;
3047 }
3048
3049 physicalSchemeId = p_Scheme->schemeId;
3050
3051 /* configure all 21 scheme registers */
3052 p_MemRegs = &p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs;
3053 intFlags = KgHwLock(p_FmPcd->p_FmPcdKg);
3054 WRITE_UINT32(p_MemRegs->kgse_ppc, schemeRegs.kgse_ppc);
3055 WRITE_UINT32(p_MemRegs->kgse_ccbs, schemeRegs.kgse_ccbs);
3056 WRITE_UINT32(p_MemRegs->kgse_mode, schemeRegs.kgse_mode);
3057 WRITE_UINT32(p_MemRegs->kgse_mv, schemeRegs.kgse_mv);
3058 WRITE_UINT32(p_MemRegs->kgse_dv0, schemeRegs.kgse_dv0);
3059 WRITE_UINT32(p_MemRegs->kgse_dv1, schemeRegs.kgse_dv1);
3060 WRITE_UINT32(p_MemRegs->kgse_ekdv, schemeRegs.kgse_ekdv);
3061 WRITE_UINT32(p_MemRegs->kgse_ekfc, schemeRegs.kgse_ekfc);
3062 WRITE_UINT32(p_MemRegs->kgse_bmch, schemeRegs.kgse_bmch);
3063 WRITE_UINT32(p_MemRegs->kgse_bmcl, schemeRegs.kgse_bmcl);
3064 WRITE_UINT32(p_MemRegs->kgse_hc, schemeRegs.kgse_hc);
3065 WRITE_UINT32(p_MemRegs->kgse_spc, schemeRegs.kgse_spc);
3066 WRITE_UINT32(p_MemRegs->kgse_fqb, schemeRegs.kgse_fqb);
3067 WRITE_UINT32(p_MemRegs->kgse_om, schemeRegs.kgse_om);
3068 WRITE_UINT32(p_MemRegs->kgse_vsp, schemeRegs.kgse_vsp);
3069 for (i=0 ; i<FM_KG_NUM_OF_GENERIC_REGS ; i++)
3070 WRITE_UINT32(p_MemRegs->kgse_gec[i], schemeRegs.kgse_gec[i]);
3071
3072 /* call indirect command for scheme write */
3073 tmpKgarReg = FmPcdKgBuildWriteSchemeActionReg(physicalSchemeId, p_SchemeParams->schemeCounter.update);
3074
3075 WriteKgarWait(p_FmPcd, tmpKgarReg);
3076 KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags);
3077
3078 if (!p_SchemeParams->modify)
3079 ValidateSchemeSw(p_Scheme);
3080 else
3081 KgSchemeFlagUnlock(p_Scheme);
3082
3083 return (t_Handle)p_Scheme;
3084 }
3085
FM_PCD_KgSchemeDelete(t_Handle h_Scheme)3086 t_Error FM_PCD_KgSchemeDelete(t_Handle h_Scheme)
3087 {
3088 t_FmPcd *p_FmPcd;
3089 uint8_t physicalSchemeId;
3090 uint32_t tmpKgarReg, intFlags;
3091 t_Error err = E_OK;
3092 t_FmPcdKgScheme *p_Scheme = (t_FmPcdKgScheme *)h_Scheme;
3093
3094 SANITY_CHECK_RETURN_ERROR(h_Scheme, E_INVALID_HANDLE);
3095
3096 p_FmPcd = (t_FmPcd*)(p_Scheme->h_FmPcd);
3097
3098 UpdateRequiredActionFlag(h_Scheme, FALSE);
3099
3100 /* check that no port is bound to this scheme */
3101 err = InvalidateSchemeSw(h_Scheme);
3102 if (err)
3103 RETURN_ERROR(MINOR, err, NO_MSG);
3104
3105 if (p_FmPcd->h_Hc)
3106 {
3107 err = FmHcPcdKgDeleteScheme(p_FmPcd->h_Hc, h_Scheme);
3108 if (p_Scheme->p_Lock)
3109 FmPcdReleaseLock(p_FmPcd, p_Scheme->p_Lock);
3110 return err;
3111 }
3112
3113 physicalSchemeId = ((t_FmPcdKgScheme *)h_Scheme)->schemeId;
3114
3115 intFlags = KgHwLock(p_FmPcd->p_FmPcdKg);
3116 /* clear mode register, including enable bit */
3117 WRITE_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_mode, 0);
3118
3119 /* call indirect command for scheme write */
3120 tmpKgarReg = FmPcdKgBuildWriteSchemeActionReg(physicalSchemeId, FALSE);
3121
3122 WriteKgarWait(p_FmPcd, tmpKgarReg);
3123 KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags);
3124
3125 if (p_Scheme->p_Lock)
3126 FmPcdReleaseLock(p_FmPcd, p_Scheme->p_Lock);
3127
3128 return E_OK;
3129 }
3130
FM_PCD_KgSchemeGetCounter(t_Handle h_Scheme)3131 uint32_t FM_PCD_KgSchemeGetCounter(t_Handle h_Scheme)
3132 {
3133 t_FmPcd *p_FmPcd;
3134 uint32_t tmpKgarReg, spc, intFlags;
3135 uint8_t physicalSchemeId;
3136
3137 SANITY_CHECK_RETURN_VALUE(h_Scheme, E_INVALID_HANDLE, 0);
3138
3139 p_FmPcd = (t_FmPcd*)(((t_FmPcdKgScheme *)h_Scheme)->h_FmPcd);
3140 if (p_FmPcd->h_Hc)
3141 return FmHcPcdKgGetSchemeCounter(p_FmPcd->h_Hc, h_Scheme);
3142
3143 physicalSchemeId = ((t_FmPcdKgScheme *)h_Scheme)->schemeId;
3144
3145 if (FmPcdKgGetRelativeSchemeId(p_FmPcd, physicalSchemeId) == FM_PCD_KG_NUM_OF_SCHEMES)
3146 REPORT_ERROR(MAJOR, E_NOT_IN_RANGE, NO_MSG);
3147
3148 tmpKgarReg = FmPcdKgBuildReadSchemeActionReg(physicalSchemeId);
3149 intFlags = KgHwLock(p_FmPcd->p_FmPcdKg);
3150 WriteKgarWait(p_FmPcd, tmpKgarReg);
3151 if (!(GET_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_mode) & KG_SCH_MODE_EN))
3152 REPORT_ERROR(MAJOR, E_ALREADY_EXISTS, ("Scheme is Invalid"));
3153 spc = GET_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_spc);
3154 KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags);
3155
3156 return spc;
3157 }
3158
FM_PCD_KgSchemeSetCounter(t_Handle h_Scheme,uint32_t value)3159 t_Error FM_PCD_KgSchemeSetCounter(t_Handle h_Scheme, uint32_t value)
3160 {
3161 t_FmPcd *p_FmPcd;
3162 uint32_t tmpKgarReg, intFlags;
3163 uint8_t physicalSchemeId;
3164
3165 SANITY_CHECK_RETURN_VALUE(h_Scheme, E_INVALID_HANDLE, 0);
3166
3167 p_FmPcd = (t_FmPcd*)(((t_FmPcdKgScheme *)h_Scheme)->h_FmPcd);
3168
3169 if (!FmPcdKgIsSchemeValidSw(h_Scheme))
3170 RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Requested scheme is invalid."));
3171
3172 if (p_FmPcd->h_Hc)
3173 return FmHcPcdKgSetSchemeCounter(p_FmPcd->h_Hc, h_Scheme, value);
3174
3175 physicalSchemeId = ((t_FmPcdKgScheme *)h_Scheme)->schemeId;
3176 /* check that schemeId is in range */
3177 if (FmPcdKgGetRelativeSchemeId(p_FmPcd, physicalSchemeId) == FM_PCD_KG_NUM_OF_SCHEMES)
3178 REPORT_ERROR(MAJOR, E_NOT_IN_RANGE, NO_MSG);
3179
3180 /* read specified scheme into scheme registers */
3181 tmpKgarReg = FmPcdKgBuildReadSchemeActionReg(physicalSchemeId);
3182 intFlags = KgHwLock(p_FmPcd->p_FmPcdKg);
3183 WriteKgarWait(p_FmPcd, tmpKgarReg);
3184 if (!(GET_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_mode) & KG_SCH_MODE_EN))
3185 {
3186 KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags);
3187 RETURN_ERROR(MAJOR, E_ALREADY_EXISTS, ("Scheme is Invalid"));
3188 }
3189
3190 /* change counter value */
3191 WRITE_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_spc, value);
3192
3193 /* call indirect command for scheme write */
3194 tmpKgarReg = FmPcdKgBuildWriteSchemeActionReg(physicalSchemeId, TRUE);
3195
3196 WriteKgarWait(p_FmPcd, tmpKgarReg);
3197 KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags);
3198
3199 return E_OK;
3200 }
3201
FM_PCD_KgSetAdditionalDataAfterParsing(t_Handle h_FmPcd,uint8_t payloadOffset)3202 t_Error FM_PCD_KgSetAdditionalDataAfterParsing(t_Handle h_FmPcd, uint8_t payloadOffset)
3203 {
3204 t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
3205 struct fman_kg_regs *p_Regs;
3206
3207 SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
3208 SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_NULL_POINTER);
3209 SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdKg, E_NULL_POINTER);
3210 SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs, E_NULL_POINTER);
3211
3212 p_Regs = p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs;
3213 if (!FmIsMaster(p_FmPcd->h_Fm))
3214 RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM_PCD_KgSetAdditionalDataAfterParsing - guest mode!"));
3215
3216 WRITE_UINT32(p_Regs->fmkg_fdor,payloadOffset);
3217
3218 return E_OK;
3219 }
3220
FM_PCD_KgSetDfltValue(t_Handle h_FmPcd,uint8_t valueId,uint32_t value)3221 t_Error FM_PCD_KgSetDfltValue(t_Handle h_FmPcd, uint8_t valueId, uint32_t value)
3222 {
3223 t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
3224 struct fman_kg_regs *p_Regs;
3225
3226 SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
3227 SANITY_CHECK_RETURN_ERROR(((valueId == 0) || (valueId == 1)), E_INVALID_VALUE);
3228 SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_NULL_POINTER);
3229 SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdKg, E_NULL_POINTER);
3230 SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs, E_NULL_POINTER);
3231
3232 p_Regs = p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs;
3233
3234 if (!FmIsMaster(p_FmPcd->h_Fm))
3235 RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM_PCD_KgSetDfltValue - guest mode!"));
3236
3237 if (valueId == 0)
3238 WRITE_UINT32(p_Regs->fmkg_gdv0r,value);
3239 else
3240 WRITE_UINT32(p_Regs->fmkg_gdv1r,value);
3241 return E_OK;
3242 }
3243