xref: /freebsd/sys/contrib/ncsw/Peripherals/FM/Pcd/fm_cc.c (revision f39bffc62c1395bde25d152c7f68fdf7cbaab414)
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_cc.c
36 
37  @Description   FM Coarse Classifier implementation
38  *//***************************************************************************/
39 #include <sys/cdefs.h>
40 #include <sys/endian.h>
41 #include "std_ext.h"
42 #include "error_ext.h"
43 #include "string_ext.h"
44 #include "debug_ext.h"
45 #include "fm_pcd_ext.h"
46 #include "fm_muram_ext.h"
47 
48 #include "fm_common.h"
49 #include "fm_pcd.h"
50 #include "fm_hc.h"
51 #include "fm_cc.h"
52 #include "crc64.h"
53 
54 /****************************************/
55 /*       static functions               */
56 /****************************************/
57 
58 
59 static t_Error CcRootTryLock(t_Handle h_FmPcdCcTree)
60 {
61     t_FmPcdCcTree *p_FmPcdCcTree = (t_FmPcdCcTree *)h_FmPcdCcTree;
62 
63     ASSERT_COND(h_FmPcdCcTree);
64 
65     if (FmPcdLockTryLock(p_FmPcdCcTree->p_Lock))
66         return E_OK;
67 
68     return ERROR_CODE(E_BUSY);
69 }
70 
71 static void CcRootReleaseLock(t_Handle h_FmPcdCcTree)
72 {
73     t_FmPcdCcTree *p_FmPcdCcTree = (t_FmPcdCcTree *)h_FmPcdCcTree;
74 
75     ASSERT_COND(h_FmPcdCcTree);
76 
77     FmPcdLockUnlock(p_FmPcdCcTree->p_Lock);
78 }
79 
80 static void UpdateNodeOwner(t_FmPcdCcNode *p_CcNode, bool add)
81 {
82     uint32_t intFlags;
83 
84     ASSERT_COND(p_CcNode);
85 
86     intFlags = XX_LockIntrSpinlock(p_CcNode->h_Spinlock);
87 
88     if (add)
89         p_CcNode->owners++;
90     else
91     {
92         ASSERT_COND(p_CcNode->owners);
93         p_CcNode->owners--;
94     }
95 
96     XX_UnlockIntrSpinlock(p_CcNode->h_Spinlock, intFlags);
97 }
98 
99 static __inline__ t_FmPcdStatsObj* DequeueStatsObj(t_List *p_List)
100 {
101     t_FmPcdStatsObj *p_StatsObj = NULL;
102     t_List *p_Next;
103 
104     if (!NCSW_LIST_IsEmpty(p_List))
105     {
106         p_Next = NCSW_LIST_FIRST(p_List);
107         p_StatsObj = NCSW_LIST_OBJECT(p_Next, t_FmPcdStatsObj, node);
108         ASSERT_COND(p_StatsObj);
109         NCSW_LIST_DelAndInit(p_Next);
110     }
111 
112     return p_StatsObj;
113 }
114 
115 static __inline__ void EnqueueStatsObj(t_List *p_List,
116                                        t_FmPcdStatsObj *p_StatsObj)
117 {
118     NCSW_LIST_AddToTail(&p_StatsObj->node, p_List);
119 }
120 
121 static void FreeStatObjects(t_List *p_List, t_Handle h_FmMuram)
122 {
123     t_FmPcdStatsObj *p_StatsObj;
124 
125     while (!NCSW_LIST_IsEmpty(p_List))
126     {
127         p_StatsObj = DequeueStatsObj(p_List);
128         ASSERT_COND(p_StatsObj);
129 
130         FM_MURAM_FreeMem(h_FmMuram, p_StatsObj->h_StatsAd);
131         FM_MURAM_FreeMem(h_FmMuram, p_StatsObj->h_StatsCounters);
132 
133         XX_Free(p_StatsObj);
134     }
135 }
136 
137 static t_FmPcdStatsObj* GetStatsObj(t_FmPcdCcNode *p_CcNode)
138 {
139     t_FmPcdStatsObj* p_StatsObj;
140     t_Handle h_FmMuram;
141 
142     ASSERT_COND(p_CcNode);
143 
144     /* If 'maxNumOfKeys' was passed, all statistics object were preallocated
145      upon node initialization */
146     if (p_CcNode->maxNumOfKeys)
147     {
148         p_StatsObj = DequeueStatsObj(&p_CcNode->availableStatsLst);
149     }
150     else
151     {
152         h_FmMuram = ((t_FmPcd *)(p_CcNode->h_FmPcd))->h_FmMuram;
153         ASSERT_COND(h_FmMuram);
154 
155         p_StatsObj = XX_Malloc(sizeof(t_FmPcdStatsObj));
156         if (!p_StatsObj)
157         {
158             REPORT_ERROR(MAJOR, E_NO_MEMORY, ("statistics object"));
159             return NULL;
160         }
161 
162         p_StatsObj->h_StatsAd = (t_Handle)FM_MURAM_AllocMem(
163                 h_FmMuram, FM_PCD_CC_AD_ENTRY_SIZE, FM_PCD_CC_AD_TABLE_ALIGN);
164         if (!p_StatsObj->h_StatsAd)
165         {
166             XX_Free(p_StatsObj);
167             REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for statistics ADs"));
168             return NULL;
169         }
170         MemSet8(p_StatsObj->h_StatsAd, 0, FM_PCD_CC_AD_ENTRY_SIZE);
171 
172         p_StatsObj->h_StatsCounters = (t_Handle)FM_MURAM_AllocMem(
173                 h_FmMuram, p_CcNode->countersArraySize,
174                 FM_PCD_CC_AD_TABLE_ALIGN);
175         if (!p_StatsObj->h_StatsCounters)
176         {
177             FM_MURAM_FreeMem(h_FmMuram, p_StatsObj->h_StatsAd);
178             XX_Free(p_StatsObj);
179             REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for statistics counters"));
180             return NULL;
181         }
182         MemSet8(p_StatsObj->h_StatsCounters, 0, p_CcNode->countersArraySize);
183     }
184 
185     return p_StatsObj;
186 }
187 
188 static void PutStatsObj(t_FmPcdCcNode *p_CcNode, t_FmPcdStatsObj *p_StatsObj)
189 {
190     t_Handle h_FmMuram;
191 
192     ASSERT_COND(p_CcNode);
193     ASSERT_COND(p_StatsObj);
194 
195     /* If 'maxNumOfKeys' was passed, all statistics object were preallocated
196      upon node initialization and now will be enqueued back to the list */
197     if (p_CcNode->maxNumOfKeys)
198     {
199         /* Nullify counters */
200         MemSet8(p_StatsObj->h_StatsCounters, 0, p_CcNode->countersArraySize);
201 
202         EnqueueStatsObj(&p_CcNode->availableStatsLst, p_StatsObj);
203     }
204     else
205     {
206         h_FmMuram = ((t_FmPcd *)(p_CcNode->h_FmPcd))->h_FmMuram;
207         ASSERT_COND(h_FmMuram);
208 
209         FM_MURAM_FreeMem(h_FmMuram, p_StatsObj->h_StatsAd);
210         FM_MURAM_FreeMem(h_FmMuram, p_StatsObj->h_StatsCounters);
211 
212         XX_Free(p_StatsObj);
213     }
214 }
215 
216 static void SetStatsCounters(t_AdOfTypeStats *p_StatsAd,
217                              uint32_t statsCountersAddr)
218 {
219     uint32_t tmp = (statsCountersAddr & FM_PCD_AD_STATS_COUNTERS_ADDR_MASK);
220 
221     WRITE_UINT32(p_StatsAd->statsTableAddr, tmp);
222 }
223 
224 
225 static void UpdateStatsAd(t_FmPcdCcStatsParams *p_FmPcdCcStatsParams,
226                           t_Handle h_Ad, uint64_t physicalMuramBase)
227 {
228     t_AdOfTypeStats *p_StatsAd;
229     uint32_t statsCountersAddr, nextActionAddr, tmp;
230 #if (DPAA_VERSION >= 11)
231     uint32_t frameLengthRangesAddr;
232 #endif /* (DPAA_VERSION >= 11) */
233 
234     p_StatsAd = (t_AdOfTypeStats *)p_FmPcdCcStatsParams->h_StatsAd;
235 
236     tmp = FM_PCD_AD_STATS_TYPE;
237 
238 #if (DPAA_VERSION >= 11)
239     if (p_FmPcdCcStatsParams->h_StatsFLRs)
240     {
241         frameLengthRangesAddr = (uint32_t)((XX_VirtToPhys(
242                 p_FmPcdCcStatsParams->h_StatsFLRs) - physicalMuramBase));
243         tmp |= (frameLengthRangesAddr & FM_PCD_AD_STATS_FLR_ADDR_MASK);
244     }
245 #endif /* (DPAA_VERSION >= 11) */
246     WRITE_UINT32(p_StatsAd->profileTableAddr, tmp);
247 
248     nextActionAddr = (uint32_t)((XX_VirtToPhys(h_Ad) - physicalMuramBase));
249     tmp = 0;
250     tmp |= (uint32_t)((nextActionAddr << FM_PCD_AD_STATS_NEXT_ACTION_SHIFT)
251             & FM_PCD_AD_STATS_NEXT_ACTION_MASK);
252     tmp |= (FM_PCD_AD_STATS_NAD_EN | FM_PCD_AD_STATS_OP_CODE);
253 
254 #if (DPAA_VERSION >= 11)
255     if (p_FmPcdCcStatsParams->h_StatsFLRs)
256         tmp |= FM_PCD_AD_STATS_FLR_EN;
257 #endif /* (DPAA_VERSION >= 11) */
258 
259     WRITE_UINT32(p_StatsAd->nextActionIndx, tmp);
260 
261     statsCountersAddr = (uint32_t)((XX_VirtToPhys(
262             p_FmPcdCcStatsParams->h_StatsCounters) - physicalMuramBase));
263     SetStatsCounters(p_StatsAd, statsCountersAddr);
264 }
265 
266 static void FillAdOfTypeContLookup(t_Handle h_Ad,
267                                    t_FmPcdCcStatsParams *p_FmPcdCcStatsParams,
268                                    t_Handle h_FmPcd, t_Handle p_CcNode,
269                                    t_Handle h_Manip, t_Handle h_FrmReplic)
270 {
271     t_FmPcdCcNode *p_Node = (t_FmPcdCcNode *)p_CcNode;
272     t_AdOfTypeContLookup *p_AdContLookup = (t_AdOfTypeContLookup *)h_Ad;
273     t_Handle h_TmpAd;
274     t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
275     uint32_t tmpReg32;
276     t_Handle p_AdNewPtr = NULL;
277 
278     UNUSED(h_Manip);
279     UNUSED(h_FrmReplic);
280 
281     /* there are 3 cases handled in this routine of building a "Continue lookup" type AD.
282      * Case 1: No Manip. The action descriptor is built within the match table.
283      *         p_AdResult = p_AdNewPtr;
284      * Case 2: Manip exists. A new AD is created - p_AdNewPtr. It is initialized
285      *         either in the FmPcdManipUpdateAdResultForCc routine or it was already
286      *         initialized and returned here.
287      *         p_AdResult (within the match table) will be initialized after
288      *         this routine returns and point to the existing AD.
289      * Case 3: Manip exists. The action descriptor is built within the match table.
290      *         FmPcdManipUpdateAdContLookupForCc returns a NULL p_AdNewPtr.
291      */
292 
293     /* As default, the "new" ptr is the current one. i.e. the content of the result
294      * AD will be written into the match table itself (case (1))*/
295     p_AdNewPtr = p_AdContLookup;
296 
297     /* Initialize an action descriptor, if current statistics mode requires an Ad */
298     if (p_FmPcdCcStatsParams)
299     {
300         ASSERT_COND(p_FmPcdCcStatsParams->h_StatsAd);
301         ASSERT_COND(p_FmPcdCcStatsParams->h_StatsCounters);
302 
303         /* Swapping addresses between statistics Ad and the current lookup AD */
304         h_TmpAd = p_FmPcdCcStatsParams->h_StatsAd;
305         p_FmPcdCcStatsParams->h_StatsAd = h_Ad;
306         h_Ad = h_TmpAd;
307 
308         p_AdNewPtr = h_Ad;
309         p_AdContLookup = h_Ad;
310 
311         /* Init statistics Ad and connect current lookup AD as 'next action' from statistics Ad */
312         UpdateStatsAd(p_FmPcdCcStatsParams, h_Ad, p_FmPcd->physicalMuramBase);
313     }
314 
315 #if DPAA_VERSION >= 11
316     if (h_Manip && h_FrmReplic)
317         FmPcdManipUpdateAdContLookupForCc(
318                 h_Manip,
319                 h_Ad,
320                 &p_AdNewPtr,
321                 (uint32_t)((XX_VirtToPhys(
322                         FrmReplicGroupGetSourceTableDescriptor(h_FrmReplic))
323                         - p_FmPcd->physicalMuramBase)));
324     else
325         if (h_FrmReplic)
326             FrmReplicGroupUpdateAd(h_FrmReplic, h_Ad, &p_AdNewPtr);
327         else
328 #endif /* (DPAA_VERSION >= 11) */
329             if (h_Manip)
330                 FmPcdManipUpdateAdContLookupForCc(
331                         h_Manip,
332                         h_Ad,
333                         &p_AdNewPtr,
334 
335 #ifdef FM_CAPWAP_SUPPORT
336                         /*no check for opcode of manip - this step can be reached only with capwap_applic_specific*/
337                         (uint32_t)((XX_VirtToPhys(p_Node->h_AdTable) - p_FmPcd->physicalMuramBase))
338 #else  /* not FM_CAPWAP_SUPPORT */
339                         (uint32_t)((XX_VirtToPhys(p_Node->h_Ad)
340                                 - p_FmPcd->physicalMuramBase))
341 #endif /* not FM_CAPWAP_SUPPORT */
342                         );
343 
344     /* if (p_AdNewPtr = NULL) --> Done. (case (3)) */
345     if (p_AdNewPtr)
346     {
347         /* cases (1) & (2) */
348         tmpReg32 = 0;
349         tmpReg32 |= FM_PCD_AD_CONT_LOOKUP_TYPE;
350         tmpReg32 |=
351                 p_Node->sizeOfExtraction ? ((p_Node->sizeOfExtraction - 1) << 24) :
352                         0;
353         tmpReg32 |= (uint32_t)(XX_VirtToPhys(p_Node->h_AdTable)
354                 - p_FmPcd->physicalMuramBase);
355         WRITE_UINT32(p_AdContLookup->ccAdBase, tmpReg32);
356 
357         tmpReg32 = 0;
358         tmpReg32 |= p_Node->numOfKeys << 24;
359         tmpReg32 |= (p_Node->lclMask ? FM_PCD_AD_CONT_LOOKUP_LCL_MASK : 0);
360         tmpReg32 |=
361                 p_Node->h_KeysMatchTable ? (uint32_t)(XX_VirtToPhys(
362                         p_Node->h_KeysMatchTable) - p_FmPcd->physicalMuramBase) :
363                         0;
364         WRITE_UINT32(p_AdContLookup->matchTblPtr, tmpReg32);
365 
366         tmpReg32 = 0;
367         tmpReg32 |= p_Node->prsArrayOffset << 24;
368         tmpReg32 |= p_Node->offset << 16;
369         tmpReg32 |= p_Node->parseCode;
370         WRITE_UINT32(p_AdContLookup->pcAndOffsets, tmpReg32);
371 
372         MemCpy8((void*)&p_AdContLookup->gmask, p_Node->p_GlblMask,
373                     CC_GLBL_MASK_SIZE);
374     }
375 }
376 
377 static t_Error AllocAndFillAdForContLookupManip(t_Handle h_CcNode)
378 {
379     t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
380     uint32_t intFlags;
381 
382     ASSERT_COND(p_CcNode);
383 
384     intFlags = XX_LockIntrSpinlock(p_CcNode->h_Spinlock);
385 
386     if (!p_CcNode->h_Ad)
387     {
388         if (p_CcNode->maxNumOfKeys)
389             p_CcNode->h_Ad = p_CcNode->h_TmpAd;
390         else
391             p_CcNode->h_Ad = (t_Handle)FM_MURAM_AllocMem(
392                     ((t_FmPcd *)(p_CcNode->h_FmPcd))->h_FmMuram,
393                     FM_PCD_CC_AD_ENTRY_SIZE, FM_PCD_CC_AD_TABLE_ALIGN);
394 
395         XX_UnlockIntrSpinlock(p_CcNode->h_Spinlock, intFlags);
396 
397         if (!p_CcNode->h_Ad)
398             RETURN_ERROR(MAJOR, E_NO_MEMORY,
399                          ("MURAM allocation for CC action descriptor"));
400 
401         MemSet8(p_CcNode->h_Ad, 0, FM_PCD_CC_AD_ENTRY_SIZE);
402 
403         FillAdOfTypeContLookup(p_CcNode->h_Ad, NULL, p_CcNode->h_FmPcd,
404                                p_CcNode, NULL, NULL);
405     }
406     else
407         XX_UnlockIntrSpinlock(p_CcNode->h_Spinlock, intFlags);
408 
409     return E_OK;
410 }
411 
412 static t_Error SetRequiredAction1(
413         t_Handle h_FmPcd, uint32_t requiredAction,
414         t_FmPcdCcKeyAndNextEngineParams *p_CcKeyAndNextEngineParamsTmp,
415         t_Handle h_AdTmp, uint16_t numOfEntries, t_Handle h_Tree)
416 {
417     t_AdOfTypeResult *p_AdTmp = (t_AdOfTypeResult *)h_AdTmp;
418     uint32_t tmpReg32;
419     t_Error err;
420     t_FmPcdCcNode *p_CcNode;
421     int i = 0;
422     uint16_t tmp = 0;
423     uint16_t profileId;
424     uint8_t relativeSchemeId, physicalSchemeId;
425     t_CcNodeInformation ccNodeInfo;
426 
427     for (i = 0; i < numOfEntries; i++)
428     {
429         if (i == 0)
430             h_AdTmp = PTR_MOVE(h_AdTmp, i*FM_PCD_CC_AD_ENTRY_SIZE);
431         else
432             h_AdTmp = PTR_MOVE(h_AdTmp, FM_PCD_CC_AD_ENTRY_SIZE);
433 
434         switch (p_CcKeyAndNextEngineParamsTmp[i].nextEngineParams.nextEngine)
435         {
436             case (e_FM_PCD_CC):
437                 if (requiredAction)
438                 {
439                     p_CcNode =
440                             p_CcKeyAndNextEngineParamsTmp[i].nextEngineParams.params.ccParams.h_CcNode;
441                     ASSERT_COND(p_CcNode);
442                     if (p_CcNode->shadowAction == requiredAction)
443                         break;
444                     if ((requiredAction & UPDATE_CC_WITH_TREE)
445                             && !(p_CcNode->shadowAction & UPDATE_CC_WITH_TREE))
446                     {
447 
448                         memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation));
449                         ccNodeInfo.h_CcNode = h_Tree;
450                         EnqueueNodeInfoToRelevantLst(&p_CcNode->ccTreesLst,
451                                                      &ccNodeInfo, NULL);
452                         p_CcKeyAndNextEngineParamsTmp[i].shadowAction |=
453                                 UPDATE_CC_WITH_TREE;
454                     }
455                     if ((requiredAction & UPDATE_CC_SHADOW_CLEAR)
456                             && !(p_CcNode->shadowAction & UPDATE_CC_SHADOW_CLEAR))
457                     {
458 
459                         p_CcNode->shadowAction = 0;
460                     }
461 
462                     if ((requiredAction & UPDATE_CC_WITH_DELETE_TREE)
463                             && !(p_CcNode->shadowAction
464                                     & UPDATE_CC_WITH_DELETE_TREE))
465                     {
466                         DequeueNodeInfoFromRelevantLst(&p_CcNode->ccTreesLst,
467                                                        h_Tree, NULL);
468                         p_CcKeyAndNextEngineParamsTmp[i].shadowAction |=
469                                 UPDATE_CC_WITH_DELETE_TREE;
470                     }
471                     if (p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].nextEngineParams.nextEngine
472                             != e_FM_PCD_INVALID)
473                         tmp = (uint8_t)(p_CcNode->numOfKeys + 1);
474                     else
475                         tmp = p_CcNode->numOfKeys;
476                     err = SetRequiredAction1(h_FmPcd, requiredAction,
477                                              p_CcNode->keyAndNextEngineParams,
478                                              p_CcNode->h_AdTable, tmp, h_Tree);
479                     if (err != E_OK)
480                         return err;
481                     if (requiredAction != UPDATE_CC_SHADOW_CLEAR)
482                         p_CcNode->shadowAction |= requiredAction;
483                 }
484                 break;
485 
486             case (e_FM_PCD_KG):
487                 if ((requiredAction & UPDATE_NIA_ENQ_WITHOUT_DMA)
488                         && !(p_CcKeyAndNextEngineParamsTmp[i].shadowAction
489                                 & UPDATE_NIA_ENQ_WITHOUT_DMA))
490                 {
491                     physicalSchemeId =
492                             FmPcdKgGetSchemeId(
493                                     p_CcKeyAndNextEngineParamsTmp[i].nextEngineParams.params.kgParams.h_DirectScheme);
494                     relativeSchemeId = FmPcdKgGetRelativeSchemeId(
495                             h_FmPcd, physicalSchemeId);
496                     if (relativeSchemeId == FM_PCD_KG_NUM_OF_SCHEMES)
497                         RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, NO_MSG);
498                     if (!FmPcdKgIsSchemeValidSw(
499                             p_CcKeyAndNextEngineParamsTmp[i].nextEngineParams.params.kgParams.h_DirectScheme))
500                         RETURN_ERROR(MAJOR, E_INVALID_STATE,
501                                      ("Invalid direct scheme."));
502                     if (!KgIsSchemeAlwaysDirect(h_FmPcd, relativeSchemeId))
503                         RETURN_ERROR(
504                                 MAJOR, E_INVALID_STATE,
505                                 ("For this action scheme has to be direct."));
506                     err =
507                             FmPcdKgCcGetSetParams(
508                                     h_FmPcd,
509                                     p_CcKeyAndNextEngineParamsTmp[i].nextEngineParams.params.kgParams.h_DirectScheme,
510                                     requiredAction, 0);
511                     if (err != E_OK)
512                         RETURN_ERROR(MAJOR, err, NO_MSG);
513                     p_CcKeyAndNextEngineParamsTmp[i].shadowAction |=
514                             requiredAction;
515                 }
516                 break;
517 
518             case (e_FM_PCD_PLCR):
519                 if ((requiredAction & UPDATE_NIA_ENQ_WITHOUT_DMA)
520                         && !(p_CcKeyAndNextEngineParamsTmp[i].shadowAction
521                                 & UPDATE_NIA_ENQ_WITHOUT_DMA))
522                 {
523                     if (!p_CcKeyAndNextEngineParamsTmp[i].nextEngineParams.params.plcrParams.overrideParams)
524                         RETURN_ERROR(
525                                 MAJOR,
526                                 E_NOT_SUPPORTED,
527                                 ("In this initialization only overrideFqid can be initialized"));
528                     if (!p_CcKeyAndNextEngineParamsTmp[i].nextEngineParams.params.plcrParams.sharedProfile)
529                         RETURN_ERROR(
530                                 MAJOR,
531                                 E_NOT_SUPPORTED,
532                                 ("In this initialization only overrideFqid can be initialized"));
533                     err =
534                             FmPcdPlcrGetAbsoluteIdByProfileParams(
535                                     h_FmPcd,
536                                     e_FM_PCD_PLCR_SHARED,
537                                     NULL,
538                                     p_CcKeyAndNextEngineParamsTmp[i].nextEngineParams.params.plcrParams.newRelativeProfileId,
539                                     &profileId);
540                     if (err != E_OK)
541                         RETURN_ERROR(MAJOR, err, NO_MSG);
542                     err = FmPcdPlcrCcGetSetParams(h_FmPcd, profileId,
543                                                   requiredAction);
544                     if (err != E_OK)
545                         RETURN_ERROR(MAJOR, err, NO_MSG);
546                     p_CcKeyAndNextEngineParamsTmp[i].shadowAction |=
547                             requiredAction;
548                 }
549                 break;
550 
551             case (e_FM_PCD_DONE):
552                 if ((requiredAction & UPDATE_NIA_ENQ_WITHOUT_DMA)
553                         && !(p_CcKeyAndNextEngineParamsTmp[i].shadowAction
554                                 & UPDATE_NIA_ENQ_WITHOUT_DMA))
555                 {
556                     tmpReg32 = GET_UINT32(p_AdTmp->nia);
557                     if ((tmpReg32 & GET_NIA_BMI_AC_ENQ_FRAME(h_FmPcd))
558                             != GET_NIA_BMI_AC_ENQ_FRAME(h_FmPcd))
559                         RETURN_ERROR(
560                                 MAJOR,
561                                 E_INVALID_STATE,
562                                 ("Next engine was previously assigned not as PCD_DONE"));
563                     tmpReg32 |= NIA_BMI_AC_ENQ_FRAME_WITHOUT_DMA;
564                     WRITE_UINT32(p_AdTmp->nia, tmpReg32);
565                     p_CcKeyAndNextEngineParamsTmp[i].shadowAction |=
566                             requiredAction;
567                 }
568                 break;
569 
570             default:
571                 break;
572         }
573     }
574 
575     return E_OK;
576 }
577 
578 static t_Error SetRequiredAction(
579         t_Handle h_FmPcd, uint32_t requiredAction,
580         t_FmPcdCcKeyAndNextEngineParams *p_CcKeyAndNextEngineParamsTmp,
581         t_Handle h_AdTmp, uint16_t numOfEntries, t_Handle h_Tree)
582 {
583     t_Error err = SetRequiredAction1(h_FmPcd, requiredAction,
584                                      p_CcKeyAndNextEngineParamsTmp, h_AdTmp,
585                                      numOfEntries, h_Tree);
586     if (err != E_OK)
587         return err;
588     return SetRequiredAction1(h_FmPcd, UPDATE_CC_SHADOW_CLEAR,
589                               p_CcKeyAndNextEngineParamsTmp, h_AdTmp,
590                               numOfEntries, h_Tree);
591 }
592 
593 static t_Error ReleaseModifiedDataStructure(
594         t_Handle h_FmPcd, t_List *h_FmPcdOldPointersLst,
595         t_List *h_FmPcdNewPointersLst,
596         t_FmPcdModifyCcKeyAdditionalParams *p_AdditionalParams,
597         bool useShadowStructs)
598 {
599     t_List *p_Pos;
600     t_Error err = E_OK;
601     t_CcNodeInformation ccNodeInfo, *p_CcNodeInformation;
602     t_Handle h_Muram;
603     t_FmPcdCcNode *p_FmPcdCcNextNode, *p_FmPcdCcWorkingOnNode;
604     t_List *p_UpdateLst;
605     uint32_t intFlags;
606 
607     SANITY_CHECK_RETURN_ERROR(h_FmPcd, E_INVALID_HANDLE);
608     SANITY_CHECK_RETURN_ERROR(p_AdditionalParams->h_CurrentNode,
609                               E_INVALID_HANDLE);
610     SANITY_CHECK_RETURN_ERROR(h_FmPcdOldPointersLst, E_INVALID_HANDLE);
611     SANITY_CHECK_RETURN_ERROR(h_FmPcdNewPointersLst, E_INVALID_HANDLE);
612 
613     /* We don't update subtree of the new node with new tree because it was done in the previous stage */
614     if (p_AdditionalParams->h_NodeForAdd)
615     {
616         p_FmPcdCcNextNode = (t_FmPcdCcNode*)p_AdditionalParams->h_NodeForAdd;
617 
618         if (!p_AdditionalParams->tree)
619             p_UpdateLst = &p_FmPcdCcNextNode->ccPrevNodesLst;
620         else
621             p_UpdateLst = &p_FmPcdCcNextNode->ccTreeIdLst;
622 
623         p_CcNodeInformation = FindNodeInfoInReleventLst(
624                 p_UpdateLst, p_AdditionalParams->h_CurrentNode,
625                 p_FmPcdCcNextNode->h_Spinlock);
626 
627         if (p_CcNodeInformation)
628             p_CcNodeInformation->index++;
629         else
630         {
631             memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation));
632             ccNodeInfo.h_CcNode = (t_Handle)p_AdditionalParams->h_CurrentNode;
633             ccNodeInfo.index = 1;
634             EnqueueNodeInfoToRelevantLst(p_UpdateLst, &ccNodeInfo,
635                                          p_FmPcdCcNextNode->h_Spinlock);
636         }
637         if (p_AdditionalParams->h_ManipForAdd)
638         {
639             p_CcNodeInformation = FindNodeInfoInReleventLst(
640                     FmPcdManipGetNodeLstPointedOnThisManip(
641                             p_AdditionalParams->h_ManipForAdd),
642                     p_AdditionalParams->h_CurrentNode,
643                     FmPcdManipGetSpinlock(p_AdditionalParams->h_ManipForAdd));
644 
645             if (p_CcNodeInformation)
646                 p_CcNodeInformation->index++;
647             else
648             {
649                 memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation));
650                 ccNodeInfo.h_CcNode =
651                         (t_Handle)p_AdditionalParams->h_CurrentNode;
652                 ccNodeInfo.index = 1;
653                 EnqueueNodeInfoToRelevantLst(
654                         FmPcdManipGetNodeLstPointedOnThisManip(
655                                 p_AdditionalParams->h_ManipForAdd),
656                         &ccNodeInfo,
657                         FmPcdManipGetSpinlock(
658                                 p_AdditionalParams->h_ManipForAdd));
659             }
660         }
661     }
662 
663     if (p_AdditionalParams->h_NodeForRmv)
664     {
665         p_FmPcdCcNextNode = (t_FmPcdCcNode*)p_AdditionalParams->h_NodeForRmv;
666 
667         if (!p_AdditionalParams->tree)
668         {
669             p_UpdateLst = &p_FmPcdCcNextNode->ccPrevNodesLst;
670             p_FmPcdCcWorkingOnNode =
671                     (t_FmPcdCcNode *)(p_AdditionalParams->h_CurrentNode);
672 
673             for (p_Pos = NCSW_LIST_FIRST(&p_FmPcdCcWorkingOnNode->ccTreesLst);
674                     p_Pos != (&p_FmPcdCcWorkingOnNode->ccTreesLst); p_Pos =
675                             NCSW_LIST_NEXT(p_Pos))
676             {
677                 p_CcNodeInformation = CC_NODE_F_OBJECT(p_Pos);
678 
679                 ASSERT_COND(p_CcNodeInformation->h_CcNode);
680 
681                 err =
682                         SetRequiredAction(
683                                 h_FmPcd,
684                                 UPDATE_CC_WITH_DELETE_TREE,
685                                 &((t_FmPcdCcNode *)(p_AdditionalParams->h_CurrentNode))->keyAndNextEngineParams[p_AdditionalParams->savedKeyIndex],
686                                 PTR_MOVE(((t_FmPcdCcNode *)(p_AdditionalParams->h_CurrentNode))->h_AdTable, p_AdditionalParams->savedKeyIndex*FM_PCD_CC_AD_ENTRY_SIZE),
687                                 1, p_CcNodeInformation->h_CcNode);
688             }
689         }
690         else
691         {
692             p_UpdateLst = &p_FmPcdCcNextNode->ccTreeIdLst;
693 
694             err =
695                     SetRequiredAction(
696                             h_FmPcd,
697                             UPDATE_CC_WITH_DELETE_TREE,
698                             &((t_FmPcdCcTree *)(p_AdditionalParams->h_CurrentNode))->keyAndNextEngineParams[p_AdditionalParams->savedKeyIndex],
699                             UINT_TO_PTR(((t_FmPcdCcTree *)(p_AdditionalParams->h_CurrentNode))->ccTreeBaseAddr + p_AdditionalParams->savedKeyIndex*FM_PCD_CC_AD_ENTRY_SIZE),
700                             1, p_AdditionalParams->h_CurrentNode);
701         }
702         if (err)
703             return err;
704 
705         /* We remove from the subtree of the removed node tree because it wasn't done in the previous stage
706          Update ccPrevNodesLst or ccTreeIdLst of the removed node
707          Update of the node owner */
708         p_CcNodeInformation = FindNodeInfoInReleventLst(
709                 p_UpdateLst, p_AdditionalParams->h_CurrentNode,
710                 p_FmPcdCcNextNode->h_Spinlock);
711 
712         ASSERT_COND(p_CcNodeInformation);
713         ASSERT_COND(p_CcNodeInformation->index);
714 
715         p_CcNodeInformation->index--;
716 
717         if (p_CcNodeInformation->index == 0)
718             DequeueNodeInfoFromRelevantLst(p_UpdateLst,
719                                            p_AdditionalParams->h_CurrentNode,
720                                            p_FmPcdCcNextNode->h_Spinlock);
721 
722         UpdateNodeOwner(p_FmPcdCcNextNode, FALSE);
723 
724         if (p_AdditionalParams->h_ManipForRmv)
725         {
726             p_CcNodeInformation = FindNodeInfoInReleventLst(
727                     FmPcdManipGetNodeLstPointedOnThisManip(
728                             p_AdditionalParams->h_ManipForRmv),
729                     p_AdditionalParams->h_CurrentNode,
730                     FmPcdManipGetSpinlock(p_AdditionalParams->h_ManipForRmv));
731 
732             ASSERT_COND(p_CcNodeInformation);
733             ASSERT_COND(p_CcNodeInformation->index);
734 
735             p_CcNodeInformation->index--;
736 
737             if (p_CcNodeInformation->index == 0)
738                 DequeueNodeInfoFromRelevantLst(
739                         FmPcdManipGetNodeLstPointedOnThisManip(
740                                 p_AdditionalParams->h_ManipForRmv),
741                         p_AdditionalParams->h_CurrentNode,
742                         FmPcdManipGetSpinlock(
743                                 p_AdditionalParams->h_ManipForRmv));
744         }
745     }
746 
747     if (p_AdditionalParams->h_ManipForRmv)
748         FmPcdManipUpdateOwner(p_AdditionalParams->h_ManipForRmv, FALSE);
749 
750     if (p_AdditionalParams->p_StatsObjForRmv)
751         PutStatsObj((t_FmPcdCcNode *)(p_AdditionalParams->h_CurrentNode),
752                     p_AdditionalParams->p_StatsObjForRmv);
753 
754 #if (DPAA_VERSION >= 11)
755     if (p_AdditionalParams->h_FrmReplicForRmv)
756         FrmReplicGroupUpdateOwner(p_AdditionalParams->h_FrmReplicForRmv,
757                                   FALSE/* remove */);
758 #endif /* (DPAA_VERSION >= 11) */
759 
760     if (!useShadowStructs)
761     {
762         h_Muram = FmPcdGetMuramHandle(h_FmPcd);
763         ASSERT_COND(h_Muram);
764 
765         if ((p_AdditionalParams->tree && !((t_FmPcd *)h_FmPcd)->p_CcShadow)
766                 || (!p_AdditionalParams->tree
767                         && !((t_FmPcdCcNode *)(p_AdditionalParams->h_CurrentNode))->maxNumOfKeys))
768         {
769             /* We release new AD which was allocated and updated for copy from to actual AD */
770             for (p_Pos = NCSW_LIST_FIRST(h_FmPcdNewPointersLst);
771                     p_Pos != (h_FmPcdNewPointersLst); p_Pos = NCSW_LIST_NEXT(p_Pos))
772             {
773 
774                 p_CcNodeInformation = CC_NODE_F_OBJECT(p_Pos);
775                 ASSERT_COND(p_CcNodeInformation->h_CcNode);
776                 FM_MURAM_FreeMem(h_Muram, p_CcNodeInformation->h_CcNode);
777             }
778         }
779 
780         /* Free Old data structure if it has to be freed - new data structure was allocated*/
781         if (p_AdditionalParams->p_AdTableOld)
782             FM_MURAM_FreeMem(h_Muram, p_AdditionalParams->p_AdTableOld);
783 
784         if (p_AdditionalParams->p_KeysMatchTableOld)
785             FM_MURAM_FreeMem(h_Muram, p_AdditionalParams->p_KeysMatchTableOld);
786     }
787 
788     /* Update current modified node with changed fields if it's required*/
789     if (!p_AdditionalParams->tree)
790     {
791         if (p_AdditionalParams->p_AdTableNew)
792             ((t_FmPcdCcNode *)(p_AdditionalParams->h_CurrentNode))->h_AdTable =
793                     p_AdditionalParams->p_AdTableNew;
794 
795         if (p_AdditionalParams->p_KeysMatchTableNew)
796             ((t_FmPcdCcNode *)(p_AdditionalParams->h_CurrentNode))->h_KeysMatchTable =
797                     p_AdditionalParams->p_KeysMatchTableNew;
798 
799         /* Locking node's spinlock before updating 'keys and next engine' structure,
800          as it maybe used to retrieve keys statistics */
801         intFlags =
802                 XX_LockIntrSpinlock(
803                         ((t_FmPcdCcNode *)(p_AdditionalParams->h_CurrentNode))->h_Spinlock);
804 
805         ((t_FmPcdCcNode *)(p_AdditionalParams->h_CurrentNode))->numOfKeys =
806                 p_AdditionalParams->numOfKeys;
807 
808         memcpy(((t_FmPcdCcNode *)(p_AdditionalParams->h_CurrentNode))->keyAndNextEngineParams,
809                &p_AdditionalParams->keyAndNextEngineParams,
810                sizeof(t_FmPcdCcKeyAndNextEngineParams) * (CC_MAX_NUM_OF_KEYS));
811 
812         XX_UnlockIntrSpinlock(
813                 ((t_FmPcdCcNode *)(p_AdditionalParams->h_CurrentNode))->h_Spinlock,
814                 intFlags);
815     }
816     else
817     {
818         uint8_t numEntries =
819                 ((t_FmPcdCcTree *)(p_AdditionalParams->h_CurrentNode))->numOfEntries;
820         ASSERT_COND(numEntries < FM_PCD_MAX_NUM_OF_CC_GROUPS);
821         memcpy(&((t_FmPcdCcTree *)(p_AdditionalParams->h_CurrentNode))->keyAndNextEngineParams,
822                &p_AdditionalParams->keyAndNextEngineParams,
823                sizeof(t_FmPcdCcKeyAndNextEngineParams) * numEntries);
824     }
825 
826     ReleaseLst(h_FmPcdOldPointersLst);
827     ReleaseLst(h_FmPcdNewPointersLst);
828 
829     XX_Free(p_AdditionalParams);
830 
831     return E_OK;
832 }
833 
834 static t_Handle BuildNewAd(
835         t_Handle h_Ad,
836         t_FmPcdModifyCcKeyAdditionalParams *p_FmPcdModifyCcKeyAdditionalParams,
837         t_FmPcdCcNode *p_CcNode,
838         t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams)
839 {
840     t_FmPcdCcNode *p_FmPcdCcNodeTmp;
841     t_Handle h_OrigAd = NULL;
842 
843     p_FmPcdCcNodeTmp = (t_FmPcdCcNode*)XX_Malloc(sizeof(t_FmPcdCcNode));
844     if (!p_FmPcdCcNodeTmp)
845     {
846         REPORT_ERROR(MAJOR, E_NO_MEMORY, ("p_FmPcdCcNodeTmp"));
847         return NULL;
848     }
849     memset(p_FmPcdCcNodeTmp, 0, sizeof(t_FmPcdCcNode));
850 
851     p_FmPcdCcNodeTmp->numOfKeys = p_FmPcdModifyCcKeyAdditionalParams->numOfKeys;
852     p_FmPcdCcNodeTmp->h_KeysMatchTable =
853             p_FmPcdModifyCcKeyAdditionalParams->p_KeysMatchTableNew;
854     p_FmPcdCcNodeTmp->h_AdTable =
855             p_FmPcdModifyCcKeyAdditionalParams->p_AdTableNew;
856 
857     p_FmPcdCcNodeTmp->lclMask = p_CcNode->lclMask;
858     p_FmPcdCcNodeTmp->parseCode = p_CcNode->parseCode;
859     p_FmPcdCcNodeTmp->offset = p_CcNode->offset;
860     p_FmPcdCcNodeTmp->prsArrayOffset = p_CcNode->prsArrayOffset;
861     p_FmPcdCcNodeTmp->ctrlFlow = p_CcNode->ctrlFlow;
862     p_FmPcdCcNodeTmp->ccKeySizeAccExtraction = p_CcNode->ccKeySizeAccExtraction;
863     p_FmPcdCcNodeTmp->sizeOfExtraction = p_CcNode->sizeOfExtraction;
864     p_FmPcdCcNodeTmp->glblMaskSize = p_CcNode->glblMaskSize;
865     p_FmPcdCcNodeTmp->p_GlblMask = p_CcNode->p_GlblMask;
866 
867     if (p_FmPcdCcNextEngineParams->nextEngine == e_FM_PCD_CC)
868     {
869         if (p_FmPcdCcNextEngineParams->h_Manip)
870         {
871             h_OrigAd = p_CcNode->h_Ad;
872             if (AllocAndFillAdForContLookupManip(
873                     p_FmPcdCcNextEngineParams->params.ccParams.h_CcNode)
874                     != E_OK)
875             {
876                 REPORT_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
877                 XX_Free(p_FmPcdCcNodeTmp);
878                 return NULL;
879             }
880         }
881         FillAdOfTypeContLookup(h_Ad, NULL, p_CcNode->h_FmPcd, p_FmPcdCcNodeTmp,
882                                h_OrigAd ? NULL : p_FmPcdCcNextEngineParams->h_Manip, NULL);
883     }
884 
885 #if (DPAA_VERSION >= 11)
886     if ((p_FmPcdCcNextEngineParams->nextEngine == e_FM_PCD_FR)
887             && (p_FmPcdCcNextEngineParams->params.frParams.h_FrmReplic))
888     {
889         FillAdOfTypeContLookup(
890                 h_Ad, NULL, p_CcNode->h_FmPcd, p_FmPcdCcNodeTmp,
891                 p_FmPcdCcNextEngineParams->h_Manip,
892                 p_FmPcdCcNextEngineParams->params.frParams.h_FrmReplic);
893     }
894 #endif /* (DPAA_VERSION >= 11) */
895 
896     XX_Free(p_FmPcdCcNodeTmp);
897 
898     return E_OK;
899 }
900 
901 static t_Error DynamicChangeHc(
902         t_Handle h_FmPcd, t_List *h_OldPointersLst, t_List *h_NewPointersLst,
903         t_FmPcdModifyCcKeyAdditionalParams *p_AdditionalParams,
904         bool useShadowStructs)
905 {
906     t_List *p_PosOld, *p_PosNew;
907     uint32_t oldAdAddrOffset, newAdAddrOffset;
908     uint16_t i = 0;
909     t_Error err = E_OK;
910     uint8_t numOfModifiedPtr;
911 
912     ASSERT_COND(h_FmPcd);
913     ASSERT_COND(h_OldPointersLst);
914     ASSERT_COND(h_NewPointersLst);
915 
916     numOfModifiedPtr = (uint8_t)NCSW_LIST_NumOfObjs(h_OldPointersLst);
917 
918     if (numOfModifiedPtr)
919     {
920         p_PosNew = NCSW_LIST_FIRST(h_NewPointersLst);
921         p_PosOld = NCSW_LIST_FIRST(h_OldPointersLst);
922 
923         /* Retrieve address of new AD */
924         newAdAddrOffset = FmPcdCcGetNodeAddrOffsetFromNodeInfo(h_FmPcd,
925                                                                p_PosNew);
926         if (newAdAddrOffset == (uint32_t)ILLEGAL_BASE)
927         {
928             ReleaseModifiedDataStructure(h_FmPcd, h_OldPointersLst,
929                                          h_NewPointersLst,
930                                          p_AdditionalParams, useShadowStructs);
931             RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("New AD address"));
932         }
933 
934         for (i = 0; i < numOfModifiedPtr; i++)
935         {
936             /* Retrieve address of current AD */
937             oldAdAddrOffset = FmPcdCcGetNodeAddrOffsetFromNodeInfo(h_FmPcd,
938                                                                    p_PosOld);
939             if (oldAdAddrOffset == (uint32_t)ILLEGAL_BASE)
940             {
941                 ReleaseModifiedDataStructure(h_FmPcd, h_OldPointersLst,
942                                              h_NewPointersLst,
943                                              p_AdditionalParams,
944                                              useShadowStructs);
945                 RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Old AD address"));
946             }
947 
948             /* Invoke host command to copy from new AD to old AD */
949             err = FmHcPcdCcDoDynamicChange(((t_FmPcd *)h_FmPcd)->h_Hc,
950                                            oldAdAddrOffset, newAdAddrOffset);
951             if (err)
952             {
953                 ReleaseModifiedDataStructure(h_FmPcd, h_OldPointersLst,
954                                              h_NewPointersLst,
955                                              p_AdditionalParams,
956                                              useShadowStructs);
957                 RETURN_ERROR(
958                         MAJOR,
959                         err,
960                         ("For part of nodes changes are done - situation is danger"));
961             }
962 
963             p_PosOld = NCSW_LIST_NEXT(p_PosOld);
964         }
965     }
966     return E_OK;
967 }
968 
969 static t_Error DoDynamicChange(
970         t_Handle h_FmPcd, t_List *h_OldPointersLst, t_List *h_NewPointersLst,
971         t_FmPcdModifyCcKeyAdditionalParams *p_AdditionalParams,
972         bool useShadowStructs)
973 {
974     t_FmPcdCcNode *p_CcNode =
975             (t_FmPcdCcNode *)(p_AdditionalParams->h_CurrentNode);
976     t_List *p_PosNew;
977     t_CcNodeInformation *p_CcNodeInfo;
978     t_FmPcdCcNextEngineParams nextEngineParams;
979     t_Handle h_Ad;
980     uint32_t keySize;
981     t_Error err = E_OK;
982     uint8_t numOfModifiedPtr;
983 
984     ASSERT_COND(h_FmPcd);
985 
986     memset(&nextEngineParams, 0, sizeof(t_FmPcdCcNextEngineParams));
987 
988     numOfModifiedPtr = (uint8_t)NCSW_LIST_NumOfObjs(h_OldPointersLst);
989 
990     if (numOfModifiedPtr)
991     {
992 
993         p_PosNew = NCSW_LIST_FIRST(h_NewPointersLst);
994 
995         /* Invoke host-command to copy from the new Ad to existing Ads */
996         err = DynamicChangeHc(h_FmPcd, h_OldPointersLst, h_NewPointersLst,
997                               p_AdditionalParams, useShadowStructs);
998         if (err)
999             RETURN_ERROR(MAJOR, err, NO_MSG);
1000 
1001 		if (useShadowStructs)
1002 		{
1003 			/* When the host-command above has ended, the old structures are 'free'and we can update
1004 			 them by copying from the new shadow structures. */
1005 			if (p_CcNode->lclMask)
1006 				keySize = (uint32_t)(2 * p_CcNode->ccKeySizeAccExtraction);
1007 			else
1008 				keySize = p_CcNode->ccKeySizeAccExtraction;
1009 
1010 			MemCpy8(p_AdditionalParams->p_KeysMatchTableOld,
1011 					   p_AdditionalParams->p_KeysMatchTableNew,
1012 					   p_CcNode->maxNumOfKeys * keySize * sizeof(uint8_t));
1013 
1014 			MemCpy8(
1015 					p_AdditionalParams->p_AdTableOld,
1016 					p_AdditionalParams->p_AdTableNew,
1017 					(uint32_t)((p_CcNode->maxNumOfKeys + 1)
1018 							* FM_PCD_CC_AD_ENTRY_SIZE));
1019 
1020 			/* Retrieve the address of the allocated Ad */
1021 			p_CcNodeInfo = CC_NODE_F_OBJECT(p_PosNew);
1022 			h_Ad = p_CcNodeInfo->h_CcNode;
1023 
1024 			/* Build a new Ad that holds the old (now updated) structures */
1025 			p_AdditionalParams->p_KeysMatchTableNew =
1026 					p_AdditionalParams->p_KeysMatchTableOld;
1027 			p_AdditionalParams->p_AdTableNew = p_AdditionalParams->p_AdTableOld;
1028 
1029 			nextEngineParams.nextEngine = e_FM_PCD_CC;
1030 			nextEngineParams.params.ccParams.h_CcNode = (t_Handle)p_CcNode;
1031 
1032 			BuildNewAd(h_Ad, p_AdditionalParams, p_CcNode, &nextEngineParams);
1033 
1034 			/* HC to copy from the new Ad (old updated structures) to current Ad (uses shadow structures) */
1035 			err = DynamicChangeHc(h_FmPcd, h_OldPointersLst, h_NewPointersLst,
1036 								  p_AdditionalParams, useShadowStructs);
1037 			if (err)
1038 				RETURN_ERROR(MAJOR, err, NO_MSG);
1039 		}
1040     }
1041 
1042     err = ReleaseModifiedDataStructure(h_FmPcd, h_OldPointersLst,
1043                                        h_NewPointersLst,
1044                                        p_AdditionalParams, useShadowStructs);
1045     if (err)
1046         RETURN_ERROR(MAJOR, err, NO_MSG);
1047 
1048     return E_OK;
1049 }
1050 
1051 #ifdef FM_CAPWAP_SUPPORT
1052 static bool IsCapwapApplSpecific(t_Handle h_Node)
1053 {
1054     t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_Node;
1055     bool isManipForCapwapApplSpecificBuild = FALSE;
1056     int i = 0;
1057 
1058     ASSERT_COND(h_Node);
1059     /* assumption that this function called only for INDEXED_FLOW_ID - so no miss*/
1060     for (i = 0; i < p_CcNode->numOfKeys; i++)
1061     {
1062         if ( p_CcNode->keyAndNextEngineParams[i].nextEngineParams.h_Manip &&
1063                 FmPcdManipIsCapwapApplSpecific(p_CcNode->keyAndNextEngineParams[i].nextEngineParams.h_Manip))
1064         {
1065             isManipForCapwapApplSpecificBuild = TRUE;
1066             break;
1067         }
1068     }
1069     return isManipForCapwapApplSpecificBuild;
1070 
1071 }
1072 #endif /* FM_CAPWAP_SUPPORT */
1073 
1074 static t_Error CcUpdateParam(
1075         t_Handle h_FmPcd, t_Handle h_PcdParams, t_Handle h_FmPort,
1076         t_FmPcdCcKeyAndNextEngineParams *p_CcKeyAndNextEngineParams,
1077         uint16_t numOfEntries, t_Handle h_Ad, bool validate, uint16_t level,
1078         t_Handle h_FmTree, bool modify)
1079 {
1080     t_FmPcdCcNode *p_CcNode;
1081     t_Error err;
1082     uint16_t tmp = 0;
1083     int i = 0;
1084     t_FmPcdCcTree *p_CcTree = (t_FmPcdCcTree *)h_FmTree;
1085 
1086     level++;
1087 
1088     if (p_CcTree->h_IpReassemblyManip)
1089     {
1090         err = FmPcdManipUpdate(h_FmPcd, h_PcdParams, h_FmPort,
1091                                p_CcTree->h_IpReassemblyManip, NULL, validate,
1092                                level, h_FmTree, modify);
1093         if (err)
1094             RETURN_ERROR(MAJOR, err, NO_MSG);
1095     }
1096 
1097     if (p_CcTree->h_CapwapReassemblyManip)
1098     {
1099         err = FmPcdManipUpdate(h_FmPcd, h_PcdParams, h_FmPort,
1100                                p_CcTree->h_CapwapReassemblyManip, NULL, validate,
1101                                level, h_FmTree, modify);
1102         if (err)
1103             RETURN_ERROR(MAJOR, err, NO_MSG);
1104     }
1105 
1106     if (numOfEntries)
1107     {
1108         for (i = 0; i < numOfEntries; i++)
1109         {
1110             if (i == 0)
1111                 h_Ad = PTR_MOVE(h_Ad, i*FM_PCD_CC_AD_ENTRY_SIZE);
1112             else
1113                 h_Ad = PTR_MOVE(h_Ad, FM_PCD_CC_AD_ENTRY_SIZE);
1114 
1115             if (p_CcKeyAndNextEngineParams[i].nextEngineParams.nextEngine
1116                     == e_FM_PCD_CC)
1117             {
1118                 p_CcNode =
1119                         p_CcKeyAndNextEngineParams[i].nextEngineParams.params.ccParams.h_CcNode;
1120                 ASSERT_COND(p_CcNode);
1121 
1122                 if (p_CcKeyAndNextEngineParams[i].nextEngineParams.h_Manip)
1123                 {
1124                     err =
1125                             FmPcdManipUpdate(
1126                                     h_FmPcd,
1127                                     NULL,
1128                                     h_FmPort,
1129                                     p_CcKeyAndNextEngineParams[i].nextEngineParams.h_Manip,
1130                                     h_Ad, validate, level, h_FmTree, modify);
1131                     if (err)
1132                         RETURN_ERROR(MAJOR, err, NO_MSG);
1133                 }
1134 
1135                 if (p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].nextEngineParams.nextEngine
1136                         != e_FM_PCD_INVALID)
1137                     tmp = (uint8_t)(p_CcNode->numOfKeys + 1);
1138                 else
1139                     tmp = p_CcNode->numOfKeys;
1140 
1141                 err = CcUpdateParam(h_FmPcd, h_PcdParams, h_FmPort,
1142                                     p_CcNode->keyAndNextEngineParams, tmp,
1143                                     p_CcNode->h_AdTable, validate, level,
1144                                     h_FmTree, modify);
1145                 if (err)
1146                     RETURN_ERROR(MAJOR, err, NO_MSG);
1147             }
1148             else
1149             {
1150                 if (p_CcKeyAndNextEngineParams[i].nextEngineParams.h_Manip)
1151                 {
1152                     err =
1153                             FmPcdManipUpdate(
1154                                     h_FmPcd,
1155                                     NULL,
1156                                     h_FmPort,
1157                                     p_CcKeyAndNextEngineParams[i].nextEngineParams.h_Manip,
1158                                     h_Ad, validate, level, h_FmTree, modify);
1159                     if (err)
1160                         RETURN_ERROR(MAJOR, err, NO_MSG);
1161                 }
1162             }
1163         }
1164     }
1165 
1166     return E_OK;
1167 }
1168 
1169 static ccPrivateInfo_t IcDefineCode(t_FmPcdCcNodeParams *p_CcNodeParam)
1170 {
1171     switch (p_CcNodeParam->extractCcParams.extractNonHdr.action)
1172     {
1173         case (e_FM_PCD_ACTION_EXACT_MATCH):
1174             switch (p_CcNodeParam->extractCcParams.extractNonHdr.src)
1175             {
1176                 case (e_FM_PCD_EXTRACT_FROM_KEY):
1177                     return CC_PRIVATE_INFO_IC_KEY_EXACT_MATCH;
1178                 case (e_FM_PCD_EXTRACT_FROM_HASH):
1179                     return CC_PRIVATE_INFO_IC_HASH_EXACT_MATCH;
1180                 default:
1181                     return CC_PRIVATE_INFO_NONE;
1182             }
1183 
1184         case (e_FM_PCD_ACTION_INDEXED_LOOKUP):
1185             switch (p_CcNodeParam->extractCcParams.extractNonHdr.src)
1186             {
1187                 case (e_FM_PCD_EXTRACT_FROM_HASH):
1188                     return CC_PRIVATE_INFO_IC_HASH_INDEX_LOOKUP;
1189                 case (e_FM_PCD_EXTRACT_FROM_FLOW_ID):
1190                     return CC_PRIVATE_INFO_IC_DEQ_FQID_INDEX_LOOKUP;
1191                 default:
1192                     return CC_PRIVATE_INFO_NONE;
1193             }
1194 
1195         default:
1196             break;
1197     }
1198 
1199     return CC_PRIVATE_INFO_NONE;
1200 }
1201 
1202 static t_CcNodeInformation * DequeueAdditionalInfoFromRelevantLst(
1203         t_List *p_List)
1204 {
1205     t_CcNodeInformation *p_CcNodeInfo = NULL;
1206 
1207     if (!NCSW_LIST_IsEmpty(p_List))
1208     {
1209         p_CcNodeInfo = CC_NODE_F_OBJECT(p_List->p_Next);
1210         NCSW_LIST_DelAndInit(&p_CcNodeInfo->node);
1211     }
1212 
1213     return p_CcNodeInfo;
1214 }
1215 
1216 void ReleaseLst(t_List *p_List)
1217 {
1218     t_CcNodeInformation *p_CcNodeInfo = NULL;
1219 
1220     if (!NCSW_LIST_IsEmpty(p_List))
1221     {
1222         p_CcNodeInfo = DequeueAdditionalInfoFromRelevantLst(p_List);
1223         while (p_CcNodeInfo)
1224         {
1225             XX_Free(p_CcNodeInfo);
1226             p_CcNodeInfo = DequeueAdditionalInfoFromRelevantLst(p_List);
1227         }
1228     }
1229 
1230     NCSW_LIST_Del(p_List);
1231 }
1232 
1233 static void DeleteNode(t_FmPcdCcNode *p_CcNode)
1234 {
1235     uint32_t i;
1236 
1237     if (!p_CcNode)
1238         return;
1239 
1240     if (p_CcNode->p_GlblMask)
1241     {
1242         XX_Free(p_CcNode->p_GlblMask);
1243         p_CcNode->p_GlblMask = NULL;
1244     }
1245 
1246     if (p_CcNode->h_KeysMatchTable)
1247     {
1248         FM_MURAM_FreeMem(FmPcdGetMuramHandle(p_CcNode->h_FmPcd),
1249                          p_CcNode->h_KeysMatchTable);
1250         p_CcNode->h_KeysMatchTable = NULL;
1251     }
1252 
1253     if (p_CcNode->h_AdTable)
1254     {
1255         FM_MURAM_FreeMem(FmPcdGetMuramHandle(p_CcNode->h_FmPcd),
1256                          p_CcNode->h_AdTable);
1257         p_CcNode->h_AdTable = NULL;
1258     }
1259 
1260     if (p_CcNode->h_Ad)
1261     {
1262         FM_MURAM_FreeMem(FmPcdGetMuramHandle(p_CcNode->h_FmPcd),
1263                          p_CcNode->h_Ad);
1264         p_CcNode->h_Ad = NULL;
1265         p_CcNode->h_TmpAd = NULL;
1266     }
1267 
1268     if (p_CcNode->h_StatsFLRs)
1269     {
1270         FM_MURAM_FreeMem(FmPcdGetMuramHandle(p_CcNode->h_FmPcd),
1271                          p_CcNode->h_StatsFLRs);
1272         p_CcNode->h_StatsFLRs = NULL;
1273     }
1274 
1275     if (p_CcNode->h_Spinlock)
1276     {
1277         XX_FreeSpinlock(p_CcNode->h_Spinlock);
1278         p_CcNode->h_Spinlock = NULL;
1279     }
1280 
1281     /* Restore the original counters pointer instead of the mutual pointer (mutual to all hash buckets) */
1282     if (p_CcNode->isHashBucket
1283             && (p_CcNode->statisticsMode != e_FM_PCD_CC_STATS_MODE_NONE))
1284         p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].p_StatsObj->h_StatsCounters =
1285                 p_CcNode->h_PrivMissStatsCounters;
1286 
1287     /* Releasing all currently used statistics objects, including 'miss' entry */
1288     for (i = 0; i < p_CcNode->numOfKeys + 1; i++)
1289         if (p_CcNode->keyAndNextEngineParams[i].p_StatsObj)
1290             PutStatsObj(p_CcNode,
1291                         p_CcNode->keyAndNextEngineParams[i].p_StatsObj);
1292 
1293     if (!NCSW_LIST_IsEmpty(&p_CcNode->availableStatsLst))
1294     {
1295         t_Handle h_FmMuram = FmPcdGetMuramHandle(p_CcNode->h_FmPcd);
1296         ASSERT_COND(h_FmMuram);
1297 
1298         FreeStatObjects(&p_CcNode->availableStatsLst, h_FmMuram);
1299     }
1300 
1301     NCSW_LIST_Del(&p_CcNode->availableStatsLst);
1302 
1303     ReleaseLst(&p_CcNode->ccPrevNodesLst);
1304     ReleaseLst(&p_CcNode->ccTreeIdLst);
1305     ReleaseLst(&p_CcNode->ccTreesLst);
1306 
1307     XX_Free(p_CcNode);
1308 }
1309 
1310 static void DeleteTree(t_FmPcdCcTree *p_FmPcdTree, t_FmPcd *p_FmPcd)
1311 {
1312     if (p_FmPcdTree)
1313     {
1314         if (p_FmPcdTree->ccTreeBaseAddr)
1315         {
1316             FM_MURAM_FreeMem(FmPcdGetMuramHandle(p_FmPcd),
1317                              UINT_TO_PTR(p_FmPcdTree->ccTreeBaseAddr));
1318             p_FmPcdTree->ccTreeBaseAddr = 0;
1319         }
1320 
1321         ReleaseLst(&p_FmPcdTree->fmPortsLst);
1322 
1323         XX_Free(p_FmPcdTree);
1324     }
1325 }
1326 
1327 static void GetCcExtractKeySize(uint8_t parseCodeRealSize,
1328                                 uint8_t *parseCodeCcSize)
1329 {
1330     if ((parseCodeRealSize > 0) && (parseCodeRealSize < 2))
1331         *parseCodeCcSize = 1;
1332     else
1333         if (parseCodeRealSize == 2)
1334             *parseCodeCcSize = 2;
1335         else
1336             if ((parseCodeRealSize > 2) && (parseCodeRealSize <= 4))
1337                 *parseCodeCcSize = 4;
1338             else
1339                 if ((parseCodeRealSize > 4) && (parseCodeRealSize <= 8))
1340                     *parseCodeCcSize = 8;
1341                 else
1342                     if ((parseCodeRealSize > 8) && (parseCodeRealSize <= 16))
1343                         *parseCodeCcSize = 16;
1344                     else
1345                         if ((parseCodeRealSize > 16)
1346                                 && (parseCodeRealSize <= 24))
1347                             *parseCodeCcSize = 24;
1348                         else
1349                             if ((parseCodeRealSize > 24)
1350                                     && (parseCodeRealSize <= 32))
1351                                 *parseCodeCcSize = 32;
1352                             else
1353                                 if ((parseCodeRealSize > 32)
1354                                         && (parseCodeRealSize <= 40))
1355                                     *parseCodeCcSize = 40;
1356                                 else
1357                                     if ((parseCodeRealSize > 40)
1358                                             && (parseCodeRealSize <= 48))
1359                                         *parseCodeCcSize = 48;
1360                                     else
1361                                         if ((parseCodeRealSize > 48)
1362                                                 && (parseCodeRealSize <= 56))
1363                                             *parseCodeCcSize = 56;
1364                                         else
1365                                             *parseCodeCcSize = 0;
1366 }
1367 
1368 static void GetSizeHeaderField(e_NetHeaderType hdr, t_FmPcdFields field,
1369 		                       uint8_t *parseCodeRealSize)
1370 {
1371     switch (hdr)
1372     {
1373         case (HEADER_TYPE_ETH):
1374             switch (field.eth)
1375             {
1376                 case (NET_HEADER_FIELD_ETH_DA):
1377                     *parseCodeRealSize = 6;
1378                     break;
1379 
1380                 case (NET_HEADER_FIELD_ETH_SA):
1381                     *parseCodeRealSize = 6;
1382                     break;
1383 
1384                 case (NET_HEADER_FIELD_ETH_TYPE):
1385                     *parseCodeRealSize = 2;
1386                     break;
1387 
1388                 default:
1389                     REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported1"));
1390                     *parseCodeRealSize = CC_SIZE_ILLEGAL;
1391                     break;
1392             }
1393             break;
1394 
1395         case (HEADER_TYPE_PPPoE):
1396             switch (field.pppoe)
1397             {
1398                 case (NET_HEADER_FIELD_PPPoE_PID):
1399                     *parseCodeRealSize = 2;
1400                     break;
1401 
1402                 default:
1403                     REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported1"));
1404                     *parseCodeRealSize = CC_SIZE_ILLEGAL;
1405                     break;
1406             }
1407             break;
1408 
1409         case (HEADER_TYPE_VLAN):
1410             switch (field.vlan)
1411             {
1412                 case (NET_HEADER_FIELD_VLAN_TCI):
1413                     *parseCodeRealSize = 2;
1414                     break;
1415 
1416                 default:
1417                     REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported2"));
1418                     *parseCodeRealSize = CC_SIZE_ILLEGAL;
1419                     break;
1420             }
1421             break;
1422 
1423         case (HEADER_TYPE_MPLS):
1424             switch (field.mpls)
1425             {
1426                 case (NET_HEADER_FIELD_MPLS_LABEL_STACK):
1427                     *parseCodeRealSize = 4;
1428                     break;
1429 
1430                 default:
1431                     REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported3"));
1432                     *parseCodeRealSize = CC_SIZE_ILLEGAL;
1433                     break;
1434             }
1435             break;
1436 
1437         case (HEADER_TYPE_IPv4):
1438             switch (field.ipv4)
1439             {
1440                 case (NET_HEADER_FIELD_IPv4_DST_IP):
1441                 case (NET_HEADER_FIELD_IPv4_SRC_IP):
1442                     *parseCodeRealSize = 4;
1443                     break;
1444 
1445                 case (NET_HEADER_FIELD_IPv4_TOS):
1446                 case (NET_HEADER_FIELD_IPv4_PROTO):
1447                     *parseCodeRealSize = 1;
1448                     break;
1449 
1450                 case (NET_HEADER_FIELD_IPv4_DST_IP
1451                         | NET_HEADER_FIELD_IPv4_SRC_IP):
1452                     *parseCodeRealSize = 8;
1453                     break;
1454 
1455                 case (NET_HEADER_FIELD_IPv4_TTL):
1456                     *parseCodeRealSize = 1;
1457                     break;
1458 
1459                 default:
1460                     REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported4"));
1461                     *parseCodeRealSize = CC_SIZE_ILLEGAL;
1462                     break;
1463             }
1464             break;
1465 
1466         case (HEADER_TYPE_IPv6):
1467             switch (field.ipv6)
1468             {
1469                 case (NET_HEADER_FIELD_IPv6_VER | NET_HEADER_FIELD_IPv6_FL
1470                         | NET_HEADER_FIELD_IPv6_TC):
1471                     *parseCodeRealSize = 4;
1472                     break;
1473 
1474                 case (NET_HEADER_FIELD_IPv6_NEXT_HDR):
1475                 case (NET_HEADER_FIELD_IPv6_HOP_LIMIT):
1476                     *parseCodeRealSize = 1;
1477                     break;
1478 
1479                 case (NET_HEADER_FIELD_IPv6_DST_IP):
1480                 case (NET_HEADER_FIELD_IPv6_SRC_IP):
1481                     *parseCodeRealSize = 16;
1482                     break;
1483 
1484                 default:
1485                     REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported5"));
1486                     *parseCodeRealSize = CC_SIZE_ILLEGAL;
1487                     break;
1488             }
1489             break;
1490 
1491         case (HEADER_TYPE_IP):
1492             switch (field.ip)
1493             {
1494                 case (NET_HEADER_FIELD_IP_DSCP):
1495                 case (NET_HEADER_FIELD_IP_PROTO):
1496                     *parseCodeRealSize = 1;
1497                     break;
1498 
1499                 default:
1500                     REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported5"));
1501                     *parseCodeRealSize = CC_SIZE_ILLEGAL;
1502                     break;
1503             }
1504             break;
1505 
1506         case (HEADER_TYPE_GRE):
1507             switch (field.gre)
1508             {
1509                 case (NET_HEADER_FIELD_GRE_TYPE):
1510                     *parseCodeRealSize = 2;
1511                     break;
1512 
1513                 default:
1514                     REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported6"));
1515                     *parseCodeRealSize = CC_SIZE_ILLEGAL;
1516                     break;
1517             }
1518             break;
1519 
1520         case (HEADER_TYPE_MINENCAP):
1521             switch (field.minencap)
1522             {
1523                 case (NET_HEADER_FIELD_MINENCAP_TYPE):
1524                     *parseCodeRealSize = 1;
1525                     break;
1526 
1527                 case (NET_HEADER_FIELD_MINENCAP_DST_IP):
1528                 case (NET_HEADER_FIELD_MINENCAP_SRC_IP):
1529                     *parseCodeRealSize = 4;
1530                     break;
1531 
1532                 case (NET_HEADER_FIELD_MINENCAP_SRC_IP
1533                         | NET_HEADER_FIELD_MINENCAP_DST_IP):
1534                     *parseCodeRealSize = 8;
1535                     break;
1536 
1537                 default:
1538                     REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported7"));
1539                     *parseCodeRealSize = CC_SIZE_ILLEGAL;
1540                     break;
1541             }
1542             break;
1543 
1544         case (HEADER_TYPE_TCP):
1545             switch (field.tcp)
1546             {
1547                 case (NET_HEADER_FIELD_TCP_PORT_SRC):
1548                 case (NET_HEADER_FIELD_TCP_PORT_DST):
1549                     *parseCodeRealSize = 2;
1550                     break;
1551 
1552                 case (NET_HEADER_FIELD_TCP_PORT_SRC
1553                         | NET_HEADER_FIELD_TCP_PORT_DST):
1554                     *parseCodeRealSize = 4;
1555                     break;
1556 
1557                 default:
1558                     REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported8"));
1559                     *parseCodeRealSize = CC_SIZE_ILLEGAL;
1560                     break;
1561             }
1562             break;
1563 
1564         case (HEADER_TYPE_UDP):
1565             switch (field.udp)
1566             {
1567                 case (NET_HEADER_FIELD_UDP_PORT_SRC):
1568                 case (NET_HEADER_FIELD_UDP_PORT_DST):
1569                     *parseCodeRealSize = 2;
1570                     break;
1571 
1572                 case (NET_HEADER_FIELD_UDP_PORT_SRC
1573                         | NET_HEADER_FIELD_UDP_PORT_DST):
1574                     *parseCodeRealSize = 4;
1575                     break;
1576 
1577                 default:
1578                     REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported9"));
1579                     *parseCodeRealSize = CC_SIZE_ILLEGAL;
1580                     break;
1581             }
1582             break;
1583 
1584         default:
1585             REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported10"));
1586             *parseCodeRealSize = CC_SIZE_ILLEGAL;
1587             break;
1588     }
1589 }
1590 
1591 t_Error ValidateNextEngineParams(
1592         t_Handle h_FmPcd, t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams,
1593         e_FmPcdCcStatsMode statsMode)
1594 {
1595     uint16_t absoluteProfileId;
1596     t_Error err = E_OK;
1597     uint8_t relativeSchemeId;
1598 
1599     if ((statsMode == e_FM_PCD_CC_STATS_MODE_NONE)
1600             && (p_FmPcdCcNextEngineParams->statisticsEn))
1601         RETURN_ERROR(
1602                 MAJOR,
1603                 E_CONFLICT,
1604                 ("Statistics are requested for a key, but statistics mode was set"
1605                 "to 'NONE' upon initialization"));
1606 
1607     switch (p_FmPcdCcNextEngineParams->nextEngine)
1608     {
1609         case (e_FM_PCD_INVALID):
1610             err = E_NOT_SUPPORTED;
1611             break;
1612 
1613         case (e_FM_PCD_DONE):
1614             if ((p_FmPcdCcNextEngineParams->params.enqueueParams.action
1615                     == e_FM_PCD_ENQ_FRAME)
1616                     && p_FmPcdCcNextEngineParams->params.enqueueParams.overrideFqid)
1617             {
1618                 if (!p_FmPcdCcNextEngineParams->params.enqueueParams.newFqid)
1619                     RETURN_ERROR(
1620                             MAJOR,
1621                             E_CONFLICT,
1622                             ("When overrideFqid is set, newFqid must not be zero"));
1623                 if (p_FmPcdCcNextEngineParams->params.enqueueParams.newFqid
1624                         & ~0x00FFFFFF)
1625                     RETURN_ERROR(
1626                             MAJOR, E_INVALID_VALUE,
1627                             ("fqidForCtrlFlow must be between 1 and 2^24-1"));
1628             }
1629             break;
1630 
1631         case (e_FM_PCD_KG):
1632             relativeSchemeId =
1633                     FmPcdKgGetRelativeSchemeId(
1634                             h_FmPcd,
1635                             FmPcdKgGetSchemeId(
1636                                     p_FmPcdCcNextEngineParams->params.kgParams.h_DirectScheme));
1637             if (relativeSchemeId == FM_PCD_KG_NUM_OF_SCHEMES)
1638                 RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, NO_MSG);
1639             if (!FmPcdKgIsSchemeValidSw(
1640                     p_FmPcdCcNextEngineParams->params.kgParams.h_DirectScheme))
1641                 RETURN_ERROR(MAJOR, E_INVALID_STATE,
1642                              ("not valid schemeIndex in KG next engine param"));
1643             if (!KgIsSchemeAlwaysDirect(h_FmPcd, relativeSchemeId))
1644                 RETURN_ERROR(
1645                         MAJOR,
1646                         E_INVALID_STATE,
1647                         ("CC Node may point only to a scheme that is always direct."));
1648             break;
1649 
1650         case (e_FM_PCD_PLCR):
1651             if (p_FmPcdCcNextEngineParams->params.plcrParams.overrideParams)
1652             {
1653                 /* if private policer profile, it may be uninitialized yet, therefore no checks are done at this stage */
1654                 if (p_FmPcdCcNextEngineParams->params.plcrParams.sharedProfile)
1655                 {
1656                     err =
1657                             FmPcdPlcrGetAbsoluteIdByProfileParams(
1658                                     h_FmPcd,
1659                                     e_FM_PCD_PLCR_SHARED,
1660                                     NULL,
1661                                     p_FmPcdCcNextEngineParams->params.plcrParams.newRelativeProfileId,
1662                                     &absoluteProfileId);
1663                     if (err)
1664                         RETURN_ERROR(MAJOR, err,
1665                                      ("Shared profile offset is out of range"));
1666                     if (!FmPcdPlcrIsProfileValid(h_FmPcd, absoluteProfileId))
1667                         RETURN_ERROR(MAJOR, E_INVALID_STATE,
1668                                      ("Invalid profile"));
1669                 }
1670             }
1671             break;
1672 
1673         case (e_FM_PCD_HASH):
1674             p_FmPcdCcNextEngineParams->nextEngine = e_FM_PCD_CC;
1675         case (e_FM_PCD_CC):
1676             if (!p_FmPcdCcNextEngineParams->params.ccParams.h_CcNode)
1677                 RETURN_ERROR(MAJOR, E_NULL_POINTER,
1678                              ("handler to next Node is NULL"));
1679             break;
1680 
1681 #if (DPAA_VERSION >= 11)
1682         case (e_FM_PCD_FR):
1683             if (!p_FmPcdCcNextEngineParams->params.frParams.h_FrmReplic)
1684                 err = E_NOT_SUPPORTED;
1685             break;
1686 #endif /* (DPAA_VERSION >= 11) */
1687 
1688         default:
1689             RETURN_ERROR(MAJOR, E_INVALID_STATE,
1690                          ("Next engine is not correct"));
1691     }
1692 
1693 
1694     return err;
1695 }
1696 
1697 static uint8_t GetGenParseCode(e_FmPcdExtractFrom src,
1698                                uint32_t offset, bool glblMask,
1699                                uint8_t *parseArrayOffset, bool fromIc,
1700                                ccPrivateInfo_t icCode)
1701 {
1702     if (!fromIc)
1703     {
1704         switch (src)
1705         {
1706             case (e_FM_PCD_EXTRACT_FROM_FRAME_START):
1707                 if (glblMask)
1708                     return CC_PC_GENERIC_WITH_MASK;
1709                 else
1710                     return CC_PC_GENERIC_WITHOUT_MASK;
1711 
1712             case (e_FM_PCD_EXTRACT_FROM_CURR_END_OF_PARSE):
1713                 *parseArrayOffset = CC_PC_PR_NEXT_HEADER_OFFSET;
1714                 if (offset)
1715                     return CC_PR_OFFSET;
1716                 else
1717                     return CC_PR_WITHOUT_OFFSET;
1718 
1719             default:
1720                 REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal 'extract from' src"));
1721                 return CC_PC_ILLEGAL;
1722         }
1723     }
1724     else
1725     {
1726         switch (icCode)
1727         {
1728             case (CC_PRIVATE_INFO_IC_KEY_EXACT_MATCH):
1729                 *parseArrayOffset = 0x50;
1730                 return CC_PC_GENERIC_IC_GMASK;
1731 
1732             case (CC_PRIVATE_INFO_IC_HASH_EXACT_MATCH):
1733                 *parseArrayOffset = 0x48;
1734                 return CC_PC_GENERIC_IC_GMASK;
1735 
1736             case (CC_PRIVATE_INFO_IC_HASH_INDEX_LOOKUP):
1737                 *parseArrayOffset = 0x48;
1738                 return CC_PC_GENERIC_IC_HASH_INDEXED;
1739 
1740             case (CC_PRIVATE_INFO_IC_DEQ_FQID_INDEX_LOOKUP):
1741                 *parseArrayOffset = 0x16;
1742                 return CC_PC_GENERIC_IC_HASH_INDEXED;
1743 
1744             default:
1745                 REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal 'extract from' src"));
1746                 break;
1747         }
1748     }
1749 
1750     return CC_PC_ILLEGAL;
1751 }
1752 
1753 static uint8_t GetFullFieldParseCode(e_NetHeaderType hdr, e_FmPcdHdrIndex index,
1754                                      t_FmPcdFields field)
1755 {
1756     switch (hdr)
1757     {
1758         case (HEADER_TYPE_NONE):
1759             ASSERT_COND(FALSE);
1760             return CC_PC_ILLEGAL;
1761 
1762         case (HEADER_TYPE_ETH):
1763             switch (field.eth)
1764             {
1765                 case (NET_HEADER_FIELD_ETH_DA):
1766                     return CC_PC_FF_MACDST;
1767                 case (NET_HEADER_FIELD_ETH_SA):
1768                     return CC_PC_FF_MACSRC;
1769                 case (NET_HEADER_FIELD_ETH_TYPE):
1770                     return CC_PC_FF_ETYPE;
1771                 default:
1772                     REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
1773                     return CC_PC_ILLEGAL;
1774             }
1775 
1776         case (HEADER_TYPE_VLAN):
1777             switch (field.vlan)
1778             {
1779                 case (NET_HEADER_FIELD_VLAN_TCI):
1780                     if ((index == e_FM_PCD_HDR_INDEX_NONE)
1781                             || (index == e_FM_PCD_HDR_INDEX_1))
1782                         return CC_PC_FF_TCI1;
1783                     if (index == e_FM_PCD_HDR_INDEX_LAST)
1784                         return CC_PC_FF_TCI2;
1785                     REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
1786                     return CC_PC_ILLEGAL;
1787                 default:
1788                     REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
1789                     return CC_PC_ILLEGAL;
1790             }
1791 
1792         case (HEADER_TYPE_MPLS):
1793             switch (field.mpls)
1794             {
1795                 case (NET_HEADER_FIELD_MPLS_LABEL_STACK):
1796                     if ((index == e_FM_PCD_HDR_INDEX_NONE)
1797                             || (index == e_FM_PCD_HDR_INDEX_1))
1798                         return CC_PC_FF_MPLS1;
1799                     if (index == e_FM_PCD_HDR_INDEX_LAST)
1800                         return CC_PC_FF_MPLS_LAST;
1801                     REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal MPLS index"));
1802                     return CC_PC_ILLEGAL;
1803                 default:
1804                     REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
1805                     return CC_PC_ILLEGAL;
1806             }
1807 
1808         case (HEADER_TYPE_IPv4):
1809             switch (field.ipv4)
1810             {
1811                 case (NET_HEADER_FIELD_IPv4_DST_IP):
1812                     if ((index == e_FM_PCD_HDR_INDEX_NONE)
1813                             || (index == e_FM_PCD_HDR_INDEX_1))
1814                         return CC_PC_FF_IPV4DST1;
1815                     if (index == e_FM_PCD_HDR_INDEX_2)
1816                         return CC_PC_FF_IPV4DST2;
1817                     REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv4 index"));
1818                     return CC_PC_ILLEGAL;
1819                 case (NET_HEADER_FIELD_IPv4_TOS):
1820                     if ((index == e_FM_PCD_HDR_INDEX_NONE)
1821                             || (index == e_FM_PCD_HDR_INDEX_1))
1822                         return CC_PC_FF_IPV4IPTOS_TC1;
1823                     if (index == e_FM_PCD_HDR_INDEX_2)
1824                         return CC_PC_FF_IPV4IPTOS_TC2;
1825                     REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv4 index"));
1826                     return CC_PC_ILLEGAL;
1827                 case (NET_HEADER_FIELD_IPv4_PROTO):
1828                     if ((index == e_FM_PCD_HDR_INDEX_NONE)
1829                             || (index == e_FM_PCD_HDR_INDEX_1))
1830                         return CC_PC_FF_IPV4PTYPE1;
1831                     if (index == e_FM_PCD_HDR_INDEX_2)
1832                         return CC_PC_FF_IPV4PTYPE2;
1833                     REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv4 index"));
1834                     return CC_PC_ILLEGAL;
1835                 case (NET_HEADER_FIELD_IPv4_SRC_IP):
1836                     if ((index == e_FM_PCD_HDR_INDEX_NONE)
1837                             || (index == e_FM_PCD_HDR_INDEX_1))
1838                         return CC_PC_FF_IPV4SRC1;
1839                     if (index == e_FM_PCD_HDR_INDEX_2)
1840                         return CC_PC_FF_IPV4SRC2;
1841                     REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv4 index"));
1842                     return CC_PC_ILLEGAL;
1843                 case (NET_HEADER_FIELD_IPv4_SRC_IP
1844                         | NET_HEADER_FIELD_IPv4_DST_IP):
1845                     if ((index == e_FM_PCD_HDR_INDEX_NONE)
1846                             || (index == e_FM_PCD_HDR_INDEX_1))
1847                         return CC_PC_FF_IPV4SRC1_IPV4DST1;
1848                     if (index == e_FM_PCD_HDR_INDEX_2)
1849                         return CC_PC_FF_IPV4SRC2_IPV4DST2;
1850                     REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv4 index"));
1851                     return CC_PC_ILLEGAL;
1852                 case (NET_HEADER_FIELD_IPv4_TTL):
1853                     return CC_PC_FF_IPV4TTL;
1854                 default:
1855                     REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
1856                     return CC_PC_ILLEGAL;
1857             }
1858 
1859         case (HEADER_TYPE_IPv6):
1860             switch (field.ipv6)
1861             {
1862                 case (NET_HEADER_FIELD_IPv6_VER | NET_HEADER_FIELD_IPv6_FL
1863                         | NET_HEADER_FIELD_IPv6_TC):
1864                     if ((index == e_FM_PCD_HDR_INDEX_NONE)
1865                             || (index == e_FM_PCD_HDR_INDEX_1))
1866                         return CC_PC_FF_IPTOS_IPV6TC1_IPV6FLOW1;
1867                     if (index == e_FM_PCD_HDR_INDEX_2)
1868                         return CC_PC_FF_IPTOS_IPV6TC2_IPV6FLOW2;
1869                     REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv6 index"));
1870                     return CC_PC_ILLEGAL;
1871 
1872                 case (NET_HEADER_FIELD_IPv6_NEXT_HDR):
1873                     if ((index == e_FM_PCD_HDR_INDEX_NONE)
1874                             || (index == e_FM_PCD_HDR_INDEX_1))
1875                         return CC_PC_FF_IPV6PTYPE1;
1876                     if (index == e_FM_PCD_HDR_INDEX_2)
1877                         return CC_PC_FF_IPV6PTYPE2;
1878                     if (index == e_FM_PCD_HDR_INDEX_LAST)
1879                         return CC_PC_FF_IPPID;
1880                     REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv6 index"));
1881                     return CC_PC_ILLEGAL;
1882 
1883                 case (NET_HEADER_FIELD_IPv6_DST_IP):
1884                     if ((index == e_FM_PCD_HDR_INDEX_NONE)
1885                             || (index == e_FM_PCD_HDR_INDEX_1))
1886                         return CC_PC_FF_IPV6DST1;
1887                     if (index == e_FM_PCD_HDR_INDEX_2)
1888                         return CC_PC_FF_IPV6DST2;
1889                     REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv6 index"));
1890                     return CC_PC_ILLEGAL;
1891 
1892                 case (NET_HEADER_FIELD_IPv6_SRC_IP):
1893                     if ((index == e_FM_PCD_HDR_INDEX_NONE)
1894                             || (index == e_FM_PCD_HDR_INDEX_1))
1895                         return CC_PC_FF_IPV6SRC1;
1896                     if (index == e_FM_PCD_HDR_INDEX_2)
1897                         return CC_PC_FF_IPV6SRC2;
1898                     REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv6 index"));
1899                     return CC_PC_ILLEGAL;
1900 
1901                 case (NET_HEADER_FIELD_IPv6_HOP_LIMIT):
1902                     return CC_PC_FF_IPV6HOP_LIMIT;
1903 
1904                 default:
1905                     REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
1906                     return CC_PC_ILLEGAL;
1907             }
1908 
1909         case (HEADER_TYPE_IP):
1910             switch (field.ip)
1911             {
1912                 case (NET_HEADER_FIELD_IP_DSCP):
1913                     if ((index == e_FM_PCD_HDR_INDEX_NONE)
1914                             || (index == e_FM_PCD_HDR_INDEX_1))
1915                         return CC_PC_FF_IPDSCP;
1916                     REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IP index"));
1917                     return CC_PC_ILLEGAL;
1918 
1919                 case (NET_HEADER_FIELD_IP_PROTO):
1920                     if (index == e_FM_PCD_HDR_INDEX_LAST)
1921                         return CC_PC_FF_IPPID;
1922                     REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IP index"));
1923                     return CC_PC_ILLEGAL;
1924 
1925                 default:
1926                     REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
1927                     return CC_PC_ILLEGAL;
1928             }
1929 
1930         case (HEADER_TYPE_GRE):
1931             switch (field.gre)
1932             {
1933                 case (NET_HEADER_FIELD_GRE_TYPE):
1934                     return CC_PC_FF_GREPTYPE;
1935 
1936                 default:
1937                     REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
1938                     return CC_PC_ILLEGAL;
1939             }
1940 
1941         case (HEADER_TYPE_MINENCAP):
1942             switch (field.minencap)
1943             {
1944                 case (NET_HEADER_FIELD_MINENCAP_TYPE):
1945                     return CC_PC_FF_MINENCAP_PTYPE;
1946 
1947                 case (NET_HEADER_FIELD_MINENCAP_DST_IP):
1948                     return CC_PC_FF_MINENCAP_IPDST;
1949 
1950                 case (NET_HEADER_FIELD_MINENCAP_SRC_IP):
1951                     return CC_PC_FF_MINENCAP_IPSRC;
1952 
1953                 case (NET_HEADER_FIELD_MINENCAP_SRC_IP
1954                         | NET_HEADER_FIELD_MINENCAP_DST_IP):
1955                     return CC_PC_FF_MINENCAP_IPSRC_IPDST;
1956 
1957                 default:
1958                     REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
1959                     return CC_PC_ILLEGAL;
1960             }
1961 
1962         case (HEADER_TYPE_TCP):
1963             switch (field.tcp)
1964             {
1965                 case (NET_HEADER_FIELD_TCP_PORT_SRC):
1966                     return CC_PC_FF_L4PSRC;
1967 
1968                 case (NET_HEADER_FIELD_TCP_PORT_DST):
1969                     return CC_PC_FF_L4PDST;
1970 
1971                 case (NET_HEADER_FIELD_TCP_PORT_DST
1972                         | NET_HEADER_FIELD_TCP_PORT_SRC):
1973                     return CC_PC_FF_L4PSRC_L4PDST;
1974 
1975                 default:
1976                     REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
1977                     return CC_PC_ILLEGAL;
1978             }
1979 
1980         case (HEADER_TYPE_PPPoE):
1981             switch (field.pppoe)
1982             {
1983                 case (NET_HEADER_FIELD_PPPoE_PID):
1984                     return CC_PC_FF_PPPPID;
1985 
1986                 default:
1987                     REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
1988                     return CC_PC_ILLEGAL;
1989             }
1990 
1991         case (HEADER_TYPE_UDP):
1992             switch (field.udp)
1993             {
1994                 case (NET_HEADER_FIELD_UDP_PORT_SRC):
1995                     return CC_PC_FF_L4PSRC;
1996 
1997                 case (NET_HEADER_FIELD_UDP_PORT_DST):
1998                     return CC_PC_FF_L4PDST;
1999 
2000                 case (NET_HEADER_FIELD_UDP_PORT_DST
2001                         | NET_HEADER_FIELD_UDP_PORT_SRC):
2002                     return CC_PC_FF_L4PSRC_L4PDST;
2003 
2004                 default:
2005                     REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
2006                     return CC_PC_ILLEGAL;
2007             }
2008 
2009         default:
2010             REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
2011             return CC_PC_ILLEGAL;
2012     }
2013 }
2014 
2015 static uint8_t GetPrParseCode(e_NetHeaderType hdr, e_FmPcdHdrIndex hdrIndex,
2016                               uint32_t offset, bool glblMask,
2017                               uint8_t *parseArrayOffset)
2018 {
2019     bool offsetRelevant = FALSE;
2020 
2021     if (offset)
2022         offsetRelevant = TRUE;
2023 
2024     switch (hdr)
2025     {
2026         case (HEADER_TYPE_NONE):
2027             ASSERT_COND(FALSE);
2028             return CC_PC_ILLEGAL;
2029 
2030         case (HEADER_TYPE_ETH):
2031             *parseArrayOffset = (uint8_t)CC_PC_PR_ETH_OFFSET;
2032             break;
2033 
2034         case (HEADER_TYPE_USER_DEFINED_SHIM1):
2035             if (offset || glblMask)
2036                 *parseArrayOffset = (uint8_t)CC_PC_PR_USER_DEFINED_SHIM1_OFFSET;
2037             else
2038                 return CC_PC_PR_SHIM1;
2039             break;
2040 
2041         case (HEADER_TYPE_USER_DEFINED_SHIM2):
2042             if (offset || glblMask)
2043                 *parseArrayOffset = (uint8_t)CC_PC_PR_USER_DEFINED_SHIM2_OFFSET;
2044             else
2045                 return CC_PC_PR_SHIM2;
2046             break;
2047 
2048         case (HEADER_TYPE_LLC_SNAP):
2049             *parseArrayOffset = CC_PC_PR_USER_LLC_SNAP_OFFSET;
2050             break;
2051 
2052         case (HEADER_TYPE_PPPoE):
2053             *parseArrayOffset = CC_PC_PR_PPPOE_OFFSET;
2054             break;
2055 
2056         case (HEADER_TYPE_MPLS):
2057             if ((hdrIndex == e_FM_PCD_HDR_INDEX_NONE)
2058                     || (hdrIndex == e_FM_PCD_HDR_INDEX_1))
2059                 *parseArrayOffset = CC_PC_PR_MPLS1_OFFSET;
2060             else
2061                 if (hdrIndex == e_FM_PCD_HDR_INDEX_LAST)
2062                     *parseArrayOffset = CC_PC_PR_MPLS_LAST_OFFSET;
2063                 else
2064                 {
2065                     REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal MPLS header index"));
2066                     return CC_PC_ILLEGAL;
2067                 }
2068             break;
2069 
2070         case (HEADER_TYPE_IPv4):
2071         case (HEADER_TYPE_IPv6):
2072             if ((hdrIndex == e_FM_PCD_HDR_INDEX_NONE)
2073                     || (hdrIndex == e_FM_PCD_HDR_INDEX_1))
2074                 *parseArrayOffset = CC_PC_PR_IP1_OFFSET;
2075             else
2076                 if (hdrIndex == e_FM_PCD_HDR_INDEX_2)
2077                     *parseArrayOffset = CC_PC_PR_IP_LAST_OFFSET;
2078                 else
2079                 {
2080                     REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IP header index"));
2081                     return CC_PC_ILLEGAL;
2082                 }
2083             break;
2084 
2085         case (HEADER_TYPE_MINENCAP):
2086             *parseArrayOffset = CC_PC_PR_MINENC_OFFSET;
2087             break;
2088 
2089         case (HEADER_TYPE_GRE):
2090             *parseArrayOffset = CC_PC_PR_GRE_OFFSET;
2091             break;
2092 
2093         case (HEADER_TYPE_TCP):
2094         case (HEADER_TYPE_UDP):
2095         case (HEADER_TYPE_IPSEC_AH):
2096         case (HEADER_TYPE_IPSEC_ESP):
2097         case (HEADER_TYPE_DCCP):
2098         case (HEADER_TYPE_SCTP):
2099             *parseArrayOffset = CC_PC_PR_L4_OFFSET;
2100             break;
2101 
2102         default:
2103             REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IP header for this type of operation"));
2104             return CC_PC_ILLEGAL;
2105     }
2106 
2107     if (offsetRelevant)
2108         return CC_PR_OFFSET;
2109     else
2110         return CC_PR_WITHOUT_OFFSET;
2111 }
2112 
2113 static uint8_t GetFieldParseCode(e_NetHeaderType hdr, t_FmPcdFields field,
2114                                  uint32_t offset, uint8_t *parseArrayOffset,
2115                                  e_FmPcdHdrIndex hdrIndex)
2116 {
2117     bool offsetRelevant = FALSE;
2118 
2119     if (offset)
2120         offsetRelevant = TRUE;
2121 
2122     switch (hdr)
2123     {
2124         case (HEADER_TYPE_NONE):
2125             ASSERT_COND(FALSE);
2126                 break;
2127         case (HEADER_TYPE_ETH):
2128             switch (field.eth)
2129             {
2130                 case (NET_HEADER_FIELD_ETH_TYPE):
2131                     *parseArrayOffset = CC_PC_PR_ETYPE_LAST_OFFSET;
2132                     break;
2133 
2134                 default:
2135                     REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
2136                     return CC_PC_ILLEGAL;
2137             }
2138             break;
2139 
2140         case (HEADER_TYPE_VLAN):
2141             switch (field.vlan)
2142             {
2143                 case (NET_HEADER_FIELD_VLAN_TCI):
2144                     if ((hdrIndex == e_FM_PCD_HDR_INDEX_NONE)
2145                             || (hdrIndex == e_FM_PCD_HDR_INDEX_1))
2146                         *parseArrayOffset = CC_PC_PR_VLAN1_OFFSET;
2147                     else
2148                         if (hdrIndex == e_FM_PCD_HDR_INDEX_LAST)
2149                             *parseArrayOffset = CC_PC_PR_VLAN2_OFFSET;
2150                     break;
2151 
2152                 default:
2153                     REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
2154                     return CC_PC_ILLEGAL;
2155             }
2156             break;
2157 
2158         default:
2159             REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal header "));
2160             return CC_PC_ILLEGAL;
2161     }
2162 
2163     if (offsetRelevant)
2164         return CC_PR_OFFSET;
2165     else
2166         return CC_PR_WITHOUT_OFFSET;
2167 }
2168 
2169 static void FillAdOfTypeResult(t_Handle h_Ad,
2170                                t_FmPcdCcStatsParams *p_FmPcdCcStatsParams,
2171                                t_FmPcd *p_FmPcd,
2172                                t_FmPcdCcNextEngineParams *p_CcNextEngineParams)
2173 {
2174     t_AdOfTypeResult *p_AdResult = (t_AdOfTypeResult *)h_Ad;
2175     t_Handle h_TmpAd;
2176     uint32_t tmp = 0, tmpNia = 0;
2177     uint16_t profileId;
2178     t_Handle p_AdNewPtr = NULL;
2179     t_Error err = E_OK;
2180 
2181     /* There are 3 cases handled in this routine of building a "result" type AD.
2182      * Case 1: No Manip. The action descriptor is built within the match table.
2183      * Case 2: Manip exists. A new AD is created - p_AdNewPtr. It is initialized
2184      *         either in the FmPcdManipUpdateAdResultForCc routine or it was already
2185      *         initialized and returned here.
2186      *         p_AdResult (within the match table) will be initialized after
2187      *         this routine returns and point to the existing AD.
2188      * Case 3: Manip exists. The action descriptor is built within the match table.
2189      *         FmPcdManipUpdateAdResultForCc returns a NULL p_AdNewPtr.
2190      *
2191      * If statistics were enabled and the statistics mode of this node requires
2192      * a statistics Ad, it will be placed after the result Ad and before the
2193      * manip Ad, if manip Ad exists here.
2194      */
2195 
2196     /* As default, the "new" ptr is the current one. i.e. the content of the result
2197      * AD will be written into the match table itself (case (1))*/
2198     p_AdNewPtr = p_AdResult;
2199 
2200     /* Initialize an action descriptor, if current statistics mode requires an Ad */
2201     if (p_FmPcdCcStatsParams)
2202     {
2203         ASSERT_COND(p_FmPcdCcStatsParams->h_StatsAd);
2204         ASSERT_COND(p_FmPcdCcStatsParams->h_StatsCounters);
2205 
2206         /* Swapping addresses between statistics Ad and the current lookup AD addresses */
2207         h_TmpAd = p_FmPcdCcStatsParams->h_StatsAd;
2208         p_FmPcdCcStatsParams->h_StatsAd = h_Ad;
2209         h_Ad = h_TmpAd;
2210 
2211         p_AdNewPtr = h_Ad;
2212         p_AdResult = h_Ad;
2213 
2214         /* Init statistics Ad and connect current lookup AD as 'next action' from statistics Ad */
2215         UpdateStatsAd(p_FmPcdCcStatsParams, h_Ad, p_FmPcd->physicalMuramBase);
2216     }
2217 
2218     /* Create manip and return p_AdNewPtr to either a new descriptor or NULL */
2219     if (p_CcNextEngineParams->h_Manip)
2220         FmPcdManipUpdateAdResultForCc(p_CcNextEngineParams->h_Manip,
2221                                       p_CcNextEngineParams, h_Ad, &p_AdNewPtr);
2222 
2223     /* if (p_AdNewPtr = NULL) --> Done. (case (3)) */
2224     if (p_AdNewPtr)
2225     {
2226         /* case (1) and (2) */
2227         switch (p_CcNextEngineParams->nextEngine)
2228         {
2229             case (e_FM_PCD_DONE):
2230                 if (p_CcNextEngineParams->params.enqueueParams.action
2231                         == e_FM_PCD_ENQ_FRAME)
2232                 {
2233                     if (p_CcNextEngineParams->params.enqueueParams.overrideFqid)
2234                     {
2235                         tmp = FM_PCD_AD_RESULT_CONTRL_FLOW_TYPE;
2236                         tmp |=
2237                                 p_CcNextEngineParams->params.enqueueParams.newFqid;
2238 #if (DPAA_VERSION >= 11)
2239                         tmp |=
2240                                 (p_CcNextEngineParams->params.enqueueParams.newRelativeStorageProfileId
2241                                         & FM_PCD_AD_RESULT_VSP_MASK)
2242                                         << FM_PCD_AD_RESULT_VSP_SHIFT;
2243 #endif /* (DPAA_VERSION >= 11) */
2244                     }
2245                     else
2246                     {
2247                         tmp = FM_PCD_AD_RESULT_DATA_FLOW_TYPE;
2248                         tmp |= FM_PCD_AD_RESULT_PLCR_DIS;
2249                     }
2250                 }
2251 
2252                 if (p_CcNextEngineParams->params.enqueueParams.action
2253                         == e_FM_PCD_DROP_FRAME)
2254                     tmpNia |= GET_NIA_BMI_AC_DISCARD_FRAME(p_FmPcd);
2255                 else
2256                     tmpNia |= GET_NIA_BMI_AC_ENQ_FRAME(p_FmPcd);
2257                 break;
2258 
2259             case (e_FM_PCD_KG):
2260                 if (p_CcNextEngineParams->params.kgParams.overrideFqid)
2261                 {
2262                     tmp = FM_PCD_AD_RESULT_CONTRL_FLOW_TYPE;
2263                     tmp |= p_CcNextEngineParams->params.kgParams.newFqid;
2264 #if (DPAA_VERSION >= 11)
2265                     tmp |=
2266                             (p_CcNextEngineParams->params.kgParams.newRelativeStorageProfileId
2267                                     & FM_PCD_AD_RESULT_VSP_MASK)
2268                                     << FM_PCD_AD_RESULT_VSP_SHIFT;
2269 #endif /* (DPAA_VERSION >= 11) */
2270                 }
2271                 else
2272                 {
2273                     tmp = FM_PCD_AD_RESULT_DATA_FLOW_TYPE;
2274                     tmp |= FM_PCD_AD_RESULT_PLCR_DIS;
2275                 }
2276                 tmpNia = NIA_KG_DIRECT;
2277                 tmpNia |= NIA_ENG_KG;
2278                 tmpNia |= NIA_KG_CC_EN;
2279                 tmpNia |= FmPcdKgGetSchemeId(
2280                         p_CcNextEngineParams->params.kgParams.h_DirectScheme);
2281                 break;
2282 
2283             case (e_FM_PCD_PLCR):
2284                 if (p_CcNextEngineParams->params.plcrParams.overrideParams)
2285                 {
2286                     tmp = FM_PCD_AD_RESULT_CONTRL_FLOW_TYPE;
2287 
2288                     /* if private policer profile, it may be uninitialized yet, therefore no checks are done at this stage */
2289                     if (p_CcNextEngineParams->params.plcrParams.sharedProfile)
2290                     {
2291                         tmpNia |= NIA_PLCR_ABSOLUTE;
2292                         err = FmPcdPlcrGetAbsoluteIdByProfileParams(
2293                                 (t_Handle)p_FmPcd,
2294                                 e_FM_PCD_PLCR_SHARED,
2295                                 NULL,
2296                                 p_CcNextEngineParams->params.plcrParams.newRelativeProfileId,
2297                                 &profileId);
2298 			if (err != E_OK)
2299 				return;
2300 
2301                     }
2302                     else
2303                         profileId =
2304                                 p_CcNextEngineParams->params.plcrParams.newRelativeProfileId;
2305 
2306                     tmp |= p_CcNextEngineParams->params.plcrParams.newFqid;
2307 #if (DPAA_VERSION >= 11)
2308                     tmp |=
2309                             (p_CcNextEngineParams->params.plcrParams.newRelativeStorageProfileId
2310                                     & FM_PCD_AD_RESULT_VSP_MASK)
2311                                     << FM_PCD_AD_RESULT_VSP_SHIFT;
2312 #endif /* (DPAA_VERSION >= 11) */
2313                     WRITE_UINT32(
2314                             p_AdResult->plcrProfile,
2315                             (uint32_t)((uint32_t)profileId << FM_PCD_AD_PROFILEID_FOR_CNTRL_SHIFT));
2316                 }
2317                 else
2318                     tmp = FM_PCD_AD_RESULT_DATA_FLOW_TYPE;
2319 
2320                 tmpNia |=
2321                         NIA_ENG_PLCR
2322                                 | p_CcNextEngineParams->params.plcrParams.newRelativeProfileId;
2323                 break;
2324 
2325             default:
2326                 return;
2327         }WRITE_UINT32(p_AdResult->fqid, tmp);
2328 
2329         if (p_CcNextEngineParams->h_Manip)
2330         {
2331             tmp = GET_UINT32(p_AdResult->plcrProfile);
2332             tmp |= (uint32_t)(XX_VirtToPhys(p_AdNewPtr)
2333                     - (p_FmPcd->physicalMuramBase)) >> 4;
2334             WRITE_UINT32(p_AdResult->plcrProfile, tmp);
2335 
2336             tmpNia |= FM_PCD_AD_RESULT_EXTENDED_MODE;
2337             tmpNia |= FM_PCD_AD_RESULT_NADEN;
2338         }
2339 
2340 #if (DPAA_VERSION >= 11)
2341         tmpNia |= FM_PCD_AD_RESULT_NO_OM_VSPE;
2342 #endif /* (DPAA_VERSION >= 11) */
2343         WRITE_UINT32(p_AdResult->nia, tmpNia);
2344     }
2345 }
2346 
2347 static t_Error CcUpdateParams(t_Handle h_FmPcd, t_Handle h_PcdParams,
2348                               t_Handle h_FmPort, t_Handle h_FmTree,
2349                               bool validate)
2350 {
2351     t_FmPcdCcTree *p_CcTree = (t_FmPcdCcTree *)h_FmTree;
2352 
2353     return CcUpdateParam(h_FmPcd, h_PcdParams, h_FmPort,
2354                          p_CcTree->keyAndNextEngineParams,
2355                          p_CcTree->numOfEntries,
2356                          UINT_TO_PTR(p_CcTree->ccTreeBaseAddr), validate, 0,
2357                          h_FmTree, FALSE);
2358 }
2359 
2360 
2361 static void ReleaseNewNodeCommonPart(
2362         t_FmPcdModifyCcKeyAdditionalParams *p_AdditionalInfo)
2363 {
2364     if (p_AdditionalInfo->p_AdTableNew)
2365         FM_MURAM_FreeMem(
2366                 FmPcdGetMuramHandle(
2367                         ((t_FmPcdCcNode *)(p_AdditionalInfo->h_CurrentNode))->h_FmPcd),
2368                 p_AdditionalInfo->p_AdTableNew);
2369 
2370     if (p_AdditionalInfo->p_KeysMatchTableNew)
2371         FM_MURAM_FreeMem(
2372                 FmPcdGetMuramHandle(
2373                         ((t_FmPcdCcNode *)(p_AdditionalInfo->h_CurrentNode))->h_FmPcd),
2374                 p_AdditionalInfo->p_KeysMatchTableNew);
2375 }
2376 
2377 static t_Error UpdateGblMask(t_FmPcdCcNode *p_CcNode, uint8_t keySize,
2378                              uint8_t *p_Mask)
2379 {
2380     uint8_t prvGlblMaskSize = p_CcNode->glblMaskSize;
2381 
2382     if (p_Mask && !p_CcNode->glblMaskUpdated && (keySize <= 4)
2383             && !p_CcNode->lclMask)
2384     {
2385         if (p_CcNode->parseCode && (p_CcNode->parseCode != CC_PC_FF_TCI1)
2386                 && (p_CcNode->parseCode != CC_PC_FF_TCI2)
2387                 && (p_CcNode->parseCode != CC_PC_FF_MPLS1)
2388                 && (p_CcNode->parseCode != CC_PC_FF_MPLS_LAST)
2389                 && (p_CcNode->parseCode != CC_PC_FF_IPV4IPTOS_TC1)
2390                 && (p_CcNode->parseCode != CC_PC_FF_IPV4IPTOS_TC2)
2391                 && (p_CcNode->parseCode != CC_PC_FF_IPTOS_IPV6TC1_IPV6FLOW1)
2392                 && (p_CcNode->parseCode != CC_PC_FF_IPDSCP)
2393                 && (p_CcNode->parseCode != CC_PC_FF_IPTOS_IPV6TC2_IPV6FLOW2))
2394         {
2395             p_CcNode->glblMaskSize = 0;
2396             p_CcNode->lclMask = TRUE;
2397         }
2398         else
2399         {
2400             memcpy(p_CcNode->p_GlblMask, p_Mask, (sizeof(uint8_t)) * keySize);
2401             p_CcNode->glblMaskUpdated = TRUE;
2402             p_CcNode->glblMaskSize = 4;
2403         }
2404     }
2405     else
2406         if (p_Mask && (keySize <= 4) && !p_CcNode->lclMask)
2407         {
2408             if (memcmp(p_CcNode->p_GlblMask, p_Mask, keySize) != 0)
2409             {
2410                 p_CcNode->lclMask = TRUE;
2411                 p_CcNode->glblMaskSize = 0;
2412             }
2413         }
2414         else
2415             if (!p_Mask && p_CcNode->glblMaskUpdated && (keySize <= 4))
2416             {
2417                 uint32_t tmpMask = 0xffffffff;
2418                 if (memcmp(p_CcNode->p_GlblMask, &tmpMask, 4) != 0)
2419                 {
2420                     p_CcNode->lclMask = TRUE;
2421                     p_CcNode->glblMaskSize = 0;
2422                 }
2423             }
2424             else
2425                 if (p_Mask)
2426                 {
2427                     p_CcNode->lclMask = TRUE;
2428                     p_CcNode->glblMaskSize = 0;
2429                 }
2430 
2431     /* In static mode (maxNumOfKeys > 0), local mask is supported
2432      only is mask support was enabled at initialization */
2433     if (p_CcNode->maxNumOfKeys && (!p_CcNode->maskSupport) && p_CcNode->lclMask)
2434     {
2435         p_CcNode->lclMask = FALSE;
2436         p_CcNode->glblMaskSize = prvGlblMaskSize;
2437         return ERROR_CODE(E_NOT_SUPPORTED);
2438     }
2439 
2440     return E_OK;
2441 }
2442 
2443 static __inline__ t_Handle GetNewAd(t_Handle h_FmPcdCcNodeOrTree, bool isTree)
2444 {
2445     t_FmPcd *p_FmPcd;
2446     t_Handle h_Ad;
2447 
2448     if (isTree)
2449         p_FmPcd = (t_FmPcd *)(((t_FmPcdCcTree *)h_FmPcdCcNodeOrTree)->h_FmPcd);
2450     else
2451         p_FmPcd = (t_FmPcd *)(((t_FmPcdCcNode *)h_FmPcdCcNodeOrTree)->h_FmPcd);
2452 
2453     if ((isTree && p_FmPcd->p_CcShadow)
2454             || (!isTree && ((t_FmPcdCcNode *)h_FmPcdCcNodeOrTree)->maxNumOfKeys))
2455     {
2456         /* The allocated shadow is divided as follows:
2457          0 . . .       16 . . .
2458          ---------------------------------------------------
2459          |   Shadow   |   Shadow Keys   |   Shadow Next    |
2460          |     Ad     |   Match Table   |   Engine Table   |
2461          | (16 bytes) | (maximal size)  |  (maximal size)  |
2462          ---------------------------------------------------
2463          */
2464         if (!p_FmPcd->p_CcShadow)
2465         {
2466             REPORT_ERROR(MAJOR, E_NO_MEMORY, ("CC Shadow not allocated"));
2467             return NULL;
2468         }
2469 
2470         h_Ad = p_FmPcd->p_CcShadow;
2471     }
2472     else
2473     {
2474         h_Ad = (t_Handle)FM_MURAM_AllocMem(FmPcdGetMuramHandle(p_FmPcd),
2475                                            FM_PCD_CC_AD_ENTRY_SIZE,
2476                                            FM_PCD_CC_AD_TABLE_ALIGN);
2477         if (!h_Ad)
2478         {
2479             REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC node action descriptor"));
2480             return NULL;
2481         }
2482     }
2483 
2484     return h_Ad;
2485 }
2486 
2487 static t_Error BuildNewNodeCommonPart(
2488         t_FmPcdCcNode *p_CcNode, int *size,
2489         t_FmPcdModifyCcKeyAdditionalParams *p_AdditionalInfo)
2490 {
2491     t_FmPcd *p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd;
2492 
2493     if (p_CcNode->lclMask)
2494         *size = 2 * p_CcNode->ccKeySizeAccExtraction;
2495     else
2496         *size = p_CcNode->ccKeySizeAccExtraction;
2497 
2498     if (p_CcNode->maxNumOfKeys == 0)
2499     {
2500         p_AdditionalInfo->p_AdTableNew = (t_Handle)FM_MURAM_AllocMem(
2501                 FmPcdGetMuramHandle(p_FmPcd),
2502                 (uint32_t)((p_AdditionalInfo->numOfKeys + 1)
2503                         * FM_PCD_CC_AD_ENTRY_SIZE),
2504                 FM_PCD_CC_AD_TABLE_ALIGN);
2505         if (!p_AdditionalInfo->p_AdTableNew)
2506             RETURN_ERROR(
2507                     MAJOR, E_NO_MEMORY,
2508                     ("MURAM allocation for CC node action descriptors table"));
2509 
2510         p_AdditionalInfo->p_KeysMatchTableNew = (t_Handle)FM_MURAM_AllocMem(
2511                 FmPcdGetMuramHandle(p_FmPcd),
2512                 (uint32_t)(*size * sizeof(uint8_t)
2513                         * (p_AdditionalInfo->numOfKeys + 1)),
2514                 FM_PCD_CC_KEYS_MATCH_TABLE_ALIGN);
2515         if (!p_AdditionalInfo->p_KeysMatchTableNew)
2516         {
2517             FM_MURAM_FreeMem(FmPcdGetMuramHandle(p_CcNode->h_FmPcd),
2518                              p_AdditionalInfo->p_AdTableNew);
2519             p_AdditionalInfo->p_AdTableNew = NULL;
2520             RETURN_ERROR(MAJOR, E_NO_MEMORY,
2521                          ("MURAM allocation for CC node key match table"));
2522         }
2523 
2524         MemSet8(
2525                 (uint8_t*)p_AdditionalInfo->p_AdTableNew,
2526                 0,
2527                 (uint32_t)((p_AdditionalInfo->numOfKeys + 1)
2528                         * FM_PCD_CC_AD_ENTRY_SIZE));
2529         MemSet8((uint8_t*)p_AdditionalInfo->p_KeysMatchTableNew, 0,
2530                    *size * sizeof(uint8_t) * (p_AdditionalInfo->numOfKeys + 1));
2531     }
2532     else
2533     {
2534         /* The allocated shadow is divided as follows:
2535          0 . . .       16 . . .
2536          ---------------------------------------------------
2537          |   Shadow   |   Shadow Keys   |   Shadow Next    |
2538          |     Ad     |   Match Table   |   Engine Table   |
2539          | (16 bytes) | (maximal size)  |  (maximal size)  |
2540          ---------------------------------------------------
2541          */
2542 
2543         if (!p_FmPcd->p_CcShadow)
2544             RETURN_ERROR(MAJOR, E_NO_MEMORY, ("CC Shadow not allocated"));
2545 
2546         p_AdditionalInfo->p_KeysMatchTableNew =
2547                 PTR_MOVE(p_FmPcd->p_CcShadow, FM_PCD_CC_AD_ENTRY_SIZE);
2548         p_AdditionalInfo->p_AdTableNew =
2549                 PTR_MOVE(p_AdditionalInfo->p_KeysMatchTableNew, p_CcNode->keysMatchTableMaxSize);
2550 
2551         MemSet8(
2552                 (uint8_t*)p_AdditionalInfo->p_AdTableNew,
2553                 0,
2554                 (uint32_t)((p_CcNode->maxNumOfKeys + 1)
2555                         * FM_PCD_CC_AD_ENTRY_SIZE));
2556         MemSet8((uint8_t*)p_AdditionalInfo->p_KeysMatchTableNew, 0,
2557                    (*size) * sizeof(uint8_t) * (p_CcNode->maxNumOfKeys));
2558     }
2559 
2560     p_AdditionalInfo->p_AdTableOld = p_CcNode->h_AdTable;
2561     p_AdditionalInfo->p_KeysMatchTableOld = p_CcNode->h_KeysMatchTable;
2562 
2563     return E_OK;
2564 }
2565 
2566 static t_Error BuildNewNodeAddOrMdfyKeyAndNextEngine(
2567         t_Handle h_FmPcd, t_FmPcdCcNode *p_CcNode, uint16_t keyIndex,
2568         t_FmPcdCcKeyParams *p_KeyParams,
2569         t_FmPcdModifyCcKeyAdditionalParams *p_AdditionalInfo, bool add)
2570 {
2571     t_Error err = E_OK;
2572     t_Handle p_AdTableNewTmp, p_KeysMatchTableNewTmp;
2573     t_Handle p_KeysMatchTableOldTmp, p_AdTableOldTmp;
2574     int size;
2575     int i = 0, j = 0;
2576     t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
2577     uint32_t requiredAction = 0;
2578     bool prvLclMask;
2579     t_CcNodeInformation *p_CcNodeInformation;
2580     t_FmPcdCcStatsParams statsParams = { 0 };
2581     t_List *p_Pos;
2582     t_FmPcdStatsObj *p_StatsObj;
2583 
2584     /* Check that new NIA is legal */
2585     err = ValidateNextEngineParams(h_FmPcd, &p_KeyParams->ccNextEngineParams,
2586                                    p_CcNode->statisticsMode);
2587     if (err)
2588         RETURN_ERROR(MAJOR, err, NO_MSG);
2589 
2590     prvLclMask = p_CcNode->lclMask;
2591 
2592     /* Check that new key is not require update of localMask */
2593     err = UpdateGblMask(p_CcNode, p_CcNode->ccKeySizeAccExtraction,
2594                         p_KeyParams->p_Mask);
2595     if (err)
2596         RETURN_ERROR(MAJOR, err, (NO_MSG));
2597 
2598     /* Update internal data structure with new next engine for the given index */
2599     memcpy(&p_AdditionalInfo->keyAndNextEngineParams[keyIndex].nextEngineParams,
2600            &p_KeyParams->ccNextEngineParams, sizeof(t_FmPcdCcNextEngineParams));
2601 
2602     memcpy(p_AdditionalInfo->keyAndNextEngineParams[keyIndex].key,
2603            p_KeyParams->p_Key, p_CcNode->userSizeOfExtraction);
2604 
2605     if ((p_AdditionalInfo->keyAndNextEngineParams[keyIndex].nextEngineParams.nextEngine
2606             == e_FM_PCD_CC)
2607             && p_AdditionalInfo->keyAndNextEngineParams[keyIndex].nextEngineParams.h_Manip)
2608     {
2609         err =
2610                 AllocAndFillAdForContLookupManip(
2611                         p_AdditionalInfo->keyAndNextEngineParams[keyIndex].nextEngineParams.params.ccParams.h_CcNode);
2612         if (err)
2613             RETURN_ERROR(MAJOR, err, (NO_MSG));
2614     }
2615 
2616     if (p_KeyParams->p_Mask)
2617         memcpy(p_AdditionalInfo->keyAndNextEngineParams[keyIndex].mask,
2618                p_KeyParams->p_Mask, p_CcNode->userSizeOfExtraction);
2619     else
2620         memset(p_AdditionalInfo->keyAndNextEngineParams[keyIndex].mask, 0xFF,
2621                p_CcNode->userSizeOfExtraction);
2622 
2623     /* Update numOfKeys */
2624     if (add)
2625         p_AdditionalInfo->numOfKeys = (uint8_t)(p_CcNode->numOfKeys + 1);
2626     else
2627         p_AdditionalInfo->numOfKeys = (uint8_t)p_CcNode->numOfKeys;
2628 
2629     /* Allocate new tables in MURAM: keys match table and action descriptors table */
2630     err = BuildNewNodeCommonPart(p_CcNode, &size, p_AdditionalInfo);
2631     if (err)
2632         RETURN_ERROR(MAJOR, err, NO_MSG);
2633 
2634     /* Check that manip is legal and what requiredAction is necessary for this manip */
2635     if (p_KeyParams->ccNextEngineParams.h_Manip)
2636     {
2637         err = FmPcdManipCheckParamsForCcNextEngine(
2638                 &p_KeyParams->ccNextEngineParams, &requiredAction);
2639         if (err)
2640             RETURN_ERROR(MAJOR, err, (NO_MSG));
2641     }
2642 
2643     p_AdditionalInfo->keyAndNextEngineParams[keyIndex].requiredAction =
2644             requiredAction;
2645     p_AdditionalInfo->keyAndNextEngineParams[keyIndex].requiredAction |=
2646             UPDATE_CC_WITH_TREE;
2647 
2648     /* Update new Ad and new Key Table according to new requirement */
2649     i = 0;
2650     for (j = 0; j < p_AdditionalInfo->numOfKeys; j++)
2651     {
2652         p_AdTableNewTmp =
2653                 PTR_MOVE(p_AdditionalInfo->p_AdTableNew, j*FM_PCD_CC_AD_ENTRY_SIZE);
2654 
2655         if (j == keyIndex)
2656         {
2657             if (p_KeyParams->ccNextEngineParams.statisticsEn)
2658             {
2659                 /* Allocate a statistics object that holds statistics AD and counters.
2660                  - For added key - New statistics AD and counters pointer need to be allocated
2661                  new statistics object. If statistics were enabled, we need to replace the
2662                  existing descriptor with a new descriptor with nullified counters.
2663                  */
2664                 p_StatsObj = GetStatsObj(p_CcNode);
2665                 ASSERT_COND(p_StatsObj);
2666 
2667                 /* Store allocated statistics object */
2668                 ASSERT_COND(keyIndex < CC_MAX_NUM_OF_KEYS);
2669                 p_AdditionalInfo->keyAndNextEngineParams[keyIndex].p_StatsObj =
2670                         p_StatsObj;
2671 
2672                 statsParams.h_StatsAd = p_StatsObj->h_StatsAd;
2673                 statsParams.h_StatsCounters = p_StatsObj->h_StatsCounters;
2674 #if (DPAA_VERSION >= 11)
2675                 statsParams.h_StatsFLRs = p_CcNode->h_StatsFLRs;
2676 
2677 #endif /* (DPAA_VERSION >= 11) */
2678 
2679                 /* Building action descriptor for the received new key */
2680                 NextStepAd(p_AdTableNewTmp, &statsParams,
2681                            &p_KeyParams->ccNextEngineParams, p_FmPcd);
2682             }
2683             else
2684             {
2685                 /* Building action descriptor for the received new key */
2686                 NextStepAd(p_AdTableNewTmp, NULL,
2687                            &p_KeyParams->ccNextEngineParams, p_FmPcd);
2688             }
2689 
2690             /* Copy the received new key into keys match table */
2691             p_KeysMatchTableNewTmp =
2692                     PTR_MOVE(p_AdditionalInfo->p_KeysMatchTableNew, j*size*sizeof(uint8_t));
2693 
2694             MemCpy8((void*)p_KeysMatchTableNewTmp, p_KeyParams->p_Key,
2695                         p_CcNode->userSizeOfExtraction);
2696 
2697             /* Update mask for the received new key */
2698             if (p_CcNode->lclMask)
2699             {
2700                 if (p_KeyParams->p_Mask)
2701                 {
2702                     MemCpy8(PTR_MOVE(p_KeysMatchTableNewTmp,
2703                             p_CcNode->ccKeySizeAccExtraction),
2704                                 p_KeyParams->p_Mask,
2705                                 p_CcNode->userSizeOfExtraction);
2706                 }
2707                 else
2708                     if (p_CcNode->ccKeySizeAccExtraction > 4)
2709                     {
2710                         MemSet8(PTR_MOVE(p_KeysMatchTableNewTmp,
2711                                 p_CcNode->ccKeySizeAccExtraction),
2712                                    0xff, p_CcNode->userSizeOfExtraction);
2713                     }
2714                     else
2715                     {
2716                         MemCpy8(PTR_MOVE(p_KeysMatchTableNewTmp,
2717                                 p_CcNode->ccKeySizeAccExtraction),
2718                                     p_CcNode->p_GlblMask,
2719                                     p_CcNode->userSizeOfExtraction);
2720                     }
2721             }
2722 
2723             /* If key modification requested, the old entry is omitted and replaced by the new parameters */
2724             if (!add)
2725                 i++;
2726         }
2727         else
2728         {
2729             /* Copy existing action descriptors to the newly allocated Ad table */
2730             p_AdTableOldTmp =
2731                     PTR_MOVE(p_AdditionalInfo->p_AdTableOld, i*FM_PCD_CC_AD_ENTRY_SIZE);
2732             MemCpy8(p_AdTableNewTmp, p_AdTableOldTmp,
2733                        FM_PCD_CC_AD_ENTRY_SIZE);
2734 
2735             /* Copy existing keys and their masks to the newly allocated keys match table */
2736             p_KeysMatchTableNewTmp =
2737                     PTR_MOVE(p_AdditionalInfo->p_KeysMatchTableNew, j * size * sizeof(uint8_t));
2738             p_KeysMatchTableOldTmp =
2739                     PTR_MOVE(p_AdditionalInfo->p_KeysMatchTableOld, i * size * sizeof(uint8_t));
2740 
2741             if (p_CcNode->lclMask)
2742             {
2743                 if (prvLclMask)
2744                 {
2745                     MemCpy8(
2746                             PTR_MOVE(p_KeysMatchTableNewTmp, p_CcNode->ccKeySizeAccExtraction),
2747                             PTR_MOVE(p_KeysMatchTableOldTmp, p_CcNode->ccKeySizeAccExtraction),
2748                             p_CcNode->ccKeySizeAccExtraction);
2749                 }
2750                 else
2751                 {
2752                     p_KeysMatchTableOldTmp =
2753                             PTR_MOVE(p_CcNode->h_KeysMatchTable,
2754                                     i * (int)p_CcNode->ccKeySizeAccExtraction * sizeof(uint8_t));
2755 
2756                     if (p_CcNode->ccKeySizeAccExtraction > 4)
2757                     {
2758                         MemSet8(PTR_MOVE(p_KeysMatchTableNewTmp,
2759                                 p_CcNode->ccKeySizeAccExtraction),
2760                                    0xff, p_CcNode->userSizeOfExtraction);
2761                     }
2762                     else
2763                     {
2764                         MemCpy8(PTR_MOVE(p_KeysMatchTableNewTmp,
2765                                 p_CcNode->ccKeySizeAccExtraction),
2766                                    p_CcNode->p_GlblMask,
2767                                    p_CcNode->userSizeOfExtraction);
2768                     }
2769                 }
2770             }
2771 
2772             MemCpy8(p_KeysMatchTableNewTmp, p_KeysMatchTableOldTmp,
2773                        p_CcNode->ccKeySizeAccExtraction);
2774 
2775             i++;
2776         }
2777     }
2778 
2779     /* Miss action descriptor */
2780     p_AdTableNewTmp =
2781             PTR_MOVE(p_AdditionalInfo->p_AdTableNew, j * FM_PCD_CC_AD_ENTRY_SIZE);
2782     p_AdTableOldTmp =
2783             PTR_MOVE(p_AdditionalInfo->p_AdTableOld, i * FM_PCD_CC_AD_ENTRY_SIZE);
2784     MemCpy8(p_AdTableNewTmp, p_AdTableOldTmp, FM_PCD_CC_AD_ENTRY_SIZE);
2785 
2786     if (!NCSW_LIST_IsEmpty(&p_CcNode->ccTreesLst))
2787     {
2788         NCSW_LIST_FOR_EACH(p_Pos, &p_CcNode->ccTreesLst)
2789         {
2790             p_CcNodeInformation = CC_NODE_F_OBJECT(p_Pos);
2791             ASSERT_COND(p_CcNodeInformation->h_CcNode);
2792             /* Update the manipulation which has to be updated from parameters of the port */
2793             /* It's has to be updated with restrictions defined in the function */
2794             err =
2795                     SetRequiredAction(
2796                             p_CcNode->h_FmPcd,
2797                             p_CcNode->shadowAction
2798                                     | p_AdditionalInfo->keyAndNextEngineParams[keyIndex].requiredAction,
2799                             &p_AdditionalInfo->keyAndNextEngineParams[keyIndex],
2800                             PTR_MOVE(p_AdditionalInfo->p_AdTableNew, keyIndex*FM_PCD_CC_AD_ENTRY_SIZE),
2801                             1, p_CcNodeInformation->h_CcNode);
2802             if (err)
2803                 RETURN_ERROR(MAJOR, err, (NO_MSG));
2804 
2805             err =
2806                     CcUpdateParam(
2807                             p_CcNode->h_FmPcd,
2808                             NULL,
2809                             NULL,
2810                             &p_AdditionalInfo->keyAndNextEngineParams[keyIndex],
2811                             1,
2812                             PTR_MOVE(p_AdditionalInfo->p_AdTableNew, keyIndex*FM_PCD_CC_AD_ENTRY_SIZE),
2813                             TRUE, p_CcNodeInformation->index,
2814                             p_CcNodeInformation->h_CcNode, TRUE);
2815             if (err)
2816                 RETURN_ERROR(MAJOR, err, (NO_MSG));
2817         }
2818     }
2819 
2820     if (p_CcNode->lclMask)
2821         memset(p_CcNode->p_GlblMask, 0xff, CC_GLBL_MASK_SIZE * sizeof(uint8_t));
2822 
2823     if (p_KeyParams->ccNextEngineParams.nextEngine == e_FM_PCD_CC)
2824         p_AdditionalInfo->h_NodeForAdd =
2825                 p_KeyParams->ccNextEngineParams.params.ccParams.h_CcNode;
2826     if (p_KeyParams->ccNextEngineParams.h_Manip)
2827         p_AdditionalInfo->h_ManipForAdd =
2828                 p_KeyParams->ccNextEngineParams.h_Manip;
2829 
2830 #if (DPAA_VERSION >= 11)
2831     if ((p_KeyParams->ccNextEngineParams.nextEngine == e_FM_PCD_FR)
2832             && (p_KeyParams->ccNextEngineParams.params.frParams.h_FrmReplic))
2833         p_AdditionalInfo->h_FrmReplicForAdd =
2834                 p_KeyParams->ccNextEngineParams.params.frParams.h_FrmReplic;
2835 #endif /* (DPAA_VERSION >= 11) */
2836 
2837     if (!add)
2838     {
2839         if (p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.nextEngine
2840                 == e_FM_PCD_CC)
2841             p_AdditionalInfo->h_NodeForRmv =
2842                     p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.params.ccParams.h_CcNode;
2843 
2844         if (p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.h_Manip)
2845             p_AdditionalInfo->h_ManipForRmv =
2846                     p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.h_Manip;
2847 
2848         /* If statistics were previously enabled, store the old statistics object to be released */
2849         if (p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj)
2850         {
2851             p_AdditionalInfo->p_StatsObjForRmv =
2852                     p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj;
2853         }
2854 
2855 #if (DPAA_VERSION >= 11)
2856         if ((p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.nextEngine
2857                 == e_FM_PCD_FR)
2858                 && (p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.params.frParams.h_FrmReplic))
2859             p_AdditionalInfo->h_FrmReplicForRmv =
2860                     p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.params.frParams.h_FrmReplic;
2861 #endif /* (DPAA_VERSION >= 11) */
2862     }
2863 
2864     return E_OK;
2865 }
2866 
2867 static t_Error BuildNewNodeRemoveKey(
2868         t_FmPcdCcNode *p_CcNode, uint16_t keyIndex,
2869         t_FmPcdModifyCcKeyAdditionalParams *p_AdditionalInfo)
2870 {
2871     int i = 0, j = 0;
2872     t_Handle p_AdTableNewTmp, p_KeysMatchTableNewTmp;
2873     t_Handle p_KeysMatchTableOldTmp, p_AdTableOldTmp;
2874     int size;
2875     t_Error err = E_OK;
2876 
2877     /*save new numOfKeys*/
2878     p_AdditionalInfo->numOfKeys = (uint16_t)(p_CcNode->numOfKeys - 1);
2879 
2880     /*function which allocates in the memory new KeyTbl, AdTbl*/
2881     err = BuildNewNodeCommonPart(p_CcNode, &size, p_AdditionalInfo);
2882     if (err)
2883         RETURN_ERROR(MAJOR, err, NO_MSG);
2884 
2885     /*update new Ad and new Key Table according to new requirement*/
2886     for (i = 0, j = 0; j < p_CcNode->numOfKeys; i++, j++)
2887     {
2888         if (j == keyIndex)
2889             j++;
2890 
2891         if (j == p_CcNode->numOfKeys)
2892             break;
2893         p_AdTableNewTmp =
2894                 PTR_MOVE(p_AdditionalInfo->p_AdTableNew, i * FM_PCD_CC_AD_ENTRY_SIZE);
2895         p_AdTableOldTmp =
2896                 PTR_MOVE(p_AdditionalInfo->p_AdTableOld, j * FM_PCD_CC_AD_ENTRY_SIZE);
2897         MemCpy8(p_AdTableNewTmp, p_AdTableOldTmp, FM_PCD_CC_AD_ENTRY_SIZE);
2898 
2899         p_KeysMatchTableOldTmp =
2900                 PTR_MOVE(p_AdditionalInfo->p_KeysMatchTableOld, j * size * sizeof(uint8_t));
2901         p_KeysMatchTableNewTmp =
2902                 PTR_MOVE(p_AdditionalInfo->p_KeysMatchTableNew, i * size * sizeof(uint8_t));
2903         MemCpy8(p_KeysMatchTableNewTmp, p_KeysMatchTableOldTmp,
2904                    size * sizeof(uint8_t));
2905     }
2906 
2907     p_AdTableNewTmp =
2908             PTR_MOVE(p_AdditionalInfo->p_AdTableNew, i * FM_PCD_CC_AD_ENTRY_SIZE);
2909     p_AdTableOldTmp =
2910             PTR_MOVE(p_AdditionalInfo->p_AdTableOld, j * FM_PCD_CC_AD_ENTRY_SIZE);
2911     MemCpy8(p_AdTableNewTmp, p_AdTableOldTmp, FM_PCD_CC_AD_ENTRY_SIZE);
2912 
2913     if (p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.nextEngine
2914             == e_FM_PCD_CC)
2915         p_AdditionalInfo->h_NodeForRmv =
2916                 p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.params.ccParams.h_CcNode;
2917 
2918     if (p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.h_Manip)
2919         p_AdditionalInfo->h_ManipForRmv =
2920                 p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.h_Manip;
2921 
2922     /* If statistics were previously enabled, store the old statistics object to be released */
2923     if (p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj)
2924     {
2925         p_AdditionalInfo->p_StatsObjForRmv =
2926                 p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj;
2927     }
2928 
2929 #if (DPAA_VERSION >= 11)
2930     if ((p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.nextEngine
2931             == e_FM_PCD_FR)
2932             && (p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.params.frParams.h_FrmReplic))
2933         p_AdditionalInfo->h_FrmReplicForRmv =
2934                 p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.params.frParams.h_FrmReplic;
2935 #endif /* (DPAA_VERSION >= 11) */
2936 
2937     return E_OK;
2938 }
2939 
2940 static t_Error BuildNewNodeModifyKey(
2941         t_FmPcdCcNode *p_CcNode, uint16_t keyIndex, uint8_t *p_Key,
2942         uint8_t *p_Mask, t_FmPcdModifyCcKeyAdditionalParams *p_AdditionalInfo)
2943 {
2944     t_FmPcd *p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd;
2945     t_Error err = E_OK;
2946     t_Handle p_AdTableNewTmp, p_KeysMatchTableNewTmp;
2947     t_Handle p_KeysMatchTableOldTmp, p_AdTableOldTmp;
2948     int size;
2949     int i = 0, j = 0;
2950     bool prvLclMask;
2951     t_FmPcdStatsObj *p_StatsObj, tmpStatsObj;
2952     p_AdditionalInfo->numOfKeys = p_CcNode->numOfKeys;
2953 
2954     prvLclMask = p_CcNode->lclMask;
2955 
2956     /* Check that new key is not require update of localMask */
2957     err = UpdateGblMask(p_CcNode, p_CcNode->ccKeySizeAccExtraction, p_Mask);
2958     if (err)
2959         RETURN_ERROR(MAJOR, err, (NO_MSG));
2960 
2961     /* Update internal data structure with new next engine for the given index */
2962     memcpy(p_AdditionalInfo->keyAndNextEngineParams[keyIndex].key, p_Key,
2963            p_CcNode->userSizeOfExtraction);
2964 
2965     if (p_Mask)
2966         memcpy(p_AdditionalInfo->keyAndNextEngineParams[keyIndex].mask, p_Mask,
2967                p_CcNode->userSizeOfExtraction);
2968     else
2969         memset(p_AdditionalInfo->keyAndNextEngineParams[keyIndex].mask, 0xFF,
2970                p_CcNode->userSizeOfExtraction);
2971 
2972     /*function which build in the memory new KeyTbl, AdTbl*/
2973     err = BuildNewNodeCommonPart(p_CcNode, &size, p_AdditionalInfo);
2974     if (err)
2975         RETURN_ERROR(MAJOR, err, NO_MSG);
2976 
2977     /*fill the New AdTable and New KeyTable*/
2978     for (j = 0, i = 0; j < p_AdditionalInfo->numOfKeys; j++, i++)
2979     {
2980         p_AdTableNewTmp =
2981                 PTR_MOVE(p_AdditionalInfo->p_AdTableNew, j*FM_PCD_CC_AD_ENTRY_SIZE);
2982         p_AdTableOldTmp =
2983                 PTR_MOVE(p_AdditionalInfo->p_AdTableOld, i*FM_PCD_CC_AD_ENTRY_SIZE);
2984 
2985         MemCpy8(p_AdTableNewTmp, p_AdTableOldTmp, FM_PCD_CC_AD_ENTRY_SIZE);
2986 
2987         if (j == keyIndex)
2988         {
2989             ASSERT_COND(keyIndex < CC_MAX_NUM_OF_KEYS);
2990             if (p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj)
2991             {
2992                 /* As statistics were enabled, we need to update the existing
2993                  statistics descriptor with a new nullified counters. */
2994                 p_StatsObj = GetStatsObj(p_CcNode);
2995                 ASSERT_COND(p_StatsObj);
2996 
2997                 SetStatsCounters(
2998                         p_AdTableNewTmp,
2999                         (uint32_t)((XX_VirtToPhys(p_StatsObj->h_StatsCounters)
3000                                 - p_FmPcd->physicalMuramBase)));
3001 
3002                 tmpStatsObj.h_StatsAd = p_StatsObj->h_StatsAd;
3003                 tmpStatsObj.h_StatsCounters = p_StatsObj->h_StatsCounters;
3004 
3005                 /* As we need to replace only the counters, we build a new statistics
3006                  object that holds the old AD and the new counters - this will be the
3007                  currently used statistics object.
3008                  The newly allocated AD is not required and may be released back to
3009                  the available objects with the previous counters pointer. */
3010                 p_StatsObj->h_StatsAd =
3011                         p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj->h_StatsAd;
3012 
3013                 p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj->h_StatsAd =
3014                         tmpStatsObj.h_StatsAd;
3015 
3016                 /* Store allocated statistics object */
3017                 p_AdditionalInfo->keyAndNextEngineParams[keyIndex].p_StatsObj =
3018                         p_StatsObj;
3019 
3020                 /* As statistics were previously enabled, store the old statistics object to be released */
3021                 p_AdditionalInfo->p_StatsObjForRmv =
3022                         p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj;
3023             }
3024 
3025             p_KeysMatchTableNewTmp =
3026                     PTR_MOVE(p_AdditionalInfo->p_KeysMatchTableNew, j * size * sizeof(uint8_t));
3027 
3028             MemCpy8(p_KeysMatchTableNewTmp, p_Key,
3029                         p_CcNode->userSizeOfExtraction);
3030 
3031             if (p_CcNode->lclMask)
3032             {
3033                 if (p_Mask)
3034                     MemCpy8(PTR_MOVE(p_KeysMatchTableNewTmp,
3035                             p_CcNode->ccKeySizeAccExtraction),
3036                                 p_Mask, p_CcNode->userSizeOfExtraction);
3037                 else
3038                     if (p_CcNode->ccKeySizeAccExtraction > 4)
3039                         MemSet8(PTR_MOVE(p_KeysMatchTableNewTmp,
3040                                 p_CcNode->ccKeySizeAccExtraction),
3041                                    0xff, p_CcNode->userSizeOfExtraction);
3042                     else
3043                         MemCpy8(PTR_MOVE(p_KeysMatchTableNewTmp,
3044                                 p_CcNode->ccKeySizeAccExtraction),
3045                                     p_CcNode->p_GlblMask,
3046                                     p_CcNode->userSizeOfExtraction);
3047             }
3048         }
3049         else
3050         {
3051             p_KeysMatchTableNewTmp =
3052                     PTR_MOVE(p_AdditionalInfo->p_KeysMatchTableNew, j * size * sizeof(uint8_t));
3053             p_KeysMatchTableOldTmp =
3054                     PTR_MOVE(p_CcNode->h_KeysMatchTable, i * size * sizeof(uint8_t));
3055 
3056             if (p_CcNode->lclMask)
3057             {
3058                 if (prvLclMask)
3059                     MemCpy8(
3060                             PTR_MOVE(p_KeysMatchTableNewTmp, p_CcNode->ccKeySizeAccExtraction),
3061                             PTR_MOVE(p_KeysMatchTableOldTmp, p_CcNode->ccKeySizeAccExtraction),
3062                             p_CcNode->userSizeOfExtraction);
3063                 else
3064                 {
3065                     p_KeysMatchTableOldTmp =
3066                             PTR_MOVE(p_CcNode->h_KeysMatchTable,
3067                                      i * (int)p_CcNode->ccKeySizeAccExtraction * sizeof(uint8_t));
3068 
3069                     if (p_CcNode->ccKeySizeAccExtraction > 4)
3070                         MemSet8(PTR_MOVE(p_KeysMatchTableNewTmp,
3071                                 p_CcNode->ccKeySizeAccExtraction),
3072                                    0xff, p_CcNode->userSizeOfExtraction);
3073                     else
3074                         MemCpy8(
3075                                 PTR_MOVE(p_KeysMatchTableNewTmp, p_CcNode->ccKeySizeAccExtraction),
3076                                 p_CcNode->p_GlblMask,
3077                                 p_CcNode->userSizeOfExtraction);
3078                 }
3079             }
3080             MemCpy8((void*)p_KeysMatchTableNewTmp, p_KeysMatchTableOldTmp,
3081                        p_CcNode->ccKeySizeAccExtraction);
3082         }
3083     }
3084 
3085     p_AdTableNewTmp =
3086             PTR_MOVE(p_AdditionalInfo->p_AdTableNew, j * FM_PCD_CC_AD_ENTRY_SIZE);
3087     p_AdTableOldTmp = PTR_MOVE(p_CcNode->h_AdTable, i * FM_PCD_CC_AD_ENTRY_SIZE);
3088 
3089     MemCpy8(p_AdTableNewTmp, p_AdTableOldTmp, FM_PCD_CC_AD_ENTRY_SIZE);
3090 
3091     return E_OK;
3092 }
3093 
3094 static t_Error BuildNewNodeModifyNextEngine(
3095         t_Handle h_FmPcd, t_Handle h_FmPcdCcNodeOrTree, uint16_t keyIndex,
3096         t_FmPcdCcNextEngineParams *p_CcNextEngineParams, t_List *h_OldLst,
3097         t_List *h_NewLst, t_FmPcdModifyCcKeyAdditionalParams *p_AdditionalInfo)
3098 {
3099     t_Error err = E_OK;
3100     uint32_t requiredAction = 0;
3101     t_List *p_Pos;
3102     t_CcNodeInformation *p_CcNodeInformation, ccNodeInfo;
3103     t_Handle p_Ad;
3104     t_FmPcdCcNode *p_FmPcdCcNode1 = NULL;
3105     t_FmPcdCcTree *p_FmPcdCcTree = NULL;
3106     t_FmPcdStatsObj *p_StatsObj;
3107     t_FmPcdCcStatsParams statsParams = { 0 };
3108 
3109     ASSERT_COND(p_CcNextEngineParams);
3110 
3111     /* check that new NIA is legal */
3112     if (!p_AdditionalInfo->tree)
3113         err = ValidateNextEngineParams(
3114                 h_FmPcd, p_CcNextEngineParams,
3115                 ((t_FmPcdCcNode *)h_FmPcdCcNodeOrTree)->statisticsMode);
3116     else
3117         /* Statistics are not supported for CC root */
3118         err = ValidateNextEngineParams(h_FmPcd, p_CcNextEngineParams,
3119                                        e_FM_PCD_CC_STATS_MODE_NONE);
3120     if (err)
3121         RETURN_ERROR(MAJOR, err, NO_MSG);
3122 
3123     /* Update internal data structure for next engine per index (index - key) */
3124     memcpy(&p_AdditionalInfo->keyAndNextEngineParams[keyIndex].nextEngineParams,
3125            p_CcNextEngineParams, sizeof(t_FmPcdCcNextEngineParams));
3126 
3127     /* Check that manip is legal and what requiredAction is necessary for this manip */
3128     if (p_CcNextEngineParams->h_Manip)
3129     {
3130         err = FmPcdManipCheckParamsForCcNextEngine(p_CcNextEngineParams,
3131                                                    &requiredAction);
3132         if (err)
3133             RETURN_ERROR(MAJOR, err, (NO_MSG));
3134     }
3135 
3136     if (!p_AdditionalInfo->tree)
3137     {
3138         p_FmPcdCcNode1 = (t_FmPcdCcNode *)h_FmPcdCcNodeOrTree;
3139         p_AdditionalInfo->numOfKeys = p_FmPcdCcNode1->numOfKeys;
3140         p_Ad = p_FmPcdCcNode1->h_AdTable;
3141 
3142         if (p_FmPcdCcNode1->keyAndNextEngineParams[keyIndex].nextEngineParams.nextEngine
3143                 == e_FM_PCD_CC)
3144             p_AdditionalInfo->h_NodeForRmv =
3145                     p_FmPcdCcNode1->keyAndNextEngineParams[keyIndex].nextEngineParams.params.ccParams.h_CcNode;
3146 
3147         if (p_FmPcdCcNode1->keyAndNextEngineParams[keyIndex].nextEngineParams.h_Manip)
3148             p_AdditionalInfo->h_ManipForRmv =
3149                     p_FmPcdCcNode1->keyAndNextEngineParams[keyIndex].nextEngineParams.h_Manip;
3150 
3151 #if (DPAA_VERSION >= 11)
3152         if ((p_FmPcdCcNode1->keyAndNextEngineParams[keyIndex].nextEngineParams.nextEngine
3153                 == e_FM_PCD_FR)
3154                 && (p_FmPcdCcNode1->keyAndNextEngineParams[keyIndex].nextEngineParams.params.frParams.h_FrmReplic))
3155             p_AdditionalInfo->h_FrmReplicForRmv =
3156                     p_FmPcdCcNode1->keyAndNextEngineParams[keyIndex].nextEngineParams.params.frParams.h_FrmReplic;
3157 #endif /* (DPAA_VERSION >= 11) */
3158     }
3159     else
3160     {
3161         p_FmPcdCcTree = (t_FmPcdCcTree *)h_FmPcdCcNodeOrTree;
3162         p_Ad = UINT_TO_PTR(p_FmPcdCcTree->ccTreeBaseAddr);
3163 
3164         if (p_FmPcdCcTree->keyAndNextEngineParams[keyIndex].nextEngineParams.nextEngine
3165                 == e_FM_PCD_CC)
3166             p_AdditionalInfo->h_NodeForRmv =
3167                     p_FmPcdCcTree->keyAndNextEngineParams[keyIndex].nextEngineParams.params.ccParams.h_CcNode;
3168 
3169         if (p_FmPcdCcTree->keyAndNextEngineParams[keyIndex].nextEngineParams.h_Manip)
3170             p_AdditionalInfo->h_ManipForRmv =
3171                     p_FmPcdCcTree->keyAndNextEngineParams[keyIndex].nextEngineParams.h_Manip;
3172 
3173 #if (DPAA_VERSION >= 11)
3174         if ((p_FmPcdCcTree->keyAndNextEngineParams[keyIndex].nextEngineParams.nextEngine
3175                 == e_FM_PCD_FR)
3176                 && (p_FmPcdCcTree->keyAndNextEngineParams[keyIndex].nextEngineParams.params.frParams.h_FrmReplic))
3177             p_AdditionalInfo->h_FrmReplicForRmv =
3178                     p_FmPcdCcTree->keyAndNextEngineParams[keyIndex].nextEngineParams.params.frParams.h_FrmReplic;
3179 #endif /* (DPAA_VERSION >= 11) */
3180     }
3181 
3182     if ((p_CcNextEngineParams->nextEngine == e_FM_PCD_CC)
3183             && p_CcNextEngineParams->h_Manip)
3184     {
3185         err = AllocAndFillAdForContLookupManip(
3186                 p_CcNextEngineParams->params.ccParams.h_CcNode);
3187         if (err)
3188             RETURN_ERROR(MAJOR, err, (NO_MSG));
3189     }
3190 
3191     ASSERT_COND(p_Ad);
3192 
3193     memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation));
3194     ccNodeInfo.h_CcNode = PTR_MOVE(p_Ad, keyIndex * FM_PCD_CC_AD_ENTRY_SIZE);
3195 
3196     /* If statistics were enabled, this Ad is the statistics Ad. Need to follow its
3197      nextAction to retrieve the actual Nia-Ad. If statistics should remain enabled,
3198      only the actual Nia-Ad should be modified. */
3199     if ((!p_AdditionalInfo->tree)
3200             && (((t_FmPcdCcNode *)h_FmPcdCcNodeOrTree)->keyAndNextEngineParams[keyIndex].p_StatsObj)
3201             && (p_CcNextEngineParams->statisticsEn))
3202         ccNodeInfo.h_CcNode =
3203                 ((t_FmPcdCcNode *)h_FmPcdCcNodeOrTree)->keyAndNextEngineParams[keyIndex].p_StatsObj->h_StatsAd;
3204 
3205     EnqueueNodeInfoToRelevantLst(h_OldLst, &ccNodeInfo, NULL);
3206 
3207     memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation));
3208     p_Ad = GetNewAd(h_FmPcdCcNodeOrTree, p_AdditionalInfo->tree);
3209     if (!p_Ad)
3210         RETURN_ERROR(MAJOR, E_NO_MEMORY,
3211                      ("MURAM allocation for CC node action descriptor"));
3212     MemSet8((uint8_t *)p_Ad, 0, FM_PCD_CC_AD_ENTRY_SIZE);
3213 
3214     /* If statistics were not enabled before, but requested now -  Allocate a statistics
3215      object that holds statistics AD and counters. */
3216     if ((!p_AdditionalInfo->tree)
3217             && (!((t_FmPcdCcNode *)h_FmPcdCcNodeOrTree)->keyAndNextEngineParams[keyIndex].p_StatsObj)
3218             && (p_CcNextEngineParams->statisticsEn))
3219     {
3220         p_StatsObj = GetStatsObj((t_FmPcdCcNode *)h_FmPcdCcNodeOrTree);
3221         ASSERT_COND(p_StatsObj);
3222 
3223         /* Store allocated statistics object */
3224         p_AdditionalInfo->keyAndNextEngineParams[keyIndex].p_StatsObj =
3225                 p_StatsObj;
3226 
3227         statsParams.h_StatsAd = p_StatsObj->h_StatsAd;
3228         statsParams.h_StatsCounters = p_StatsObj->h_StatsCounters;
3229 
3230 #if (DPAA_VERSION >= 11)
3231         statsParams.h_StatsFLRs =
3232                 ((t_FmPcdCcNode *)h_FmPcdCcNodeOrTree)->h_StatsFLRs;
3233 
3234 #endif /* (DPAA_VERSION >= 11) */
3235 
3236         NextStepAd(p_Ad, &statsParams, p_CcNextEngineParams, h_FmPcd);
3237     }
3238     else
3239         NextStepAd(p_Ad, NULL, p_CcNextEngineParams, h_FmPcd);
3240 
3241     ccNodeInfo.h_CcNode = p_Ad;
3242     EnqueueNodeInfoToRelevantLst(h_NewLst, &ccNodeInfo, NULL);
3243 
3244     p_AdditionalInfo->keyAndNextEngineParams[keyIndex].requiredAction =
3245             requiredAction;
3246     p_AdditionalInfo->keyAndNextEngineParams[keyIndex].requiredAction |=
3247             UPDATE_CC_WITH_TREE;
3248 
3249     if (!p_AdditionalInfo->tree)
3250     {
3251         ASSERT_COND(p_FmPcdCcNode1);
3252         if (!NCSW_LIST_IsEmpty(&p_FmPcdCcNode1->ccTreesLst))
3253         {
3254             NCSW_LIST_FOR_EACH(p_Pos, &p_FmPcdCcNode1->ccTreesLst)
3255             {
3256                 p_CcNodeInformation = CC_NODE_F_OBJECT(p_Pos);
3257 
3258                 ASSERT_COND(p_CcNodeInformation->h_CcNode);
3259                 /* Update the manipulation which has to be updated from parameters of the port
3260                  it's has to be updated with restrictions defined in the function */
3261 
3262                 err =
3263                         SetRequiredAction(
3264                                 p_FmPcdCcNode1->h_FmPcd,
3265                                 p_FmPcdCcNode1->shadowAction
3266                                         | p_AdditionalInfo->keyAndNextEngineParams[keyIndex].requiredAction,
3267                                 &p_AdditionalInfo->keyAndNextEngineParams[keyIndex],
3268                                 p_Ad, 1, p_CcNodeInformation->h_CcNode);
3269                 if (err)
3270                     RETURN_ERROR(MAJOR, err, (NO_MSG));
3271 
3272                 err = CcUpdateParam(
3273                         p_FmPcdCcNode1->h_FmPcd, NULL, NULL,
3274                         &p_AdditionalInfo->keyAndNextEngineParams[keyIndex], 1,
3275                         p_Ad, TRUE, p_CcNodeInformation->index,
3276                         p_CcNodeInformation->h_CcNode, TRUE);
3277                 if (err)
3278                     RETURN_ERROR(MAJOR, err, (NO_MSG));
3279             }
3280         }
3281     }
3282     else
3283     {
3284         ASSERT_COND(p_FmPcdCcTree);
3285 
3286         err =
3287                 SetRequiredAction(
3288                         h_FmPcd,
3289                         p_FmPcdCcTree->requiredAction
3290                                 | p_AdditionalInfo->keyAndNextEngineParams[keyIndex].requiredAction,
3291                         &p_AdditionalInfo->keyAndNextEngineParams[keyIndex],
3292                         p_Ad, 1, (t_Handle)p_FmPcdCcTree);
3293         if (err)
3294             RETURN_ERROR(MAJOR, err, (NO_MSG));
3295 
3296         err = CcUpdateParam(h_FmPcd, NULL, NULL,
3297                             &p_AdditionalInfo->keyAndNextEngineParams[keyIndex],
3298                             1, p_Ad, TRUE, 0, (t_Handle)p_FmPcdCcTree, TRUE);
3299         if (err)
3300             RETURN_ERROR(MAJOR, err, (NO_MSG));
3301     }
3302 
3303     if (p_CcNextEngineParams->nextEngine == e_FM_PCD_CC)
3304         p_AdditionalInfo->h_NodeForAdd =
3305                 p_CcNextEngineParams->params.ccParams.h_CcNode;
3306     if (p_CcNextEngineParams->h_Manip)
3307         p_AdditionalInfo->h_ManipForAdd = p_CcNextEngineParams->h_Manip;
3308 
3309     /* If statistics were previously enabled, but now are disabled,
3310      store the old statistics object to be released */
3311     if ((!p_AdditionalInfo->tree)
3312             && (((t_FmPcdCcNode *)h_FmPcdCcNodeOrTree)->keyAndNextEngineParams[keyIndex].p_StatsObj)
3313             && (!p_CcNextEngineParams->statisticsEn))
3314     {
3315         p_AdditionalInfo->p_StatsObjForRmv =
3316                 ((t_FmPcdCcNode *)h_FmPcdCcNodeOrTree)->keyAndNextEngineParams[keyIndex].p_StatsObj;
3317 
3318 
3319         p_AdditionalInfo->keyAndNextEngineParams[keyIndex].p_StatsObj = NULL;
3320     }
3321 #if (DPAA_VERSION >= 11)
3322     if ((p_CcNextEngineParams->nextEngine == e_FM_PCD_FR)
3323             && (p_CcNextEngineParams->params.frParams.h_FrmReplic))
3324         p_AdditionalInfo->h_FrmReplicForAdd =
3325                 p_CcNextEngineParams->params.frParams.h_FrmReplic;
3326 #endif /* (DPAA_VERSION >= 11) */
3327 
3328     return E_OK;
3329 }
3330 
3331 static void UpdateAdPtrOfNodesWhichPointsOnCrntMdfNode(
3332         t_FmPcdCcNode *p_CrntMdfNode, t_List *h_OldLst,
3333         t_FmPcdCcNextEngineParams **p_NextEngineParams)
3334 {
3335     t_CcNodeInformation *p_CcNodeInformation;
3336     t_FmPcdCcNode *p_NodePtrOnCurrentMdfNode = NULL;
3337     t_List *p_Pos;
3338     int i = 0;
3339     t_Handle p_AdTablePtOnCrntCurrentMdfNode/*, p_AdTableNewModified*/;
3340     t_CcNodeInformation ccNodeInfo;
3341 
3342     NCSW_LIST_FOR_EACH(p_Pos, &p_CrntMdfNode->ccPrevNodesLst)
3343     {
3344         p_CcNodeInformation = CC_NODE_F_OBJECT(p_Pos);
3345         p_NodePtrOnCurrentMdfNode =
3346                 (t_FmPcdCcNode *)p_CcNodeInformation->h_CcNode;
3347 
3348         ASSERT_COND(p_NodePtrOnCurrentMdfNode);
3349 
3350         /* Search in the previous node which exact index points on this current modified node for getting AD */
3351         for (i = 0; i < p_NodePtrOnCurrentMdfNode->numOfKeys + 1; i++)
3352         {
3353             if (p_NodePtrOnCurrentMdfNode->keyAndNextEngineParams[i].nextEngineParams.nextEngine
3354                     == e_FM_PCD_CC)
3355             {
3356                 if (p_NodePtrOnCurrentMdfNode->keyAndNextEngineParams[i].nextEngineParams.params.ccParams.h_CcNode
3357                         == (t_Handle)p_CrntMdfNode)
3358                 {
3359                     if (p_NodePtrOnCurrentMdfNode->keyAndNextEngineParams[i].nextEngineParams.h_Manip)
3360                         p_AdTablePtOnCrntCurrentMdfNode = p_CrntMdfNode->h_Ad;
3361                     else
3362                         if (p_NodePtrOnCurrentMdfNode->keyAndNextEngineParams[i].p_StatsObj)
3363                             p_AdTablePtOnCrntCurrentMdfNode =
3364                                     p_NodePtrOnCurrentMdfNode->keyAndNextEngineParams[i].p_StatsObj->h_StatsAd;
3365                         else
3366                             p_AdTablePtOnCrntCurrentMdfNode =
3367                                     PTR_MOVE(p_NodePtrOnCurrentMdfNode->h_AdTable, i*FM_PCD_CC_AD_ENTRY_SIZE);
3368 
3369                     memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation));
3370                     ccNodeInfo.h_CcNode = p_AdTablePtOnCrntCurrentMdfNode;
3371                     EnqueueNodeInfoToRelevantLst(h_OldLst, &ccNodeInfo, NULL);
3372 
3373                     if (!(*p_NextEngineParams))
3374                         *p_NextEngineParams =
3375                                 &p_NodePtrOnCurrentMdfNode->keyAndNextEngineParams[i].nextEngineParams;
3376                 }
3377             }
3378         }
3379 
3380         ASSERT_COND(i != p_NodePtrOnCurrentMdfNode->numOfKeys);
3381     }
3382 }
3383 
3384 static void UpdateAdPtrOfTreesWhichPointsOnCrntMdfNode(
3385         t_FmPcdCcNode *p_CrntMdfNode, t_List *h_OldLst,
3386         t_FmPcdCcNextEngineParams **p_NextEngineParams)
3387 {
3388     t_CcNodeInformation *p_CcNodeInformation;
3389     t_FmPcdCcTree *p_TreePtrOnCurrentMdfNode = NULL;
3390     t_List *p_Pos;
3391     int i = 0;
3392     t_Handle p_AdTableTmp;
3393     t_CcNodeInformation ccNodeInfo;
3394 
3395     NCSW_LIST_FOR_EACH(p_Pos, &p_CrntMdfNode->ccTreeIdLst)
3396     {
3397         p_CcNodeInformation = CC_NODE_F_OBJECT(p_Pos);
3398         p_TreePtrOnCurrentMdfNode =
3399                 (t_FmPcdCcTree *)p_CcNodeInformation->h_CcNode;
3400 
3401         ASSERT_COND(p_TreePtrOnCurrentMdfNode);
3402 
3403         /*search in the trees which exact index points on this current modified node for getting AD */
3404         for (i = 0; i < p_TreePtrOnCurrentMdfNode->numOfEntries; i++)
3405         {
3406             if (p_TreePtrOnCurrentMdfNode->keyAndNextEngineParams[i].nextEngineParams.nextEngine
3407                     == e_FM_PCD_CC)
3408             {
3409                 if (p_TreePtrOnCurrentMdfNode->keyAndNextEngineParams[i].nextEngineParams.params.ccParams.h_CcNode
3410                         == (t_Handle)p_CrntMdfNode)
3411                 {
3412                     p_AdTableTmp =
3413                             UINT_TO_PTR(p_TreePtrOnCurrentMdfNode->ccTreeBaseAddr + i*FM_PCD_CC_AD_ENTRY_SIZE);
3414                     memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation));
3415                     ccNodeInfo.h_CcNode = p_AdTableTmp;
3416                     EnqueueNodeInfoToRelevantLst(h_OldLst, &ccNodeInfo, NULL);
3417 
3418                     if (!(*p_NextEngineParams))
3419                         *p_NextEngineParams =
3420                                 &p_TreePtrOnCurrentMdfNode->keyAndNextEngineParams[i].nextEngineParams;
3421                 }
3422             }
3423         }
3424 
3425         ASSERT_COND(i == p_TreePtrOnCurrentMdfNode->numOfEntries);
3426     }
3427 }
3428 
3429 static t_FmPcdModifyCcKeyAdditionalParams * ModifyNodeCommonPart(
3430         t_Handle h_FmPcdCcNodeOrTree, uint16_t keyIndex,
3431         e_ModifyState modifyState, bool ttlCheck, bool hashCheck, bool tree)
3432 {
3433     t_FmPcdModifyCcKeyAdditionalParams *p_FmPcdModifyCcKeyAdditionalParams;
3434     int i = 0, j = 0;
3435     bool wasUpdate = FALSE;
3436     t_FmPcdCcNode *p_CcNode = NULL;
3437     t_FmPcdCcTree *p_FmPcdCcTree;
3438     uint16_t numOfKeys;
3439     t_FmPcdCcKeyAndNextEngineParams *p_KeyAndNextEngineParams;
3440 
3441     SANITY_CHECK_RETURN_VALUE(h_FmPcdCcNodeOrTree, E_INVALID_HANDLE, NULL);
3442 
3443     if (!tree)
3444     {
3445         p_CcNode = (t_FmPcdCcNode *)h_FmPcdCcNodeOrTree;
3446         numOfKeys = p_CcNode->numOfKeys;
3447 
3448         /* node has to be pointed by another node or tree */
3449 
3450         p_KeyAndNextEngineParams = (t_FmPcdCcKeyAndNextEngineParams *)XX_Malloc(
3451                 sizeof(t_FmPcdCcKeyAndNextEngineParams) * (numOfKeys + 1));
3452         if (!p_KeyAndNextEngineParams)
3453         {
3454             REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Next engine and required action structure"));
3455             return NULL;
3456         }
3457         memcpy(p_KeyAndNextEngineParams, p_CcNode->keyAndNextEngineParams,
3458                (numOfKeys + 1) * sizeof(t_FmPcdCcKeyAndNextEngineParams));
3459 
3460         if (ttlCheck)
3461         {
3462             if ((p_CcNode->parseCode == CC_PC_FF_IPV4TTL)
3463                     || (p_CcNode->parseCode == CC_PC_FF_IPV6HOP_LIMIT))
3464             {
3465                 XX_Free(p_KeyAndNextEngineParams);
3466                 REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("nodeId of CC_PC_FF_IPV4TTL or CC_PC_FF_IPV6HOP_LIMIT can not be used for this operation"));
3467                 return NULL;
3468             }
3469         }
3470 
3471         if (hashCheck)
3472         {
3473             if (p_CcNode->parseCode == CC_PC_GENERIC_IC_HASH_INDEXED)
3474             {
3475                 XX_Free(p_KeyAndNextEngineParams);
3476                 REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("nodeId of CC_PC_GENERIC_IC_HASH_INDEXED can not be used for this operation"));
3477                 return NULL;
3478             }
3479         }
3480     }
3481     else
3482     {
3483         p_FmPcdCcTree = (t_FmPcdCcTree *)h_FmPcdCcNodeOrTree;
3484         numOfKeys = p_FmPcdCcTree->numOfEntries;
3485 
3486         p_KeyAndNextEngineParams = (t_FmPcdCcKeyAndNextEngineParams *)XX_Malloc(
3487                 sizeof(t_FmPcdCcKeyAndNextEngineParams)
3488                         * FM_PCD_MAX_NUM_OF_CC_GROUPS);
3489         if (!p_KeyAndNextEngineParams)
3490         {
3491             REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Next engine and required action structure"));
3492             return NULL;
3493         }
3494         memcpy(p_KeyAndNextEngineParams,
3495                p_FmPcdCcTree->keyAndNextEngineParams,
3496                FM_PCD_MAX_NUM_OF_CC_GROUPS
3497                        * sizeof(t_FmPcdCcKeyAndNextEngineParams));
3498     }
3499 
3500     p_FmPcdModifyCcKeyAdditionalParams =
3501             (t_FmPcdModifyCcKeyAdditionalParams *)XX_Malloc(
3502                     sizeof(t_FmPcdModifyCcKeyAdditionalParams));
3503     if (!p_FmPcdModifyCcKeyAdditionalParams)
3504     {
3505         XX_Free(p_KeyAndNextEngineParams);
3506         REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Allocation of internal data structure FAILED"));
3507         return NULL;
3508     }
3509     memset(p_FmPcdModifyCcKeyAdditionalParams, 0,
3510            sizeof(t_FmPcdModifyCcKeyAdditionalParams));
3511 
3512     p_FmPcdModifyCcKeyAdditionalParams->h_CurrentNode = h_FmPcdCcNodeOrTree;
3513     p_FmPcdModifyCcKeyAdditionalParams->savedKeyIndex = keyIndex;
3514 
3515     while (i < numOfKeys)
3516     {
3517         if ((j == keyIndex) && !wasUpdate)
3518         {
3519             if (modifyState == e_MODIFY_STATE_ADD)
3520                 j++;
3521             else
3522                 if (modifyState == e_MODIFY_STATE_REMOVE)
3523                     i++;
3524             wasUpdate = TRUE;
3525         }
3526         else
3527         {
3528             memcpy(&p_FmPcdModifyCcKeyAdditionalParams->keyAndNextEngineParams[j],
3529                    p_KeyAndNextEngineParams + i,
3530                    sizeof(t_FmPcdCcKeyAndNextEngineParams));
3531             i++;
3532             j++;
3533         }
3534     }
3535 
3536     if (keyIndex == numOfKeys)
3537     {
3538         if (modifyState == e_MODIFY_STATE_ADD)
3539             j++;
3540     }
3541 
3542     memcpy(&p_FmPcdModifyCcKeyAdditionalParams->keyAndNextEngineParams[j],
3543            p_KeyAndNextEngineParams + numOfKeys,
3544            sizeof(t_FmPcdCcKeyAndNextEngineParams));
3545 
3546     XX_Free(p_KeyAndNextEngineParams);
3547 
3548     return p_FmPcdModifyCcKeyAdditionalParams;
3549 }
3550 
3551 static t_Error UpdatePtrWhichPointOnCrntMdfNode(
3552         t_FmPcdCcNode *p_CcNode,
3553         t_FmPcdModifyCcKeyAdditionalParams *p_FmPcdModifyCcKeyAdditionalParams,
3554         t_List *h_OldLst, t_List *h_NewLst)
3555 {
3556     t_FmPcdCcNextEngineParams *p_NextEngineParams = NULL;
3557     t_CcNodeInformation ccNodeInfo = { 0 };
3558     t_Handle h_NewAd;
3559     t_Handle h_OrigAd = NULL;
3560 
3561     /* Building a list of all action descriptors that point to the previous node */
3562     if (!NCSW_LIST_IsEmpty(&p_CcNode->ccPrevNodesLst))
3563         UpdateAdPtrOfNodesWhichPointsOnCrntMdfNode(p_CcNode, h_OldLst,
3564                                                    &p_NextEngineParams);
3565 
3566     if (!NCSW_LIST_IsEmpty(&p_CcNode->ccTreeIdLst))
3567         UpdateAdPtrOfTreesWhichPointsOnCrntMdfNode(p_CcNode, h_OldLst,
3568                                                    &p_NextEngineParams);
3569 
3570     /* This node must be found as next engine of one of its previous nodes or trees*/
3571     if (p_NextEngineParams)
3572     {
3573         /* Building a new action descriptor that points to the modified node */
3574         h_NewAd = GetNewAd(p_CcNode, FALSE);
3575         if (!h_NewAd)
3576             RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG);
3577         MemSet8(h_NewAd, 0, FM_PCD_CC_AD_ENTRY_SIZE);
3578 
3579         h_OrigAd = p_CcNode->h_Ad;
3580         BuildNewAd(h_NewAd, p_FmPcdModifyCcKeyAdditionalParams, p_CcNode,
3581                    p_NextEngineParams);
3582 
3583         ccNodeInfo.h_CcNode = h_NewAd;
3584         EnqueueNodeInfoToRelevantLst(h_NewLst, &ccNodeInfo, NULL);
3585 
3586         if (p_NextEngineParams->h_Manip && !h_OrigAd)
3587             FmPcdManipUpdateOwner(p_NextEngineParams->h_Manip, FALSE);
3588     }
3589     return E_OK;
3590 }
3591 
3592 static void UpdateCcRootOwner(t_FmPcdCcTree *p_FmPcdCcTree, bool add)
3593 {
3594     ASSERT_COND(p_FmPcdCcTree);
3595 
3596     /* this routine must be protected by the calling routine! */
3597 
3598     if (add)
3599         p_FmPcdCcTree->owners++;
3600     else
3601     {
3602         ASSERT_COND(p_FmPcdCcTree->owners);
3603         p_FmPcdCcTree->owners--;
3604     }
3605 }
3606 
3607 static t_Error CheckAndSetManipParamsWithCcNodeParams(t_FmPcdCcNode *p_CcNode)
3608 {
3609     t_Error err = E_OK;
3610     int i = 0;
3611 
3612     for (i = 0; i < p_CcNode->numOfKeys; i++)
3613     {
3614         if (p_CcNode->keyAndNextEngineParams[i].nextEngineParams.h_Manip)
3615         {
3616             err =
3617                     FmPcdManipCheckParamsWithCcNodeParams(
3618                             p_CcNode->keyAndNextEngineParams[i].nextEngineParams.h_Manip,
3619                             (t_Handle)p_CcNode);
3620             if (err)
3621                 return err;
3622         }
3623     }
3624 
3625     return err;
3626 }
3627 static t_Error ValidateAndCalcStatsParams(t_FmPcdCcNode *p_CcNode,
3628                                           t_FmPcdCcNodeParams *p_CcNodeParam,
3629                                           uint32_t *p_NumOfRanges,
3630                                           uint32_t *p_CountersArraySize)
3631 {
3632     e_FmPcdCcStatsMode statisticsMode = p_CcNode->statisticsMode;
3633     uint32_t i;
3634 
3635     UNUSED(p_CcNodeParam);
3636 
3637     switch (statisticsMode)
3638     {
3639         case e_FM_PCD_CC_STATS_MODE_NONE:
3640             for (i = 0; i < p_CcNode->numOfKeys; i++)
3641                 if (p_CcNodeParam->keysParams.keyParams[i].ccNextEngineParams.statisticsEn)
3642                     RETURN_ERROR(
3643                             MAJOR,
3644                             E_INVALID_VALUE,
3645                             ("Statistics cannot be enabled for key %d when statistics mode was set to 'NONE'", i));
3646             return E_OK;
3647 
3648         case e_FM_PCD_CC_STATS_MODE_FRAME:
3649         case e_FM_PCD_CC_STATS_MODE_BYTE_AND_FRAME:
3650             *p_NumOfRanges = 1;
3651             *p_CountersArraySize = 2 * FM_PCD_CC_STATS_COUNTER_SIZE;
3652             return E_OK;
3653 
3654 #if (DPAA_VERSION >= 11)
3655         case e_FM_PCD_CC_STATS_MODE_RMON:
3656         {
3657             uint16_t *p_FrameLengthRanges =
3658                     p_CcNodeParam->keysParams.frameLengthRanges;
3659             uint32_t i;
3660 
3661             if (p_FrameLengthRanges[0] <= 0)
3662                 RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Statistics mode"));
3663 
3664             if (p_FrameLengthRanges[0] == 0xFFFF)
3665             {
3666                 *p_NumOfRanges = 1;
3667                 *p_CountersArraySize = 2 * FM_PCD_CC_STATS_COUNTER_SIZE;
3668                 return E_OK;
3669             }
3670 
3671             for (i = 1; i < FM_PCD_CC_STATS_MAX_NUM_OF_FLR; i++)
3672             {
3673                 if (p_FrameLengthRanges[i - 1] >= p_FrameLengthRanges[i])
3674                     RETURN_ERROR(
3675                             MAJOR,
3676                             E_INVALID_VALUE,
3677                             ("Frame length range must be larger at least by 1 from preceding range"));
3678 
3679                 /* Stop when last range is reached */
3680                 if (p_FrameLengthRanges[i] == 0xFFFF)
3681                     break;
3682             }
3683 
3684             if ((i >= FM_PCD_CC_STATS_MAX_NUM_OF_FLR)
3685                     || (p_FrameLengthRanges[i] != 0xFFFF))
3686                 RETURN_ERROR(MAJOR, E_INVALID_VALUE,
3687                              ("Last Frame length range must be 0xFFFF"));
3688 
3689             *p_NumOfRanges = i + 1;
3690 
3691             /* Allocate an extra counter for byte count, as counters
3692              array always begins with byte count */
3693             *p_CountersArraySize = (*p_NumOfRanges + 1)
3694                     * FM_PCD_CC_STATS_COUNTER_SIZE;
3695 
3696         }
3697             return E_OK;
3698 #endif /* (DPAA_VERSION >= 11) */
3699 
3700         default:
3701             RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Statistics mode"));
3702     }
3703 }
3704 
3705 static t_Error CheckParams(t_Handle h_FmPcd, t_FmPcdCcNodeParams *p_CcNodeParam,
3706                            t_FmPcdCcNode *p_CcNode, bool *isKeyTblAlloc)
3707 {
3708     int tmp = 0;
3709     t_FmPcdCcKeyParams *p_KeyParams;
3710     t_Error err;
3711     uint32_t requiredAction = 0;
3712 
3713     /* Validate statistics parameters */
3714     err = ValidateAndCalcStatsParams(p_CcNode, p_CcNodeParam,
3715                                      &(p_CcNode->numOfStatsFLRs),
3716                                      &(p_CcNode->countersArraySize));
3717     if (err)
3718         RETURN_ERROR(MAJOR, err, ("Invalid statistics parameters"));
3719 
3720     /* Validate next engine parameters on Miss */
3721     err = ValidateNextEngineParams(
3722             h_FmPcd, &p_CcNodeParam->keysParams.ccNextEngineParamsForMiss,
3723             p_CcNode->statisticsMode);
3724     if (err)
3725         RETURN_ERROR(MAJOR, err,
3726                      ("For this node MissNextEngineParams are not valid"));
3727 
3728     if (p_CcNodeParam->keysParams.ccNextEngineParamsForMiss.h_Manip)
3729     {
3730         err = FmPcdManipCheckParamsForCcNextEngine(
3731                 &p_CcNodeParam->keysParams.ccNextEngineParamsForMiss,
3732                 &requiredAction);
3733         if (err)
3734             RETURN_ERROR(MAJOR, err, (NO_MSG));
3735     }
3736 
3737     memcpy(&p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].nextEngineParams,
3738            &p_CcNodeParam->keysParams.ccNextEngineParamsForMiss,
3739            sizeof(t_FmPcdCcNextEngineParams));
3740 
3741     p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].requiredAction =
3742             requiredAction;
3743 
3744     if ((p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].nextEngineParams.nextEngine
3745             == e_FM_PCD_CC)
3746             && p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].nextEngineParams.h_Manip)
3747     {
3748         err =
3749                 AllocAndFillAdForContLookupManip(
3750                         p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].nextEngineParams.params.ccParams.h_CcNode);
3751         if (err)
3752             RETURN_ERROR(MAJOR, err, (NO_MSG));
3753     }
3754 
3755     for (tmp = 0; tmp < p_CcNode->numOfKeys; tmp++)
3756     {
3757         p_KeyParams = &p_CcNodeParam->keysParams.keyParams[tmp];
3758 
3759         if (!p_KeyParams->p_Key)
3760             RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("p_Key is not initialized"));
3761 
3762         err = ValidateNextEngineParams(h_FmPcd,
3763                                        &p_KeyParams->ccNextEngineParams,
3764                                        p_CcNode->statisticsMode);
3765         if (err)
3766             RETURN_ERROR(MAJOR, err, (NO_MSG));
3767 
3768         err = UpdateGblMask(p_CcNode, p_CcNodeParam->keysParams.keySize,
3769                             p_KeyParams->p_Mask);
3770         if (err)
3771             RETURN_ERROR(MAJOR, err, (NO_MSG));
3772 
3773         if (p_KeyParams->ccNextEngineParams.h_Manip)
3774         {
3775             err = FmPcdManipCheckParamsForCcNextEngine(
3776                     &p_KeyParams->ccNextEngineParams, &requiredAction);
3777             if (err)
3778                 RETURN_ERROR(MAJOR, err, (NO_MSG));
3779         }
3780 
3781         /* Store 'key' parameters - key, mask (if passed by the user) */
3782         memcpy(p_CcNode->keyAndNextEngineParams[tmp].key, p_KeyParams->p_Key,
3783                p_CcNodeParam->keysParams.keySize);
3784 
3785         if (p_KeyParams->p_Mask)
3786             memcpy(p_CcNode->keyAndNextEngineParams[tmp].mask,
3787                    p_KeyParams->p_Mask, p_CcNodeParam->keysParams.keySize);
3788         else
3789             memset((void *)(p_CcNode->keyAndNextEngineParams[tmp].mask), 0xFF,
3790                    p_CcNodeParam->keysParams.keySize);
3791 
3792         /* Store next engine parameters */
3793         memcpy(&p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams,
3794                &p_KeyParams->ccNextEngineParams,
3795                sizeof(t_FmPcdCcNextEngineParams));
3796 
3797         p_CcNode->keyAndNextEngineParams[tmp].requiredAction = requiredAction;
3798 
3799         if ((p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.nextEngine
3800                 == e_FM_PCD_CC)
3801                 && p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.h_Manip)
3802         {
3803             err =
3804                     AllocAndFillAdForContLookupManip(
3805                             p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.params.ccParams.h_CcNode);
3806             if (err)
3807                 RETURN_ERROR(MAJOR, err, (NO_MSG));
3808         }
3809     }
3810 
3811     if (p_CcNode->maxNumOfKeys)
3812     {
3813         if (p_CcNode->maxNumOfKeys < p_CcNode->numOfKeys)
3814             RETURN_ERROR(
3815                     MAJOR,
3816                     E_INVALID_VALUE,
3817                     ("Number of keys exceed the provided maximal number of keys"));
3818     }
3819 
3820     *isKeyTblAlloc = TRUE;
3821 
3822     return E_OK;
3823 }
3824 
3825 static t_Error Ipv4TtlOrIpv6HopLimitCheckParams(
3826         t_Handle h_FmPcd, t_FmPcdCcNodeParams *p_CcNodeParam,
3827         t_FmPcdCcNode *p_CcNode, bool *isKeyTblAlloc)
3828 {
3829     int tmp = 0;
3830     t_FmPcdCcKeyParams *p_KeyParams;
3831     t_Error err;
3832     uint8_t key = 0x01;
3833     uint32_t requiredAction = 0;
3834 
3835     if (p_CcNode->numOfKeys != 1)
3836         RETURN_ERROR(
3837                 MAJOR,
3838                 E_INVALID_VALUE,
3839                 ("For node of the type IPV4_TTL or IPV6_HOP_LIMIT the maximal supported 'numOfKeys' is 1"));
3840 
3841     if ((p_CcNodeParam->keysParams.maxNumOfKeys)
3842             && (p_CcNodeParam->keysParams.maxNumOfKeys != 1))
3843         RETURN_ERROR(
3844                 MAJOR,
3845                 E_INVALID_VALUE,
3846                 ("For node of the type IPV4_TTL or IPV6_HOP_LIMIT the maximal supported 'maxNumOfKeys' is 1"));
3847 
3848     /* Validate statistics parameters */
3849     err = ValidateAndCalcStatsParams(p_CcNode, p_CcNodeParam,
3850                                      &(p_CcNode->numOfStatsFLRs),
3851                                      &(p_CcNode->countersArraySize));
3852     if (err)
3853         RETURN_ERROR(MAJOR, err, ("Invalid statistics parameters"));
3854 
3855     err = ValidateNextEngineParams(
3856             h_FmPcd, &p_CcNodeParam->keysParams.ccNextEngineParamsForMiss,
3857             p_CcNodeParam->keysParams.statisticsMode);
3858     if (err)
3859         RETURN_ERROR(MAJOR, err,
3860                      ("For this node MissNextEngineParams are not valid"));
3861 
3862     if (p_CcNodeParam->keysParams.ccNextEngineParamsForMiss.h_Manip)
3863     {
3864         err = FmPcdManipCheckParamsForCcNextEngine(
3865                 &p_CcNodeParam->keysParams.ccNextEngineParamsForMiss,
3866                 &requiredAction);
3867         if (err)
3868             RETURN_ERROR(MAJOR, err, (NO_MSG));
3869     }
3870 
3871     memcpy(&p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].nextEngineParams,
3872            &p_CcNodeParam->keysParams.ccNextEngineParamsForMiss,
3873            sizeof(t_FmPcdCcNextEngineParams));
3874 
3875     p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].requiredAction =
3876             requiredAction;
3877 
3878     if ((p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].nextEngineParams.nextEngine
3879             == e_FM_PCD_CC)
3880             && p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].nextEngineParams.h_Manip)
3881     {
3882         err =
3883                 AllocAndFillAdForContLookupManip(
3884                         p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].nextEngineParams.params.ccParams.h_CcNode);
3885         if (err)
3886             RETURN_ERROR(MAJOR, err, (NO_MSG));
3887     }
3888 
3889     for (tmp = 0; tmp < p_CcNode->numOfKeys; tmp++)
3890     {
3891         p_KeyParams = &p_CcNodeParam->keysParams.keyParams[tmp];
3892 
3893         if (p_KeyParams->p_Mask)
3894             RETURN_ERROR(
3895                     MAJOR,
3896                     E_INVALID_VALUE,
3897                     ("For node of the type IPV4_TTL or IPV6_HOP_LIMIT p_Mask can not be initialized"));
3898 
3899         if (memcmp(p_KeyParams->p_Key, &key, 1) != 0)
3900             RETURN_ERROR(
3901                     MAJOR,
3902                     E_INVALID_VALUE,
3903                     ("For node of the type IPV4_TTL or IPV6_HOP_LIMIT p_Key has to be 1"));
3904 
3905         err = ValidateNextEngineParams(h_FmPcd,
3906                                        &p_KeyParams->ccNextEngineParams,
3907                                        p_CcNode->statisticsMode);
3908         if (err)
3909             RETURN_ERROR(MAJOR, err, (NO_MSG));
3910 
3911         if (p_KeyParams->ccNextEngineParams.h_Manip)
3912         {
3913             err = FmPcdManipCheckParamsForCcNextEngine(
3914                     &p_KeyParams->ccNextEngineParams, &requiredAction);
3915             if (err)
3916                 RETURN_ERROR(MAJOR, err, (NO_MSG));
3917         }
3918 
3919         /* Store 'key' parameters - key (fixed to 0x01), key size of 1 byte and full mask */
3920         p_CcNode->keyAndNextEngineParams[tmp].key[0] = key;
3921         p_CcNode->keyAndNextEngineParams[tmp].mask[0] = 0xFF;
3922 
3923         /* Store NextEngine parameters */
3924         memcpy(&p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams,
3925                &p_KeyParams->ccNextEngineParams,
3926                sizeof(t_FmPcdCcNextEngineParams));
3927 
3928         if ((p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.nextEngine
3929                 == e_FM_PCD_CC)
3930                 && p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.h_Manip)
3931         {
3932             err =
3933                     AllocAndFillAdForContLookupManip(
3934                             p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.params.ccParams.h_CcNode);
3935             if (err)
3936                 RETURN_ERROR(MAJOR, err, (NO_MSG));
3937         }
3938         p_CcNode->keyAndNextEngineParams[tmp].requiredAction = requiredAction;
3939     }
3940 
3941     *isKeyTblAlloc = FALSE;
3942 
3943     return E_OK;
3944 }
3945 
3946 static t_Error IcHashIndexedCheckParams(t_Handle h_FmPcd,
3947                                         t_FmPcdCcNodeParams *p_CcNodeParam,
3948                                         t_FmPcdCcNode *p_CcNode,
3949                                         bool *isKeyTblAlloc)
3950 {
3951     int tmp = 0, countOnes = 0;
3952     t_FmPcdCcKeyParams *p_KeyParams;
3953     t_Error err;
3954     uint16_t glblMask = p_CcNodeParam->extractCcParams.extractNonHdr.icIndxMask;
3955     uint16_t countMask = (uint16_t)(glblMask >> 4);
3956     uint32_t requiredAction = 0;
3957 
3958     if (glblMask & 0x000f)
3959         RETURN_ERROR(MAJOR, E_INVALID_VALUE,
3960                      ("icIndxMask has to be with last nibble 0"));
3961 
3962     while (countMask)
3963     {
3964         countOnes++;
3965         countMask = (uint16_t)(countMask >> 1);
3966     }
3967 
3968     if (!POWER_OF_2(p_CcNode->numOfKeys))
3969         RETURN_ERROR(
3970                 MAJOR,
3971                 E_INVALID_VALUE,
3972                 ("For Node of the type INDEXED numOfKeys has to be powerOfTwo"));
3973 
3974     if (p_CcNode->numOfKeys != ((uint32_t)1 << countOnes))
3975         RETURN_ERROR(
3976                 MAJOR,
3977                 E_INVALID_VALUE,
3978                 ("For Node of the type IC_HASH_INDEXED numOfKeys has to be powerOfTwo"));
3979 
3980     if (p_CcNodeParam->keysParams.maxNumOfKeys
3981             && (p_CcNodeParam->keysParams.maxNumOfKeys != p_CcNode->numOfKeys))
3982         RETURN_ERROR(
3983                 MAJOR,
3984                 E_INVALID_VALUE,
3985                 ("For Node of the type INDEXED 'maxNumOfKeys' should be 0 or equal 'numOfKeys'"));
3986 
3987     /* Validate statistics parameters */
3988     err = ValidateAndCalcStatsParams(p_CcNode, p_CcNodeParam,
3989                                      &(p_CcNode->numOfStatsFLRs),
3990                                      &(p_CcNode->countersArraySize));
3991     if (err)
3992         RETURN_ERROR(MAJOR, err, ("Invalid statistics parameters"));
3993 
3994     err = ValidateNextEngineParams(
3995             h_FmPcd, &p_CcNodeParam->keysParams.ccNextEngineParamsForMiss,
3996             p_CcNode->statisticsMode);
3997     if (GET_ERROR_TYPE(err) != E_NOT_SUPPORTED)
3998         RETURN_ERROR(
3999                 MAJOR,
4000                 err,
4001                 ("MissNextEngineParams for the node of the type IC_INDEX_HASH has to be UnInitialized"));
4002 
4003     for (tmp = 0; tmp < p_CcNode->numOfKeys; tmp++)
4004     {
4005         p_KeyParams = &p_CcNodeParam->keysParams.keyParams[tmp];
4006 
4007         if (p_KeyParams->p_Mask || p_KeyParams->p_Key)
4008             RETURN_ERROR(
4009                     MAJOR,
4010                     E_INVALID_VALUE,
4011                     ("For Node of the type IC_HASH_INDEXED p_Key or p_Mask has to be NULL"));
4012 
4013         if ((glblMask & (tmp * 16)) == (tmp * 16))
4014         {
4015             err = ValidateNextEngineParams(h_FmPcd,
4016                                            &p_KeyParams->ccNextEngineParams,
4017                                            p_CcNode->statisticsMode);
4018             if (err)
4019                 RETURN_ERROR(
4020                         MAJOR,
4021                         err,
4022                         ("This index has to be initialized for the node of the type IC_INDEX_HASH according to settings of GlobalMask "));
4023 
4024             if (p_KeyParams->ccNextEngineParams.h_Manip)
4025             {
4026                 err = FmPcdManipCheckParamsForCcNextEngine(
4027                         &p_KeyParams->ccNextEngineParams, &requiredAction);
4028                 if (err)
4029                     RETURN_ERROR(MAJOR, err, (NO_MSG));
4030                 p_CcNode->keyAndNextEngineParams[tmp].requiredAction =
4031                         requiredAction;
4032             }
4033 
4034             memcpy(&p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams,
4035                    &p_KeyParams->ccNextEngineParams,
4036                    sizeof(t_FmPcdCcNextEngineParams));
4037 
4038             if ((p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.nextEngine
4039                     == e_FM_PCD_CC)
4040                     && p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.h_Manip)
4041             {
4042                 err =
4043                         AllocAndFillAdForContLookupManip(
4044                                 p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.params.ccParams.h_CcNode);
4045                 if (err)
4046                     RETURN_ERROR(MAJOR, err, (NO_MSG));
4047             }
4048         }
4049         else
4050         {
4051             err = ValidateNextEngineParams(h_FmPcd,
4052                                            &p_KeyParams->ccNextEngineParams,
4053                                            p_CcNode->statisticsMode);
4054             if (GET_ERROR_TYPE(err) != E_NOT_SUPPORTED)
4055                 RETURN_ERROR(
4056                         MAJOR,
4057                         err,
4058                         ("This index has to be UnInitialized for the node of the type IC_INDEX_HASH according to settings of GlobalMask"));
4059         }
4060     }
4061 
4062     *isKeyTblAlloc = FALSE;
4063     glblMask = htobe16(glblMask);
4064     memcpy(PTR_MOVE(p_CcNode->p_GlblMask, 2), &glblMask, 2);
4065 
4066     return E_OK;
4067 }
4068 
4069 static t_Error ModifyNextEngineParamNode(
4070         t_Handle h_FmPcd, t_Handle h_FmPcdCcNode, uint16_t keyIndex,
4071         t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams)
4072 {
4073     t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_FmPcdCcNode;
4074     t_FmPcd *p_FmPcd;
4075     t_List h_OldPointersLst, h_NewPointersLst;
4076     t_FmPcdModifyCcKeyAdditionalParams *p_ModifyKeyParams;
4077     t_Error err = E_OK;
4078 
4079     SANITY_CHECK_RETURN_ERROR(h_FmPcd, E_INVALID_VALUE);
4080     SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE);
4081 
4082     if (keyIndex >= p_CcNode->numOfKeys)
4083         RETURN_ERROR(MAJOR, E_INVALID_STATE,
4084                      ("keyIndex > previously cleared last index + 1"));
4085 
4086     p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd;
4087 
4088     INIT_LIST(&h_OldPointersLst);
4089     INIT_LIST(&h_NewPointersLst);
4090 
4091     p_ModifyKeyParams = ModifyNodeCommonPart(p_CcNode, keyIndex,
4092                                              e_MODIFY_STATE_CHANGE, FALSE,
4093                                              FALSE, FALSE);
4094     if (!p_ModifyKeyParams)
4095         RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
4096 
4097     if (p_CcNode->maxNumOfKeys
4098             && !TRY_LOCK(p_FmPcd->h_ShadowSpinlock, &p_FmPcd->shadowLock))
4099     {
4100         XX_Free(p_ModifyKeyParams);
4101         return ERROR_CODE(E_BUSY);
4102     }
4103 
4104     err = BuildNewNodeModifyNextEngine(h_FmPcd, p_CcNode, keyIndex,
4105                                        p_FmPcdCcNextEngineParams,
4106                                        &h_OldPointersLst, &h_NewPointersLst,
4107                                        p_ModifyKeyParams);
4108     if (err)
4109     {
4110         XX_Free(p_ModifyKeyParams);
4111         if (p_CcNode->maxNumOfKeys)
4112             RELEASE_LOCK(p_FmPcd->shadowLock);
4113         RETURN_ERROR(MAJOR, err, NO_MSG);
4114     }
4115 
4116     err = DoDynamicChange(p_FmPcd, &h_OldPointersLst, &h_NewPointersLst,
4117                           p_ModifyKeyParams, FALSE);
4118 
4119     if (p_CcNode->maxNumOfKeys)
4120         RELEASE_LOCK(p_FmPcd->shadowLock);
4121 
4122     return err;
4123 }
4124 
4125 static t_Error FindKeyIndex(t_Handle h_CcNode, uint8_t keySize, uint8_t *p_Key,
4126                             uint8_t *p_Mask, uint16_t *p_KeyIndex)
4127 {
4128     t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
4129     uint8_t tmpMask[FM_PCD_MAX_SIZE_OF_KEY];
4130     uint16_t i;
4131 
4132     ASSERT_COND(p_Key);
4133     ASSERT_COND(p_KeyIndex);
4134     ASSERT_COND(keySize < FM_PCD_MAX_SIZE_OF_KEY);
4135 
4136     if (keySize != p_CcNode->userSizeOfExtraction)
4137         RETURN_ERROR(
4138                 MINOR, E_INVALID_VALUE,
4139                 ("Key size doesn't match the extraction size of the node"));
4140 
4141     /* If user didn't pass a mask for this key, we'll look for full extraction mask */
4142     if (!p_Mask)
4143         memset(tmpMask, 0xFF, keySize);
4144 
4145     for (i = 0; i < p_CcNode->numOfKeys; i++)
4146     {
4147         /* Comparing received key */
4148         if (memcmp(p_Key, p_CcNode->keyAndNextEngineParams[i].key, keySize)
4149                 == 0)
4150         {
4151             if (p_Mask)
4152             {
4153                 /* If a user passed a mask for this key, it must match to the existing key's mask for a correct match */
4154                 if (memcmp(p_Mask, p_CcNode->keyAndNextEngineParams[i].mask,
4155                            keySize) == 0)
4156                 {
4157                     *p_KeyIndex = i;
4158                     return E_OK;
4159                 }
4160             }
4161             else
4162             {
4163                 /* If user didn't pass a mask for this key, check if the existing key mask is full extraction */
4164                 if (memcmp(tmpMask, p_CcNode->keyAndNextEngineParams[i].mask,
4165                            keySize) == 0)
4166                 {
4167                     *p_KeyIndex = i;
4168                     return E_OK;
4169                 }
4170             }
4171         }
4172     }
4173 
4174     return ERROR_CODE(E_NOT_FOUND);
4175 }
4176 
4177 static t_Error CalcAndUpdateCcShadow(t_FmPcdCcNode *p_CcNode,
4178                                      bool isKeyTblAlloc,
4179                                      uint32_t *p_MatchTableSize,
4180                                      uint32_t *p_AdTableSize)
4181 {
4182     uint32_t shadowSize;
4183     t_Error err;
4184 
4185     /* Calculate keys table maximal size - each entry consists of a key and a mask,
4186      (if local mask support is requested) */
4187     *p_MatchTableSize = p_CcNode->ccKeySizeAccExtraction * sizeof(uint8_t)
4188             * p_CcNode->maxNumOfKeys;
4189 
4190     if (p_CcNode->maskSupport)
4191         *p_MatchTableSize *= 2;
4192 
4193     /* Calculate next action descriptors table, including one more entry for miss */
4194     *p_AdTableSize = (uint32_t)((p_CcNode->maxNumOfKeys + 1)
4195             * FM_PCD_CC_AD_ENTRY_SIZE);
4196 
4197     /* Calculate maximal shadow size of this node.
4198      All shadow structures will be used for runtime modifications host command. If
4199      keys table was allocated for this node, the keys table and next engines table may
4200      be modified in run time (entries added or removed), so shadow tables are requires.
4201      Otherwise, the only supported runtime modification is a specific next engine update
4202      and this requires shadow memory of a single AD */
4203 
4204     /* Shadow size should be enough to hold the following 3 structures:
4205      * 1 - an action descriptor */
4206     shadowSize = FM_PCD_CC_AD_ENTRY_SIZE;
4207 
4208     /* 2 - keys match table, if was allocated for the current node */
4209     if (isKeyTblAlloc)
4210         shadowSize += *p_MatchTableSize;
4211 
4212     /* 3 - next action descriptors table */
4213     shadowSize += *p_AdTableSize;
4214 
4215     /* Update shadow to the calculated size */
4216     err = FmPcdUpdateCcShadow(p_CcNode->h_FmPcd, (uint32_t)shadowSize,
4217                               FM_PCD_CC_AD_TABLE_ALIGN);
4218     if (err != E_OK)
4219     {
4220         DeleteNode(p_CcNode);
4221         RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC node shadow"));
4222     }
4223 
4224     return E_OK;
4225 }
4226 
4227 static t_Error AllocStatsObjs(t_FmPcdCcNode *p_CcNode)
4228 {
4229     t_FmPcdStatsObj *p_StatsObj;
4230     t_Handle h_FmMuram, h_StatsAd, h_StatsCounters;
4231     uint32_t i;
4232 
4233     h_FmMuram = FmPcdGetMuramHandle(p_CcNode->h_FmPcd);
4234     if (!h_FmMuram)
4235         RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("FM MURAM"));
4236 
4237     /* Allocate statistics ADs and statistics counter. An extra pair (AD + counters)
4238      will be allocated to support runtime modifications */
4239     for (i = 0; i < p_CcNode->maxNumOfKeys + 2; i++)
4240     {
4241         /* Allocate list object structure */
4242         p_StatsObj = XX_Malloc(sizeof(t_FmPcdStatsObj));
4243         if (!p_StatsObj)
4244         {
4245             FreeStatObjects(&p_CcNode->availableStatsLst, h_FmMuram);
4246             RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Statistics object"));
4247         }
4248         memset(p_StatsObj, 0, sizeof(t_FmPcdStatsObj));
4249 
4250         /* Allocate statistics AD from MURAM */
4251         h_StatsAd = (t_Handle)FM_MURAM_AllocMem(h_FmMuram,
4252                                                 FM_PCD_CC_AD_ENTRY_SIZE,
4253                                                 FM_PCD_CC_AD_TABLE_ALIGN);
4254         if (!h_StatsAd)
4255         {
4256             FreeStatObjects(&p_CcNode->availableStatsLst, h_FmMuram);
4257             XX_Free(p_StatsObj);
4258             RETURN_ERROR(MAJOR, E_NO_MEMORY,
4259                          ("MURAM allocation for statistics ADs"));
4260         }
4261         MemSet8(h_StatsAd, 0, FM_PCD_CC_AD_ENTRY_SIZE);
4262 
4263         /* Allocate statistics counters from MURAM */
4264         h_StatsCounters = (t_Handle)FM_MURAM_AllocMem(
4265                 h_FmMuram, p_CcNode->countersArraySize,
4266                 FM_PCD_CC_AD_TABLE_ALIGN);
4267         if (!h_StatsCounters)
4268         {
4269             FreeStatObjects(&p_CcNode->availableStatsLst, h_FmMuram);
4270             FM_MURAM_FreeMem(h_FmMuram, h_StatsAd);
4271             XX_Free(p_StatsObj);
4272             RETURN_ERROR(MAJOR, E_NO_MEMORY,
4273                          ("MURAM allocation for statistics counters"));
4274         }
4275         MemSet8(h_StatsCounters, 0, p_CcNode->countersArraySize);
4276 
4277         p_StatsObj->h_StatsAd = h_StatsAd;
4278         p_StatsObj->h_StatsCounters = h_StatsCounters;
4279 
4280         EnqueueStatsObj(&p_CcNode->availableStatsLst, p_StatsObj);
4281     }
4282 
4283     return E_OK;
4284 }
4285 
4286 static t_Error MatchTableGetKeyStatistics(
4287         t_FmPcdCcNode *p_CcNode, uint16_t keyIndex,
4288         t_FmPcdCcKeyStatistics *p_KeyStatistics)
4289 {
4290     uint32_t *p_StatsCounters, i;
4291 
4292     if (p_CcNode->statisticsMode == e_FM_PCD_CC_STATS_MODE_NONE)
4293         RETURN_ERROR(MAJOR, E_INVALID_STATE,
4294                      ("Statistics were not enabled for this match table"));
4295 
4296     if (!p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj)
4297         RETURN_ERROR(MAJOR, E_INVALID_STATE,
4298                      ("Statistics were not enabled for this key"));
4299 
4300     memset(p_KeyStatistics, 0, sizeof(t_FmPcdCcKeyStatistics));
4301 
4302     p_StatsCounters =
4303             p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj->h_StatsCounters;
4304     ASSERT_COND(p_StatsCounters);
4305 
4306     p_KeyStatistics->byteCount = GET_UINT32(*p_StatsCounters);
4307 
4308     for (i = 1; i <= p_CcNode->numOfStatsFLRs; i++)
4309     {
4310         p_StatsCounters =
4311                 PTR_MOVE(p_StatsCounters, FM_PCD_CC_STATS_COUNTER_SIZE);
4312 
4313         p_KeyStatistics->frameCount += GET_UINT32(*p_StatsCounters);
4314 
4315 #if (DPAA_VERSION >= 11)
4316         p_KeyStatistics->frameLengthRangeCount[i - 1] =
4317                 GET_UINT32(*p_StatsCounters);
4318 #endif /* (DPAA_VERSION >= 11) */
4319     }
4320 
4321     return E_OK;
4322 }
4323 
4324 static t_Error MatchTableSet(t_Handle h_FmPcd, t_FmPcdCcNode *p_CcNode,
4325                              t_FmPcdCcNodeParams *p_CcNodeParam)
4326 {
4327     t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;
4328     t_FmPcdCcNode *p_FmPcdCcNextNode;
4329     t_Error err = E_OK;
4330     uint32_t tmp, keySize;
4331     bool glblMask = FALSE;
4332     t_FmPcdCcKeyParams *p_KeyParams;
4333     t_Handle h_FmMuram, p_KeysMatchTblTmp, p_AdTableTmp;
4334 #if (DPAA_VERSION >= 11)
4335     t_Handle h_StatsFLRs;
4336 #endif /* (DPAA_VERSION >= 11) */
4337     bool fullField = FALSE;
4338     ccPrivateInfo_t icCode = CC_PRIVATE_INFO_NONE;
4339     bool isKeyTblAlloc, fromIc = FALSE;
4340     uint32_t matchTableSize, adTableSize;
4341     t_CcNodeInformation ccNodeInfo, *p_CcInformation;
4342     t_FmPcdStatsObj *p_StatsObj;
4343     t_FmPcdCcStatsParams statsParams = { 0 };
4344     t_Handle h_Manip;
4345 
4346     ASSERT_COND(h_FmPcd);
4347     ASSERT_COND(p_CcNode);
4348     ASSERT_COND(p_CcNodeParam);
4349 
4350     p_CcNode->p_GlblMask = (t_Handle)XX_Malloc(
4351             CC_GLBL_MASK_SIZE * sizeof(uint8_t));
4352     memset(p_CcNode->p_GlblMask, 0, CC_GLBL_MASK_SIZE * sizeof(uint8_t));
4353 
4354     p_CcNode->h_FmPcd = h_FmPcd;
4355     p_CcNode->numOfKeys = p_CcNodeParam->keysParams.numOfKeys;
4356     p_CcNode->maxNumOfKeys = p_CcNodeParam->keysParams.maxNumOfKeys;
4357     p_CcNode->maskSupport = p_CcNodeParam->keysParams.maskSupport;
4358     p_CcNode->statisticsMode = p_CcNodeParam->keysParams.statisticsMode;
4359 
4360     /* For backward compatibility - even if statistics mode is nullified,
4361      we'll fix it to frame mode so we can support per-key request for
4362      statistics using 'statisticsEn' in next engine parameters */
4363     if (!p_CcNode->maxNumOfKeys
4364             && (p_CcNode->statisticsMode == e_FM_PCD_CC_STATS_MODE_NONE))
4365         p_CcNode->statisticsMode = e_FM_PCD_CC_STATS_MODE_FRAME;
4366 
4367     h_FmMuram = FmPcdGetMuramHandle(h_FmPcd);
4368     if (!h_FmMuram)
4369         RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("FM MURAM"));
4370 
4371     INIT_LIST(&p_CcNode->ccPrevNodesLst);
4372     INIT_LIST(&p_CcNode->ccTreeIdLst);
4373     INIT_LIST(&p_CcNode->ccTreesLst);
4374     INIT_LIST(&p_CcNode->availableStatsLst);
4375 
4376     p_CcNode->h_Spinlock = XX_InitSpinlock();
4377     if (!p_CcNode->h_Spinlock)
4378     {
4379         DeleteNode(p_CcNode);
4380         RETURN_ERROR(MAJOR, E_NO_MEMORY, ("CC node spinlock"));
4381     }
4382 
4383     if ((p_CcNodeParam->extractCcParams.type == e_FM_PCD_EXTRACT_BY_HDR)
4384             && ((p_CcNodeParam->extractCcParams.extractByHdr.hdr
4385                     == HEADER_TYPE_IPv4)
4386                     || (p_CcNodeParam->extractCcParams.extractByHdr.hdr
4387                             == HEADER_TYPE_IPv6))
4388             && (p_CcNodeParam->extractCcParams.extractByHdr.type
4389                     == e_FM_PCD_EXTRACT_FULL_FIELD)
4390             && ((p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fullField.ipv6
4391                     == NET_HEADER_FIELD_IPv6_HOP_LIMIT)
4392                     || (p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fullField.ipv4
4393                             == NET_HEADER_FIELD_IPv4_TTL)))
4394     {
4395         err = Ipv4TtlOrIpv6HopLimitCheckParams(h_FmPcd, p_CcNodeParam, p_CcNode,
4396                                                &isKeyTblAlloc);
4397         glblMask = FALSE;
4398     }
4399     else
4400         if ((p_CcNodeParam->extractCcParams.type == e_FM_PCD_EXTRACT_NON_HDR)
4401                 && ((p_CcNodeParam->extractCcParams.extractNonHdr.src
4402                         == e_FM_PCD_EXTRACT_FROM_KEY)
4403                         || (p_CcNodeParam->extractCcParams.extractNonHdr.src
4404                                 == e_FM_PCD_EXTRACT_FROM_HASH)
4405                         || (p_CcNodeParam->extractCcParams.extractNonHdr.src
4406                                 == e_FM_PCD_EXTRACT_FROM_FLOW_ID)))
4407         {
4408             if ((p_CcNodeParam->extractCcParams.extractNonHdr.src
4409                     == e_FM_PCD_EXTRACT_FROM_FLOW_ID)
4410                     && (p_CcNodeParam->extractCcParams.extractNonHdr.offset != 0))
4411             {
4412                 DeleteNode(p_CcNode);
4413                 RETURN_ERROR(
4414                         MAJOR,
4415                         E_INVALID_VALUE,
4416                         ("In the case of the extraction from e_FM_PCD_EXTRACT_FROM_FLOW_ID offset has to be 0"));
4417             }
4418 
4419             icCode = IcDefineCode(p_CcNodeParam);
4420             fromIc = TRUE;
4421             if (icCode == CC_PRIVATE_INFO_NONE)
4422             {
4423                 DeleteNode(p_CcNode);
4424                 RETURN_ERROR(
4425                         MAJOR,
4426                         E_INVALID_STATE,
4427                         ("user asked extraction from IC and field in internal context or action wasn't initialized in the right way"));
4428             }
4429 
4430             if ((icCode == CC_PRIVATE_INFO_IC_DEQ_FQID_INDEX_LOOKUP)
4431                     || (icCode == CC_PRIVATE_INFO_IC_HASH_INDEX_LOOKUP))
4432             {
4433                 err = IcHashIndexedCheckParams(h_FmPcd, p_CcNodeParam, p_CcNode,
4434                                                &isKeyTblAlloc);
4435                 glblMask = TRUE;
4436             }
4437             else
4438             {
4439                 err = CheckParams(h_FmPcd, p_CcNodeParam, p_CcNode,
4440                                   &isKeyTblAlloc);
4441                 if (p_CcNode->glblMaskSize)
4442                     glblMask = TRUE;
4443             }
4444         }
4445         else
4446         {
4447             err = CheckParams(h_FmPcd, p_CcNodeParam, p_CcNode, &isKeyTblAlloc);
4448             if (p_CcNode->glblMaskSize)
4449                 glblMask = TRUE;
4450         }
4451 
4452     if (err)
4453     {
4454         DeleteNode(p_CcNode);
4455         RETURN_ERROR(MAJOR, err, NO_MSG);
4456     }
4457 
4458     switch (p_CcNodeParam->extractCcParams.type)
4459     {
4460         case (e_FM_PCD_EXTRACT_BY_HDR):
4461             switch (p_CcNodeParam->extractCcParams.extractByHdr.type)
4462             {
4463                 case (e_FM_PCD_EXTRACT_FULL_FIELD):
4464                     p_CcNode->parseCode =
4465                             GetFullFieldParseCode(
4466                                     p_CcNodeParam->extractCcParams.extractByHdr.hdr,
4467                                     p_CcNodeParam->extractCcParams.extractByHdr.hdrIndex,
4468                                     p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fullField);
4469                     GetSizeHeaderField(
4470                             p_CcNodeParam->extractCcParams.extractByHdr.hdr,
4471                             p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fullField,
4472                             &p_CcNode->sizeOfExtraction);
4473                     fullField = TRUE;
4474                     if ((p_CcNode->parseCode != CC_PC_FF_TCI1)
4475                             && (p_CcNode->parseCode != CC_PC_FF_TCI2)
4476                             && (p_CcNode->parseCode != CC_PC_FF_MPLS1)
4477                             && (p_CcNode->parseCode != CC_PC_FF_MPLS_LAST)
4478                             && (p_CcNode->parseCode != CC_PC_FF_IPV4IPTOS_TC1)
4479                             && (p_CcNode->parseCode != CC_PC_FF_IPV4IPTOS_TC2)
4480                             && (p_CcNode->parseCode
4481                                     != CC_PC_FF_IPTOS_IPV6TC1_IPV6FLOW1)
4482                             && (p_CcNode->parseCode != CC_PC_FF_IPDSCP)
4483                             && (p_CcNode->parseCode
4484                                     != CC_PC_FF_IPTOS_IPV6TC2_IPV6FLOW2)
4485                             && glblMask)
4486                     {
4487                         glblMask = FALSE;
4488                         p_CcNode->glblMaskSize = 4;
4489                         p_CcNode->lclMask = TRUE;
4490                     }
4491                     break;
4492 
4493                 case (e_FM_PCD_EXTRACT_FROM_HDR):
4494                     p_CcNode->sizeOfExtraction =
4495                             p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fromHdr.size;
4496                     p_CcNode->offset =
4497                             p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fromHdr.offset;
4498                     p_CcNode->userOffset =
4499                             p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fromHdr.offset;
4500                     p_CcNode->parseCode =
4501                             GetPrParseCode(
4502                                     p_CcNodeParam->extractCcParams.extractByHdr.hdr,
4503                                     p_CcNodeParam->extractCcParams.extractByHdr.hdrIndex,
4504                                     p_CcNode->offset, glblMask,
4505                                     &p_CcNode->prsArrayOffset);
4506                     break;
4507 
4508                 case (e_FM_PCD_EXTRACT_FROM_FIELD):
4509                     p_CcNode->offset =
4510                             p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fromField.offset;
4511                     p_CcNode->userOffset =
4512                             p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fromField.offset;
4513                     p_CcNode->sizeOfExtraction =
4514                             p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fromField.size;
4515                     p_CcNode->parseCode =
4516                             GetFieldParseCode(
4517                                     p_CcNodeParam->extractCcParams.extractByHdr.hdr,
4518                                     p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fromField.field,
4519                                     p_CcNode->offset,
4520                                     &p_CcNode->prsArrayOffset,
4521                                     p_CcNodeParam->extractCcParams.extractByHdr.hdrIndex);
4522                     break;
4523 
4524                 default:
4525                     DeleteNode(p_CcNode);
4526                     RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);
4527             }
4528             break;
4529 
4530         case (e_FM_PCD_EXTRACT_NON_HDR):
4531             /* get the field code for the generic extract */
4532             p_CcNode->sizeOfExtraction =
4533                     p_CcNodeParam->extractCcParams.extractNonHdr.size;
4534             p_CcNode->offset =
4535                     p_CcNodeParam->extractCcParams.extractNonHdr.offset;
4536             p_CcNode->userOffset =
4537                     p_CcNodeParam->extractCcParams.extractNonHdr.offset;
4538             p_CcNode->parseCode = GetGenParseCode(
4539                     p_CcNodeParam->extractCcParams.extractNonHdr.src,
4540                     p_CcNode->offset, glblMask, &p_CcNode->prsArrayOffset,
4541                     fromIc, icCode);
4542 
4543             if (p_CcNode->parseCode == CC_PC_GENERIC_IC_HASH_INDEXED)
4544             {
4545                 if ((p_CcNode->offset + p_CcNode->sizeOfExtraction) > 8)
4546                 {
4547                     DeleteNode(p_CcNode);
4548                     RETURN_ERROR(
4549                             MAJOR,
4550                             E_INVALID_SELECTION,
4551                             ("when node of the type CC_PC_GENERIC_IC_HASH_INDEXED offset + size can not be bigger then size of HASH 64 bits (8 bytes)"));
4552                 }
4553             }
4554             if ((p_CcNode->parseCode == CC_PC_GENERIC_IC_GMASK)
4555                     || (p_CcNode->parseCode == CC_PC_GENERIC_IC_HASH_INDEXED))
4556             {
4557                 p_CcNode->offset += p_CcNode->prsArrayOffset;
4558                 p_CcNode->prsArrayOffset = 0;
4559             }
4560             break;
4561 
4562         default:
4563             DeleteNode(p_CcNode);
4564             RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);
4565     }
4566 
4567     if (p_CcNode->parseCode == CC_PC_ILLEGAL)
4568     {
4569         DeleteNode(p_CcNode);
4570         RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("illegal extraction type"));
4571     }
4572 
4573     if ((p_CcNode->sizeOfExtraction > FM_PCD_MAX_SIZE_OF_KEY)
4574             || !p_CcNode->sizeOfExtraction)
4575     {
4576         DeleteNode(p_CcNode);
4577         RETURN_ERROR(MAJOR, E_INVALID_VALUE,
4578                      ("sizeOfExatrction can not be greater than 56 and not 0"));
4579     }
4580 
4581     if (p_CcNodeParam->keysParams.keySize != p_CcNode->sizeOfExtraction)
4582     {
4583         DeleteNode(p_CcNode);
4584         RETURN_ERROR(MAJOR, E_INVALID_VALUE,
4585                      ("keySize has to be equal to sizeOfExtraction"));
4586     }
4587 
4588     p_CcNode->userSizeOfExtraction = p_CcNode->sizeOfExtraction;
4589 
4590     if (!glblMask)
4591         memset(p_CcNode->p_GlblMask, 0xff, CC_GLBL_MASK_SIZE * sizeof(uint8_t));
4592 
4593     err = CheckAndSetManipParamsWithCcNodeParams(p_CcNode);
4594     if (err != E_OK)
4595     {
4596         DeleteNode(p_CcNode);
4597         RETURN_ERROR(MAJOR, E_INVALID_VALUE,
4598                      ("keySize has to be equal to sizeOfExtraction"));
4599     }
4600 
4601     /* Calculating matching table entry size by rounding up the user-defined size of extraction to valid entry size */
4602     GetCcExtractKeySize(p_CcNode->sizeOfExtraction,
4603                         &p_CcNode->ccKeySizeAccExtraction);
4604 
4605     /* If local mask is used, it is stored next to each key in the keys match table */
4606     if (p_CcNode->lclMask)
4607         keySize = (uint32_t)(2 * p_CcNode->ccKeySizeAccExtraction);
4608     else
4609         keySize = p_CcNode->ccKeySizeAccExtraction;
4610 
4611     /* Update CC shadow with maximal size required by this node */
4612     if (p_CcNode->maxNumOfKeys)
4613     {
4614         err = CalcAndUpdateCcShadow(p_CcNode, isKeyTblAlloc, &matchTableSize,
4615                                     &adTableSize);
4616         if (err != E_OK)
4617         {
4618             DeleteNode(p_CcNode);
4619             RETURN_ERROR(MAJOR, err, NO_MSG);
4620         }
4621 
4622         p_CcNode->keysMatchTableMaxSize = matchTableSize;
4623 
4624         if (p_CcNode->statisticsMode != e_FM_PCD_CC_STATS_MODE_NONE)
4625         {
4626             err = AllocStatsObjs(p_CcNode);
4627             if (err != E_OK)
4628             {
4629                 DeleteNode(p_CcNode);
4630                 RETURN_ERROR(MAJOR, err, NO_MSG);
4631             }
4632         }
4633 
4634         /* If manipulation will be initialized before this node, it will use the table
4635          descriptor in the AD table of previous node and this node will need an extra
4636          AD as his table descriptor. */
4637         p_CcNode->h_TmpAd = (t_Handle)FM_MURAM_AllocMem(
4638                 h_FmMuram, FM_PCD_CC_AD_ENTRY_SIZE, FM_PCD_CC_AD_TABLE_ALIGN);
4639         if (!p_CcNode->h_TmpAd)
4640         {
4641             DeleteNode(p_CcNode);
4642             RETURN_ERROR(MAJOR, E_NO_MEMORY,
4643                          ("MURAM allocation for CC action descriptor"));
4644         }
4645     }
4646     else
4647     {
4648         matchTableSize = (uint32_t)(keySize * sizeof(uint8_t)
4649                 * (p_CcNode->numOfKeys + 1));
4650         adTableSize = (uint32_t)(FM_PCD_CC_AD_ENTRY_SIZE
4651                 * (p_CcNode->numOfKeys + 1));
4652     }
4653 
4654 #if (DPAA_VERSION >= 11)
4655     switch (p_CcNode->statisticsMode)
4656     {
4657 
4658         case e_FM_PCD_CC_STATS_MODE_RMON:
4659             /* If RMON statistics or RMON conditional statistics modes are requested,
4660              allocate frame length ranges array */
4661             p_CcNode->h_StatsFLRs = FM_MURAM_AllocMem(
4662                     h_FmMuram,
4663                     (uint32_t)(p_CcNode->numOfStatsFLRs)
4664                             * FM_PCD_CC_STATS_FLR_SIZE,
4665                     FM_PCD_CC_AD_TABLE_ALIGN);
4666 
4667             if (!p_CcNode->h_StatsFLRs)
4668             {
4669                 DeleteNode(p_CcNode);
4670                 RETURN_ERROR(
4671                         MAJOR, E_NO_MEMORY,
4672                         ("MURAM allocation for CC frame length ranges array"));
4673             }
4674 
4675             /* Initialize using value received from the user */
4676             for (tmp = 0; tmp < p_CcNode->numOfStatsFLRs; tmp++)
4677             {
4678                 uint16_t flr =
4679                          cpu_to_be16(p_CcNodeParam->keysParams.frameLengthRanges[tmp]);
4680 
4681                 h_StatsFLRs =
4682                         PTR_MOVE(p_CcNode->h_StatsFLRs, tmp * FM_PCD_CC_STATS_FLR_SIZE);
4683 
4684                 MemCpy8(h_StatsFLRs,
4685                             &flr,
4686                             FM_PCD_CC_STATS_FLR_SIZE);
4687             }
4688             break;
4689 
4690         default:
4691             break;
4692     }
4693 #endif /* (DPAA_VERSION >= 11) */
4694 
4695     /* Allocate keys match table. Not required for some CC nodes, for example for IPv4 TTL
4696      identification, IPv6 hop count identification, etc. */
4697     if (isKeyTblAlloc)
4698     {
4699         p_CcNode->h_KeysMatchTable = (t_Handle)FM_MURAM_AllocMem(
4700                 h_FmMuram, matchTableSize, FM_PCD_CC_KEYS_MATCH_TABLE_ALIGN);
4701         if (!p_CcNode->h_KeysMatchTable)
4702         {
4703             DeleteNode(p_CcNode);
4704             RETURN_ERROR(MAJOR, E_NO_MEMORY,
4705                          ("MURAM allocation for CC node key match table"));
4706         }
4707         MemSet8((uint8_t *)p_CcNode->h_KeysMatchTable, 0, matchTableSize);
4708     }
4709 
4710     /* Allocate action descriptors table */
4711     p_CcNode->h_AdTable = (t_Handle)FM_MURAM_AllocMem(h_FmMuram, adTableSize,
4712                                                       FM_PCD_CC_AD_TABLE_ALIGN);
4713     if (!p_CcNode->h_AdTable)
4714     {
4715         DeleteNode(p_CcNode);
4716         RETURN_ERROR(MAJOR, E_NO_MEMORY,
4717                      ("MURAM allocation for CC node action descriptors table"));
4718     }
4719     MemSet8((uint8_t *)p_CcNode->h_AdTable, 0, adTableSize);
4720 
4721     p_KeysMatchTblTmp = p_CcNode->h_KeysMatchTable;
4722     p_AdTableTmp = p_CcNode->h_AdTable;
4723 
4724     /* For each key, create the key and the next step AD */
4725     for (tmp = 0; tmp < p_CcNode->numOfKeys; tmp++)
4726     {
4727         p_KeyParams = &p_CcNodeParam->keysParams.keyParams[tmp];
4728 
4729         if (p_KeysMatchTblTmp)
4730         {
4731             /* Copy the key */
4732             MemCpy8((void*)p_KeysMatchTblTmp, p_KeyParams->p_Key,
4733                         p_CcNode->sizeOfExtraction);
4734 
4735             /* Copy the key mask or initialize it to 0xFF..F */
4736             if (p_CcNode->lclMask && p_KeyParams->p_Mask)
4737             {
4738                 MemCpy8(PTR_MOVE(p_KeysMatchTblTmp,
4739                         p_CcNode->ccKeySizeAccExtraction), /* User's size of extraction rounded up to a valid matching table entry size */
4740                             p_KeyParams->p_Mask, p_CcNode->sizeOfExtraction); /* Exact size of extraction as received from the user */
4741             }
4742             else
4743                 if (p_CcNode->lclMask)
4744                 {
4745                     MemSet8(PTR_MOVE(p_KeysMatchTblTmp,
4746                             p_CcNode->ccKeySizeAccExtraction), /* User's size of extraction rounded up to a valid matching table entry size */
4747                                0xff, p_CcNode->sizeOfExtraction); /* Exact size of extraction as received from the user */
4748                 }
4749 
4750             p_KeysMatchTblTmp =
4751                     PTR_MOVE(p_KeysMatchTblTmp, keySize * sizeof(uint8_t));
4752         }
4753 
4754         /* Create the next action descriptor in the match table */
4755         if (p_KeyParams->ccNextEngineParams.statisticsEn)
4756         {
4757             p_StatsObj = GetStatsObj(p_CcNode);
4758             ASSERT_COND(p_StatsObj);
4759 
4760             statsParams.h_StatsAd = p_StatsObj->h_StatsAd;
4761             statsParams.h_StatsCounters = p_StatsObj->h_StatsCounters;
4762 #if (DPAA_VERSION >= 11)
4763             statsParams.h_StatsFLRs = p_CcNode->h_StatsFLRs;
4764 
4765 #endif /* (DPAA_VERSION >= 11) */
4766             NextStepAd(p_AdTableTmp, &statsParams,
4767                        &p_KeyParams->ccNextEngineParams, p_FmPcd);
4768 
4769             p_CcNode->keyAndNextEngineParams[tmp].p_StatsObj = p_StatsObj;
4770         }
4771         else
4772         {
4773             NextStepAd(p_AdTableTmp, NULL, &p_KeyParams->ccNextEngineParams,
4774                        p_FmPcd);
4775 
4776             p_CcNode->keyAndNextEngineParams[tmp].p_StatsObj = NULL;
4777         }
4778 
4779         p_AdTableTmp = PTR_MOVE(p_AdTableTmp, FM_PCD_CC_AD_ENTRY_SIZE);
4780     }
4781 
4782     /* Update next engine for the 'miss' entry */
4783     if (p_CcNodeParam->keysParams.ccNextEngineParamsForMiss.statisticsEn)
4784     {
4785         p_StatsObj = GetStatsObj(p_CcNode);
4786         ASSERT_COND(p_StatsObj);
4787 
4788         /* All 'bucket' nodes of a hash table should share the same statistics counters,
4789          allocated by the hash table. So, if this node is a bucket of a hash table,
4790          we'll replace the locally allocated counters with the shared counters. */
4791         if (p_CcNode->isHashBucket)
4792         {
4793             ASSERT_COND(p_CcNode->h_MissStatsCounters);
4794 
4795             /* Store original counters pointer and replace it with mutual preallocated pointer */
4796             p_CcNode->h_PrivMissStatsCounters = p_StatsObj->h_StatsCounters;
4797             p_StatsObj->h_StatsCounters = p_CcNode->h_MissStatsCounters;
4798         }
4799 
4800         statsParams.h_StatsAd = p_StatsObj->h_StatsAd;
4801         statsParams.h_StatsCounters = p_StatsObj->h_StatsCounters;
4802 #if (DPAA_VERSION >= 11)
4803         statsParams.h_StatsFLRs = p_CcNode->h_StatsFLRs;
4804 
4805 #endif /* (DPAA_VERSION >= 11) */
4806 
4807         NextStepAd(p_AdTableTmp, &statsParams,
4808                    &p_CcNodeParam->keysParams.ccNextEngineParamsForMiss,
4809                    p_FmPcd);
4810 
4811         p_CcNode->keyAndNextEngineParams[tmp].p_StatsObj = p_StatsObj;
4812     }
4813     else
4814     {
4815         NextStepAd(p_AdTableTmp, NULL,
4816                    &p_CcNodeParam->keysParams.ccNextEngineParamsForMiss,
4817                    p_FmPcd);
4818 
4819         p_CcNode->keyAndNextEngineParams[tmp].p_StatsObj = NULL;
4820     }
4821 
4822     /* This parameter will be used to initialize the "key length" field in the action descriptor
4823      that points to this node and it should be 0 for full field extraction */
4824     if (fullField == TRUE)
4825         p_CcNode->sizeOfExtraction = 0;
4826 
4827     for (tmp = 0; tmp < MIN(p_CcNode->numOfKeys + 1, CC_MAX_NUM_OF_KEYS); tmp++)
4828     {
4829         if (p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.nextEngine
4830                 == e_FM_PCD_CC)
4831         {
4832             p_FmPcdCcNextNode =
4833                     (t_FmPcdCcNode*)p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.params.ccParams.h_CcNode;
4834             p_CcInformation = FindNodeInfoInReleventLst(
4835                     &p_FmPcdCcNextNode->ccPrevNodesLst, (t_Handle)p_CcNode,
4836                     p_FmPcdCcNextNode->h_Spinlock);
4837             if (!p_CcInformation)
4838             {
4839                 memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation));
4840                 ccNodeInfo.h_CcNode = (t_Handle)p_CcNode;
4841                 ccNodeInfo.index = 1;
4842                 EnqueueNodeInfoToRelevantLst(&p_FmPcdCcNextNode->ccPrevNodesLst,
4843                                              &ccNodeInfo,
4844                                              p_FmPcdCcNextNode->h_Spinlock);
4845             }
4846             else
4847                 p_CcInformation->index++;
4848 
4849             if (p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.h_Manip)
4850             {
4851                 h_Manip =
4852                         p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.h_Manip;
4853                 p_CcInformation = FindNodeInfoInReleventLst(
4854                         FmPcdManipGetNodeLstPointedOnThisManip(h_Manip),
4855                         (t_Handle)p_CcNode, FmPcdManipGetSpinlock(h_Manip));
4856                 if (!p_CcInformation)
4857                 {
4858                     memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation));
4859                     ccNodeInfo.h_CcNode = (t_Handle)p_CcNode;
4860                     ccNodeInfo.index = 1;
4861                     EnqueueNodeInfoToRelevantLst(
4862                             FmPcdManipGetNodeLstPointedOnThisManip(h_Manip),
4863                             &ccNodeInfo, FmPcdManipGetSpinlock(h_Manip));
4864                 }
4865                 else
4866                     p_CcInformation->index++;
4867             }
4868         }
4869     }
4870 
4871     p_AdTableTmp = p_CcNode->h_AdTable;
4872 
4873     if (!FmPcdLockTryLockAll(h_FmPcd))
4874     {
4875         FM_PCD_MatchTableDelete((t_Handle)p_CcNode);
4876         DBG(TRACE, ("FmPcdLockTryLockAll failed"));
4877         return ERROR_CODE(E_BUSY);
4878     }
4879 
4880     /* Required action for each next engine */
4881     for (tmp = 0; tmp < MIN(p_CcNode->numOfKeys + 1, CC_MAX_NUM_OF_KEYS); tmp++)
4882     {
4883         if (p_CcNode->keyAndNextEngineParams[tmp].requiredAction)
4884         {
4885             err = SetRequiredAction(
4886                     h_FmPcd,
4887                     p_CcNode->keyAndNextEngineParams[tmp].requiredAction,
4888                     &p_CcNode->keyAndNextEngineParams[tmp], p_AdTableTmp, 1,
4889                     NULL);
4890             if (err)
4891             {
4892                 FmPcdLockUnlockAll(h_FmPcd);
4893                 FM_PCD_MatchTableDelete((t_Handle)p_CcNode);
4894                 RETURN_ERROR(MAJOR, err, NO_MSG);
4895             }
4896             p_AdTableTmp = PTR_MOVE(p_AdTableTmp, FM_PCD_CC_AD_ENTRY_SIZE);
4897         }
4898     }
4899 
4900     FmPcdLockUnlockAll(h_FmPcd);
4901 
4902     return E_OK;
4903 }
4904 /************************** End of static functions **************************/
4905 
4906 /*****************************************************************************/
4907 /*              Inter-module API routines                                    */
4908 /*****************************************************************************/
4909 
4910 t_CcNodeInformation* FindNodeInfoInReleventLst(t_List *p_List, t_Handle h_Info,
4911                                                t_Handle h_Spinlock)
4912 {
4913     t_CcNodeInformation *p_CcInformation;
4914     t_List *p_Pos;
4915     uint32_t intFlags;
4916 
4917     intFlags = XX_LockIntrSpinlock(h_Spinlock);
4918 
4919     for (p_Pos = NCSW_LIST_FIRST(p_List); p_Pos != (p_List);
4920             p_Pos = NCSW_LIST_NEXT(p_Pos))
4921     {
4922         p_CcInformation = CC_NODE_F_OBJECT(p_Pos);
4923 
4924         ASSERT_COND(p_CcInformation->h_CcNode);
4925 
4926         if (p_CcInformation->h_CcNode == h_Info)
4927         {
4928             XX_UnlockIntrSpinlock(h_Spinlock, intFlags);
4929             return p_CcInformation;
4930         }
4931     }
4932 
4933     XX_UnlockIntrSpinlock(h_Spinlock, intFlags);
4934 
4935     return NULL;
4936 }
4937 
4938 void EnqueueNodeInfoToRelevantLst(t_List *p_List, t_CcNodeInformation *p_CcInfo,
4939                                   t_Handle h_Spinlock)
4940 {
4941     t_CcNodeInformation *p_CcInformation;
4942     uint32_t intFlags = 0;
4943 
4944     p_CcInformation = (t_CcNodeInformation *)XX_Malloc(
4945             sizeof(t_CcNodeInformation));
4946 
4947     if (p_CcInformation)
4948     {
4949         memset(p_CcInformation, 0, sizeof(t_CcNodeInformation));
4950         memcpy(p_CcInformation, p_CcInfo, sizeof(t_CcNodeInformation));
4951         INIT_LIST(&p_CcInformation->node);
4952 
4953         if (h_Spinlock)
4954             intFlags = XX_LockIntrSpinlock(h_Spinlock);
4955 
4956         NCSW_LIST_AddToTail(&p_CcInformation->node, p_List);
4957 
4958         if (h_Spinlock)
4959             XX_UnlockIntrSpinlock(h_Spinlock, intFlags);
4960     }
4961     else
4962         REPORT_ERROR(MAJOR, E_NO_MEMORY, ("CC Node Information"));
4963 }
4964 
4965 void DequeueNodeInfoFromRelevantLst(t_List *p_List, t_Handle h_Info,
4966                                     t_Handle h_Spinlock)
4967 {
4968     t_CcNodeInformation *p_CcInformation = NULL;
4969     uint32_t intFlags = 0;
4970     t_List *p_Pos;
4971 
4972     if (h_Spinlock)
4973         intFlags = XX_LockIntrSpinlock(h_Spinlock);
4974 
4975     if (NCSW_LIST_IsEmpty(p_List))
4976     {
4977         XX_RestoreAllIntr(intFlags);
4978         return;
4979     }
4980 
4981     for (p_Pos = NCSW_LIST_FIRST(p_List); p_Pos != (p_List);
4982             p_Pos = NCSW_LIST_NEXT(p_Pos))
4983     {
4984         p_CcInformation = CC_NODE_F_OBJECT(p_Pos);
4985         ASSERT_COND(p_CcInformation);
4986         ASSERT_COND(p_CcInformation->h_CcNode);
4987         if (p_CcInformation->h_CcNode == h_Info)
4988             break;
4989     }
4990 
4991     if (p_CcInformation)
4992     {
4993         NCSW_LIST_DelAndInit(&p_CcInformation->node);
4994         XX_Free(p_CcInformation);
4995     }
4996 
4997     if (h_Spinlock)
4998         XX_UnlockIntrSpinlock(h_Spinlock, intFlags);
4999 }
5000 
5001 void NextStepAd(t_Handle h_Ad, t_FmPcdCcStatsParams *p_FmPcdCcStatsParams,
5002                 t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams,
5003                 t_FmPcd *p_FmPcd)
5004 {
5005     switch (p_FmPcdCcNextEngineParams->nextEngine)
5006     {
5007         case (e_FM_PCD_KG):
5008         case (e_FM_PCD_PLCR):
5009         case (e_FM_PCD_DONE):
5010             /* if NIA is not CC, create a "result" type AD */
5011             FillAdOfTypeResult(h_Ad, p_FmPcdCcStatsParams, p_FmPcd,
5012                                p_FmPcdCcNextEngineParams);
5013             break;
5014 #if (DPAA_VERSION >= 11)
5015         case (e_FM_PCD_FR):
5016             if (p_FmPcdCcNextEngineParams->params.frParams.h_FrmReplic)
5017             {
5018                 FillAdOfTypeContLookup(
5019                         h_Ad, p_FmPcdCcStatsParams, p_FmPcd,
5020                         p_FmPcdCcNextEngineParams->params.ccParams.h_CcNode,
5021                         p_FmPcdCcNextEngineParams->h_Manip,
5022                         p_FmPcdCcNextEngineParams->params.frParams.h_FrmReplic);
5023                 FrmReplicGroupUpdateOwner(
5024                         p_FmPcdCcNextEngineParams->params.frParams.h_FrmReplic,
5025                         TRUE/* add */);
5026             }
5027             break;
5028 #endif /* (DPAA_VERSION >= 11) */
5029 
5030         case (e_FM_PCD_CC):
5031             /* if NIA is not CC, create a TD to continue the CC lookup */
5032             FillAdOfTypeContLookup(
5033                     h_Ad, p_FmPcdCcStatsParams, p_FmPcd,
5034                     p_FmPcdCcNextEngineParams->params.ccParams.h_CcNode,
5035                     p_FmPcdCcNextEngineParams->h_Manip, NULL);
5036 
5037             UpdateNodeOwner(p_FmPcdCcNextEngineParams->params.ccParams.h_CcNode,
5038                             TRUE);
5039             break;
5040 
5041         default:
5042             return;
5043     }
5044 }
5045 
5046 t_Error FmPcdCcTreeAddIPR(t_Handle h_FmPcd, t_Handle h_FmTree,
5047                           t_Handle h_NetEnv, t_Handle h_IpReassemblyManip,
5048                           bool createSchemes)
5049 {
5050     t_FmPcdCcTree *p_FmPcdCcTree = (t_FmPcdCcTree *)h_FmTree;
5051     t_FmPcdCcNextEngineParams nextEngineParams;
5052     t_NetEnvParams netEnvParams;
5053     t_Handle h_Ad;
5054     bool isIpv6Present;
5055     uint8_t ipv4GroupId, ipv6GroupId;
5056     t_Error err;
5057 
5058     ASSERT_COND(p_FmPcdCcTree);
5059 
5060     /* this routine must be protected by the calling routine! */
5061 
5062     memset(&nextEngineParams, 0, sizeof(t_FmPcdCcNextEngineParams));
5063     memset(&netEnvParams, 0, sizeof(t_NetEnvParams));
5064 
5065     h_Ad = UINT_TO_PTR(p_FmPcdCcTree->ccTreeBaseAddr);
5066 
5067     isIpv6Present = FmPcdManipIpReassmIsIpv6Hdr(h_IpReassemblyManip);
5068 
5069     if (isIpv6Present
5070             && (p_FmPcdCcTree->numOfEntries > (FM_PCD_MAX_NUM_OF_CC_GROUPS - 2)))
5071         RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("need two free entries for IPR"));
5072 
5073     if (p_FmPcdCcTree->numOfEntries > (FM_PCD_MAX_NUM_OF_CC_GROUPS - 1))
5074         RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("need two free entries for IPR"));
5075 
5076     nextEngineParams.nextEngine = e_FM_PCD_DONE;
5077     nextEngineParams.h_Manip = h_IpReassemblyManip;
5078 
5079     /* Lock tree */
5080     err = CcRootTryLock(p_FmPcdCcTree);
5081     if (err)
5082         return ERROR_CODE(E_BUSY);
5083 
5084     if (p_FmPcdCcTree->h_IpReassemblyManip == h_IpReassemblyManip)
5085     {
5086         CcRootReleaseLock(p_FmPcdCcTree);
5087         return E_OK;
5088     }
5089 
5090     if ((p_FmPcdCcTree->h_IpReassemblyManip)
5091             && (p_FmPcdCcTree->h_IpReassemblyManip != h_IpReassemblyManip))
5092     {
5093         CcRootReleaseLock(p_FmPcdCcTree);
5094         RETURN_ERROR(MAJOR, E_INVALID_STATE,
5095                      ("This tree was previously updated with different IPR"));
5096     }
5097 
5098     /* Initialize IPR for the first time for this tree */
5099     if (isIpv6Present)
5100     {
5101         ipv6GroupId = p_FmPcdCcTree->numOfGrps++;
5102         p_FmPcdCcTree->fmPcdGroupParam[ipv6GroupId].baseGroupEntry =
5103                 (FM_PCD_MAX_NUM_OF_CC_GROUPS - 2);
5104 
5105         if (createSchemes)
5106         {
5107             err = FmPcdManipBuildIpReassmScheme(h_FmPcd, h_NetEnv,
5108                                                 p_FmPcdCcTree,
5109                                                 h_IpReassemblyManip, FALSE,
5110                                                 ipv6GroupId);
5111             if (err)
5112             {
5113                 p_FmPcdCcTree->numOfGrps--;
5114                 CcRootReleaseLock(p_FmPcdCcTree);
5115                 RETURN_ERROR(MAJOR, err, NO_MSG);
5116             }
5117         }
5118 
5119         NextStepAd(
5120                 PTR_MOVE(h_Ad, (FM_PCD_MAX_NUM_OF_CC_GROUPS-2) * FM_PCD_CC_AD_ENTRY_SIZE),
5121                 NULL, &nextEngineParams, h_FmPcd);
5122     }
5123 
5124     ipv4GroupId = p_FmPcdCcTree->numOfGrps++;
5125     p_FmPcdCcTree->fmPcdGroupParam[ipv4GroupId].totalBitsMask = 0;
5126     p_FmPcdCcTree->fmPcdGroupParam[ipv4GroupId].baseGroupEntry =
5127             (FM_PCD_MAX_NUM_OF_CC_GROUPS - 1);
5128 
5129     if (createSchemes)
5130     {
5131         err = FmPcdManipBuildIpReassmScheme(h_FmPcd, h_NetEnv, p_FmPcdCcTree,
5132                                             h_IpReassemblyManip, TRUE,
5133                                             ipv4GroupId);
5134         if (err)
5135         {
5136             p_FmPcdCcTree->numOfGrps--;
5137             if (isIpv6Present)
5138             {
5139                 p_FmPcdCcTree->numOfGrps--;
5140                 FmPcdManipDeleteIpReassmSchemes(h_IpReassemblyManip);
5141             }
5142             CcRootReleaseLock(p_FmPcdCcTree);
5143             RETURN_ERROR(MAJOR, err, NO_MSG);
5144         }
5145     }
5146 
5147     NextStepAd(
5148             PTR_MOVE(h_Ad, (FM_PCD_MAX_NUM_OF_CC_GROUPS-1) * FM_PCD_CC_AD_ENTRY_SIZE),
5149             NULL, &nextEngineParams, h_FmPcd);
5150 
5151     p_FmPcdCcTree->h_IpReassemblyManip = h_IpReassemblyManip;
5152 
5153     CcRootReleaseLock(p_FmPcdCcTree);
5154 
5155     return E_OK;
5156 }
5157 
5158 t_Error FmPcdCcTreeAddCPR(t_Handle h_FmPcd, t_Handle h_FmTree,
5159                           t_Handle h_NetEnv, t_Handle h_ReassemblyManip,
5160                           bool createSchemes)
5161 {
5162     t_FmPcdCcTree *p_FmPcdCcTree = (t_FmPcdCcTree *)h_FmTree;
5163     t_FmPcdCcNextEngineParams nextEngineParams;
5164     t_NetEnvParams netEnvParams;
5165     t_Handle h_Ad;
5166     uint8_t groupId;
5167     t_Error err;
5168 
5169     ASSERT_COND(p_FmPcdCcTree);
5170 
5171     /* this routine must be protected by the calling routine! */
5172     memset(&nextEngineParams, 0, sizeof(t_FmPcdCcNextEngineParams));
5173     memset(&netEnvParams, 0, sizeof(t_NetEnvParams));
5174 
5175     h_Ad = UINT_TO_PTR(p_FmPcdCcTree->ccTreeBaseAddr);
5176 
5177     if (p_FmPcdCcTree->numOfEntries > (FM_PCD_MAX_NUM_OF_CC_GROUPS - 1))
5178         RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("need one free entries for CPR"));
5179 
5180     nextEngineParams.nextEngine = e_FM_PCD_DONE;
5181     nextEngineParams.h_Manip = h_ReassemblyManip;
5182 
5183     /* Lock tree */
5184     err = CcRootTryLock(p_FmPcdCcTree);
5185     if (err)
5186         return ERROR_CODE(E_BUSY);
5187 
5188     if (p_FmPcdCcTree->h_CapwapReassemblyManip == h_ReassemblyManip)
5189     {
5190         CcRootReleaseLock(p_FmPcdCcTree);
5191         return E_OK;
5192     }
5193 
5194     if ((p_FmPcdCcTree->h_CapwapReassemblyManip)
5195             && (p_FmPcdCcTree->h_CapwapReassemblyManip != h_ReassemblyManip))
5196     {
5197         CcRootReleaseLock(p_FmPcdCcTree);
5198         RETURN_ERROR(MAJOR, E_INVALID_STATE,
5199                      ("This tree was previously updated with different CPR"));
5200     }
5201 
5202     groupId = p_FmPcdCcTree->numOfGrps++;
5203     p_FmPcdCcTree->fmPcdGroupParam[groupId].baseGroupEntry =
5204             (FM_PCD_MAX_NUM_OF_CC_GROUPS - 1);
5205 
5206     if (createSchemes)
5207     {
5208         err = FmPcdManipBuildCapwapReassmScheme(h_FmPcd, h_NetEnv,
5209                                                 p_FmPcdCcTree,
5210                                                 h_ReassemblyManip, groupId);
5211         if (err)
5212         {
5213             p_FmPcdCcTree->numOfGrps--;
5214             CcRootReleaseLock(p_FmPcdCcTree);
5215             RETURN_ERROR(MAJOR, err, NO_MSG);
5216         }
5217     }
5218 
5219     NextStepAd(
5220             PTR_MOVE(h_Ad, (FM_PCD_MAX_NUM_OF_CC_GROUPS-1) * FM_PCD_CC_AD_ENTRY_SIZE),
5221             NULL, &nextEngineParams, h_FmPcd);
5222 
5223     p_FmPcdCcTree->h_CapwapReassemblyManip = h_ReassemblyManip;
5224 
5225     CcRootReleaseLock(p_FmPcdCcTree);
5226 
5227     return E_OK;
5228 }
5229 
5230 t_Handle FmPcdCcTreeGetSavedManipParams(t_Handle h_FmTree)
5231 {
5232     t_FmPcdCcTree *p_FmPcdCcTree = (t_FmPcdCcTree *)h_FmTree;
5233 
5234     ASSERT_COND(p_FmPcdCcTree);
5235 
5236     return p_FmPcdCcTree->h_FmPcdCcSavedManipParams;
5237 }
5238 
5239 void FmPcdCcTreeSetSavedManipParams(t_Handle h_FmTree,
5240                                     t_Handle h_SavedManipParams)
5241 {
5242     t_FmPcdCcTree *p_FmPcdCcTree = (t_FmPcdCcTree *)h_FmTree;
5243 
5244     ASSERT_COND(p_FmPcdCcTree);
5245 
5246     p_FmPcdCcTree->h_FmPcdCcSavedManipParams = h_SavedManipParams;
5247 }
5248 
5249 uint8_t FmPcdCcGetParseCode(t_Handle h_CcNode)
5250 {
5251     t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
5252 
5253     ASSERT_COND(p_CcNode);
5254 
5255     return p_CcNode->parseCode;
5256 }
5257 
5258 uint8_t FmPcdCcGetOffset(t_Handle h_CcNode)
5259 {
5260     t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
5261 
5262     ASSERT_COND(p_CcNode);
5263 
5264     return p_CcNode->offset;
5265 }
5266 
5267 uint16_t FmPcdCcGetNumOfKeys(t_Handle h_CcNode)
5268 {
5269     t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
5270 
5271     ASSERT_COND(p_CcNode);
5272 
5273     return p_CcNode->numOfKeys;
5274 }
5275 
5276 t_Error FmPcdCcModifyNextEngineParamTree(
5277         t_Handle h_FmPcd, t_Handle h_FmPcdCcTree, uint8_t grpId, uint8_t index,
5278         t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams)
5279 {
5280     t_FmPcdCcTree *p_FmPcdCcTree = (t_FmPcdCcTree *)h_FmPcdCcTree;
5281     t_FmPcd *p_FmPcd;
5282     t_List h_OldPointersLst, h_NewPointersLst;
5283     uint16_t keyIndex;
5284     t_FmPcdModifyCcKeyAdditionalParams *p_ModifyKeyParams;
5285     t_Error err = E_OK;
5286 
5287     SANITY_CHECK_RETURN_ERROR(h_FmPcd, E_INVALID_HANDLE);
5288     SANITY_CHECK_RETURN_ERROR(h_FmPcdCcTree, E_INVALID_HANDLE);
5289     SANITY_CHECK_RETURN_ERROR((grpId <= 7), E_INVALID_VALUE);
5290 
5291     if (grpId >= p_FmPcdCcTree->numOfGrps)
5292         RETURN_ERROR(MAJOR, E_INVALID_HANDLE,
5293                      ("grpId you asked > numOfGroup of relevant tree"));
5294 
5295     if (index >= p_FmPcdCcTree->fmPcdGroupParam[grpId].numOfEntriesInGroup)
5296         RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("index > numOfEntriesInGroup"));
5297 
5298     p_FmPcd = (t_FmPcd *)h_FmPcd;
5299 
5300     INIT_LIST(&h_OldPointersLst);
5301     INIT_LIST(&h_NewPointersLst);
5302 
5303     keyIndex = (uint16_t)(p_FmPcdCcTree->fmPcdGroupParam[grpId].baseGroupEntry
5304             + index);
5305 
5306     p_ModifyKeyParams = ModifyNodeCommonPart(p_FmPcdCcTree, keyIndex,
5307                                              e_MODIFY_STATE_CHANGE, FALSE,
5308                                              FALSE, TRUE);
5309     if (!p_ModifyKeyParams)
5310         RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
5311 
5312     p_ModifyKeyParams->tree = TRUE;
5313 
5314     if (p_FmPcd->p_CcShadow
5315             && !TRY_LOCK(p_FmPcd->h_ShadowSpinlock, &p_FmPcd->shadowLock))
5316     {
5317         XX_Free(p_ModifyKeyParams);
5318         return ERROR_CODE(E_BUSY);
5319     }
5320 
5321     err = BuildNewNodeModifyNextEngine(p_FmPcd, p_FmPcdCcTree, keyIndex,
5322                                        p_FmPcdCcNextEngineParams,
5323                                        &h_OldPointersLst, &h_NewPointersLst,
5324                                        p_ModifyKeyParams);
5325     if (err)
5326     {
5327         XX_Free(p_ModifyKeyParams);
5328         RETURN_ERROR(MAJOR, err, NO_MSG);
5329     }
5330 
5331     err = DoDynamicChange(p_FmPcd, &h_OldPointersLst, &h_NewPointersLst,
5332                           p_ModifyKeyParams, FALSE);
5333 
5334     if (p_FmPcd->p_CcShadow)
5335         RELEASE_LOCK(p_FmPcd->shadowLock);
5336 
5337     return err;
5338 
5339 }
5340 
5341 t_Error FmPcdCcRemoveKey(t_Handle h_FmPcd, t_Handle h_FmPcdCcNode,
5342                          uint16_t keyIndex)
5343 {
5344 
5345     t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_FmPcdCcNode;
5346     t_FmPcd *p_FmPcd;
5347     t_FmPcdModifyCcKeyAdditionalParams *p_ModifyKeyParams;
5348     t_List h_OldPointersLst, h_NewPointersLst;
5349     bool useShadowStructs = FALSE;
5350     t_Error err = E_OK;
5351 
5352     if (keyIndex >= p_CcNode->numOfKeys)
5353         RETURN_ERROR(MAJOR, E_INVALID_VALUE,
5354                      ("impossible to remove key when numOfKeys <= keyIndex"));
5355 
5356     if (p_CcNode->h_FmPcd != h_FmPcd)
5357         RETURN_ERROR(
5358                 MAJOR,
5359                 E_INVALID_VALUE,
5360                 ("handler to FmPcd is different from the handle provided at node initialization time"));
5361 
5362     p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd;
5363 
5364     INIT_LIST(&h_OldPointersLst);
5365     INIT_LIST(&h_NewPointersLst);
5366 
5367     p_ModifyKeyParams = ModifyNodeCommonPart(p_CcNode, keyIndex,
5368                                              e_MODIFY_STATE_REMOVE, TRUE, TRUE,
5369                                              FALSE);
5370     if (!p_ModifyKeyParams)
5371         RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
5372 
5373     if (p_CcNode->maxNumOfKeys)
5374     {
5375         if (!TRY_LOCK(p_FmPcd->h_ShadowSpinlock, &p_FmPcd->shadowLock))
5376         {
5377             XX_Free(p_ModifyKeyParams);
5378             return ERROR_CODE(E_BUSY);
5379         }
5380 
5381         useShadowStructs = TRUE;
5382     }
5383 
5384     err = BuildNewNodeRemoveKey(p_CcNode, keyIndex, p_ModifyKeyParams);
5385     if (err)
5386     {
5387         XX_Free(p_ModifyKeyParams);
5388         if (p_CcNode->maxNumOfKeys)
5389             RELEASE_LOCK(p_FmPcd->shadowLock);
5390         RETURN_ERROR(MAJOR, err, NO_MSG);
5391     }
5392 
5393     err = UpdatePtrWhichPointOnCrntMdfNode(p_CcNode, p_ModifyKeyParams,
5394                                            &h_OldPointersLst,
5395                                            &h_NewPointersLst);
5396     if (err)
5397     {
5398         ReleaseNewNodeCommonPart(p_ModifyKeyParams);
5399         XX_Free(p_ModifyKeyParams);
5400         if (p_CcNode->maxNumOfKeys)
5401             RELEASE_LOCK(p_FmPcd->shadowLock);
5402         RETURN_ERROR(MAJOR, err, NO_MSG);
5403     }
5404 
5405     err = DoDynamicChange(p_FmPcd, &h_OldPointersLst, &h_NewPointersLst,
5406                           p_ModifyKeyParams, useShadowStructs);
5407 
5408     if (p_CcNode->maxNumOfKeys)
5409         RELEASE_LOCK(p_FmPcd->shadowLock);
5410 
5411     return err;
5412 }
5413 
5414 t_Error FmPcdCcModifyKey(t_Handle h_FmPcd, t_Handle h_FmPcdCcNode,
5415                          uint16_t keyIndex, uint8_t keySize, uint8_t *p_Key,
5416                          uint8_t *p_Mask)
5417 {
5418     t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_FmPcdCcNode;
5419     t_FmPcd *p_FmPcd;
5420     t_List h_OldPointersLst, h_NewPointersLst;
5421     t_FmPcdModifyCcKeyAdditionalParams *p_ModifyKeyParams;
5422     uint16_t tmpKeyIndex;
5423     bool useShadowStructs = FALSE;
5424     t_Error err = E_OK;
5425 
5426     if (keyIndex >= p_CcNode->numOfKeys)
5427         RETURN_ERROR(MAJOR, E_INVALID_STATE,
5428                      ("keyIndex > previously cleared last index + 1"));
5429 
5430     if (keySize != p_CcNode->userSizeOfExtraction)
5431         RETURN_ERROR(
5432                 MAJOR,
5433                 E_INVALID_VALUE,
5434                 ("size for ModifyKey has to be the same as defined in SetNode"));
5435 
5436     if (p_CcNode->h_FmPcd != h_FmPcd)
5437         RETURN_ERROR(
5438                 MAJOR,
5439                 E_INVALID_VALUE,
5440                 ("handler to FmPcd is different from the handle provided at node initialization time"));
5441 
5442     err = FindKeyIndex(h_FmPcdCcNode, keySize, p_Key, p_Mask, &tmpKeyIndex);
5443     if (GET_ERROR_TYPE(err) != E_NOT_FOUND)
5444         RETURN_ERROR(
5445                 MINOR,
5446                 E_ALREADY_EXISTS,
5447                 ("The received key and mask pair was already found in the match table of the provided node"));
5448 
5449     p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd;
5450 
5451     INIT_LIST(&h_OldPointersLst);
5452     INIT_LIST(&h_NewPointersLst);
5453 
5454     p_ModifyKeyParams = ModifyNodeCommonPart(p_CcNode, keyIndex,
5455                                              e_MODIFY_STATE_CHANGE, TRUE, TRUE,
5456                                              FALSE);
5457     if (!p_ModifyKeyParams)
5458         RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
5459 
5460     if (p_CcNode->maxNumOfKeys)
5461     {
5462         if (!TRY_LOCK(p_FmPcd->h_ShadowSpinlock, &p_FmPcd->shadowLock))
5463         {
5464             XX_Free(p_ModifyKeyParams);
5465             return ERROR_CODE(E_BUSY);
5466         }
5467 
5468         useShadowStructs = TRUE;
5469     }
5470 
5471     err = BuildNewNodeModifyKey(p_CcNode, keyIndex, p_Key, p_Mask,
5472                                 p_ModifyKeyParams);
5473     if (err)
5474     {
5475         XX_Free(p_ModifyKeyParams);
5476         if (p_CcNode->maxNumOfKeys)
5477             RELEASE_LOCK(p_FmPcd->shadowLock);
5478         RETURN_ERROR(MAJOR, err, NO_MSG);
5479     }
5480 
5481     err = UpdatePtrWhichPointOnCrntMdfNode(p_CcNode, p_ModifyKeyParams,
5482                                            &h_OldPointersLst,
5483                                            &h_NewPointersLst);
5484     if (err)
5485     {
5486         ReleaseNewNodeCommonPart(p_ModifyKeyParams);
5487         XX_Free(p_ModifyKeyParams);
5488         if (p_CcNode->maxNumOfKeys)
5489             RELEASE_LOCK(p_FmPcd->shadowLock);
5490         RETURN_ERROR(MAJOR, err, NO_MSG);
5491     }
5492 
5493     err = DoDynamicChange(p_FmPcd, &h_OldPointersLst, &h_NewPointersLst,
5494                           p_ModifyKeyParams, useShadowStructs);
5495 
5496     if (p_CcNode->maxNumOfKeys)
5497         RELEASE_LOCK(p_FmPcd->shadowLock);
5498 
5499     return err;
5500 }
5501 
5502 t_Error FmPcdCcModifyMissNextEngineParamNode(
5503         t_Handle h_FmPcd, t_Handle h_FmPcdCcNode,
5504         t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams)
5505 {
5506     t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_FmPcdCcNode;
5507     t_FmPcd *p_FmPcd;
5508     t_List h_OldPointersLst, h_NewPointersLst;
5509     uint16_t keyIndex;
5510     t_FmPcdModifyCcKeyAdditionalParams *p_ModifyKeyParams;
5511     t_Error err = E_OK;
5512 
5513     SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_VALUE);
5514 
5515     keyIndex = p_CcNode->numOfKeys;
5516 
5517     p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd;
5518 
5519     INIT_LIST(&h_OldPointersLst);
5520     INIT_LIST(&h_NewPointersLst);
5521 
5522     p_ModifyKeyParams = ModifyNodeCommonPart(p_CcNode, keyIndex,
5523                                              e_MODIFY_STATE_CHANGE, FALSE, TRUE,
5524                                              FALSE);
5525     if (!p_ModifyKeyParams)
5526         RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
5527 
5528     if (p_CcNode->maxNumOfKeys
5529             && !TRY_LOCK(p_FmPcd->h_ShadowSpinlock, &p_FmPcd->shadowLock))
5530     {
5531         XX_Free(p_ModifyKeyParams);
5532         return ERROR_CODE(E_BUSY);
5533     }
5534 
5535     err = BuildNewNodeModifyNextEngine(h_FmPcd, p_CcNode, keyIndex,
5536                                        p_FmPcdCcNextEngineParams,
5537                                        &h_OldPointersLst, &h_NewPointersLst,
5538                                        p_ModifyKeyParams);
5539     if (err)
5540     {
5541         XX_Free(p_ModifyKeyParams);
5542         if (p_CcNode->maxNumOfKeys)
5543             RELEASE_LOCK(p_FmPcd->shadowLock);
5544         RETURN_ERROR(MAJOR, err, NO_MSG);
5545     }
5546 
5547     err = DoDynamicChange(p_FmPcd, &h_OldPointersLst, &h_NewPointersLst,
5548                           p_ModifyKeyParams, FALSE);
5549 
5550     if (p_CcNode->maxNumOfKeys)
5551         RELEASE_LOCK(p_FmPcd->shadowLock);
5552 
5553     return err;
5554 }
5555 
5556 t_Error FmPcdCcAddKey(t_Handle h_FmPcd, t_Handle h_FmPcdCcNode,
5557                       uint16_t keyIndex, uint8_t keySize,
5558                       t_FmPcdCcKeyParams *p_FmPcdCcKeyParams)
5559 {
5560     t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_FmPcdCcNode;
5561     t_FmPcd *p_FmPcd;
5562     t_FmPcdModifyCcKeyAdditionalParams *p_ModifyKeyParams;
5563     t_List h_OldPointersLst, h_NewPointersLst;
5564     bool useShadowStructs = FALSE;
5565     uint16_t tmpKeyIndex;
5566     t_Error err = E_OK;
5567 
5568     if (keyIndex > p_CcNode->numOfKeys)
5569         RETURN_ERROR(MAJOR, E_NOT_IN_RANGE,
5570                      ("keyIndex > previously cleared last index + 1"));
5571 
5572     if (keySize != p_CcNode->userSizeOfExtraction)
5573         RETURN_ERROR(
5574                 MAJOR,
5575                 E_INVALID_VALUE,
5576                 ("keySize has to be defined as it was defined in initialization step"));
5577 
5578     if (p_CcNode->h_FmPcd != h_FmPcd)
5579         RETURN_ERROR(
5580                 MAJOR,
5581                 E_INVALID_VALUE,
5582                 ("handler to FmPcd is different from the handle provided at node initialization time"));
5583 
5584     if (p_CcNode->maxNumOfKeys)
5585     {
5586         if (p_CcNode->numOfKeys == p_CcNode->maxNumOfKeys)
5587             RETURN_ERROR(
5588                     MAJOR,
5589                     E_FULL,
5590                     ("number of keys exceeds the maximal number of keys provided at node initialization time"));
5591     }
5592     else
5593         if (p_CcNode->numOfKeys == FM_PCD_MAX_NUM_OF_KEYS)
5594             RETURN_ERROR(
5595                     MAJOR,
5596                     E_INVALID_VALUE,
5597                     ("number of keys can not be larger than %d", FM_PCD_MAX_NUM_OF_KEYS));
5598 
5599     err = FindKeyIndex(h_FmPcdCcNode, keySize, p_FmPcdCcKeyParams->p_Key,
5600                        p_FmPcdCcKeyParams->p_Mask, &tmpKeyIndex);
5601     if (GET_ERROR_TYPE(err) != E_NOT_FOUND)
5602         RETURN_ERROR(
5603                 MAJOR,
5604                 E_ALREADY_EXISTS,
5605                 ("The received key and mask pair was already found in the match table of the provided node"));
5606 
5607     p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd;
5608 
5609     INIT_LIST(&h_OldPointersLst);
5610     INIT_LIST(&h_NewPointersLst);
5611 
5612     p_ModifyKeyParams = ModifyNodeCommonPart(p_CcNode, keyIndex,
5613                                              e_MODIFY_STATE_ADD, TRUE, TRUE,
5614                                              FALSE);
5615     if (!p_ModifyKeyParams)
5616         RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
5617 
5618     if (p_CcNode->maxNumOfKeys)
5619     {
5620         if (!TRY_LOCK(p_FmPcd->h_ShadowSpinlock, &p_FmPcd->shadowLock))
5621         {
5622             XX_Free(p_ModifyKeyParams);
5623             return ERROR_CODE(E_BUSY);
5624         }
5625 
5626         useShadowStructs = TRUE;
5627     }
5628 
5629     err = BuildNewNodeAddOrMdfyKeyAndNextEngine(h_FmPcd, p_CcNode, keyIndex,
5630                                                 p_FmPcdCcKeyParams,
5631                                                 p_ModifyKeyParams, TRUE);
5632     if (err)
5633     {
5634         ReleaseNewNodeCommonPart(p_ModifyKeyParams);
5635         XX_Free(p_ModifyKeyParams);
5636         if (p_CcNode->maxNumOfKeys)
5637             RELEASE_LOCK(p_FmPcd->shadowLock);
5638         RETURN_ERROR(MAJOR, err, NO_MSG);
5639     }
5640 
5641     err = UpdatePtrWhichPointOnCrntMdfNode(p_CcNode, p_ModifyKeyParams,
5642                                            &h_OldPointersLst,
5643                                            &h_NewPointersLst);
5644     if (err)
5645     {
5646         ReleaseNewNodeCommonPart(p_ModifyKeyParams);
5647         XX_Free(p_ModifyKeyParams);
5648         if (p_CcNode->maxNumOfKeys)
5649             RELEASE_LOCK(p_FmPcd->shadowLock);
5650         RETURN_ERROR(MAJOR, err, NO_MSG);
5651     }
5652 
5653     err = DoDynamicChange(p_FmPcd, &h_OldPointersLst, &h_NewPointersLst,
5654                           p_ModifyKeyParams, useShadowStructs);
5655     if (p_CcNode->maxNumOfKeys)
5656         RELEASE_LOCK(p_FmPcd->shadowLock);
5657 
5658     return err;
5659 }
5660 
5661 t_Error FmPcdCcModifyKeyAndNextEngine(t_Handle h_FmPcd, t_Handle h_FmPcdCcNode,
5662                                       uint16_t keyIndex, uint8_t keySize,
5663                                       t_FmPcdCcKeyParams *p_FmPcdCcKeyParams)
5664 {
5665     t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_FmPcdCcNode;
5666     t_FmPcd *p_FmPcd;
5667     t_List h_OldPointersLst, h_NewPointersLst;
5668     t_FmPcdModifyCcKeyAdditionalParams *p_ModifyKeyParams;
5669     uint16_t tmpKeyIndex;
5670     bool useShadowStructs = FALSE;
5671     t_Error err = E_OK;
5672 
5673     if (keyIndex > p_CcNode->numOfKeys)
5674         RETURN_ERROR(MAJOR, E_INVALID_STATE,
5675                      ("keyIndex > previously cleared last index + 1"));
5676 
5677     if (keySize != p_CcNode->userSizeOfExtraction)
5678         RETURN_ERROR(
5679                 MAJOR,
5680                 E_INVALID_VALUE,
5681                 ("keySize has to be defined as it was defined in initialization step"));
5682 
5683     if (p_CcNode->h_FmPcd != h_FmPcd)
5684         RETURN_ERROR(
5685                 MAJOR,
5686                 E_INVALID_VALUE,
5687                 ("handler to FmPcd is different from the handle provided at node initialization time"));
5688 
5689     err = FindKeyIndex(h_FmPcdCcNode, keySize, p_FmPcdCcKeyParams->p_Key,
5690                        p_FmPcdCcKeyParams->p_Mask, &tmpKeyIndex);
5691     if (GET_ERROR_TYPE(err) != E_NOT_FOUND)
5692         RETURN_ERROR(
5693                 MINOR,
5694                 E_ALREADY_EXISTS,
5695                 ("The received key and mask pair was already found in the match table of the provided node"));
5696 
5697     p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd;
5698 
5699     INIT_LIST(&h_OldPointersLst);
5700     INIT_LIST(&h_NewPointersLst);
5701 
5702     p_ModifyKeyParams = ModifyNodeCommonPart(p_CcNode, keyIndex,
5703                                              e_MODIFY_STATE_CHANGE, TRUE, TRUE,
5704                                              FALSE);
5705     if (!p_ModifyKeyParams)
5706         RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
5707 
5708     if (p_CcNode->maxNumOfKeys)
5709     {
5710         if (!TRY_LOCK(p_FmPcd->h_ShadowSpinlock, &p_FmPcd->shadowLock))
5711         {
5712             XX_Free(p_ModifyKeyParams);
5713             return ERROR_CODE(E_BUSY);
5714         }
5715 
5716         useShadowStructs = TRUE;
5717     }
5718 
5719     err = BuildNewNodeAddOrMdfyKeyAndNextEngine(h_FmPcd, p_CcNode, keyIndex,
5720                                                 p_FmPcdCcKeyParams,
5721                                                 p_ModifyKeyParams, FALSE);
5722     if (err)
5723     {
5724         ReleaseNewNodeCommonPart(p_ModifyKeyParams);
5725         XX_Free(p_ModifyKeyParams);
5726         if (p_CcNode->maxNumOfKeys)
5727             RELEASE_LOCK(p_FmPcd->shadowLock);
5728         RETURN_ERROR(MAJOR, err, NO_MSG);
5729     }
5730 
5731     err = UpdatePtrWhichPointOnCrntMdfNode(p_CcNode, p_ModifyKeyParams,
5732                                            &h_OldPointersLst,
5733                                            &h_NewPointersLst);
5734     if (err)
5735     {
5736         ReleaseNewNodeCommonPart(p_ModifyKeyParams);
5737         XX_Free(p_ModifyKeyParams);
5738         if (p_CcNode->maxNumOfKeys)
5739             RELEASE_LOCK(p_FmPcd->shadowLock);
5740         RETURN_ERROR(MAJOR, err, NO_MSG);
5741     }
5742 
5743     err = DoDynamicChange(p_FmPcd, &h_OldPointersLst, &h_NewPointersLst,
5744                           p_ModifyKeyParams, useShadowStructs);
5745 
5746     if (p_CcNode->maxNumOfKeys)
5747         RELEASE_LOCK(p_FmPcd->shadowLock);
5748 
5749     return err;
5750 }
5751 
5752 uint32_t FmPcdCcGetNodeAddrOffsetFromNodeInfo(t_Handle h_FmPcd,
5753                                               t_Handle h_Pointer)
5754 {
5755     t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;
5756     t_CcNodeInformation *p_CcNodeInfo;
5757 
5758     SANITY_CHECK_RETURN_VALUE(h_FmPcd, E_INVALID_HANDLE,
5759                               (uint32_t)ILLEGAL_BASE);
5760 
5761     p_CcNodeInfo = CC_NODE_F_OBJECT(h_Pointer);
5762 
5763     return (uint32_t)(XX_VirtToPhys(p_CcNodeInfo->h_CcNode)
5764             - p_FmPcd->physicalMuramBase);
5765 }
5766 
5767 t_Error FmPcdCcGetGrpParams(t_Handle h_FmPcdCcTree, uint8_t grpId,
5768                             uint32_t *p_GrpBits, uint8_t *p_GrpBase)
5769 {
5770     t_FmPcdCcTree *p_FmPcdCcTree = (t_FmPcdCcTree *)h_FmPcdCcTree;
5771 
5772     SANITY_CHECK_RETURN_ERROR(h_FmPcdCcTree, E_INVALID_HANDLE);
5773 
5774     if (grpId >= p_FmPcdCcTree->numOfGrps)
5775         RETURN_ERROR(MAJOR, E_INVALID_HANDLE,
5776                      ("grpId you asked > numOfGroup of relevant tree"));
5777 
5778     *p_GrpBits = p_FmPcdCcTree->fmPcdGroupParam[grpId].totalBitsMask;
5779     *p_GrpBase = p_FmPcdCcTree->fmPcdGroupParam[grpId].baseGroupEntry;
5780 
5781     return E_OK;
5782 }
5783 
5784 t_Error FmPcdCcBindTree(t_Handle h_FmPcd, t_Handle h_PcdParams,
5785                         t_Handle h_FmPcdCcTree, uint32_t *p_Offset,
5786                         t_Handle h_FmPort)
5787 {
5788     t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
5789     t_FmPcdCcTree *p_FmPcdCcTree = (t_FmPcdCcTree *)h_FmPcdCcTree;
5790     t_Error err = E_OK;
5791 
5792     SANITY_CHECK_RETURN_ERROR(h_FmPcd, E_INVALID_HANDLE);
5793     SANITY_CHECK_RETURN_ERROR(h_FmPcdCcTree, E_INVALID_HANDLE);
5794 
5795     /* this routine must be protected by the calling routine by locking all PCD modules! */
5796 
5797     err = CcUpdateParams(h_FmPcd, h_PcdParams, h_FmPort, h_FmPcdCcTree, TRUE);
5798 
5799     if (err == E_OK)
5800         UpdateCcRootOwner(p_FmPcdCcTree, TRUE);
5801 
5802     *p_Offset = (uint32_t)(XX_VirtToPhys(
5803             UINT_TO_PTR(p_FmPcdCcTree->ccTreeBaseAddr))
5804             - p_FmPcd->physicalMuramBase);
5805 
5806     return err;
5807 }
5808 
5809 t_Error FmPcdCcUnbindTree(t_Handle h_FmPcd, t_Handle h_FmPcdCcTree)
5810 {
5811     t_FmPcdCcTree *p_FmPcdCcTree = (t_FmPcdCcTree *)h_FmPcdCcTree;
5812 
5813     /* this routine must be protected by the calling routine by locking all PCD modules! */
5814 
5815     UNUSED(h_FmPcd);
5816 
5817     SANITY_CHECK_RETURN_ERROR(h_FmPcdCcTree, E_INVALID_HANDLE);
5818 
5819     UpdateCcRootOwner(p_FmPcdCcTree, FALSE);
5820 
5821     return E_OK;
5822 }
5823 
5824 t_Error FmPcdCcNodeTreeTryLock(t_Handle h_FmPcd, t_Handle h_FmPcdCcNode,
5825                                t_List *p_List)
5826 {
5827     t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_FmPcdCcNode;
5828     t_List *p_Pos, *p_Tmp;
5829     t_CcNodeInformation *p_CcNodeInfo, nodeInfo;
5830     uint32_t intFlags;
5831     t_Error err = E_OK;
5832 
5833     intFlags = FmPcdLock(h_FmPcd);
5834 
5835     NCSW_LIST_FOR_EACH(p_Pos, &p_CcNode->ccTreesLst)
5836     {
5837         p_CcNodeInfo = CC_NODE_F_OBJECT(p_Pos);
5838         ASSERT_COND(p_CcNodeInfo->h_CcNode);
5839 
5840         err = CcRootTryLock(p_CcNodeInfo->h_CcNode);
5841 
5842         if (err)
5843         {
5844             NCSW_LIST_FOR_EACH(p_Tmp, &p_CcNode->ccTreesLst)
5845             {
5846                 if (p_Tmp == p_Pos)
5847                     break;
5848 
5849                 CcRootReleaseLock(p_CcNodeInfo->h_CcNode);
5850             }
5851             break;
5852         }
5853 
5854         memset(&nodeInfo, 0, sizeof(t_CcNodeInformation));
5855         nodeInfo.h_CcNode = p_CcNodeInfo->h_CcNode;
5856         EnqueueNodeInfoToRelevantLst(p_List, &nodeInfo, NULL);
5857     }
5858 
5859     FmPcdUnlock(h_FmPcd, intFlags);
5860     CORE_MemoryBarrier();
5861 
5862     return err;
5863 }
5864 
5865 void FmPcdCcNodeTreeReleaseLock(t_Handle h_FmPcd, t_List *p_List)
5866 {
5867     t_List *p_Pos;
5868     t_CcNodeInformation *p_CcNodeInfo;
5869     t_Handle h_FmPcdCcTree;
5870     uint32_t intFlags;
5871 
5872     intFlags = FmPcdLock(h_FmPcd);
5873 
5874     NCSW_LIST_FOR_EACH(p_Pos, p_List)
5875     {
5876         p_CcNodeInfo = CC_NODE_F_OBJECT(p_Pos);
5877         h_FmPcdCcTree = p_CcNodeInfo->h_CcNode;
5878         CcRootReleaseLock(h_FmPcdCcTree);
5879     }
5880 
5881     ReleaseLst(p_List);
5882 
5883     FmPcdUnlock(h_FmPcd, intFlags);
5884     CORE_MemoryBarrier();
5885 }
5886 
5887 t_Error FmPcdUpdateCcShadow(t_FmPcd *p_FmPcd, uint32_t size, uint32_t align)
5888 {
5889     uint32_t intFlags;
5890     uint32_t newSize = 0, newAlign = 0;
5891     bool allocFail = FALSE;
5892 
5893     ASSERT_COND(p_FmPcd);
5894 
5895     if (!size)
5896         RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("size must be larger then 0"));
5897 
5898     if (!POWER_OF_2(align))
5899         RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("alignment must be power of 2"));
5900 
5901     newSize = p_FmPcd->ccShadowSize;
5902     newAlign = p_FmPcd->ccShadowAlign;
5903 
5904     /* Check if current shadow is large enough to hold the requested size */
5905     if (size > p_FmPcd->ccShadowSize)
5906         newSize = size;
5907 
5908     /* Check if current shadow matches the requested alignment */
5909     if (align > p_FmPcd->ccShadowAlign)
5910         newAlign = align;
5911 
5912     /* If a bigger shadow size or bigger shadow alignment are required,
5913      a new shadow will be allocated */
5914     if ((newSize != p_FmPcd->ccShadowSize)
5915             || (newAlign != p_FmPcd->ccShadowAlign))
5916     {
5917         intFlags = FmPcdLock(p_FmPcd);
5918 
5919         if (p_FmPcd->p_CcShadow)
5920         {
5921             FM_MURAM_FreeMem(FmPcdGetMuramHandle(p_FmPcd), p_FmPcd->p_CcShadow);
5922             p_FmPcd->ccShadowSize = 0;
5923             p_FmPcd->ccShadowAlign = 0;
5924         }
5925 
5926         p_FmPcd->p_CcShadow = FM_MURAM_AllocMem(FmPcdGetMuramHandle(p_FmPcd),
5927                                                 newSize, newAlign);
5928         if (!p_FmPcd->p_CcShadow)
5929         {
5930             allocFail = TRUE;
5931 
5932             /* If new shadow size allocation failed,
5933              re-allocate with previous parameters */
5934             p_FmPcd->p_CcShadow = FM_MURAM_AllocMem(
5935                     FmPcdGetMuramHandle(p_FmPcd), p_FmPcd->ccShadowSize,
5936                     p_FmPcd->ccShadowAlign);
5937         }
5938 
5939         FmPcdUnlock(p_FmPcd, intFlags);
5940 
5941         if (allocFail)
5942             RETURN_ERROR(MAJOR, E_NO_MEMORY,
5943                          ("MURAM allocation for CC Shadow memory"));
5944 
5945         p_FmPcd->ccShadowSize = newSize;
5946         p_FmPcd->ccShadowAlign = newAlign;
5947     }
5948 
5949     return E_OK;
5950 }
5951 
5952 #if (DPAA_VERSION >= 11)
5953 void FmPcdCcGetAdTablesThatPointOnReplicGroup(t_Handle h_Node,
5954                                               t_Handle h_ReplicGroup,
5955                                               t_List *p_AdTables,
5956                                               uint32_t *p_NumOfAdTables)
5957 {
5958     t_FmPcdCcNode *p_CurrentNode = (t_FmPcdCcNode *)h_Node;
5959     int i = 0;
5960     void * p_AdTable;
5961     t_CcNodeInformation ccNodeInfo;
5962 
5963     ASSERT_COND(h_Node);
5964     *p_NumOfAdTables = 0;
5965 
5966     /* search in the current node which exact index points on this current replicator group for getting AD */
5967     for (i = 0; i < p_CurrentNode->numOfKeys + 1; i++)
5968     {
5969         if ((p_CurrentNode->keyAndNextEngineParams[i].nextEngineParams.nextEngine
5970                 == e_FM_PCD_FR)
5971                 && ((p_CurrentNode->keyAndNextEngineParams[i].nextEngineParams.params.frParams.h_FrmReplic
5972                         == (t_Handle)h_ReplicGroup)))
5973         {
5974             /* save the current ad table in the list */
5975             /* this entry uses the input replicator group */
5976             p_AdTable =
5977                     PTR_MOVE(p_CurrentNode->h_AdTable, i*FM_PCD_CC_AD_ENTRY_SIZE);
5978             memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation));
5979             ccNodeInfo.h_CcNode = p_AdTable;
5980             EnqueueNodeInfoToRelevantLst(p_AdTables, &ccNodeInfo, NULL);
5981             (*p_NumOfAdTables)++;
5982         }
5983     }
5984 
5985     ASSERT_COND(i != p_CurrentNode->numOfKeys);
5986 }
5987 #endif /* (DPAA_VERSION >= 11) */
5988 /*********************** End of inter-module routines ************************/
5989 
5990 /****************************************/
5991 /*       API Init unit functions        */
5992 /****************************************/
5993 
5994 t_Handle FM_PCD_CcRootBuild(t_Handle h_FmPcd,
5995                             t_FmPcdCcTreeParams *p_PcdGroupsParam)
5996 {
5997     t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;
5998     t_Error err = E_OK;
5999     int i = 0, j = 0, k = 0;
6000     t_FmPcdCcTree *p_FmPcdCcTree;
6001     uint8_t numOfEntries;
6002     t_Handle p_CcTreeTmp;
6003     t_FmPcdCcGrpParams *p_FmPcdCcGroupParams;
6004     t_FmPcdCcKeyAndNextEngineParams *p_Params, *p_KeyAndNextEngineParams;
6005     t_NetEnvParams netEnvParams;
6006     uint8_t lastOne = 0;
6007     uint32_t requiredAction = 0;
6008     t_FmPcdCcNode *p_FmPcdCcNextNode;
6009     t_CcNodeInformation ccNodeInfo, *p_CcInformation;
6010 
6011     SANITY_CHECK_RETURN_VALUE(h_FmPcd, E_INVALID_HANDLE, NULL);
6012     SANITY_CHECK_RETURN_VALUE(p_PcdGroupsParam, E_INVALID_HANDLE, NULL);
6013 
6014     if (p_PcdGroupsParam->numOfGrps > FM_PCD_MAX_NUM_OF_CC_GROUPS)
6015     {
6016         REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("numOfGrps should not exceed %d", FM_PCD_MAX_NUM_OF_CC_GROUPS));
6017         return NULL;
6018     }
6019 
6020     p_FmPcdCcTree = (t_FmPcdCcTree*)XX_Malloc(sizeof(t_FmPcdCcTree));
6021     if (!p_FmPcdCcTree)
6022     {
6023         REPORT_ERROR(MAJOR, E_NO_MEMORY, ("PCD tree structure"));
6024         return NULL;
6025     }
6026     memset(p_FmPcdCcTree, 0, sizeof(t_FmPcdCcTree));
6027     p_FmPcdCcTree->h_FmPcd = h_FmPcd;
6028 
6029     p_Params = (t_FmPcdCcKeyAndNextEngineParams*)XX_Malloc(
6030             FM_PCD_MAX_NUM_OF_CC_GROUPS
6031                     * sizeof(t_FmPcdCcKeyAndNextEngineParams));
6032     memset(p_Params,
6033            0,
6034            FM_PCD_MAX_NUM_OF_CC_GROUPS
6035                    * sizeof(t_FmPcdCcKeyAndNextEngineParams));
6036 
6037     INIT_LIST(&p_FmPcdCcTree->fmPortsLst);
6038 
6039 #ifdef FM_CAPWAP_SUPPORT
6040     if ((p_PcdGroupsParam->numOfGrps == 1) &&
6041             (p_PcdGroupsParam->ccGrpParams[0].numOfDistinctionUnits == 0) &&
6042             (p_PcdGroupsParam->ccGrpParams[0].nextEnginePerEntriesInGrp[0].nextEngine == e_FM_PCD_CC) &&
6043             p_PcdGroupsParam->ccGrpParams[0].nextEnginePerEntriesInGrp[0].params.ccParams.h_CcNode &&
6044             IsCapwapApplSpecific(p_PcdGroupsParam->ccGrpParams[0].nextEnginePerEntriesInGrp[0].params.ccParams.h_CcNode))
6045     {
6046         p_PcdGroupsParam->ccGrpParams[0].nextEnginePerEntriesInGrp[0].h_Manip = FmPcdManipApplSpecificBuild();
6047         if (!p_PcdGroupsParam->ccGrpParams[0].nextEnginePerEntriesInGrp[0].h_Manip)
6048         {
6049             DeleteTree(p_FmPcdCcTree,p_FmPcd);
6050             XX_Free(p_Params);
6051             REPORT_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
6052             return NULL;
6053         }
6054     }
6055 #endif /* FM_CAPWAP_SUPPORT */
6056 
6057     numOfEntries = 0;
6058     p_FmPcdCcTree->netEnvId = FmPcdGetNetEnvId(p_PcdGroupsParam->h_NetEnv);
6059 
6060     for (i = 0; i < p_PcdGroupsParam->numOfGrps; i++)
6061     {
6062         p_FmPcdCcGroupParams = &p_PcdGroupsParam->ccGrpParams[i];
6063 
6064         if (p_FmPcdCcGroupParams->numOfDistinctionUnits
6065                 > FM_PCD_MAX_NUM_OF_CC_UNITS)
6066         {
6067             DeleteTree(p_FmPcdCcTree, p_FmPcd);
6068             XX_Free(p_Params);
6069             REPORT_ERROR(MAJOR, E_INVALID_VALUE,
6070                     ("numOfDistinctionUnits (group %d) should not exceed %d", i, FM_PCD_MAX_NUM_OF_CC_UNITS));
6071             return NULL;
6072         }
6073 
6074         p_FmPcdCcTree->fmPcdGroupParam[i].baseGroupEntry = numOfEntries;
6075         p_FmPcdCcTree->fmPcdGroupParam[i].numOfEntriesInGroup = (uint8_t)(0x01
6076                 << p_FmPcdCcGroupParams->numOfDistinctionUnits);
6077         numOfEntries += p_FmPcdCcTree->fmPcdGroupParam[i].numOfEntriesInGroup;
6078         if (numOfEntries > FM_PCD_MAX_NUM_OF_CC_GROUPS)
6079         {
6080             DeleteTree(p_FmPcdCcTree, p_FmPcd);
6081             XX_Free(p_Params);
6082             REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("numOfEntries can not be larger than %d", FM_PCD_MAX_NUM_OF_CC_GROUPS));
6083             return NULL;
6084         }
6085 
6086         if (lastOne)
6087         {
6088             if (p_FmPcdCcTree->fmPcdGroupParam[i].numOfEntriesInGroup > lastOne)
6089             {
6090                 DeleteTree(p_FmPcdCcTree, p_FmPcd);
6091                 XX_Free(p_Params);
6092                 REPORT_ERROR(MAJOR, E_CONFLICT, ("numOfEntries per group must be set in descending order"));
6093                 return NULL;
6094             }
6095         }
6096 
6097         lastOne = p_FmPcdCcTree->fmPcdGroupParam[i].numOfEntriesInGroup;
6098 
6099         netEnvParams.netEnvId = p_FmPcdCcTree->netEnvId;
6100         netEnvParams.numOfDistinctionUnits =
6101                 p_FmPcdCcGroupParams->numOfDistinctionUnits;
6102 
6103         memcpy(netEnvParams.unitIds, &p_FmPcdCcGroupParams->unitIds,
6104                (sizeof(uint8_t)) * p_FmPcdCcGroupParams->numOfDistinctionUnits);
6105 
6106         err = PcdGetUnitsVector(p_FmPcd, &netEnvParams);
6107         if (err)
6108         {
6109             DeleteTree(p_FmPcdCcTree, p_FmPcd);
6110             XX_Free(p_Params);
6111             REPORT_ERROR(MAJOR, err, NO_MSG);
6112             return NULL;
6113         }
6114 
6115         p_FmPcdCcTree->fmPcdGroupParam[i].totalBitsMask = netEnvParams.vector;
6116         for (j = 0; j < p_FmPcdCcTree->fmPcdGroupParam[i].numOfEntriesInGroup;
6117                 j++)
6118         {
6119             err = ValidateNextEngineParams(
6120                     h_FmPcd,
6121                     &p_FmPcdCcGroupParams->nextEnginePerEntriesInGrp[j],
6122                     e_FM_PCD_CC_STATS_MODE_NONE);
6123             if (err)
6124             {
6125                 DeleteTree(p_FmPcdCcTree, p_FmPcd);
6126                 XX_Free(p_Params);
6127                 REPORT_ERROR(MAJOR, err, (NO_MSG));
6128                 return NULL;
6129             }
6130 
6131             if (p_FmPcdCcGroupParams->nextEnginePerEntriesInGrp[j].h_Manip)
6132             {
6133                 err = FmPcdManipCheckParamsForCcNextEngine(
6134                         &p_FmPcdCcGroupParams->nextEnginePerEntriesInGrp[j],
6135                         &requiredAction);
6136                 if (err)
6137                 {
6138                     DeleteTree(p_FmPcdCcTree, p_FmPcd);
6139                     XX_Free(p_Params);
6140                     REPORT_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
6141                     return NULL;
6142                 }
6143             }
6144             p_KeyAndNextEngineParams = p_Params + k;
6145 
6146             memcpy(&p_KeyAndNextEngineParams->nextEngineParams,
6147                    &p_FmPcdCcGroupParams->nextEnginePerEntriesInGrp[j],
6148                    sizeof(t_FmPcdCcNextEngineParams));
6149 
6150             if ((p_KeyAndNextEngineParams->nextEngineParams.nextEngine
6151                     == e_FM_PCD_CC)
6152                     && p_KeyAndNextEngineParams->nextEngineParams.h_Manip)
6153             {
6154                 err =
6155                         AllocAndFillAdForContLookupManip(
6156                                 p_KeyAndNextEngineParams->nextEngineParams.params.ccParams.h_CcNode);
6157                 if (err)
6158                 {
6159                     DeleteTree(p_FmPcdCcTree, p_FmPcd);
6160                     XX_Free(p_Params);
6161                     REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC Tree"));
6162                     return NULL;
6163                 }
6164             }
6165 
6166             requiredAction |= UPDATE_CC_WITH_TREE;
6167             p_KeyAndNextEngineParams->requiredAction = requiredAction;
6168 
6169             k++;
6170         }
6171     }
6172 
6173     p_FmPcdCcTree->numOfEntries = (uint8_t)k;
6174     p_FmPcdCcTree->numOfGrps = p_PcdGroupsParam->numOfGrps;
6175 
6176     p_FmPcdCcTree->ccTreeBaseAddr =
6177             PTR_TO_UINT(FM_MURAM_AllocMem(FmPcdGetMuramHandle(h_FmPcd),
6178                             (uint32_t)( FM_PCD_MAX_NUM_OF_CC_GROUPS * FM_PCD_CC_AD_ENTRY_SIZE),
6179                             FM_PCD_CC_TREE_ADDR_ALIGN));
6180     if (!p_FmPcdCcTree->ccTreeBaseAddr)
6181     {
6182         DeleteTree(p_FmPcdCcTree, p_FmPcd);
6183         XX_Free(p_Params);
6184         REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC Tree"));
6185         return NULL;
6186     }
6187     MemSet8(
6188             UINT_TO_PTR(p_FmPcdCcTree->ccTreeBaseAddr), 0,
6189             (uint32_t)(FM_PCD_MAX_NUM_OF_CC_GROUPS * FM_PCD_CC_AD_ENTRY_SIZE));
6190 
6191     p_CcTreeTmp = UINT_TO_PTR(p_FmPcdCcTree->ccTreeBaseAddr);
6192 
6193     for (i = 0; i < numOfEntries; i++)
6194     {
6195         p_KeyAndNextEngineParams = p_Params + i;
6196 
6197         NextStepAd(p_CcTreeTmp, NULL,
6198                    &p_KeyAndNextEngineParams->nextEngineParams, p_FmPcd);
6199 
6200         p_CcTreeTmp = PTR_MOVE(p_CcTreeTmp, FM_PCD_CC_AD_ENTRY_SIZE);
6201 
6202         memcpy(&p_FmPcdCcTree->keyAndNextEngineParams[i],
6203                p_KeyAndNextEngineParams,
6204                sizeof(t_FmPcdCcKeyAndNextEngineParams));
6205 
6206         if (p_FmPcdCcTree->keyAndNextEngineParams[i].nextEngineParams.nextEngine
6207                 == e_FM_PCD_CC)
6208         {
6209             p_FmPcdCcNextNode =
6210                     (t_FmPcdCcNode*)p_FmPcdCcTree->keyAndNextEngineParams[i].nextEngineParams.params.ccParams.h_CcNode;
6211             p_CcInformation = FindNodeInfoInReleventLst(
6212                     &p_FmPcdCcNextNode->ccTreeIdLst, (t_Handle)p_FmPcdCcTree,
6213                     p_FmPcdCcNextNode->h_Spinlock);
6214 
6215             if (!p_CcInformation)
6216             {
6217                 memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation));
6218                 ccNodeInfo.h_CcNode = (t_Handle)p_FmPcdCcTree;
6219                 ccNodeInfo.index = 1;
6220                 EnqueueNodeInfoToRelevantLst(&p_FmPcdCcNextNode->ccTreeIdLst,
6221                                              &ccNodeInfo,
6222                                              p_FmPcdCcNextNode->h_Spinlock);
6223             }
6224             else
6225                 p_CcInformation->index++;
6226         }
6227     }
6228 
6229     FmPcdIncNetEnvOwners(h_FmPcd, p_FmPcdCcTree->netEnvId);
6230     p_CcTreeTmp = UINT_TO_PTR(p_FmPcdCcTree->ccTreeBaseAddr);
6231 
6232     if (!FmPcdLockTryLockAll(p_FmPcd))
6233     {
6234         FM_PCD_CcRootDelete(p_FmPcdCcTree);
6235         XX_Free(p_Params);
6236         DBG(TRACE, ("FmPcdLockTryLockAll failed"));
6237         return NULL;
6238     }
6239 
6240     for (i = 0; i < numOfEntries; i++)
6241     {
6242         if (p_FmPcdCcTree->keyAndNextEngineParams[i].requiredAction)
6243         {
6244             err = SetRequiredAction(
6245                     h_FmPcd,
6246                     p_FmPcdCcTree->keyAndNextEngineParams[i].requiredAction,
6247                     &p_FmPcdCcTree->keyAndNextEngineParams[i], p_CcTreeTmp, 1,
6248                     p_FmPcdCcTree);
6249             if (err)
6250             {
6251                 FmPcdLockUnlockAll(p_FmPcd);
6252                 FM_PCD_CcRootDelete(p_FmPcdCcTree);
6253                 XX_Free(p_Params);
6254                 REPORT_ERROR(MAJOR, E_NO_MEMORY, ("No memory"));
6255                 return NULL;
6256             }
6257             p_CcTreeTmp = PTR_MOVE(p_CcTreeTmp, FM_PCD_CC_AD_ENTRY_SIZE);
6258         }
6259     }
6260 
6261     FmPcdLockUnlockAll(p_FmPcd);
6262     p_FmPcdCcTree->p_Lock = FmPcdAcquireLock(p_FmPcd);
6263     if (!p_FmPcdCcTree->p_Lock)
6264     {
6265         FM_PCD_CcRootDelete(p_FmPcdCcTree);
6266         XX_Free(p_Params);
6267         REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM CC lock"));
6268         return NULL;
6269     }
6270 
6271     XX_Free(p_Params);
6272 
6273     return p_FmPcdCcTree;
6274 }
6275 
6276 t_Error FM_PCD_CcRootDelete(t_Handle h_CcTree)
6277 {
6278     t_FmPcd *p_FmPcd;
6279     t_FmPcdCcTree *p_CcTree = (t_FmPcdCcTree *)h_CcTree;
6280     int i = 0;
6281 
6282     SANITY_CHECK_RETURN_ERROR(p_CcTree, E_INVALID_STATE);
6283     p_FmPcd = (t_FmPcd *)p_CcTree->h_FmPcd;
6284     SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
6285 
6286     FmPcdDecNetEnvOwners(p_FmPcd, p_CcTree->netEnvId);
6287 
6288     if (p_CcTree->owners)
6289         RETURN_ERROR(
6290                 MAJOR,
6291                 E_INVALID_SELECTION,
6292                 ("the tree with this ID can not be removed because this tree is occupied, first - unbind this tree"));
6293 
6294     /* Delete ip-reassembly schemes if exist */
6295     if (p_CcTree->h_IpReassemblyManip)
6296     {
6297         FmPcdManipDeleteIpReassmSchemes(p_CcTree->h_IpReassemblyManip);
6298         FmPcdManipUpdateOwner(p_CcTree->h_IpReassemblyManip, FALSE);
6299     }
6300 
6301     /* Delete capwap-reassembly schemes if exist */
6302     if (p_CcTree->h_CapwapReassemblyManip)
6303     {
6304         FmPcdManipDeleteCapwapReassmSchemes(p_CcTree->h_CapwapReassemblyManip);
6305         FmPcdManipUpdateOwner(p_CcTree->h_CapwapReassemblyManip, FALSE);
6306     }
6307 
6308     for (i = 0; i < p_CcTree->numOfEntries; i++)
6309     {
6310         if (p_CcTree->keyAndNextEngineParams[i].nextEngineParams.nextEngine
6311                 == e_FM_PCD_CC)
6312             UpdateNodeOwner(
6313                     p_CcTree->keyAndNextEngineParams[i].nextEngineParams.params.ccParams.h_CcNode,
6314                     FALSE);
6315 
6316         if (p_CcTree->keyAndNextEngineParams[i].nextEngineParams.h_Manip)
6317             FmPcdManipUpdateOwner(
6318                     p_CcTree->keyAndNextEngineParams[i].nextEngineParams.h_Manip,
6319                     FALSE);
6320 
6321 #ifdef FM_CAPWAP_SUPPORT
6322         if ((p_CcTree->numOfGrps == 1) &&
6323                 (p_CcTree->fmPcdGroupParam[0].numOfEntriesInGroup == 1) &&
6324                 (p_CcTree->keyAndNextEngineParams[0].nextEngineParams.nextEngine == e_FM_PCD_CC) &&
6325                 p_CcTree->keyAndNextEngineParams[0].nextEngineParams.params.ccParams.h_CcNode &&
6326                 IsCapwapApplSpecific(p_CcTree->keyAndNextEngineParams[0].nextEngineParams.params.ccParams.h_CcNode))
6327         {
6328             if (FM_PCD_ManipNodeDelete(p_CcTree->keyAndNextEngineParams[0].nextEngineParams.h_Manip) != E_OK)
6329             return E_INVALID_STATE;
6330         }
6331 #endif /* FM_CAPWAP_SUPPORT */
6332 
6333 #if (DPAA_VERSION >= 11)
6334         if ((p_CcTree->keyAndNextEngineParams[i].nextEngineParams.nextEngine
6335                 == e_FM_PCD_FR)
6336                 && (p_CcTree->keyAndNextEngineParams[i].nextEngineParams.params.frParams.h_FrmReplic))
6337             FrmReplicGroupUpdateOwner(
6338                     p_CcTree->keyAndNextEngineParams[i].nextEngineParams.params.frParams.h_FrmReplic,
6339                     FALSE);
6340 #endif /* (DPAA_VERSION >= 11) */
6341     }
6342 
6343     if (p_CcTree->p_Lock)
6344         FmPcdReleaseLock(p_CcTree->h_FmPcd, p_CcTree->p_Lock);
6345 
6346     DeleteTree(p_CcTree, p_FmPcd);
6347 
6348     return E_OK;
6349 }
6350 
6351 t_Error FM_PCD_CcRootModifyNextEngine(
6352         t_Handle h_CcTree, uint8_t grpId, uint8_t index,
6353         t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams)
6354 {
6355     t_FmPcd *p_FmPcd;
6356     t_FmPcdCcTree *p_CcTree = (t_FmPcdCcTree *)h_CcTree;
6357     t_Error err = E_OK;
6358 
6359     SANITY_CHECK_RETURN_ERROR(p_FmPcdCcNextEngineParams, E_NULL_POINTER);
6360     SANITY_CHECK_RETURN_ERROR(p_CcTree, E_INVALID_STATE);
6361     p_FmPcd = (t_FmPcd *)p_CcTree->h_FmPcd;
6362     SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
6363 
6364     if (!FmPcdLockTryLockAll(p_FmPcd))
6365     {
6366         DBG(TRACE, ("FmPcdLockTryLockAll failed"));
6367         return ERROR_CODE(E_BUSY);
6368     }
6369 
6370     err = FmPcdCcModifyNextEngineParamTree(p_FmPcd, p_CcTree, grpId, index,
6371                                            p_FmPcdCcNextEngineParams);
6372     FmPcdLockUnlockAll(p_FmPcd);
6373 
6374     if (err)
6375     {
6376         RETURN_ERROR(MAJOR, err, NO_MSG);
6377     }
6378 
6379     return E_OK;
6380 }
6381 
6382 t_Handle FM_PCD_MatchTableSet(t_Handle h_FmPcd,
6383                               t_FmPcdCcNodeParams *p_CcNodeParam)
6384 {
6385     t_FmPcdCcNode *p_CcNode;
6386     t_Error err;
6387 
6388     SANITY_CHECK_RETURN_VALUE(h_FmPcd, E_INVALID_HANDLE, NULL);
6389     SANITY_CHECK_RETURN_VALUE(p_CcNodeParam, E_NULL_POINTER, NULL);
6390 
6391     p_CcNode = (t_FmPcdCcNode*)XX_Malloc(sizeof(t_FmPcdCcNode));
6392     if (!p_CcNode)
6393     {
6394         REPORT_ERROR(MAJOR, E_NO_MEMORY, ("No memory"));
6395         return NULL;
6396     }
6397     memset(p_CcNode, 0, sizeof(t_FmPcdCcNode));
6398 
6399     err = MatchTableSet(h_FmPcd, p_CcNode, p_CcNodeParam);
6400 
6401     switch(GET_ERROR_TYPE(err)
6402 )    {
6403         case E_OK:
6404         break;
6405 
6406         case E_BUSY:
6407         DBG(TRACE, ("E_BUSY error"));
6408         return NULL;
6409 
6410         default:
6411         REPORT_ERROR(MAJOR, err, NO_MSG);
6412         return NULL;
6413     }
6414 
6415     return p_CcNode;
6416 }
6417 
6418 t_Error FM_PCD_MatchTableDelete(t_Handle h_CcNode)
6419 {
6420     t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
6421     int i = 0;
6422 
6423     SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE);
6424     SANITY_CHECK_RETURN_ERROR(p_CcNode->h_FmPcd, E_INVALID_HANDLE);
6425 
6426     if (p_CcNode->owners)
6427         RETURN_ERROR(
6428                 MAJOR,
6429                 E_INVALID_STATE,
6430                 ("This node cannot be removed because it is occupied; first unbind this node"));
6431 
6432     for (i = 0; i < p_CcNode->numOfKeys; i++)
6433         if (p_CcNode->keyAndNextEngineParams[i].nextEngineParams.nextEngine
6434                 == e_FM_PCD_CC)
6435             UpdateNodeOwner(
6436                     p_CcNode->keyAndNextEngineParams[i].nextEngineParams.params.ccParams.h_CcNode,
6437                     FALSE);
6438 
6439     if (p_CcNode->keyAndNextEngineParams[i].nextEngineParams.nextEngine
6440             == e_FM_PCD_CC)
6441         UpdateNodeOwner(
6442                 p_CcNode->keyAndNextEngineParams[i].nextEngineParams.params.ccParams.h_CcNode,
6443                 FALSE);
6444 
6445     /* Handle also Miss entry */
6446     for (i = 0; i < p_CcNode->numOfKeys + 1; i++)
6447     {
6448         if (p_CcNode->keyAndNextEngineParams[i].nextEngineParams.h_Manip)
6449             FmPcdManipUpdateOwner(
6450                     p_CcNode->keyAndNextEngineParams[i].nextEngineParams.h_Manip,
6451                     FALSE);
6452 
6453 #if (DPAA_VERSION >= 11)
6454         if ((p_CcNode->keyAndNextEngineParams[i].nextEngineParams.nextEngine
6455                 == e_FM_PCD_FR)
6456                 && (p_CcNode->keyAndNextEngineParams[i].nextEngineParams.params.frParams.h_FrmReplic))
6457         {
6458             FrmReplicGroupUpdateOwner(
6459                     p_CcNode->keyAndNextEngineParams[i].nextEngineParams.params.frParams.h_FrmReplic,
6460                     FALSE);
6461         }
6462 #endif /* (DPAA_VERSION >= 11) */
6463     }
6464 
6465     DeleteNode(p_CcNode);
6466 
6467     return E_OK;
6468 }
6469 
6470 t_Error FM_PCD_MatchTableAddKey(t_Handle h_CcNode, uint16_t keyIndex,
6471                                 uint8_t keySize,
6472                                 t_FmPcdCcKeyParams *p_KeyParams)
6473 {
6474     t_FmPcd *p_FmPcd;
6475     t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
6476     t_Error err = E_OK;
6477 
6478     SANITY_CHECK_RETURN_ERROR(p_KeyParams, E_NULL_POINTER);
6479     SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE);
6480     p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd;
6481     SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
6482     SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_HANDLE);
6483 
6484     if (keyIndex == FM_PCD_LAST_KEY_INDEX)
6485         keyIndex = p_CcNode->numOfKeys;
6486 
6487     if (!FmPcdLockTryLockAll(p_FmPcd))
6488     {
6489         DBG(TRACE, ("FmPcdLockTryLockAll failed"));
6490         return ERROR_CODE(E_BUSY);
6491     }
6492 
6493     err = FmPcdCcAddKey(p_FmPcd, p_CcNode, keyIndex, keySize, p_KeyParams);
6494 
6495     FmPcdLockUnlockAll(p_FmPcd);
6496 
6497     switch(GET_ERROR_TYPE(err)
6498 )    {
6499         case E_OK:
6500         return E_OK;
6501 
6502         case E_BUSY:
6503         DBG(TRACE, ("E_BUSY error"));
6504         return ERROR_CODE(E_BUSY);
6505 
6506         default:
6507         RETURN_ERROR(MAJOR, err, NO_MSG);
6508     }
6509 }
6510 
6511 t_Error FM_PCD_MatchTableRemoveKey(t_Handle h_CcNode, uint16_t keyIndex)
6512 {
6513     t_FmPcd *p_FmPcd;
6514     t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
6515     t_Error err = E_OK;
6516 
6517     SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE);
6518     p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd;
6519     SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
6520     SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_HANDLE);
6521 
6522     if (!FmPcdLockTryLockAll(p_FmPcd))
6523     {
6524         DBG(TRACE, ("FmPcdLockTryLockAll failed"));
6525         return ERROR_CODE(E_BUSY);
6526     }
6527 
6528     err = FmPcdCcRemoveKey(p_FmPcd, p_CcNode, keyIndex);
6529 
6530     FmPcdLockUnlockAll(p_FmPcd);
6531 
6532     switch(GET_ERROR_TYPE(err)
6533 )    {
6534         case E_OK:
6535         return E_OK;
6536 
6537         case E_BUSY:
6538         DBG(TRACE, ("E_BUSY error"));
6539         return ERROR_CODE(E_BUSY);
6540 
6541         default:
6542         RETURN_ERROR(MAJOR, err, NO_MSG);
6543     }
6544 
6545     return E_OK;
6546 }
6547 
6548 t_Error FM_PCD_MatchTableModifyKey(t_Handle h_CcNode, uint16_t keyIndex,
6549                                    uint8_t keySize, uint8_t *p_Key,
6550                                    uint8_t *p_Mask)
6551 {
6552     t_FmPcd *p_FmPcd;
6553     t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
6554     t_Error err = E_OK;
6555 
6556     SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE);
6557     SANITY_CHECK_RETURN_ERROR(p_Key, E_NULL_POINTER);
6558     p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd;
6559     SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
6560     SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_HANDLE);
6561 
6562 
6563     if (!FmPcdLockTryLockAll(p_FmPcd))
6564     {
6565         DBG(TRACE, ("FmPcdLockTryLockAll failed"));
6566         return ERROR_CODE(E_BUSY);
6567     }
6568 
6569     err = FmPcdCcModifyKey(p_FmPcd, p_CcNode, keyIndex, keySize, p_Key, p_Mask);
6570 
6571     FmPcdLockUnlockAll(p_FmPcd);
6572 
6573     switch(GET_ERROR_TYPE(err)
6574 )    {
6575         case E_OK:
6576         return E_OK;
6577 
6578         case E_BUSY:
6579         DBG(TRACE, ("E_BUSY error"));
6580         return ERROR_CODE(E_BUSY);
6581 
6582         default:
6583         RETURN_ERROR(MAJOR, err, NO_MSG);
6584     }
6585 }
6586 
6587 t_Error FM_PCD_MatchTableModifyNextEngine(
6588         t_Handle h_CcNode, uint16_t keyIndex,
6589         t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams)
6590 {
6591     t_FmPcd *p_FmPcd;
6592     t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
6593     t_Error err = E_OK;
6594 
6595     SANITY_CHECK_RETURN_ERROR(p_FmPcdCcNextEngineParams, E_NULL_POINTER);
6596     SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE);
6597     p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd;
6598     SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
6599     SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_HANDLE);
6600 
6601     if (!FmPcdLockTryLockAll(p_FmPcd))
6602     {
6603         DBG(TRACE, ("FmPcdLockTryLockAll failed"));
6604         return ERROR_CODE(E_BUSY);
6605     }
6606 
6607     err = ModifyNextEngineParamNode(p_FmPcd, p_CcNode, keyIndex,
6608                                     p_FmPcdCcNextEngineParams);
6609 
6610     FmPcdLockUnlockAll(p_FmPcd);
6611 
6612     switch(GET_ERROR_TYPE(err)
6613 )    {
6614         case E_OK:
6615         return E_OK;
6616 
6617         case E_BUSY:
6618         DBG(TRACE, ("E_BUSY error"));
6619         return ERROR_CODE(E_BUSY);
6620 
6621         default:
6622         RETURN_ERROR(MAJOR, err, NO_MSG);
6623     }
6624 }
6625 
6626 t_Error FM_PCD_MatchTableModifyMissNextEngine(
6627         t_Handle h_CcNode, t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams)
6628 {
6629     t_FmPcd *p_FmPcd;
6630     t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
6631     t_Error err = E_OK;
6632 
6633     SANITY_CHECK_RETURN_ERROR(p_FmPcdCcNextEngineParams, E_NULL_POINTER);
6634     SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE);
6635     p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd;
6636     SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
6637     SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_HANDLE);
6638 
6639     if (!FmPcdLockTryLockAll(p_FmPcd))
6640     {
6641         DBG(TRACE, ("FmPcdLockTryLockAll failed"));
6642         return ERROR_CODE(E_BUSY);
6643     }
6644 
6645     err = FmPcdCcModifyMissNextEngineParamNode(p_FmPcd, p_CcNode,
6646                                                p_FmPcdCcNextEngineParams);
6647 
6648     FmPcdLockUnlockAll(p_FmPcd);
6649 
6650     switch(GET_ERROR_TYPE(err)
6651 )    {
6652         case E_OK:
6653         return E_OK;
6654 
6655         case E_BUSY:
6656         DBG(TRACE, ("E_BUSY error"));
6657         return ERROR_CODE(E_BUSY);
6658 
6659         default:
6660         RETURN_ERROR(MAJOR, err, NO_MSG);
6661     }
6662 }
6663 
6664 t_Error FM_PCD_MatchTableModifyKeyAndNextEngine(t_Handle h_CcNode,
6665                                                 uint16_t keyIndex,
6666                                                 uint8_t keySize,
6667                                                 t_FmPcdCcKeyParams *p_KeyParams)
6668 {
6669     t_FmPcd *p_FmPcd;
6670     t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
6671     t_Error err = E_OK;
6672 
6673     SANITY_CHECK_RETURN_ERROR(p_KeyParams, E_NULL_POINTER);
6674     SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE);
6675     p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd;
6676     SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
6677     SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_HANDLE);
6678 
6679     if (!FmPcdLockTryLockAll(p_FmPcd))
6680     {
6681         DBG(TRACE, ("FmPcdLockTryLockAll failed"));
6682         return ERROR_CODE(E_BUSY);
6683     }
6684 
6685     err = FmPcdCcModifyKeyAndNextEngine(p_FmPcd, p_CcNode, keyIndex, keySize,
6686                                         p_KeyParams);
6687 
6688     FmPcdLockUnlockAll(p_FmPcd);
6689 
6690     switch(GET_ERROR_TYPE(err)
6691 )    {
6692         case E_OK:
6693         return E_OK;
6694 
6695         case E_BUSY:
6696         DBG(TRACE, ("E_BUSY error"));
6697         return ERROR_CODE(E_BUSY);
6698 
6699         default:
6700         RETURN_ERROR(MAJOR, err, NO_MSG);
6701     }
6702 }
6703 
6704 t_Error FM_PCD_MatchTableFindNRemoveKey(t_Handle h_CcNode, uint8_t keySize,
6705                                         uint8_t *p_Key, uint8_t *p_Mask)
6706 {
6707     t_FmPcd *p_FmPcd;
6708     t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
6709     uint16_t keyIndex;
6710     t_Error err;
6711 
6712     SANITY_CHECK_RETURN_ERROR(p_Key, E_NULL_POINTER);
6713     SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE);
6714     p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd;
6715     SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
6716     SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_HANDLE);
6717 
6718     if (!FmPcdLockTryLockAll(p_FmPcd))
6719     {
6720         DBG(TRACE, ("FmPcdLockTryLockAll failed"));
6721         return ERROR_CODE(E_BUSY);
6722     }
6723 
6724     err = FindKeyIndex(p_CcNode, keySize, p_Key, p_Mask, &keyIndex);
6725     if (GET_ERROR_TYPE(err) != E_OK)
6726     {
6727         FmPcdLockUnlockAll(p_FmPcd);
6728         RETURN_ERROR(
6729                 MAJOR,
6730                 err,
6731                 ("The received key and mask pair was not found in the match table of the provided node"));
6732     }
6733 
6734     err = FmPcdCcRemoveKey(p_FmPcd, p_CcNode, keyIndex);
6735 
6736     FmPcdLockUnlockAll(p_FmPcd);
6737 
6738     switch(GET_ERROR_TYPE(err)
6739 )    {
6740         case E_OK:
6741         return E_OK;
6742 
6743         case E_BUSY:
6744         DBG(TRACE, ("E_BUSY error"));
6745         return ERROR_CODE(E_BUSY);
6746 
6747         default:
6748         RETURN_ERROR(MAJOR, err, NO_MSG);
6749     }
6750 }
6751 
6752 t_Error FM_PCD_MatchTableFindNModifyNextEngine(
6753         t_Handle h_CcNode, uint8_t keySize, uint8_t *p_Key, uint8_t *p_Mask,
6754         t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams)
6755 {
6756     t_FmPcd *p_FmPcd;
6757     t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
6758     uint16_t keyIndex;
6759     t_Error err;
6760 
6761     SANITY_CHECK_RETURN_ERROR(p_Key, E_NULL_POINTER);
6762     SANITY_CHECK_RETURN_ERROR(p_FmPcdCcNextEngineParams, E_NULL_POINTER);
6763     SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE);
6764     p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd;
6765     SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
6766     SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_HANDLE);
6767 
6768     if (!FmPcdLockTryLockAll(p_FmPcd))
6769     {
6770         DBG(TRACE, ("FmPcdLockTryLockAll failed"));
6771         return ERROR_CODE(E_BUSY);
6772     }
6773 
6774     err = FindKeyIndex(p_CcNode, keySize, p_Key, p_Mask, &keyIndex);
6775     if (GET_ERROR_TYPE(err) != E_OK)
6776     {
6777         FmPcdLockUnlockAll(p_FmPcd);
6778         RETURN_ERROR(
6779                 MAJOR,
6780                 err,
6781                 ("The received key and mask pair was not found in the match table of the provided node"));
6782     }
6783 
6784     err = ModifyNextEngineParamNode(p_FmPcd, p_CcNode, keyIndex,
6785                                     p_FmPcdCcNextEngineParams);
6786 
6787     FmPcdLockUnlockAll(p_FmPcd);
6788 
6789     switch(GET_ERROR_TYPE(err)
6790 )    {
6791         case E_OK:
6792         return E_OK;
6793 
6794         case E_BUSY:
6795         DBG(TRACE, ("E_BUSY error"));
6796         return ERROR_CODE(E_BUSY);
6797 
6798         default:
6799         RETURN_ERROR(MAJOR, err, NO_MSG);
6800     }
6801 }
6802 
6803 t_Error FM_PCD_MatchTableFindNModifyKeyAndNextEngine(
6804         t_Handle h_CcNode, uint8_t keySize, uint8_t *p_Key, uint8_t *p_Mask,
6805         t_FmPcdCcKeyParams *p_KeyParams)
6806 {
6807     t_FmPcd *p_FmPcd;
6808     t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
6809     uint16_t keyIndex;
6810     t_Error err;
6811 
6812     SANITY_CHECK_RETURN_ERROR(p_Key, E_NULL_POINTER);
6813     SANITY_CHECK_RETURN_ERROR(p_KeyParams, E_NULL_POINTER);
6814     SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE);
6815     p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd;
6816     SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
6817     SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_HANDLE);
6818 
6819     if (!FmPcdLockTryLockAll(p_FmPcd))
6820     {
6821         DBG(TRACE, ("FmPcdLockTryLockAll failed"));
6822         return ERROR_CODE(E_BUSY);
6823     }
6824 
6825     err = FindKeyIndex(p_CcNode, keySize, p_Key, p_Mask, &keyIndex);
6826     if (GET_ERROR_TYPE(err) != E_OK)
6827     {
6828         FmPcdLockUnlockAll(p_FmPcd);
6829         RETURN_ERROR(
6830                 MAJOR,
6831                 err,
6832                 ("The received key and mask pair was not found in the match table of the provided node"));
6833     }
6834 
6835     err = FmPcdCcModifyKeyAndNextEngine(p_FmPcd, h_CcNode, keyIndex, keySize,
6836                                         p_KeyParams);
6837 
6838     FmPcdLockUnlockAll(p_FmPcd);
6839 
6840     switch(GET_ERROR_TYPE(err)
6841 )    {
6842         case E_OK:
6843         return E_OK;
6844 
6845         case E_BUSY:
6846         DBG(TRACE, ("E_BUSY error"));
6847         return ERROR_CODE(E_BUSY);
6848 
6849         default:
6850         RETURN_ERROR(MAJOR, err, NO_MSG);
6851     }
6852 }
6853 
6854 t_Error FM_PCD_MatchTableFindNModifyKey(t_Handle h_CcNode, uint8_t keySize,
6855                                         uint8_t *p_Key, uint8_t *p_Mask,
6856                                         uint8_t *p_NewKey, uint8_t *p_NewMask)
6857 {
6858     t_FmPcd *p_FmPcd;
6859     t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
6860     t_List h_List;
6861     uint16_t keyIndex;
6862     t_Error err;
6863 
6864     SANITY_CHECK_RETURN_ERROR(p_Key, E_NULL_POINTER);
6865     SANITY_CHECK_RETURN_ERROR(p_NewKey, E_NULL_POINTER);
6866     SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE);
6867     p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd;
6868     SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
6869     SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_HANDLE);
6870 
6871     INIT_LIST(&h_List);
6872 
6873     err = FmPcdCcNodeTreeTryLock(p_FmPcd, p_CcNode, &h_List);
6874     if (err)
6875     {
6876         DBG(TRACE, ("Node's trees lock failed"));
6877         return ERROR_CODE(E_BUSY);
6878     }
6879 
6880     err = FindKeyIndex(p_CcNode, keySize, p_Key, p_Mask, &keyIndex);
6881     if (GET_ERROR_TYPE(err) != E_OK)
6882     {
6883         FmPcdCcNodeTreeReleaseLock(p_FmPcd, &h_List);
6884         RETURN_ERROR(MAJOR, err,
6885                      ("The received key and mask pair was not found in the "
6886                      "match table of the provided node"));
6887     }
6888 
6889     err = FmPcdCcModifyKey(p_FmPcd, p_CcNode, keyIndex, keySize, p_NewKey,
6890                            p_NewMask);
6891 
6892     FmPcdCcNodeTreeReleaseLock(p_FmPcd, &h_List);
6893 
6894     switch(GET_ERROR_TYPE(err)
6895 )    {
6896         case E_OK:
6897         return E_OK;
6898 
6899         case E_BUSY:
6900         DBG(TRACE, ("E_BUSY error"));
6901         return ERROR_CODE(E_BUSY);
6902 
6903         default:
6904         RETURN_ERROR(MAJOR, err, NO_MSG);
6905     }
6906 }
6907 
6908 t_Error FM_PCD_MatchTableGetNextEngine(
6909         t_Handle h_CcNode, uint16_t keyIndex,
6910         t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams)
6911 {
6912     t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
6913 
6914     SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE);
6915     SANITY_CHECK_RETURN_ERROR(p_FmPcdCcNextEngineParams, E_NULL_POINTER);
6916 
6917     if (keyIndex >= p_CcNode->numOfKeys)
6918         RETURN_ERROR(MAJOR, E_INVALID_STATE,
6919                      ("keyIndex exceeds current number of keys"));
6920 
6921     if (keyIndex > (FM_PCD_MAX_NUM_OF_KEYS - 1))
6922         RETURN_ERROR(
6923                 MAJOR,
6924                 E_INVALID_VALUE,
6925                 ("keyIndex can not be larger than %d", (FM_PCD_MAX_NUM_OF_KEYS - 1)));
6926 
6927     memcpy(p_FmPcdCcNextEngineParams,
6928            &p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams,
6929            sizeof(t_FmPcdCcNextEngineParams));
6930 
6931     return E_OK;
6932 }
6933 
6934 
6935 uint32_t FM_PCD_MatchTableGetKeyCounter(t_Handle h_CcNode, uint16_t keyIndex)
6936 {
6937     t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
6938     uint32_t *p_StatsCounters, frameCount;
6939     uint32_t intFlags;
6940 
6941     SANITY_CHECK_RETURN_VALUE(p_CcNode, E_INVALID_HANDLE, 0);
6942 
6943     if (p_CcNode->statisticsMode == e_FM_PCD_CC_STATS_MODE_NONE)
6944     {
6945         REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Statistics were not enabled for this match table"));
6946         return 0;
6947     }
6948 
6949     if ((p_CcNode->statisticsMode != e_FM_PCD_CC_STATS_MODE_FRAME)
6950             && (p_CcNode->statisticsMode
6951                     != e_FM_PCD_CC_STATS_MODE_BYTE_AND_FRAME))
6952     {
6953         REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Frame count is not supported in the statistics mode of this match table"));
6954         return 0;
6955     }
6956 
6957     intFlags = XX_LockIntrSpinlock(p_CcNode->h_Spinlock);
6958 
6959     if (keyIndex >= p_CcNode->numOfKeys)
6960     {
6961         XX_UnlockIntrSpinlock(p_CcNode->h_Spinlock, intFlags);
6962         REPORT_ERROR(MAJOR, E_INVALID_STATE, ("The provided keyIndex exceeds the number of keys in this match table"));
6963         return 0;
6964     }
6965 
6966     if (!p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj)
6967     {
6968         XX_UnlockIntrSpinlock(p_CcNode->h_Spinlock, intFlags);
6969         REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Statistics were not enabled for this key"));
6970         return 0;
6971     }
6972 
6973     p_StatsCounters =
6974             p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj->h_StatsCounters;
6975     ASSERT_COND(p_StatsCounters);
6976 
6977     /* The first counter is byte counter, so we need to advance to the next counter */
6978     frameCount = GET_UINT32(*(uint32_t *)(PTR_MOVE(p_StatsCounters,
6979                             FM_PCD_CC_STATS_COUNTER_SIZE)));
6980 
6981     XX_UnlockIntrSpinlock(p_CcNode->h_Spinlock, intFlags);
6982 
6983     return frameCount;
6984 }
6985 
6986 t_Error FM_PCD_MatchTableGetKeyStatistics(
6987         t_Handle h_CcNode, uint16_t keyIndex,
6988         t_FmPcdCcKeyStatistics *p_KeyStatistics)
6989 {
6990     t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
6991     uint32_t intFlags;
6992     t_Error err;
6993 
6994     SANITY_CHECK_RETURN_ERROR(h_CcNode, E_INVALID_HANDLE);
6995     SANITY_CHECK_RETURN_ERROR(p_KeyStatistics, E_NULL_POINTER);
6996 
6997     intFlags = XX_LockIntrSpinlock(p_CcNode->h_Spinlock);
6998 
6999     if (keyIndex >= p_CcNode->numOfKeys)
7000         RETURN_ERROR(
7001                 MAJOR,
7002                 E_INVALID_STATE,
7003                 ("The provided keyIndex exceeds the number of keys in this match table"));
7004 
7005     err = MatchTableGetKeyStatistics(p_CcNode, keyIndex, p_KeyStatistics);
7006 
7007     XX_UnlockIntrSpinlock(p_CcNode->h_Spinlock, intFlags);
7008 
7009     if (err != E_OK)
7010         RETURN_ERROR(MAJOR, err, NO_MSG);
7011 
7012     return E_OK;
7013 }
7014 
7015 t_Error FM_PCD_MatchTableGetMissStatistics(
7016         t_Handle h_CcNode, t_FmPcdCcKeyStatistics *p_MissStatistics)
7017 {
7018     t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
7019     uint32_t intFlags;
7020     t_Error err;
7021 
7022     SANITY_CHECK_RETURN_ERROR(h_CcNode, E_INVALID_HANDLE);
7023     SANITY_CHECK_RETURN_ERROR(p_MissStatistics, E_NULL_POINTER);
7024 
7025     intFlags = XX_LockIntrSpinlock(p_CcNode->h_Spinlock);
7026 
7027     err = MatchTableGetKeyStatistics(p_CcNode, p_CcNode->numOfKeys,
7028                                      p_MissStatistics);
7029 
7030     XX_UnlockIntrSpinlock(p_CcNode->h_Spinlock, intFlags);
7031 
7032     if (err != E_OK)
7033         RETURN_ERROR(MAJOR, err, NO_MSG);
7034 
7035     return E_OK;
7036 }
7037 
7038 t_Error FM_PCD_MatchTableFindNGetKeyStatistics(
7039         t_Handle h_CcNode, uint8_t keySize, uint8_t *p_Key, uint8_t *p_Mask,
7040         t_FmPcdCcKeyStatistics *p_KeyStatistics)
7041 {
7042     t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
7043     uint16_t keyIndex;
7044     uint32_t intFlags;
7045     t_Error err;
7046 
7047     SANITY_CHECK_RETURN_ERROR(p_Key, E_NULL_POINTER);
7048     SANITY_CHECK_RETURN_ERROR(p_KeyStatistics, E_NULL_POINTER);
7049 
7050     intFlags = XX_LockIntrSpinlock(p_CcNode->h_Spinlock);
7051 
7052     err = FindKeyIndex(p_CcNode, keySize, p_Key, p_Mask, &keyIndex);
7053     if (GET_ERROR_TYPE(err) != E_OK)
7054     {
7055         XX_UnlockIntrSpinlock(p_CcNode->h_Spinlock, intFlags);
7056         RETURN_ERROR(MAJOR, err,
7057                      ("The received key and mask pair was not found in the "
7058                      "match table of the provided node"));
7059     }
7060 
7061     ASSERT_COND(keyIndex < p_CcNode->numOfKeys);
7062 
7063     err = MatchTableGetKeyStatistics(p_CcNode, keyIndex, p_KeyStatistics);
7064 
7065     XX_UnlockIntrSpinlock(p_CcNode->h_Spinlock, intFlags);
7066 
7067     if (err != E_OK)
7068         RETURN_ERROR(MAJOR, err, NO_MSG);
7069 
7070     return E_OK;
7071 }
7072 
7073 t_Error FM_PCD_MatchTableGetIndexedHashBucket(t_Handle h_CcNode,
7074                                               uint8_t keySize, uint8_t *p_Key,
7075                                               uint8_t hashShift,
7076                                               t_Handle *p_CcNodeBucketHandle,
7077                                               uint8_t *p_BucketIndex,
7078                                               uint16_t *p_LastIndex)
7079 {
7080     t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
7081     uint16_t glblMask;
7082     uint64_t crc64 = 0;
7083 
7084     SANITY_CHECK_RETURN_ERROR(h_CcNode, E_INVALID_HANDLE);
7085     SANITY_CHECK_RETURN_ERROR(
7086             p_CcNode->parseCode == CC_PC_GENERIC_IC_HASH_INDEXED,
7087             E_INVALID_STATE);
7088     SANITY_CHECK_RETURN_ERROR(p_Key, E_NULL_POINTER);
7089     SANITY_CHECK_RETURN_ERROR(p_CcNodeBucketHandle, E_NULL_POINTER);
7090 
7091     memcpy(&glblMask, PTR_MOVE(p_CcNode->p_GlblMask, 2), 2);
7092     glblMask = be16toh(glblMask);
7093 
7094     crc64 = crc64_init();
7095     crc64 = crc64_compute(p_Key, keySize, crc64);
7096     crc64 >>= hashShift;
7097 
7098     *p_BucketIndex = (uint8_t)(((crc64 >> (8 * (6 - p_CcNode->userOffset)))
7099             & glblMask) >> 4);
7100     if (*p_BucketIndex >= p_CcNode->numOfKeys)
7101         RETURN_ERROR(MINOR, E_NOT_IN_RANGE, ("bucket index!"));
7102 
7103     *p_CcNodeBucketHandle =
7104             p_CcNode->keyAndNextEngineParams[*p_BucketIndex].nextEngineParams.params.ccParams.h_CcNode;
7105     if (!*p_CcNodeBucketHandle)
7106         RETURN_ERROR(MINOR, E_NOT_FOUND, ("bucket!"));
7107 
7108     *p_LastIndex = ((t_FmPcdCcNode *)*p_CcNodeBucketHandle)->numOfKeys;
7109 
7110     return E_OK;
7111 }
7112 
7113 t_Handle FM_PCD_HashTableSet(t_Handle h_FmPcd, t_FmPcdHashTableParams *p_Param)
7114 {
7115     t_FmPcdCcNode *p_CcNodeHashTbl;
7116     t_FmPcdCcNodeParams *p_IndxHashCcNodeParam, *p_ExactMatchCcNodeParam;
7117     t_FmPcdCcNode *p_CcNode;
7118     t_Handle h_MissStatsCounters = NULL;
7119     t_FmPcdCcKeyParams *p_HashKeyParams;
7120     int i;
7121     uint16_t numOfSets, numOfWays, countMask, onesCount = 0;
7122     bool statsEnForMiss = FALSE;
7123     t_Error err;
7124 
7125     SANITY_CHECK_RETURN_VALUE(h_FmPcd, E_INVALID_HANDLE, NULL);
7126     SANITY_CHECK_RETURN_VALUE(p_Param, E_NULL_POINTER, NULL);
7127 
7128     if (p_Param->maxNumOfKeys == 0)
7129     {
7130         REPORT_ERROR(MINOR, E_INVALID_VALUE, ("Max number of keys must be higher then 0"));
7131         return NULL;
7132     }
7133 
7134     if (p_Param->hashResMask == 0)
7135     {
7136         REPORT_ERROR(MINOR, E_INVALID_VALUE, ("Hash result mask must differ from 0"));
7137         return NULL;
7138     }
7139 
7140     /*Fix: QorIQ SDK / QSDK-2131*/
7141     if (p_Param->ccNextEngineParamsForMiss.nextEngine == e_FM_PCD_INVALID)
7142     {
7143         REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Next PCD Engine for on-miss entry is invalid. On-miss entry is always required. You can use e_FM_PCD_DONE."));
7144         return NULL;
7145     }
7146 
7147 #if (DPAA_VERSION >= 11)
7148     if (p_Param->statisticsMode == e_FM_PCD_CC_STATS_MODE_RMON)
7149     {
7150         REPORT_ERROR(MAJOR, E_INVALID_VALUE,
7151                 ("RMON statistics mode is not supported for hash table"));
7152         return NULL;
7153     }
7154 #endif /* (DPAA_VERSION >= 11) */
7155 
7156     p_ExactMatchCcNodeParam = (t_FmPcdCcNodeParams*)XX_Malloc(
7157             sizeof(t_FmPcdCcNodeParams));
7158     if (!p_ExactMatchCcNodeParam)
7159     {
7160         REPORT_ERROR(MAJOR, E_NO_MEMORY, ("p_ExactMatchCcNodeParam"));
7161         return NULL;
7162     }
7163     memset(p_ExactMatchCcNodeParam, 0, sizeof(t_FmPcdCcNodeParams));
7164 
7165     p_IndxHashCcNodeParam = (t_FmPcdCcNodeParams*)XX_Malloc(
7166             sizeof(t_FmPcdCcNodeParams));
7167     if (!p_IndxHashCcNodeParam)
7168     {
7169         XX_Free(p_ExactMatchCcNodeParam);
7170         REPORT_ERROR(MAJOR, E_NO_MEMORY, ("p_IndxHashCcNodeParam"));
7171         return NULL;
7172     }
7173     memset(p_IndxHashCcNodeParam, 0, sizeof(t_FmPcdCcNodeParams));
7174 
7175     /* Calculate number of sets and number of ways of the hash table */
7176     countMask = (uint16_t)(p_Param->hashResMask >> 4);
7177     while (countMask)
7178     {
7179         onesCount++;
7180         countMask = (uint16_t)(countMask >> 1);
7181     }
7182 
7183     numOfSets = (uint16_t)(1 << onesCount);
7184     numOfWays = (uint16_t)DIV_CEIL(p_Param->maxNumOfKeys, numOfSets);
7185 
7186     if (p_Param->maxNumOfKeys % numOfSets)
7187         DBG(INFO, ("'maxNumOfKeys' is not a multiple of hash number of ways, so number of ways will be rounded up"));
7188 
7189     if ((p_Param->statisticsMode == e_FM_PCD_CC_STATS_MODE_FRAME)
7190             || (p_Param->statisticsMode == e_FM_PCD_CC_STATS_MODE_BYTE_AND_FRAME))
7191     {
7192         /* Allocating a statistics counters table that will be used by all
7193          'miss' entries of the hash table */
7194         h_MissStatsCounters = (t_Handle)FM_MURAM_AllocMem(
7195                 FmPcdGetMuramHandle(h_FmPcd), 2 * FM_PCD_CC_STATS_COUNTER_SIZE,
7196                 FM_PCD_CC_AD_TABLE_ALIGN);
7197         if (!h_MissStatsCounters)
7198         {
7199             REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for statistics table for hash miss"));
7200             XX_Free(p_IndxHashCcNodeParam);
7201             XX_Free(p_ExactMatchCcNodeParam);
7202             return NULL;
7203         }
7204         memset(h_MissStatsCounters, 0, (2 * FM_PCD_CC_STATS_COUNTER_SIZE));
7205 
7206         /* Always enable statistics for 'miss', so that a statistics AD will be
7207          initialized from the start. We'll store the requested 'statistics enable'
7208          value and it will be used when statistics are read by the user. */
7209         statsEnForMiss = p_Param->ccNextEngineParamsForMiss.statisticsEn;
7210         p_Param->ccNextEngineParamsForMiss.statisticsEn = TRUE;
7211     }
7212 
7213     /* Building exact-match node params, will be used to create the hash buckets */
7214     p_ExactMatchCcNodeParam->extractCcParams.type = e_FM_PCD_EXTRACT_NON_HDR;
7215 
7216     p_ExactMatchCcNodeParam->extractCcParams.extractNonHdr.src =
7217             e_FM_PCD_EXTRACT_FROM_KEY;
7218     p_ExactMatchCcNodeParam->extractCcParams.extractNonHdr.action =
7219             e_FM_PCD_ACTION_EXACT_MATCH;
7220     p_ExactMatchCcNodeParam->extractCcParams.extractNonHdr.offset = 0;
7221     p_ExactMatchCcNodeParam->extractCcParams.extractNonHdr.size =
7222             p_Param->matchKeySize;
7223 
7224     p_ExactMatchCcNodeParam->keysParams.maxNumOfKeys = numOfWays;
7225     p_ExactMatchCcNodeParam->keysParams.maskSupport = FALSE;
7226     p_ExactMatchCcNodeParam->keysParams.statisticsMode =
7227             p_Param->statisticsMode;
7228     p_ExactMatchCcNodeParam->keysParams.numOfKeys = 0;
7229     p_ExactMatchCcNodeParam->keysParams.keySize = p_Param->matchKeySize;
7230     p_ExactMatchCcNodeParam->keysParams.ccNextEngineParamsForMiss =
7231             p_Param->ccNextEngineParamsForMiss;
7232 
7233     p_HashKeyParams = p_IndxHashCcNodeParam->keysParams.keyParams;
7234 
7235     for (i = 0; i < numOfSets; i++)
7236     {
7237         /* Each exact-match node will be marked as a 'bucket' and provided with
7238            a pointer to statistics counters, to be used for 'miss' entry
7239            statistics */
7240         p_CcNode = (t_FmPcdCcNode *)XX_Malloc(sizeof(t_FmPcdCcNode));
7241         if (!p_CcNode)
7242             break;
7243         memset(p_CcNode, 0, sizeof(t_FmPcdCcNode));
7244 
7245         p_CcNode->isHashBucket = TRUE;
7246         p_CcNode->h_MissStatsCounters = h_MissStatsCounters;
7247 
7248         err = MatchTableSet(h_FmPcd, p_CcNode, p_ExactMatchCcNodeParam);
7249         if (err)
7250             break;
7251 
7252         p_HashKeyParams[i].ccNextEngineParams.nextEngine = e_FM_PCD_CC;
7253         p_HashKeyParams[i].ccNextEngineParams.statisticsEn = FALSE;
7254         p_HashKeyParams[i].ccNextEngineParams.params.ccParams.h_CcNode =
7255                 p_CcNode;
7256     }
7257 
7258     if (i < numOfSets)
7259     {
7260         for (i = i - 1; i >= 0; i--)
7261             FM_PCD_MatchTableDelete(
7262                     p_HashKeyParams[i].ccNextEngineParams.params.ccParams.h_CcNode);
7263 
7264         FM_MURAM_FreeMem(FmPcdGetMuramHandle(h_FmPcd), h_MissStatsCounters);
7265 
7266         REPORT_ERROR(MAJOR, E_NULL_POINTER, NO_MSG);
7267         XX_Free(p_IndxHashCcNodeParam);
7268         XX_Free(p_ExactMatchCcNodeParam);
7269         return NULL;
7270     }
7271 
7272     /* Creating indexed-hash CC node */
7273     p_IndxHashCcNodeParam->extractCcParams.type = e_FM_PCD_EXTRACT_NON_HDR;
7274     p_IndxHashCcNodeParam->extractCcParams.extractNonHdr.src =
7275             e_FM_PCD_EXTRACT_FROM_HASH;
7276     p_IndxHashCcNodeParam->extractCcParams.extractNonHdr.action =
7277             e_FM_PCD_ACTION_INDEXED_LOOKUP;
7278     p_IndxHashCcNodeParam->extractCcParams.extractNonHdr.icIndxMask =
7279             p_Param->hashResMask;
7280     p_IndxHashCcNodeParam->extractCcParams.extractNonHdr.offset =
7281             p_Param->hashShift;
7282     p_IndxHashCcNodeParam->extractCcParams.extractNonHdr.size = 2;
7283 
7284     p_IndxHashCcNodeParam->keysParams.maxNumOfKeys = numOfSets;
7285     p_IndxHashCcNodeParam->keysParams.maskSupport = FALSE;
7286     p_IndxHashCcNodeParam->keysParams.statisticsMode =
7287             e_FM_PCD_CC_STATS_MODE_NONE;
7288     /* Number of keys of this node is number of sets of the hash */
7289     p_IndxHashCcNodeParam->keysParams.numOfKeys = numOfSets;
7290     p_IndxHashCcNodeParam->keysParams.keySize = 2;
7291 
7292     p_CcNodeHashTbl = FM_PCD_MatchTableSet(h_FmPcd, p_IndxHashCcNodeParam);
7293 
7294     if (p_CcNodeHashTbl)
7295     {
7296         p_CcNodeHashTbl->kgHashShift = p_Param->kgHashShift;
7297 
7298         /* Storing the allocated counters for buckets 'miss' in the hash table
7299          and if statistics for miss were enabled. */
7300         p_CcNodeHashTbl->h_MissStatsCounters = h_MissStatsCounters;
7301         p_CcNodeHashTbl->statsEnForMiss = statsEnForMiss;
7302     }
7303 
7304     XX_Free(p_IndxHashCcNodeParam);
7305     XX_Free(p_ExactMatchCcNodeParam);
7306 
7307     return p_CcNodeHashTbl;
7308 }
7309 
7310 t_Error FM_PCD_HashTableDelete(t_Handle h_HashTbl)
7311 {
7312     t_FmPcdCcNode *p_HashTbl = (t_FmPcdCcNode *)h_HashTbl;
7313     t_Handle h_FmPcd;
7314     t_Handle *p_HashBuckets, h_MissStatsCounters;
7315     uint16_t i, numOfBuckets;
7316     t_Error err;
7317 
7318     SANITY_CHECK_RETURN_ERROR(p_HashTbl, E_INVALID_HANDLE);
7319 
7320     /* Store all hash buckets before the hash is freed */
7321     numOfBuckets = p_HashTbl->numOfKeys;
7322 
7323     p_HashBuckets = (t_Handle *)XX_Malloc(numOfBuckets * sizeof(t_Handle));
7324     if (!p_HashBuckets)
7325         RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG);
7326 
7327     for (i = 0; i < numOfBuckets; i++)
7328         p_HashBuckets[i] =
7329                 p_HashTbl->keyAndNextEngineParams[i].nextEngineParams.params.ccParams.h_CcNode;
7330 
7331     h_FmPcd = p_HashTbl->h_FmPcd;
7332     h_MissStatsCounters = p_HashTbl->h_MissStatsCounters;
7333 
7334     /* Free the hash */
7335     err = FM_PCD_MatchTableDelete(p_HashTbl);
7336 
7337     /* Free each hash bucket */
7338     for (i = 0; i < numOfBuckets; i++)
7339         err |= FM_PCD_MatchTableDelete(p_HashBuckets[i]);
7340 
7341     XX_Free(p_HashBuckets);
7342 
7343     /* Free statistics counters for 'miss', if these were allocated */
7344     if (h_MissStatsCounters)
7345         FM_MURAM_FreeMem(FmPcdGetMuramHandle(h_FmPcd), h_MissStatsCounters);
7346 
7347     if (err)
7348         RETURN_ERROR(MAJOR, err, NO_MSG);
7349 
7350     return E_OK;
7351 }
7352 
7353 t_Error FM_PCD_HashTableAddKey(t_Handle h_HashTbl, uint8_t keySize,
7354                                t_FmPcdCcKeyParams *p_KeyParams)
7355 {
7356     t_FmPcdCcNode *p_HashTbl = (t_FmPcdCcNode *)h_HashTbl;
7357     t_Handle h_HashBucket;
7358     uint8_t bucketIndex;
7359     uint16_t lastIndex;
7360     t_Error err;
7361 
7362     SANITY_CHECK_RETURN_ERROR(p_HashTbl, E_INVALID_HANDLE);
7363     SANITY_CHECK_RETURN_ERROR(p_KeyParams, E_NULL_POINTER);
7364     SANITY_CHECK_RETURN_ERROR(p_KeyParams->p_Key, E_NULL_POINTER);
7365 
7366     if (p_KeyParams->p_Mask)
7367         RETURN_ERROR(MAJOR, E_INVALID_VALUE,
7368                      ("Keys masks not supported for hash table"));
7369 
7370     err = FM_PCD_MatchTableGetIndexedHashBucket(p_HashTbl, keySize,
7371                                                 p_KeyParams->p_Key,
7372                                                 p_HashTbl->kgHashShift,
7373                                                 &h_HashBucket, &bucketIndex,
7374                                                 &lastIndex);
7375     if (err)
7376         RETURN_ERROR(MAJOR, err, NO_MSG);
7377 
7378     return FM_PCD_MatchTableAddKey(h_HashBucket, FM_PCD_LAST_KEY_INDEX, keySize,
7379                                    p_KeyParams);
7380 }
7381 
7382 t_Error FM_PCD_HashTableRemoveKey(t_Handle h_HashTbl, uint8_t keySize,
7383                                   uint8_t *p_Key)
7384 {
7385     t_FmPcdCcNode *p_HashTbl = (t_FmPcdCcNode *)h_HashTbl;
7386     t_Handle h_HashBucket;
7387     uint8_t bucketIndex;
7388     uint16_t lastIndex;
7389     t_Error err;
7390 
7391     SANITY_CHECK_RETURN_ERROR(p_HashTbl, E_INVALID_HANDLE);
7392     SANITY_CHECK_RETURN_ERROR(p_Key, E_NULL_POINTER);
7393 
7394     err = FM_PCD_MatchTableGetIndexedHashBucket(p_HashTbl, keySize, p_Key,
7395                                                 p_HashTbl->kgHashShift,
7396                                                 &h_HashBucket, &bucketIndex,
7397                                                 &lastIndex);
7398     if (err)
7399         RETURN_ERROR(MAJOR, err, NO_MSG);
7400 
7401     return FM_PCD_MatchTableFindNRemoveKey(h_HashBucket, keySize, p_Key, NULL);
7402 }
7403 
7404 t_Error FM_PCD_HashTableModifyNextEngine(
7405         t_Handle h_HashTbl, uint8_t keySize, uint8_t *p_Key,
7406         t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams)
7407 {
7408     t_FmPcdCcNode *p_HashTbl = (t_FmPcdCcNode *)h_HashTbl;
7409     t_Handle h_HashBucket;
7410     uint8_t bucketIndex;
7411     uint16_t lastIndex;
7412     t_Error err;
7413 
7414     SANITY_CHECK_RETURN_ERROR(p_HashTbl, E_INVALID_HANDLE);
7415     SANITY_CHECK_RETURN_ERROR(p_Key, E_NULL_POINTER);
7416     SANITY_CHECK_RETURN_ERROR(p_FmPcdCcNextEngineParams, E_NULL_POINTER);
7417 
7418     err = FM_PCD_MatchTableGetIndexedHashBucket(p_HashTbl, keySize, p_Key,
7419                                                 p_HashTbl->kgHashShift,
7420                                                 &h_HashBucket, &bucketIndex,
7421                                                 &lastIndex);
7422     if (err)
7423         RETURN_ERROR(MAJOR, err, NO_MSG);
7424 
7425     return FM_PCD_MatchTableFindNModifyNextEngine(h_HashBucket, keySize, p_Key,
7426                                                   NULL,
7427                                                   p_FmPcdCcNextEngineParams);
7428 }
7429 
7430 t_Error FM_PCD_HashTableModifyMissNextEngine(
7431         t_Handle h_HashTbl,
7432         t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams)
7433 {
7434     t_FmPcdCcNode *p_HashTbl = (t_FmPcdCcNode *)h_HashTbl;
7435     t_Handle h_HashBucket;
7436     uint8_t i;
7437     bool nullifyMissStats = FALSE;
7438     t_Error err;
7439 
7440     SANITY_CHECK_RETURN_ERROR(h_HashTbl, E_INVALID_HANDLE);
7441     SANITY_CHECK_RETURN_ERROR(p_FmPcdCcNextEngineParams, E_NULL_POINTER);
7442 
7443     if ((!p_HashTbl->h_MissStatsCounters)
7444             && (p_FmPcdCcNextEngineParams->statisticsEn))
7445         RETURN_ERROR(
7446                 MAJOR,
7447                 E_CONFLICT,
7448                 ("Statistics are requested for a key, but statistics mode was set"
7449                 "to 'NONE' upon initialization"));
7450 
7451     if (p_HashTbl->h_MissStatsCounters)
7452     {
7453         if ((!p_HashTbl->statsEnForMiss)
7454                 && (p_FmPcdCcNextEngineParams->statisticsEn))
7455             nullifyMissStats = TRUE;
7456 
7457         if ((p_HashTbl->statsEnForMiss)
7458                 && (!p_FmPcdCcNextEngineParams->statisticsEn))
7459         {
7460             p_HashTbl->statsEnForMiss = FALSE;
7461             p_FmPcdCcNextEngineParams->statisticsEn = TRUE;
7462         }
7463     }
7464 
7465     for (i = 0; i < p_HashTbl->numOfKeys; i++)
7466     {
7467         h_HashBucket =
7468                 p_HashTbl->keyAndNextEngineParams[i].nextEngineParams.params.ccParams.h_CcNode;
7469 
7470         err = FM_PCD_MatchTableModifyMissNextEngine(h_HashBucket,
7471                                                     p_FmPcdCcNextEngineParams);
7472         if (err)
7473             RETURN_ERROR(MAJOR, err, NO_MSG);
7474     }
7475 
7476     if (nullifyMissStats)
7477     {
7478         memset(p_HashTbl->h_MissStatsCounters, 0,
7479                (2 * FM_PCD_CC_STATS_COUNTER_SIZE));
7480         memset(p_HashTbl->h_MissStatsCounters, 0,
7481                (2 * FM_PCD_CC_STATS_COUNTER_SIZE));
7482         p_HashTbl->statsEnForMiss = TRUE;
7483     }
7484 
7485     return E_OK;
7486 }
7487 
7488 
7489 t_Error FM_PCD_HashTableGetMissNextEngine(
7490         t_Handle h_HashTbl,
7491         t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams)
7492 {
7493     t_FmPcdCcNode *p_HashTbl = (t_FmPcdCcNode *)h_HashTbl;
7494     t_FmPcdCcNode *p_HashBucket;
7495 
7496     SANITY_CHECK_RETURN_ERROR(p_HashTbl, E_INVALID_HANDLE);
7497 
7498     /* Miss next engine of each bucket was initialized with the next engine of the hash table */
7499     p_HashBucket =
7500             p_HashTbl->keyAndNextEngineParams[0].nextEngineParams.params.ccParams.h_CcNode;
7501 
7502     memcpy(p_FmPcdCcNextEngineParams,
7503            &p_HashBucket->keyAndNextEngineParams[p_HashBucket->numOfKeys].nextEngineParams,
7504            sizeof(t_FmPcdCcNextEngineParams));
7505 
7506     return E_OK;
7507 }
7508 
7509 t_Error FM_PCD_HashTableFindNGetKeyStatistics(
7510         t_Handle h_HashTbl, uint8_t keySize, uint8_t *p_Key,
7511         t_FmPcdCcKeyStatistics *p_KeyStatistics)
7512 {
7513     t_FmPcdCcNode *p_HashTbl = (t_FmPcdCcNode *)h_HashTbl;
7514     t_Handle h_HashBucket;
7515     uint8_t bucketIndex;
7516     uint16_t lastIndex;
7517     t_Error err;
7518 
7519     SANITY_CHECK_RETURN_ERROR(p_HashTbl, E_INVALID_HANDLE);
7520     SANITY_CHECK_RETURN_ERROR(p_Key, E_NULL_POINTER);
7521     SANITY_CHECK_RETURN_ERROR(p_KeyStatistics, E_NULL_POINTER);
7522 
7523     err = FM_PCD_MatchTableGetIndexedHashBucket(p_HashTbl, keySize, p_Key,
7524                                                 p_HashTbl->kgHashShift,
7525                                                 &h_HashBucket, &bucketIndex,
7526                                                 &lastIndex);
7527     if (err)
7528         RETURN_ERROR(MAJOR, err, NO_MSG);
7529 
7530     return FM_PCD_MatchTableFindNGetKeyStatistics(h_HashBucket, keySize, p_Key,
7531                                                   NULL, p_KeyStatistics);
7532 }
7533 
7534 t_Error FM_PCD_HashTableGetMissStatistics(
7535         t_Handle h_HashTbl, t_FmPcdCcKeyStatistics *p_MissStatistics)
7536 {
7537     t_FmPcdCcNode *p_HashTbl = (t_FmPcdCcNode *)h_HashTbl;
7538     t_Handle h_HashBucket;
7539 
7540     SANITY_CHECK_RETURN_ERROR(p_HashTbl, E_INVALID_HANDLE);
7541     SANITY_CHECK_RETURN_ERROR(p_MissStatistics, E_NULL_POINTER);
7542 
7543     if (!p_HashTbl->statsEnForMiss)
7544         RETURN_ERROR(MAJOR, E_INVALID_STATE,
7545                      ("Statistics were not enabled for miss"));
7546 
7547     h_HashBucket =
7548             p_HashTbl->keyAndNextEngineParams[0].nextEngineParams.params.ccParams.h_CcNode;
7549 
7550     return FM_PCD_MatchTableGetMissStatistics(h_HashBucket, p_MissStatistics);
7551 }
7552