diff options
25 files changed, 1147 insertions, 469 deletions
diff --git a/arch/powerpc/boot/dts/fsl/b4420si-post.dtsi b/arch/powerpc/boot/dts/fsl/b4420si-post.dtsi index f039c52..0198d22 100644 --- a/arch/powerpc/boot/dts/fsl/b4420si-post.dtsi +++ b/arch/powerpc/boot/dts/fsl/b4420si-post.dtsi @@ -318,5 +318,13 @@ L2: l2-cache-controller@c20000 { compatible = "fsl,b4420-l2-cache-controller"; + reg = <0xc20000 0x1000>; + next-level-cache = <&cpc>; + }; + + L2_2: l2-cache-controller@c60000 { + compatible = "fsl,b4420-l2-cache-controller"; + reg = <0xc60000 0x1000>; + next-level-cache = <&cpc>; }; }; diff --git a/arch/powerpc/boot/dts/fsl/b4420si-pre.dtsi b/arch/powerpc/boot/dts/fsl/b4420si-pre.dtsi index d56ac22..ee7263b 100644 --- a/arch/powerpc/boot/dts/fsl/b4420si-pre.dtsi +++ b/arch/powerpc/boot/dts/fsl/b4420si-pre.dtsi @@ -90,4 +90,27 @@ next-level-cache = <&L2>; }; }; + + dsp-clusters { + #address-cells = <1>; + #size-cells = <0>; + + dsp-cluster0 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,sc3900-cluster"; + reg = <0>; + + dsp0: dsp@0 { + compatible = "fsl,sc3900"; + reg = <0>; + next-level-cache = <&L2_2>; + }; + dsp1: dsp@1 { + compatible = "fsl,sc3900"; + reg = <1>; + next-level-cache = <&L2_2>; + }; + }; + }; }; diff --git a/arch/powerpc/boot/dts/fsl/b4860si-post.dtsi b/arch/powerpc/boot/dts/fsl/b4860si-post.dtsi index a166d1c..4d35d4f 100644 --- a/arch/powerpc/boot/dts/fsl/b4860si-post.dtsi +++ b/arch/powerpc/boot/dts/fsl/b4860si-post.dtsi @@ -376,7 +376,7 @@ &rio { compatible = "fsl,srio"; - interrupts = <16 2 1 11>; + interrupts = <16 2 1 20>; #address-cells = <2>; #size-cells = <2>; fsl,iommu-parent = <&pamu0>; @@ -516,10 +516,31 @@ L2: l2-cache-controller@c20000 { compatible = "fsl,b4860-l2-cache-controller"; + reg = <0xc20000 0x1000>; + next-level-cache = <&cpc>; + }; + + L2_2: l2-cache-controller@c60000 { + compatible = "fsl,b4860-l2-cache-controller"; + reg = <0xc60000 0x1000>; + next-level-cache = <&cpc>; + }; + + L2_3: l2-cache-controller@ca0000 { + compatible = "fsl,b4860-l2-cache-controller"; + reg = <0xca0000 0x1000>; + next-level-cache = <&cpc>; + }; + + L2_4: l2-cache-controller@ce0000 { + compatible = "fsl,b4860-l2-cache-controller"; + reg = <0xce0000 0x1000>; + next-level-cache = <&cpc>; }; /include/ "qoriq-rman-0.dtsi" rman: rman@1e0000 { fsl,qman-channels-id = <0x820 0x821>; + interrupts = <16 2 1 20>; }; }; diff --git a/arch/powerpc/boot/dts/fsl/b4860si-pre.dtsi b/arch/powerpc/boot/dts/fsl/b4860si-pre.dtsi index 6c85eca..e344468 100644 --- a/arch/powerpc/boot/dts/fsl/b4860si-pre.dtsi +++ b/arch/powerpc/boot/dts/fsl/b4860si-pre.dtsi @@ -105,4 +105,63 @@ next-level-cache = <&L2>; }; }; + + dsp-clusters { + #address-cells = <1>; + #size-cells = <0>; + + dsp-cluster0 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,sc3900-cluster"; + reg = <0>; + + dsp0: dsp@0 { + compatible = "fsl,sc3900"; + reg = <0>; + next-level-cache = <&L2_2>; + }; + dsp1: dsp@1 { + compatible = "fsl,sc3900"; + reg = <1>; + next-level-cache = <&L2_2>; + }; + }; + + dsp-cluster1 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,sc3900-cluster"; + reg = <1>; + + dsp2: dsp@2 { + compatible = "fsl,sc3900"; + reg = <2>; + next-level-cache = <&L2_3>; + }; + dsp3: dsp@3 { + compatible = "fsl,sc3900"; + reg = <3>; + next-level-cache = <&L2_3>; + }; + }; + + dsp-cluster2 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,sc3900-cluster"; + reg = <2>; + + dsp4: dsp@4 { + compatible = "fsl,sc3900"; + reg = <4>; + next-level-cache = <&L2_4>; + }; + dsp5: dsp@5 { + compatible = "fsl,sc3900"; + reg = <5>; + next-level-cache = <&L2_4>; + }; + }; + }; }; diff --git a/arch/powerpc/boot/dts/fsl/b4si-post.dtsi b/arch/powerpc/boot/dts/fsl/b4si-post.dtsi index 6e2781e..55ced62 100644 --- a/arch/powerpc/boot/dts/fsl/b4si-post.dtsi +++ b/arch/powerpc/boot/dts/fsl/b4si-post.dtsi @@ -329,9 +329,4 @@ /include/ "qoriq-duart-1.dtsi" /include/ "qoriq-sec5.3-0.dtsi" - L2: l2-cache-controller@c20000 { - compatible = "fsl,b4-l2-cache-controller"; - reg = <0xc20000 0x1000>; - next-level-cache = <&cpc>; - }; }; diff --git a/arch/powerpc/configs/85xx/e6500rev2_defconfig b/arch/powerpc/configs/85xx/e6500rev2_defconfig index 26a586a..819d403 100644 --- a/arch/powerpc/configs/85xx/e6500rev2_defconfig +++ b/arch/powerpc/configs/85xx/e6500rev2_defconfig @@ -1,5 +1,7 @@ CONFIG_PPC64=y CONFIG_PPC_BOOK3E_64=y +# CONFIG_FSL_ERRATUM_A_004801 is not set +# CONFIG_FSL_ERRATUM_A_005337 is not set CONFIG_ALTIVEC=y CONFIG_SMP=y CONFIG_NR_CPUS=24 diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h index b7d2747..e354127 100644 --- a/arch/powerpc/include/asm/cputable.h +++ b/arch/powerpc/include/asm/cputable.h @@ -369,12 +369,12 @@ extern const char *powerpc_base_platform; #define CPU_FTRS_E5500 (CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN | \ CPU_FTR_L2CSR | CPU_FTR_LWSYNC | CPU_FTR_NOEXECUTE | \ CPU_FTR_DBELL | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \ - CPU_FTR_DEBUG_LVL_EXC | CPU_FTR_EMB_HV) + CPU_FTR_DEBUG_LVL_EXC | CPU_FTR_EMB_HV | CPU_FTR_CELL_TB_BUG) #define CPU_FTRS_E6500 (CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN | \ CPU_FTR_L2CSR | CPU_FTR_LWSYNC | CPU_FTR_NOEXECUTE | \ CPU_FTR_DBELL | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \ CPU_FTR_DEBUG_LVL_EXC | CPU_FTR_EMB_HV | CPU_FTR_ALTIVEC_COMP | \ - CPU_FTR_SMT) + CPU_FTR_CELL_TB_BUG | CPU_FTR_SMT) #define CPU_FTRS_GENERIC_32 (CPU_FTR_COMMON | CPU_FTR_NODSISRALIGN) /* 64-bit CPUs */ diff --git a/arch/powerpc/include/asm/ppc_asm.h b/arch/powerpc/include/asm/ppc_asm.h index 635fc0b..3a853ae 100644 --- a/arch/powerpc/include/asm/ppc_asm.h +++ b/arch/powerpc/include/asm/ppc_asm.h @@ -362,7 +362,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_601) #define ISYNC_601 #endif -#ifdef CONFIG_PPC_CELL +#if defined(CONFIG_PPC_CELL) || defined(CONFIG_PPC_FSL_BOOK3E) #define MFTB(dest) \ 90: mftb dest; \ BEGIN_FTR_SECTION_NESTED(96); \ diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h index 234a850..16fbb66 100644 --- a/arch/powerpc/include/asm/reg.h +++ b/arch/powerpc/include/asm/reg.h @@ -1060,7 +1060,7 @@ : "memory") #ifdef __powerpc64__ -#ifdef CONFIG_PPC_CELL +#if defined(CONFIG_PPC_CELL) || defined(CONFIG_PPC_FSL_BOOK3E) #define mftb() ({unsigned long rval; \ asm volatile( \ "90: mftb %0;\n" \ diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c index d0ad730..43cc5c9 100644 --- a/arch/powerpc/platforms/85xx/smp.c +++ b/arch/powerpc/platforms/85xx/smp.c @@ -130,7 +130,30 @@ static void __cpuinit mpc85xx_give_timebase(void) tb_req = 0; mpc85xx_timebase_freeze(1); +#ifdef CONFIG_PPC64 + /* + * e5500/e6500 have a workaround for erratum A-006958 in place + * that will reread the timebase until TBL is non-zero. + * That would be a bad thing when the timebase is frozen. + * + * Thus, we read it manually, and instead of checking that + * TBL is non-zero, we ensure that TB does not change. We don't + * do that for the main mftb implementation, because it requires + * a scratch register + */ + { + u64 prev; + + asm volatile("mftb %0" : "=r" (timebase)); + + do { + prev = timebase; + asm volatile("mftb %0" : "=r" (timebase)); + } while (prev != timebase); + } +#else timebase = get_tb(); +#endif mb(); tb_valid = 1; diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_cc.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_cc.c index a68ff12..a8a52b2 100644 --- a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_cc.c +++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_cc.c @@ -1192,6 +1192,10 @@ static void DeleteNode(t_FmPcdCcNode *p_CcNode) p_CcNode->h_Spinlock = NULL; } + /* Restore the original counters pointer instead of the mutual pointer (mutual to all hash buckets) */ + if (p_CcNode->isHashBucket && (p_CcNode->statisticsMode != e_FM_PCD_CC_STATS_MODE_NONE)) + p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].p_StatsObj->h_StatsCounters = p_CcNode->h_PrivMissStatsCounters; + /* Releasing all currently used statistics objects, including 'miss' entry */ for (i = 0; i < p_CcNode->numOfKeys + 1; i++) if (p_CcNode->keyAndNextEngineParams[i].p_StatsObj) @@ -1200,7 +1204,6 @@ static void DeleteNode(t_FmPcdCcNode *p_CcNode) if (!LIST_IsEmpty(&p_CcNode->availableStatsLst)) { t_Handle h_FmMuram = FmPcdGetMuramHandle(p_CcNode->h_FmPcd); - ASSERT_COND(h_FmMuram); FreeStatObjects(&p_CcNode->availableStatsLst, h_FmMuram); @@ -1490,7 +1493,7 @@ t_Error ValidateNextEngineParams(t_Handle h_FmPcd, (p_FmPcdCcNextEngineParams->statisticsEn)) RETURN_ERROR(MAJOR, E_CONFLICT, ("Statistics are requested for a key, but statistics mode was set" - "to 'NONE' upon initialization of this match table")); + "to 'NONE' upon initialization")); switch (p_FmPcdCcNextEngineParams->nextEngine) { @@ -3397,13 +3400,18 @@ static t_Error ValidateAndCalcStatsParams(t_FmPcdCcNode *p_CcNode, uint32_t *p_NumOfRanges, uint32_t *p_CountersArraySize) { - e_FmPcdCcStatsMode statisticsMode = p_CcNode->statisticsMode; + e_FmPcdCcStatsMode statisticsMode = p_CcNode->statisticsMode; + uint32_t i; UNUSED(p_CcNodeParam); switch (statisticsMode) { case e_FM_PCD_CC_STATS_MODE_NONE: + for (i = 0; i < p_CcNode->numOfKeys; i++) + if (p_CcNodeParam->keysParams.keyParams[i].ccNextEngineParams.statisticsEn) + RETURN_ERROR(MAJOR, E_INVALID_VALUE, + ("Statistics cannot be enabled for key %d when statistics mode was set to 'NONE'", i)); return E_OK; case e_FM_PCD_CC_STATS_MODE_FRAME: @@ -3983,9 +3991,6 @@ static t_Error MatchTableGetKeyStatistics(t_FmPcdCcNode *p_CcNode, if (p_CcNode->statisticsMode == e_FM_PCD_CC_STATS_MODE_NONE) RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Statistics were not enabled for this match table")); - if (keyIndex >= p_CcNode->numOfKeys) - RETURN_ERROR(MAJOR, E_INVALID_STATE, ("The provided keyIndex exceeds the number of keys in this match table")); - if (!p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj) RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Statistics were not enabled for this key")); @@ -5014,377 +5019,11 @@ void FmPcdCcGetAdTablesThatPointOnReplicGroup(t_Handle h_Node, ASSERT_COND(i != p_CurrentNode->numOfKeys); } #endif /* (DPAA_VERSION >= 11) */ -/*********************** End of inter-module routines ************************/ - -/****************************************/ -/* API Init unit functions */ -/****************************************/ - -t_Handle FM_PCD_CcRootBuild(t_Handle h_FmPcd, t_FmPcdCcTreeParams *p_PcdGroupsParam) -{ - t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; - t_Error err = E_OK; - int i = 0, j = 0, k = 0; - t_FmPcdCcTree *p_FmPcdCcTree; - uint8_t numOfEntries; - t_Handle p_CcTreeTmp; - t_FmPcdCcGrpParams *p_FmPcdCcGroupParams; - t_FmPcdCcKeyAndNextEngineParams *p_Params, *p_KeyAndNextEngineParams; - t_NetEnvParams netEnvParams; - uint8_t lastOne = 0; - uint32_t requiredAction = 0; - t_FmPcdCcNode *p_FmPcdCcNextNode; - t_CcNodeInformation ccNodeInfo, *p_CcInformation; - - SANITY_CHECK_RETURN_VALUE(h_FmPcd,E_INVALID_HANDLE, NULL); - SANITY_CHECK_RETURN_VALUE(p_PcdGroupsParam,E_INVALID_HANDLE, NULL); - - if (p_PcdGroupsParam->numOfGrps > FM_PCD_MAX_NUM_OF_CC_GROUPS) - { - REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("numOfGrps should not exceed %d", FM_PCD_MAX_NUM_OF_CC_GROUPS)); - return NULL; - } - - p_FmPcdCcTree = (t_FmPcdCcTree*)XX_Malloc(sizeof(t_FmPcdCcTree)); - if (!p_FmPcdCcTree) - { - REPORT_ERROR(MAJOR, E_NO_MEMORY, ("PCD tree structure")); - return NULL; - } - memset(p_FmPcdCcTree, 0, sizeof(t_FmPcdCcTree)); - p_FmPcdCcTree->h_FmPcd = h_FmPcd; - - p_Params = (t_FmPcdCcKeyAndNextEngineParams*)XX_Malloc(FM_PCD_MAX_NUM_OF_CC_GROUPS * sizeof(t_FmPcdCcKeyAndNextEngineParams)); - memset(p_Params, 0, FM_PCD_MAX_NUM_OF_CC_GROUPS * sizeof(t_FmPcdCcKeyAndNextEngineParams)); - - INIT_LIST(&p_FmPcdCcTree->fmPortsLst); - -#ifdef FM_CAPWAP_SUPPORT - if ((p_PcdGroupsParam->numOfGrps == 1) && - (p_PcdGroupsParam->ccGrpParams[0].numOfDistinctionUnits == 0) && - (p_PcdGroupsParam->ccGrpParams[0].nextEnginePerEntriesInGrp[0].nextEngine == e_FM_PCD_CC) && - p_PcdGroupsParam->ccGrpParams[0].nextEnginePerEntriesInGrp[0].params.ccParams.h_CcNode && - IsCapwapApplSpecific(p_PcdGroupsParam->ccGrpParams[0].nextEnginePerEntriesInGrp[0].params.ccParams.h_CcNode)) - { - p_PcdGroupsParam->ccGrpParams[0].nextEnginePerEntriesInGrp[0].h_Manip = FmPcdManipApplSpecificBuild(); - if (!p_PcdGroupsParam->ccGrpParams[0].nextEnginePerEntriesInGrp[0].h_Manip) - { - DeleteTree(p_FmPcdCcTree,p_FmPcd); - XX_Free(p_Params); - REPORT_ERROR(MAJOR, E_INVALID_STATE, NO_MSG); - return NULL; - } - } -#endif /* FM_CAPWAP_SUPPORT */ - - numOfEntries = 0; - p_FmPcdCcTree->netEnvId = FmPcdGetNetEnvId(p_PcdGroupsParam->h_NetEnv); - - for (i = 0; i < p_PcdGroupsParam->numOfGrps; i++) - { - p_FmPcdCcGroupParams = &p_PcdGroupsParam->ccGrpParams[i]; - - if (p_FmPcdCcGroupParams->numOfDistinctionUnits > FM_PCD_MAX_NUM_OF_CC_UNITS) - { - DeleteTree(p_FmPcdCcTree,p_FmPcd); - XX_Free(p_Params); - REPORT_ERROR(MAJOR, E_INVALID_VALUE, - ("numOfDistinctionUnits (group %d) should not exceed %d", i, FM_PCD_MAX_NUM_OF_CC_UNITS)); - return NULL; - } - - p_FmPcdCcTree->fmPcdGroupParam[i].baseGroupEntry = numOfEntries; - p_FmPcdCcTree->fmPcdGroupParam[i].numOfEntriesInGroup =(uint8_t)( 0x01 << p_FmPcdCcGroupParams->numOfDistinctionUnits); - numOfEntries += p_FmPcdCcTree->fmPcdGroupParam[i].numOfEntriesInGroup; - if (numOfEntries > FM_PCD_MAX_NUM_OF_CC_GROUPS) - { - DeleteTree(p_FmPcdCcTree,p_FmPcd); - XX_Free(p_Params); - REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("numOfEntries can not be larger than %d", FM_PCD_MAX_NUM_OF_CC_GROUPS)); - return NULL; - } - - if (lastOne) - { - if (p_FmPcdCcTree->fmPcdGroupParam[i].numOfEntriesInGroup > lastOne) - { - DeleteTree(p_FmPcdCcTree,p_FmPcd); - XX_Free(p_Params); - REPORT_ERROR(MAJOR, E_CONFLICT, ("numOfEntries per group must be set in descending order")); - return NULL; - } - } - - lastOne = p_FmPcdCcTree->fmPcdGroupParam[i].numOfEntriesInGroup; - - netEnvParams.netEnvId = p_FmPcdCcTree->netEnvId; - netEnvParams.numOfDistinctionUnits = p_FmPcdCcGroupParams->numOfDistinctionUnits; - - memcpy(netEnvParams.unitIds, - &p_FmPcdCcGroupParams->unitIds, - (sizeof(uint8_t)) * p_FmPcdCcGroupParams->numOfDistinctionUnits); - - err = PcdGetUnitsVector(p_FmPcd, &netEnvParams); - if (err) - { - DeleteTree(p_FmPcdCcTree,p_FmPcd); - XX_Free(p_Params); - REPORT_ERROR(MAJOR, err, NO_MSG); - return NULL; - } - - p_FmPcdCcTree->fmPcdGroupParam[i].totalBitsMask = netEnvParams.vector; - for (j = 0; j < p_FmPcdCcTree->fmPcdGroupParam[i].numOfEntriesInGroup; j++) - { - err = ValidateNextEngineParams(h_FmPcd, - &p_FmPcdCcGroupParams->nextEnginePerEntriesInGrp[j], - e_FM_PCD_CC_STATS_MODE_NONE); - if (err) - { - DeleteTree(p_FmPcdCcTree,p_FmPcd); - XX_Free(p_Params); - REPORT_ERROR(MAJOR, err, (NO_MSG)); - return NULL; - } - - if (p_FmPcdCcGroupParams->nextEnginePerEntriesInGrp[j].h_Manip) - { - err = FmPcdManipCheckParamsForCcNextEngine(&p_FmPcdCcGroupParams->nextEnginePerEntriesInGrp[j], &requiredAction); - if (err) - { - DeleteTree(p_FmPcdCcTree,p_FmPcd); - XX_Free(p_Params); - REPORT_ERROR(MAJOR, E_INVALID_STATE, NO_MSG); - return NULL; - } - } - p_KeyAndNextEngineParams = p_Params+k; - - memcpy(&p_KeyAndNextEngineParams->nextEngineParams, - &p_FmPcdCcGroupParams->nextEnginePerEntriesInGrp[j], - sizeof(t_FmPcdCcNextEngineParams)); - - if ((p_KeyAndNextEngineParams->nextEngineParams.nextEngine == e_FM_PCD_CC) - && p_KeyAndNextEngineParams->nextEngineParams.h_Manip) - { - err = AllocAndFillAdForContLookupManip(p_KeyAndNextEngineParams->nextEngineParams.params.ccParams.h_CcNode); - if (err) - { - DeleteTree(p_FmPcdCcTree,p_FmPcd); - XX_Free(p_Params); - REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC Tree")); - return NULL; - } - } - - requiredAction |= UPDATE_CC_WITH_TREE; - p_KeyAndNextEngineParams->requiredAction = requiredAction; - - k++; - } - } - - p_FmPcdCcTree->numOfEntries = (uint8_t)k; - p_FmPcdCcTree->numOfGrps = p_PcdGroupsParam->numOfGrps; - - p_FmPcdCcTree->ccTreeBaseAddr = - PTR_TO_UINT(FM_MURAM_AllocMem(FmPcdGetMuramHandle(h_FmPcd), - (uint32_t)( FM_PCD_MAX_NUM_OF_CC_GROUPS * FM_PCD_CC_AD_ENTRY_SIZE), - FM_PCD_CC_TREE_ADDR_ALIGN)); - if (!p_FmPcdCcTree->ccTreeBaseAddr) - { - DeleteTree(p_FmPcdCcTree,p_FmPcd); - XX_Free(p_Params); - REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC Tree")); - return NULL; - } - IOMemSet32(UINT_TO_PTR(p_FmPcdCcTree->ccTreeBaseAddr), 0, (uint32_t)(FM_PCD_MAX_NUM_OF_CC_GROUPS * FM_PCD_CC_AD_ENTRY_SIZE)); - - p_CcTreeTmp = UINT_TO_PTR(p_FmPcdCcTree->ccTreeBaseAddr); - - j = 0; - for (i = 0; i < numOfEntries; i++) - { - p_KeyAndNextEngineParams = p_Params + i; - - NextStepAd(p_CcTreeTmp, - NULL, - &p_KeyAndNextEngineParams->nextEngineParams, - p_FmPcd); - - p_CcTreeTmp = PTR_MOVE(p_CcTreeTmp, FM_PCD_CC_AD_ENTRY_SIZE); - - memcpy(&p_FmPcdCcTree->keyAndNextEngineParams[i], - p_KeyAndNextEngineParams, - sizeof(t_FmPcdCcKeyAndNextEngineParams)); - - if (p_FmPcdCcTree->keyAndNextEngineParams[i].nextEngineParams.nextEngine== e_FM_PCD_CC) - { - p_FmPcdCcNextNode = (t_FmPcdCcNode*)p_FmPcdCcTree->keyAndNextEngineParams[i].nextEngineParams.params.ccParams.h_CcNode; - p_CcInformation = FindNodeInfoInReleventLst(&p_FmPcdCcNextNode->ccTreeIdLst, - (t_Handle)p_FmPcdCcTree, - p_FmPcdCcNextNode->h_Spinlock); - - if (!p_CcInformation) - { - memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation)); - ccNodeInfo.h_CcNode = (t_Handle)p_FmPcdCcTree; - ccNodeInfo.index = 1; - EnqueueNodeInfoToRelevantLst(&p_FmPcdCcNextNode->ccTreeIdLst, - &ccNodeInfo, - p_FmPcdCcNextNode->h_Spinlock); - } - else - p_CcInformation->index++; - } - } - - FmPcdIncNetEnvOwners(h_FmPcd, p_FmPcdCcTree->netEnvId); - p_CcTreeTmp = UINT_TO_PTR(p_FmPcdCcTree->ccTreeBaseAddr); - - if (!FmPcdLockTryLockAll(p_FmPcd)) - { - FM_PCD_CcRootDelete(p_FmPcdCcTree); - XX_Free(p_Params); - DBG(TRACE, ("FmPcdLockTryLockAll failed")); - return NULL; - } - - for (i = 0; i < numOfEntries; i++) - { - if (p_FmPcdCcTree->keyAndNextEngineParams[i].requiredAction) - { - err = SetRequiredAction(h_FmPcd, - p_FmPcdCcTree->keyAndNextEngineParams[i].requiredAction, - &p_FmPcdCcTree->keyAndNextEngineParams[i], - p_CcTreeTmp, - 1, - p_FmPcdCcTree); - if (err) - { - FmPcdLockUnlockAll(p_FmPcd); - FM_PCD_CcRootDelete(p_FmPcdCcTree); - XX_Free(p_Params); - REPORT_ERROR(MAJOR, E_NO_MEMORY, ("No memory")); - return NULL; - } - p_CcTreeTmp = PTR_MOVE(p_CcTreeTmp, FM_PCD_CC_AD_ENTRY_SIZE); - } - } - - FmPcdLockUnlockAll(p_FmPcd); - p_FmPcdCcTree->p_Lock = FmPcdAcquireLock(p_FmPcd); - if (!p_FmPcdCcTree->p_Lock) - { - FM_PCD_CcRootDelete(p_FmPcdCcTree); - XX_Free(p_Params); - REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM CC lock")); - return NULL; - } - - XX_Free(p_Params); - - return p_FmPcdCcTree; -} - -t_Error FM_PCD_CcRootDelete(t_Handle h_CcTree) -{ - t_FmPcd *p_FmPcd; - t_FmPcdCcTree *p_CcTree = (t_FmPcdCcTree *)h_CcTree; - int i= 0; - - SANITY_CHECK_RETURN_ERROR(p_CcTree,E_INVALID_STATE); - p_FmPcd = (t_FmPcd *)p_CcTree->h_FmPcd; - SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); - - FmPcdDecNetEnvOwners(p_FmPcd, p_CcTree->netEnvId); - - if (p_CcTree->owners) - RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("the tree with this ID can not be removed because this tree is occupied, first - unbind this tree")); - - /* Delete reassembly schemes if exist */ - if (p_CcTree->h_IpReassemblyManip) - { - FmPcdManipDeleteIpReassmSchemes(p_CcTree->h_IpReassemblyManip); - FmPcdManipUpdateOwner(p_CcTree->h_IpReassemblyManip, FALSE); - } - - for (i = 0; i <p_CcTree->numOfEntries; i++) - { - if (p_CcTree->keyAndNextEngineParams[i].nextEngineParams.nextEngine == e_FM_PCD_CC) - UpdateNodeOwner(p_CcTree->keyAndNextEngineParams[i].nextEngineParams.params.ccParams.h_CcNode, FALSE); - - if (p_CcTree->keyAndNextEngineParams[i].nextEngineParams.h_Manip) - FmPcdManipUpdateOwner(p_CcTree->keyAndNextEngineParams[i].nextEngineParams.h_Manip, FALSE); - -#ifdef FM_CAPWAP_SUPPORT - if ((p_CcTree->numOfGrps == 1) && - (p_CcTree->fmPcdGroupParam[0].numOfEntriesInGroup == 1) && - (p_CcTree->keyAndNextEngineParams[0].nextEngineParams.nextEngine == e_FM_PCD_CC) && - p_CcTree->keyAndNextEngineParams[0].nextEngineParams.params.ccParams.h_CcNode && - IsCapwapApplSpecific(p_CcTree->keyAndNextEngineParams[0].nextEngineParams.params.ccParams.h_CcNode)) - { - if (FM_PCD_ManipNodeDelete(p_CcTree->keyAndNextEngineParams[0].nextEngineParams.h_Manip) != E_OK) - return E_INVALID_STATE; - } -#endif /* FM_CAPWAP_SUPPORT */ - -#if (DPAA_VERSION >= 11) - if ((p_CcTree->keyAndNextEngineParams[i].nextEngineParams.nextEngine == e_FM_PCD_FR) && - (p_CcTree->keyAndNextEngineParams[i].nextEngineParams.params.frParams.h_FrmReplic)) - FrmReplicGroupUpdateOwner(p_CcTree->keyAndNextEngineParams[i].nextEngineParams.params.frParams.h_FrmReplic, - FALSE); -#endif /* (DPAA_VERSION >= 11) */ - } - - if (p_CcTree->p_Lock) - FmPcdReleaseLock(p_CcTree->h_FmPcd, p_CcTree->p_Lock); - - DeleteTree(p_CcTree, p_FmPcd); - - return E_OK; -} - -t_Error FM_PCD_CcRootModifyNextEngine(t_Handle h_CcTree, - uint8_t grpId, - uint8_t index, - t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams) -{ - t_FmPcd *p_FmPcd; - t_FmPcdCcTree *p_CcTree = (t_FmPcdCcTree *)h_CcTree; - t_Error err = E_OK; - - SANITY_CHECK_RETURN_ERROR(p_FmPcdCcNextEngineParams, E_NULL_POINTER); - SANITY_CHECK_RETURN_ERROR(p_CcTree,E_INVALID_STATE); - p_FmPcd = (t_FmPcd *)p_CcTree->h_FmPcd; - SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); - - if (!FmPcdLockTryLockAll(p_FmPcd)) - { - DBG(TRACE, ("FmPcdLockTryLockAll failed")); - return ERROR_CODE(E_BUSY); - } - - err = FmPcdCcModifyNextEngineParamTree(p_FmPcd, - p_CcTree, - grpId, - index, - p_FmPcdCcNextEngineParams); - FmPcdLockUnlockAll(p_FmPcd); - - if (err) - { - RETURN_ERROR(MAJOR, err, NO_MSG); - } - - return E_OK; -} - -t_Handle FM_PCD_MatchTableSet(t_Handle h_FmPcd, t_FmPcdCcNodeParams *p_CcNodeParam) +t_Error FmPcdCcMatchTableSet(t_Handle h_FmPcd, t_FmPcdCcNode *p_CcNode, t_FmPcdCcNodeParams *p_CcNodeParam) { t_FmPcd *p_FmPcd = (t_FmPcd *) h_FmPcd; - t_FmPcdCcNode *p_CcNode, *p_FmPcdCcNextNode; + t_FmPcdCcNode *p_FmPcdCcNextNode; t_Error err = E_OK; uint32_t tmp, keySize; bool glblMask = FALSE; @@ -5402,15 +5041,9 @@ t_Handle FM_PCD_MatchTableSet(t_Handle h_FmPcd, t_FmPcdCcNodeParams *p_CcNodePar t_FmPcdCcStatsParams statsParams = {0}; t_Handle h_Manip; - SANITY_CHECK_RETURN_VALUE(h_FmPcd,E_INVALID_HANDLE,NULL); - - p_CcNode = (t_FmPcdCcNode*)XX_Malloc(sizeof(t_FmPcdCcNode)); - if (!p_CcNode) - { - REPORT_ERROR(MAJOR, E_NO_MEMORY, ("No memory")); - return NULL; - } - memset(p_CcNode, 0, sizeof(t_FmPcdCcNode)); + ASSERT_COND(h_FmPcd); + ASSERT_COND(p_CcNode); + ASSERT_COND(p_CcNodeParam); p_CcNode->p_GlblMask = (t_Handle)XX_Malloc(CC_GLBL_MASK_SIZE * sizeof(uint8_t)); memset(p_CcNode->p_GlblMask, 0, CC_GLBL_MASK_SIZE * sizeof(uint8_t)); @@ -5430,10 +5063,7 @@ t_Handle FM_PCD_MatchTableSet(t_Handle h_FmPcd, t_FmPcdCcNodeParams *p_CcNodePar h_FmMuram = FmPcdGetMuramHandle(h_FmPcd); if (!h_FmMuram) - { - REPORT_ERROR(MAJOR, E_INVALID_HANDLE, ("FM MURAM")); - return NULL; - } + RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("FM MURAM")); INIT_LIST(&p_CcNode->ccPrevNodesLst); INIT_LIST(&p_CcNode->ccTreeIdLst); @@ -5444,8 +5074,7 @@ t_Handle FM_PCD_MatchTableSet(t_Handle h_FmPcd, t_FmPcdCcNodeParams *p_CcNodePar if (!p_CcNode->h_Spinlock) { DeleteNode(p_CcNode); - REPORT_ERROR(MAJOR, E_NO_MEMORY, ("CC node spinlock")); - return NULL; + RETURN_ERROR(MAJOR, E_NO_MEMORY, ("CC node spinlock")); } if ((p_CcNodeParam->extractCcParams.type == e_FM_PCD_EXTRACT_BY_HDR) && @@ -5466,18 +5095,18 @@ t_Handle FM_PCD_MatchTableSet(t_Handle h_FmPcd, t_FmPcdCcNodeParams *p_CcNodePar if ((p_CcNodeParam->extractCcParams.extractNonHdr.src == e_FM_PCD_EXTRACT_FROM_FLOW_ID) && (p_CcNodeParam->extractCcParams.extractNonHdr.offset != 0)) { - REPORT_ERROR(MAJOR, E_INVALID_VALUE, + DeleteNode(p_CcNode); + RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("In the case of the extraction from e_FM_PCD_EXTRACT_FROM_FLOW_ID offset has to be 0")); - return NULL; } icCode = IcDefineCode(p_CcNodeParam); fromIc = TRUE; if (icCode == CC_PRIVATE_INFO_NONE) { - REPORT_ERROR(MAJOR, E_INVALID_STATE, + DeleteNode(p_CcNode); + RETURN_ERROR(MAJOR, E_INVALID_STATE, ("user asked extraction from IC and field in internal context or action wasn't initialized in the right way")); - return NULL; } if ((icCode == CC_PRIVATE_INFO_IC_DEQ_FQID_INDEX_LOOKUP) || @@ -5503,8 +5132,7 @@ t_Handle FM_PCD_MatchTableSet(t_Handle h_FmPcd, t_FmPcdCcNodeParams *p_CcNodePar if (err) { DeleteNode(p_CcNode); - REPORT_ERROR(MAJOR, err, NO_MSG); - return NULL; + RETURN_ERROR(MAJOR, err, NO_MSG); } switch (p_CcNodeParam->extractCcParams.type) @@ -5564,8 +5192,7 @@ t_Handle FM_PCD_MatchTableSet(t_Handle h_FmPcd, t_FmPcdCcNodeParams *p_CcNodePar default: DeleteNode(p_CcNode); - REPORT_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); - return NULL; + RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); } break; @@ -5587,8 +5214,7 @@ t_Handle FM_PCD_MatchTableSet(t_Handle h_FmPcd, t_FmPcdCcNodeParams *p_CcNodePar if ((p_CcNode->offset + p_CcNode->sizeOfExtraction) > 8) { DeleteNode(p_CcNode); - REPORT_ERROR(MAJOR, E_INVALID_SELECTION,("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)")); - return NULL; + RETURN_ERROR(MAJOR, E_INVALID_SELECTION,("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)")); } } if ((p_CcNode->parseCode == CC_PC_GENERIC_IC_GMASK) || @@ -5601,30 +5227,26 @@ t_Handle FM_PCD_MatchTableSet(t_Handle h_FmPcd, t_FmPcdCcNodeParams *p_CcNodePar default: DeleteNode(p_CcNode); - REPORT_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); - return NULL; + RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); } if (p_CcNode->parseCode == CC_PC_ILLEGAL) { DeleteNode(p_CcNode); - REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("illegal extraction type")); - return NULL; + RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("illegal extraction type")); } if ((p_CcNode->sizeOfExtraction > FM_PCD_MAX_SIZE_OF_KEY) || !p_CcNode->sizeOfExtraction) { DeleteNode(p_CcNode); - REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("sizeOfExatrction can not be greater than 56 and not 0")); - return NULL; + RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("sizeOfExatrction can not be greater than 56 and not 0")); } if (p_CcNodeParam->keysParams.keySize != p_CcNode->sizeOfExtraction) { DeleteNode(p_CcNode); - REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("keySize has to be equal to sizeOfExtraction")); - return NULL; + RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("keySize has to be equal to sizeOfExtraction")); } p_CcNode->userSizeOfExtraction = p_CcNode->sizeOfExtraction; @@ -5636,8 +5258,7 @@ t_Handle FM_PCD_MatchTableSet(t_Handle h_FmPcd, t_FmPcdCcNodeParams *p_CcNodePar if (err != E_OK) { DeleteNode(p_CcNode); - REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("keySize has to be equal to sizeOfExtraction")); - return NULL; + RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("keySize has to be equal to sizeOfExtraction")); } /* Calculating matching table entry size by rounding up the user-defined size of extraction to valid entry size */ @@ -5659,8 +5280,7 @@ t_Handle FM_PCD_MatchTableSet(t_Handle h_FmPcd, t_FmPcdCcNodeParams *p_CcNodePar if (err != E_OK) { DeleteNode(p_CcNode); - REPORT_ERROR(MAJOR, err, NO_MSG); - return NULL; + RETURN_ERROR(MAJOR, err, NO_MSG); } p_CcNode->keysMatchTableMaxSize = matchTableSize; @@ -5671,8 +5291,7 @@ t_Handle FM_PCD_MatchTableSet(t_Handle h_FmPcd, t_FmPcdCcNodeParams *p_CcNodePar if (err != E_OK) { DeleteNode(p_CcNode); - REPORT_ERROR(MAJOR, err, NO_MSG); - return NULL; + RETURN_ERROR(MAJOR, err, NO_MSG); } } @@ -5685,8 +5304,7 @@ t_Handle FM_PCD_MatchTableSet(t_Handle h_FmPcd, t_FmPcdCcNodeParams *p_CcNodePar if (!p_CcNode->h_TmpAd) { DeleteNode(p_CcNode); - REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC action descriptor")); - return NULL; + RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC action descriptor")); } } else @@ -5710,8 +5328,7 @@ t_Handle FM_PCD_MatchTableSet(t_Handle h_FmPcd, t_FmPcdCcNodeParams *p_CcNodePar if (!p_CcNode->h_StatsFLRs) { DeleteNode(p_CcNode); - REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC frame length ranges array")); - return NULL; + RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC frame length ranges array")); } /* Initialize using value received from the user */ @@ -5742,8 +5359,7 @@ t_Handle FM_PCD_MatchTableSet(t_Handle h_FmPcd, t_FmPcdCcNodeParams *p_CcNodePar if (!p_CcNode->h_KeysMatchTable) { DeleteNode(p_CcNode); - REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC node key match table")); - return NULL; + RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC node key match table")); } IOMemSet32((uint8_t *)p_CcNode->h_KeysMatchTable, 0, @@ -5758,8 +5374,7 @@ t_Handle FM_PCD_MatchTableSet(t_Handle h_FmPcd, t_FmPcdCcNodeParams *p_CcNodePar if (!p_CcNode->h_AdTable) { DeleteNode(p_CcNode); - REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC node action descriptors table")); - return NULL; + RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC node action descriptors table")); } IOMemSet32((uint8_t *)p_CcNode->h_AdTable, 0, adTableSize); @@ -5833,6 +5448,18 @@ t_Handle FM_PCD_MatchTableSet(t_Handle h_FmPcd, t_FmPcdCcNodeParams *p_CcNodePar p_StatsObj = GetStatsObj(p_CcNode); ASSERT_COND(p_StatsObj); + /* All 'bucket' nodes of a hash table should share the same statistics counters, + allocated by the hash table. So, if this node is a bucket of a hash table, + we'll replace the locally allocated counters with the shared counters. */ + if (p_CcNode->isHashBucket) + { + ASSERT_COND(p_CcNode->h_MissStatsCounters); + + /* Store original counters pointer and replace it with mutual preallocated pointer */ + p_CcNode->h_PrivMissStatsCounters = p_StatsObj->h_StatsCounters; + p_StatsObj->h_StatsCounters = p_CcNode->h_MissStatsCounters; + } + statsParams.h_StatsAd = p_StatsObj->h_StatsAd; statsParams.h_StatsCounters = p_StatsObj->h_StatsCounters; #if (DPAA_VERSION >= 11) @@ -5909,7 +5536,7 @@ t_Handle FM_PCD_MatchTableSet(t_Handle h_FmPcd, t_FmPcdCcNodeParams *p_CcNodePar { FM_PCD_MatchTableDelete((t_Handle)p_CcNode); DBG(TRACE, ("FmPcdLockTryLockAll failed")); - return NULL; + return ERROR_CODE(E_BUSY); } /* Required action for each next engine */ @@ -5927,8 +5554,7 @@ t_Handle FM_PCD_MatchTableSet(t_Handle h_FmPcd, t_FmPcdCcNodeParams *p_CcNodePar { FmPcdLockUnlockAll(h_FmPcd); FM_PCD_MatchTableDelete((t_Handle)p_CcNode); - REPORT_ERROR(MAJOR, err, NO_MSG); - return NULL; + RETURN_ERROR(MAJOR, err, NO_MSG); } p_AdTableTmp = PTR_MOVE(p_AdTableTmp, FM_PCD_CC_AD_ENTRY_SIZE); } @@ -5936,6 +5562,407 @@ t_Handle FM_PCD_MatchTableSet(t_Handle h_FmPcd, t_FmPcdCcNodeParams *p_CcNodePar FmPcdLockUnlockAll(h_FmPcd); + return E_OK; +} +/*********************** End of inter-module routines ************************/ + + +/****************************************/ +/* API Init unit functions */ +/****************************************/ + +t_Handle FM_PCD_CcRootBuild(t_Handle h_FmPcd, t_FmPcdCcTreeParams *p_PcdGroupsParam) +{ + t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; + t_Error err = E_OK; + int i = 0, j = 0, k = 0; + t_FmPcdCcTree *p_FmPcdCcTree; + uint8_t numOfEntries; + t_Handle p_CcTreeTmp; + t_FmPcdCcGrpParams *p_FmPcdCcGroupParams; + t_FmPcdCcKeyAndNextEngineParams *p_Params, *p_KeyAndNextEngineParams; + t_NetEnvParams netEnvParams; + uint8_t lastOne = 0; + uint32_t requiredAction = 0; + t_FmPcdCcNode *p_FmPcdCcNextNode; + t_CcNodeInformation ccNodeInfo, *p_CcInformation; + + SANITY_CHECK_RETURN_VALUE(h_FmPcd,E_INVALID_HANDLE, NULL); + SANITY_CHECK_RETURN_VALUE(p_PcdGroupsParam,E_INVALID_HANDLE, NULL); + + if (p_PcdGroupsParam->numOfGrps > FM_PCD_MAX_NUM_OF_CC_GROUPS) + { + REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("numOfGrps should not exceed %d", FM_PCD_MAX_NUM_OF_CC_GROUPS)); + return NULL; + } + + p_FmPcdCcTree = (t_FmPcdCcTree*)XX_Malloc(sizeof(t_FmPcdCcTree)); + if (!p_FmPcdCcTree) + { + REPORT_ERROR(MAJOR, E_NO_MEMORY, ("PCD tree structure")); + return NULL; + } + memset(p_FmPcdCcTree, 0, sizeof(t_FmPcdCcTree)); + p_FmPcdCcTree->h_FmPcd = h_FmPcd; + + p_Params = (t_FmPcdCcKeyAndNextEngineParams*)XX_Malloc(FM_PCD_MAX_NUM_OF_CC_GROUPS * sizeof(t_FmPcdCcKeyAndNextEngineParams)); + memset(p_Params, 0, FM_PCD_MAX_NUM_OF_CC_GROUPS * sizeof(t_FmPcdCcKeyAndNextEngineParams)); + + INIT_LIST(&p_FmPcdCcTree->fmPortsLst); + +#ifdef FM_CAPWAP_SUPPORT + if ((p_PcdGroupsParam->numOfGrps == 1) && + (p_PcdGroupsParam->ccGrpParams[0].numOfDistinctionUnits == 0) && + (p_PcdGroupsParam->ccGrpParams[0].nextEnginePerEntriesInGrp[0].nextEngine == e_FM_PCD_CC) && + p_PcdGroupsParam->ccGrpParams[0].nextEnginePerEntriesInGrp[0].params.ccParams.h_CcNode && + IsCapwapApplSpecific(p_PcdGroupsParam->ccGrpParams[0].nextEnginePerEntriesInGrp[0].params.ccParams.h_CcNode)) + { + p_PcdGroupsParam->ccGrpParams[0].nextEnginePerEntriesInGrp[0].h_Manip = FmPcdManipApplSpecificBuild(); + if (!p_PcdGroupsParam->ccGrpParams[0].nextEnginePerEntriesInGrp[0].h_Manip) + { + DeleteTree(p_FmPcdCcTree,p_FmPcd); + XX_Free(p_Params); + REPORT_ERROR(MAJOR, E_INVALID_STATE, NO_MSG); + return NULL; + } + } +#endif /* FM_CAPWAP_SUPPORT */ + + numOfEntries = 0; + p_FmPcdCcTree->netEnvId = FmPcdGetNetEnvId(p_PcdGroupsParam->h_NetEnv); + + for (i = 0; i < p_PcdGroupsParam->numOfGrps; i++) + { + p_FmPcdCcGroupParams = &p_PcdGroupsParam->ccGrpParams[i]; + + if (p_FmPcdCcGroupParams->numOfDistinctionUnits > FM_PCD_MAX_NUM_OF_CC_UNITS) + { + DeleteTree(p_FmPcdCcTree,p_FmPcd); + XX_Free(p_Params); + REPORT_ERROR(MAJOR, E_INVALID_VALUE, + ("numOfDistinctionUnits (group %d) should not exceed %d", i, FM_PCD_MAX_NUM_OF_CC_UNITS)); + return NULL; + } + + p_FmPcdCcTree->fmPcdGroupParam[i].baseGroupEntry = numOfEntries; + p_FmPcdCcTree->fmPcdGroupParam[i].numOfEntriesInGroup =(uint8_t)( 0x01 << p_FmPcdCcGroupParams->numOfDistinctionUnits); + numOfEntries += p_FmPcdCcTree->fmPcdGroupParam[i].numOfEntriesInGroup; + if (numOfEntries > FM_PCD_MAX_NUM_OF_CC_GROUPS) + { + DeleteTree(p_FmPcdCcTree,p_FmPcd); + XX_Free(p_Params); + REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("numOfEntries can not be larger than %d", FM_PCD_MAX_NUM_OF_CC_GROUPS)); + return NULL; + } + + if (lastOne) + { + if (p_FmPcdCcTree->fmPcdGroupParam[i].numOfEntriesInGroup > lastOne) + { + DeleteTree(p_FmPcdCcTree,p_FmPcd); + XX_Free(p_Params); + REPORT_ERROR(MAJOR, E_CONFLICT, ("numOfEntries per group must be set in descending order")); + return NULL; + } + } + + lastOne = p_FmPcdCcTree->fmPcdGroupParam[i].numOfEntriesInGroup; + + netEnvParams.netEnvId = p_FmPcdCcTree->netEnvId; + netEnvParams.numOfDistinctionUnits = p_FmPcdCcGroupParams->numOfDistinctionUnits; + + memcpy(netEnvParams.unitIds, + &p_FmPcdCcGroupParams->unitIds, + (sizeof(uint8_t)) * p_FmPcdCcGroupParams->numOfDistinctionUnits); + + err = PcdGetUnitsVector(p_FmPcd, &netEnvParams); + if (err) + { + DeleteTree(p_FmPcdCcTree,p_FmPcd); + XX_Free(p_Params); + REPORT_ERROR(MAJOR, err, NO_MSG); + return NULL; + } + + p_FmPcdCcTree->fmPcdGroupParam[i].totalBitsMask = netEnvParams.vector; + for (j = 0; j < p_FmPcdCcTree->fmPcdGroupParam[i].numOfEntriesInGroup; j++) + { + err = ValidateNextEngineParams(h_FmPcd, + &p_FmPcdCcGroupParams->nextEnginePerEntriesInGrp[j], + e_FM_PCD_CC_STATS_MODE_NONE); + if (err) + { + DeleteTree(p_FmPcdCcTree,p_FmPcd); + XX_Free(p_Params); + REPORT_ERROR(MAJOR, err, (NO_MSG)); + return NULL; + } + + if (p_FmPcdCcGroupParams->nextEnginePerEntriesInGrp[j].h_Manip) + { + err = FmPcdManipCheckParamsForCcNextEngine(&p_FmPcdCcGroupParams->nextEnginePerEntriesInGrp[j], &requiredAction); + if (err) + { + DeleteTree(p_FmPcdCcTree,p_FmPcd); + XX_Free(p_Params); + REPORT_ERROR(MAJOR, E_INVALID_STATE, NO_MSG); + return NULL; + } + } + p_KeyAndNextEngineParams = p_Params+k; + + memcpy(&p_KeyAndNextEngineParams->nextEngineParams, + &p_FmPcdCcGroupParams->nextEnginePerEntriesInGrp[j], + sizeof(t_FmPcdCcNextEngineParams)); + + if ((p_KeyAndNextEngineParams->nextEngineParams.nextEngine == e_FM_PCD_CC) + && p_KeyAndNextEngineParams->nextEngineParams.h_Manip) + { + err = AllocAndFillAdForContLookupManip(p_KeyAndNextEngineParams->nextEngineParams.params.ccParams.h_CcNode); + if (err) + { + DeleteTree(p_FmPcdCcTree,p_FmPcd); + XX_Free(p_Params); + REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC Tree")); + return NULL; + } + } + + requiredAction |= UPDATE_CC_WITH_TREE; + p_KeyAndNextEngineParams->requiredAction = requiredAction; + + k++; + } + } + + p_FmPcdCcTree->numOfEntries = (uint8_t)k; + p_FmPcdCcTree->numOfGrps = p_PcdGroupsParam->numOfGrps; + + p_FmPcdCcTree->ccTreeBaseAddr = + PTR_TO_UINT(FM_MURAM_AllocMem(FmPcdGetMuramHandle(h_FmPcd), + (uint32_t)( FM_PCD_MAX_NUM_OF_CC_GROUPS * FM_PCD_CC_AD_ENTRY_SIZE), + FM_PCD_CC_TREE_ADDR_ALIGN)); + if (!p_FmPcdCcTree->ccTreeBaseAddr) + { + DeleteTree(p_FmPcdCcTree,p_FmPcd); + XX_Free(p_Params); + REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC Tree")); + return NULL; + } + IOMemSet32(UINT_TO_PTR(p_FmPcdCcTree->ccTreeBaseAddr), 0, (uint32_t)(FM_PCD_MAX_NUM_OF_CC_GROUPS * FM_PCD_CC_AD_ENTRY_SIZE)); + + p_CcTreeTmp = UINT_TO_PTR(p_FmPcdCcTree->ccTreeBaseAddr); + + j = 0; + for (i = 0; i < numOfEntries; i++) + { + p_KeyAndNextEngineParams = p_Params + i; + + NextStepAd(p_CcTreeTmp, + NULL, + &p_KeyAndNextEngineParams->nextEngineParams, + p_FmPcd); + + p_CcTreeTmp = PTR_MOVE(p_CcTreeTmp, FM_PCD_CC_AD_ENTRY_SIZE); + + memcpy(&p_FmPcdCcTree->keyAndNextEngineParams[i], + p_KeyAndNextEngineParams, + sizeof(t_FmPcdCcKeyAndNextEngineParams)); + + if (p_FmPcdCcTree->keyAndNextEngineParams[i].nextEngineParams.nextEngine== e_FM_PCD_CC) + { + p_FmPcdCcNextNode = (t_FmPcdCcNode*)p_FmPcdCcTree->keyAndNextEngineParams[i].nextEngineParams.params.ccParams.h_CcNode; + p_CcInformation = FindNodeInfoInReleventLst(&p_FmPcdCcNextNode->ccTreeIdLst, + (t_Handle)p_FmPcdCcTree, + p_FmPcdCcNextNode->h_Spinlock); + + if (!p_CcInformation) + { + memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation)); + ccNodeInfo.h_CcNode = (t_Handle)p_FmPcdCcTree; + ccNodeInfo.index = 1; + EnqueueNodeInfoToRelevantLst(&p_FmPcdCcNextNode->ccTreeIdLst, + &ccNodeInfo, + p_FmPcdCcNextNode->h_Spinlock); + } + else + p_CcInformation->index++; + } + } + + FmPcdIncNetEnvOwners(h_FmPcd, p_FmPcdCcTree->netEnvId); + p_CcTreeTmp = UINT_TO_PTR(p_FmPcdCcTree->ccTreeBaseAddr); + + if (!FmPcdLockTryLockAll(p_FmPcd)) + { + FM_PCD_CcRootDelete(p_FmPcdCcTree); + XX_Free(p_Params); + DBG(TRACE, ("FmPcdLockTryLockAll failed")); + return NULL; + } + + for (i = 0; i < numOfEntries; i++) + { + if (p_FmPcdCcTree->keyAndNextEngineParams[i].requiredAction) + { + err = SetRequiredAction(h_FmPcd, + p_FmPcdCcTree->keyAndNextEngineParams[i].requiredAction, + &p_FmPcdCcTree->keyAndNextEngineParams[i], + p_CcTreeTmp, + 1, + p_FmPcdCcTree); + if (err) + { + FmPcdLockUnlockAll(p_FmPcd); + FM_PCD_CcRootDelete(p_FmPcdCcTree); + XX_Free(p_Params); + REPORT_ERROR(MAJOR, E_NO_MEMORY, ("No memory")); + return NULL; + } + p_CcTreeTmp = PTR_MOVE(p_CcTreeTmp, FM_PCD_CC_AD_ENTRY_SIZE); + } + } + + FmPcdLockUnlockAll(p_FmPcd); + p_FmPcdCcTree->p_Lock = FmPcdAcquireLock(p_FmPcd); + if (!p_FmPcdCcTree->p_Lock) + { + FM_PCD_CcRootDelete(p_FmPcdCcTree); + XX_Free(p_Params); + REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM CC lock")); + return NULL; + } + + XX_Free(p_Params); + + return p_FmPcdCcTree; +} + +t_Error FM_PCD_CcRootDelete(t_Handle h_CcTree) +{ + t_FmPcd *p_FmPcd; + t_FmPcdCcTree *p_CcTree = (t_FmPcdCcTree *)h_CcTree; + int i= 0; + + SANITY_CHECK_RETURN_ERROR(p_CcTree,E_INVALID_STATE); + p_FmPcd = (t_FmPcd *)p_CcTree->h_FmPcd; + SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); + + FmPcdDecNetEnvOwners(p_FmPcd, p_CcTree->netEnvId); + + if (p_CcTree->owners) + RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("the tree with this ID can not be removed because this tree is occupied, first - unbind this tree")); + + /* Delete reassembly schemes if exist */ + if (p_CcTree->h_IpReassemblyManip) + { + FmPcdManipDeleteIpReassmSchemes(p_CcTree->h_IpReassemblyManip); + FmPcdManipUpdateOwner(p_CcTree->h_IpReassemblyManip, FALSE); + } + + for (i = 0; i <p_CcTree->numOfEntries; i++) + { + if (p_CcTree->keyAndNextEngineParams[i].nextEngineParams.nextEngine == e_FM_PCD_CC) + UpdateNodeOwner(p_CcTree->keyAndNextEngineParams[i].nextEngineParams.params.ccParams.h_CcNode, FALSE); + + if (p_CcTree->keyAndNextEngineParams[i].nextEngineParams.h_Manip) + FmPcdManipUpdateOwner(p_CcTree->keyAndNextEngineParams[i].nextEngineParams.h_Manip, FALSE); + +#ifdef FM_CAPWAP_SUPPORT + if ((p_CcTree->numOfGrps == 1) && + (p_CcTree->fmPcdGroupParam[0].numOfEntriesInGroup == 1) && + (p_CcTree->keyAndNextEngineParams[0].nextEngineParams.nextEngine == e_FM_PCD_CC) && + p_CcTree->keyAndNextEngineParams[0].nextEngineParams.params.ccParams.h_CcNode && + IsCapwapApplSpecific(p_CcTree->keyAndNextEngineParams[0].nextEngineParams.params.ccParams.h_CcNode)) + { + if (FM_PCD_ManipNodeDelete(p_CcTree->keyAndNextEngineParams[0].nextEngineParams.h_Manip) != E_OK) + return E_INVALID_STATE; + } +#endif /* FM_CAPWAP_SUPPORT */ + +#if (DPAA_VERSION >= 11) + if ((p_CcTree->keyAndNextEngineParams[i].nextEngineParams.nextEngine == e_FM_PCD_FR) && + (p_CcTree->keyAndNextEngineParams[i].nextEngineParams.params.frParams.h_FrmReplic)) + FrmReplicGroupUpdateOwner(p_CcTree->keyAndNextEngineParams[i].nextEngineParams.params.frParams.h_FrmReplic, + FALSE); +#endif /* (DPAA_VERSION >= 11) */ + } + + if (p_CcTree->p_Lock) + FmPcdReleaseLock(p_CcTree->h_FmPcd, p_CcTree->p_Lock); + + DeleteTree(p_CcTree, p_FmPcd); + + return E_OK; +} + +t_Error FM_PCD_CcRootModifyNextEngine(t_Handle h_CcTree, + uint8_t grpId, + uint8_t index, + t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams) +{ + t_FmPcd *p_FmPcd; + t_FmPcdCcTree *p_CcTree = (t_FmPcdCcTree *)h_CcTree; + t_Error err = E_OK; + + SANITY_CHECK_RETURN_ERROR(p_FmPcdCcNextEngineParams, E_NULL_POINTER); + SANITY_CHECK_RETURN_ERROR(p_CcTree,E_INVALID_STATE); + p_FmPcd = (t_FmPcd *)p_CcTree->h_FmPcd; + SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); + + if (!FmPcdLockTryLockAll(p_FmPcd)) + { + DBG(TRACE, ("FmPcdLockTryLockAll failed")); + return ERROR_CODE(E_BUSY); + } + + err = FmPcdCcModifyNextEngineParamTree(p_FmPcd, + p_CcTree, + grpId, + index, + p_FmPcdCcNextEngineParams); + FmPcdLockUnlockAll(p_FmPcd); + + if (err) + { + RETURN_ERROR(MAJOR, err, NO_MSG); + } + + return E_OK; +} + +t_Handle FM_PCD_MatchTableSet(t_Handle h_FmPcd, t_FmPcdCcNodeParams *p_CcNodeParam) +{ + t_FmPcdCcNode *p_CcNode; + t_Error err; + + SANITY_CHECK_RETURN_VALUE(h_FmPcd, E_INVALID_HANDLE, NULL); + SANITY_CHECK_RETURN_VALUE(p_CcNodeParam, E_NULL_POINTER, NULL); + + p_CcNode = (t_FmPcdCcNode*)XX_Malloc(sizeof(t_FmPcdCcNode)); + if (!p_CcNode) + { + REPORT_ERROR(MAJOR, E_NO_MEMORY, ("No memory")); + return NULL; + } + memset(p_CcNode, 0, sizeof(t_FmPcdCcNode)); + + err = FmPcdCcMatchTableSet(h_FmPcd, p_CcNode, p_CcNodeParam); + + switch (GET_ERROR_TYPE(err)) + { + case E_OK: + break; + + case E_BUSY: + DBG(TRACE, ("E_BUSY error")); + return NULL; + + default: + REPORT_ERROR(MAJOR, err, NO_MSG); + return NULL; + } + return p_CcNode; } @@ -6536,6 +6563,9 @@ t_Error FM_PCD_MatchTableGetKeyStatistics(t_Handle h_CcNode, intFlags = XX_LockIntrSpinlock(p_CcNode->h_Spinlock); + if (keyIndex >= p_CcNode->numOfKeys) + RETURN_ERROR(MAJOR, E_INVALID_STATE, ("The provided keyIndex exceeds the number of keys in this match table")); + err = MatchTableGetKeyStatistics(p_CcNode, keyIndex, p_KeyStatistics); @@ -6548,6 +6578,30 @@ t_Error FM_PCD_MatchTableGetKeyStatistics(t_Handle h_CcNode, return E_OK; } +t_Error FM_PCD_MatchTableGetMissStatistics(t_Handle h_CcNode, + t_FmPcdCcKeyStatistics *p_MissStatistics) +{ + t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode; + uint32_t intFlags; + t_Error err; + + SANITY_CHECK_RETURN_ERROR(h_CcNode, E_INVALID_HANDLE); + SANITY_CHECK_RETURN_ERROR(p_MissStatistics, E_NULL_POINTER); + + intFlags = XX_LockIntrSpinlock(p_CcNode->h_Spinlock); + + err = MatchTableGetKeyStatistics(p_CcNode, + p_CcNode->numOfKeys, + p_MissStatistics); + + XX_UnlockIntrSpinlock(p_CcNode->h_Spinlock, intFlags); + + if (err != E_OK) + RETURN_ERROR(MAJOR, err, NO_MSG); + + return E_OK; +} + t_Error FM_PCD_MatchTableFindNGetKeyStatistics(t_Handle h_CcNode, uint8_t keySize, uint8_t *p_Key, @@ -6572,6 +6626,8 @@ t_Error FM_PCD_MatchTableFindNGetKeyStatistics(t_Handle h_CcNode "match table of the provided node")); } + ASSERT_COND(keyIndex < p_CcNode->numOfKeys); + err = MatchTableGetKeyStatistics(p_CcNode, keyIndex, p_KeyStatistics); @@ -6624,10 +6680,13 @@ t_Handle FM_PCD_HashTableSet(t_Handle h_FmPcd, t_FmPcdHashTableParams *p_Param) { t_FmPcdCcNode *p_CcNodeHashTbl; t_FmPcdCcNodeParams *p_IndxHashCcNodeParam, *p_ExactMatchCcNodeParam; - t_Handle h_CcNode; + t_FmPcdCcNode *p_CcNode; + t_Handle h_MissStatsCounters = NULL; t_FmPcdCcKeyParams *p_HashKeyParams; int i; uint16_t numOfSets, numOfWays, countMask, onesCount = 0; + bool statsEnForMiss = FALSE; + t_Error err; SANITY_CHECK_RETURN_VALUE(h_FmPcd, E_INVALID_HANDLE, NULL); SANITY_CHECK_RETURN_VALUE(p_Param, E_NULL_POINTER, NULL); @@ -6684,6 +6743,28 @@ t_Handle FM_PCD_HashTableSet(t_Handle h_FmPcd, t_FmPcdHashTableParams *p_Param) if (p_Param->maxNumOfKeys % numOfSets) DBG(INFO, ("'maxNumOfKeys' is not a multiple of hash number of ways, so number of ways will be rounded up")); + if ((p_Param->statisticsMode == e_FM_PCD_CC_STATS_MODE_FRAME) || + (p_Param->statisticsMode == e_FM_PCD_CC_STATS_MODE_BYTE_AND_FRAME)) + { + /* Allocating a statistics counters table that will be used by all + 'miss' entries of the hash table */ + h_MissStatsCounters = (t_Handle)FM_MURAM_AllocMem(FmPcdGetMuramHandle(h_FmPcd), + 2 * FM_PCD_CC_STATS_COUNTER_SIZE, + FM_PCD_CC_AD_TABLE_ALIGN); + if (!h_MissStatsCounters) + { + REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for statistics table for hash miss")); + return NULL; + } + memset(h_MissStatsCounters, 0, (2 * FM_PCD_CC_STATS_COUNTER_SIZE)); + + /* Always enable statistics for 'miss', so that a statistics AD will be + initialized from the start. We'll store the requested 'statistics enable' + value and it will be used when statistics are read by the user. */ + statsEnForMiss = p_Param->ccNextEngineParamsForMiss.statisticsEn; + p_Param->ccNextEngineParamsForMiss.statisticsEn = TRUE; + } + /* Building exact-match node params, will be used to create the hash buckets */ p_ExactMatchCcNodeParam->extractCcParams.type = e_FM_PCD_EXTRACT_NON_HDR; @@ -6703,13 +6784,23 @@ t_Handle FM_PCD_HashTableSet(t_Handle h_FmPcd, t_FmPcdHashTableParams *p_Param) for (i = 0; i < numOfSets; i++) { - h_CcNode = FM_PCD_MatchTableSet(h_FmPcd, p_ExactMatchCcNodeParam); - if (!h_CcNode) + /* Each exact-match node will be marked as a 'bucket' and provided with a pointer to statistics counters, + to be used for 'miss' entry statistics */ + p_CcNode = (t_FmPcdCcNode *)XX_Malloc(sizeof(t_FmPcdCcNode)); + if (!p_CcNode) + break; + memset(p_CcNode, 0, sizeof(t_FmPcdCcNode)); + + p_CcNode->isHashBucket = TRUE; + p_CcNode->h_MissStatsCounters = h_MissStatsCounters; + + err = FmPcdCcMatchTableSet(h_FmPcd, p_CcNode, p_ExactMatchCcNodeParam); + if (err) break; p_HashKeyParams[i].ccNextEngineParams.nextEngine = e_FM_PCD_CC; p_HashKeyParams[i].ccNextEngineParams.statisticsEn = FALSE; - p_HashKeyParams[i].ccNextEngineParams.params.ccParams.h_CcNode = h_CcNode; + p_HashKeyParams[i].ccNextEngineParams.params.ccParams.h_CcNode = p_CcNode; } if (i < numOfSets) @@ -6717,6 +6808,8 @@ t_Handle FM_PCD_HashTableSet(t_Handle h_FmPcd, t_FmPcdHashTableParams *p_Param) for (i = i-1; i >=0; i--) FM_PCD_MatchTableDelete(p_HashKeyParams[i].ccNextEngineParams.params.ccParams.h_CcNode); + FM_MURAM_FreeMem(FmPcdGetMuramHandle(h_FmPcd), h_MissStatsCounters); + REPORT_ERROR(MAJOR, E_NULL_POINTER, NO_MSG); XX_Free(p_IndxHashCcNodeParam); XX_Free(p_ExactMatchCcNodeParam); @@ -6738,10 +6831,17 @@ t_Handle FM_PCD_HashTableSet(t_Handle h_FmPcd, t_FmPcdHashTableParams *p_Param) p_IndxHashCcNodeParam->keysParams.keySize = 2; p_CcNodeHashTbl = FM_PCD_MatchTableSet(h_FmPcd, p_IndxHashCcNodeParam); - + if (p_CcNodeHashTbl) p_CcNodeHashTbl->kgHashShift = p_Param->kgHashShift; - + + /* Storing the allocated counters for buckets 'miss' in the hash table + and is statistics for miss wre enabled. */ + p_CcNodeHashTbl->h_MissStatsCounters = h_MissStatsCounters; + p_CcNodeHashTbl->statsEnForMiss = statsEnForMiss; + + XX_Print("Hash 0x%x: 0x%x\n", p_CcNodeHashTbl, h_MissStatsCounters); + XX_Free(p_IndxHashCcNodeParam); XX_Free(p_ExactMatchCcNodeParam); @@ -6751,12 +6851,14 @@ t_Handle FM_PCD_HashTableSet(t_Handle h_FmPcd, t_FmPcdHashTableParams *p_Param) t_Error FM_PCD_HashTableDelete(t_Handle h_HashTbl) { t_FmPcdCcNode *p_HashTbl = (t_FmPcdCcNode *)h_HashTbl; - t_Handle *p_HashBuckets; + t_Handle h_FmPcd; + t_Handle *p_HashBuckets, h_MissStatsCounters; uint16_t i, numOfBuckets; t_Error err; SANITY_CHECK_RETURN_ERROR(p_HashTbl, E_INVALID_HANDLE); + /* Store all hash buckets before the hash is freed */ numOfBuckets = p_HashTbl->numOfKeys; p_HashBuckets = (t_Handle *)XX_Malloc(numOfBuckets * sizeof(t_Handle)); @@ -6766,14 +6868,23 @@ t_Error FM_PCD_HashTableDelete(t_Handle h_HashTbl) for (i = 0; i < numOfBuckets; i++) p_HashBuckets[i] = p_HashTbl->keyAndNextEngineParams[i].nextEngineParams.params.ccParams.h_CcNode; + h_FmPcd = p_HashTbl->h_FmPcd; + h_MissStatsCounters = p_HashTbl->h_MissStatsCounters; + + /* Free the hash */ err = FM_PCD_MatchTableDelete(p_HashTbl); + /* Free each hash bucket */ for (i = 0; i < numOfBuckets; i++) err |= FM_PCD_MatchTableDelete(p_HashBuckets[i]); if (err) RETURN_ERROR(MAJOR, err, NO_MSG); + /* Free statistics counters for 'miss', id these were allocated */ + if (h_MissStatsCounters) + FM_MURAM_FreeMem(FmPcdGetMuramHandle(h_FmPcd), h_MissStatsCounters); + XX_Free(p_HashBuckets); return E_OK; @@ -6879,11 +6990,29 @@ t_Error FM_PCD_HashTableModifyMissNextEngine(t_Handle h_HashTbl t_FmPcdCcNode *p_HashTbl = (t_FmPcdCcNode *)h_HashTbl; t_Handle h_HashBucket; uint8_t i; + bool nullifyMissStats = FALSE; t_Error err; SANITY_CHECK_RETURN_ERROR(h_HashTbl, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(p_FmPcdCcNextEngineParams, E_NULL_POINTER); + if ((!p_HashTbl->h_MissStatsCounters) && (p_FmPcdCcNextEngineParams->statisticsEn)) + RETURN_ERROR(MAJOR, E_CONFLICT, + ("Statistics are requested for a key, but statistics mode was set" + "to 'NONE' upon initialization")); + + if (p_HashTbl->h_MissStatsCounters) + { + if ((!p_HashTbl->statsEnForMiss) && (p_FmPcdCcNextEngineParams->statisticsEn)) + nullifyMissStats = TRUE; + + if ((p_HashTbl->statsEnForMiss) && (!p_FmPcdCcNextEngineParams->statisticsEn)) + { + p_HashTbl->statsEnForMiss = FALSE; + p_FmPcdCcNextEngineParams->statisticsEn = TRUE; + } + } + for (i = 0; i < p_HashTbl->numOfKeys; i++) { h_HashBucket = p_HashTbl->keyAndNextEngineParams[i].nextEngineParams.params.ccParams.h_CcNode; @@ -6894,6 +7023,13 @@ t_Error FM_PCD_HashTableModifyMissNextEngine(t_Handle h_HashTbl RETURN_ERROR(MAJOR, err, NO_MSG); } + if (nullifyMissStats) + { + memset(p_HashTbl->h_MissStatsCounters, 0, (2 * FM_PCD_CC_STATS_COUNTER_SIZE)); + memset(p_HashTbl->h_MissStatsCounters, 0, (2 * FM_PCD_CC_STATS_COUNTER_SIZE)); + p_HashTbl->statsEnForMiss = TRUE; + } + return E_OK; } @@ -6947,3 +7083,21 @@ t_Error FM_PCD_HashTableFindNGetKeyStatistics(t_Handle h_HashTbl NULL, p_KeyStatistics); } + +t_Error FM_PCD_HashTableGetMissStatistics(t_Handle h_HashTbl, + t_FmPcdCcKeyStatistics *p_MissStatistics) +{ + t_FmPcdCcNode *p_HashTbl = (t_FmPcdCcNode *)h_HashTbl; + t_Handle h_HashBucket; + + SANITY_CHECK_RETURN_ERROR(p_HashTbl, E_INVALID_HANDLE); + SANITY_CHECK_RETURN_ERROR(p_MissStatistics, E_NULL_POINTER); + + if (!p_HashTbl->statsEnForMiss) + RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Statistics were not enabled for miss")); + + h_HashBucket = p_HashTbl->keyAndNextEngineParams[0].nextEngineParams.params.ccParams.h_CcNode; + + return FM_PCD_MatchTableGetMissStatistics(h_HashBucket, + p_MissStatistics); +} diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_cc.h b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_cc.h index eeb43a2..997eb5d 100644 --- a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_cc.h +++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_cc.h @@ -310,6 +310,17 @@ typedef struct uint32_t numOfStatsFLRs; uint32_t countersArraySize; + bool isHashBucket; /**< Valid for match table node that is a bucket of a hash table only */ + t_Handle h_MissStatsCounters; /**< Valid for hash table node and match table that is a bucket; + Holds the statistics counters allocated by the hash table and + are shared by all hash table buckets; */ + t_Handle h_PrivMissStatsCounters; /**< Valid for match table node that is a bucket of a hash table only; + Holds the statistics counters that were allocated for this node + and replaced by the shared counters (allocated by the hash table); */ + bool statsEnForMiss; /**< Valid for hash table node only; TRUE is statistics are currently + enabled for hash 'miss', FALSE otherwise; This parameter effects the + returned statistics count to user, statistics AD always present for 'miss' + for all hash buckets; */ bool glblMaskUpdated; t_Handle p_GlblMask; bool lclMask; diff --git a/drivers/net/ethernet/freescale/fman/inc/Peripherals/fm_pcd_ext.h b/drivers/net/ethernet/freescale/fman/inc/Peripherals/fm_pcd_ext.h index e2199e4..00750ba 100644 --- a/drivers/net/ethernet/freescale/fman/inc/Peripherals/fm_pcd_ext.h +++ b/drivers/net/ethernet/freescale/fman/inc/Peripherals/fm_pcd_ext.h @@ -1058,7 +1058,9 @@ typedef enum e_FmPcdPlcrRateMode { *//***************************************************************************/ typedef enum e_FmPcdDoneAction { e_FM_PCD_ENQ_FRAME = 0, /**< Enqueue frame */ - e_FM_PCD_DROP_FRAME /**< Drop frame */ + e_FM_PCD_DROP_FRAME /**< Mark this frame as error frame and continue + to error flow; 'FM_PORT_FRM_ERR_CLS_DISCARD' + flag will be set for this frame. */ } e_FmPcdDoneAction; /**************************************************************************//** @@ -2070,8 +2072,7 @@ typedef struct t_FmPcdPlcrProfileParams { /**************************************************************************//** @Description Parameters for selecting a location for requested manipulation *//***************************************************************************/ -typedef struct t_FmManipHdrInfo -{ +typedef struct t_FmManipHdrInfo { e_NetHeaderType hdr; /**< Header selection */ e_FmPcdHdrIndex hdrIndex; /**< Relevant only for MPLS, VLAN and tunneled IP. Otherwise should be cleared. */ bool byField; /**< TRUE if the location of manipulation is according to some field in the specific header*/ @@ -2565,7 +2566,7 @@ typedef struct t_FmPcdManipParams { *//***************************************************************************/ typedef struct t_FmPcdManipReassemIpStats { /* common counters for both IPv4 and IPv6 */ - uint32_t timeout; /**< Counts the number of TimeOut occurrences */ + uint32_t timeout; /**< Counts the number of timeout occurrences */ uint32_t rfdPoolBusy; /**< Counts the number of failed attempts to allocate a Reassembly Frame Descriptor */ uint32_t internalBufferBusy; /**< Counts the number of times an internal buffer busy occurred */ @@ -2932,7 +2933,8 @@ t_Error FM_PCD_MatchTableDelete(t_Handle h_CcNode); @Return E_OK on success; Error code otherwise. - @Cautions Allowed only following FM_PCD_MatchTableSet(). + @Cautions Allowed only following FM_PCD_MatchTableSet(); + Not relevant in the case the node is of type 'INDEXED_LOOKUP'. *//***************************************************************************/ t_Error FM_PCD_MatchTableModifyMissNextEngine(t_Handle h_CcNode, t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams); @@ -3185,6 +3187,29 @@ t_Error FM_PCD_MatchTableGetKeyStatistics(t_Handle h_CcNode, t_FmPcdCcKeyStatistics *p_KeyStatistics); /**************************************************************************//** + @Function FM_PCD_MatchTableGetMissStatistics + + @Description This routine may be used to get statistics counters of miss entry + in a CC Node. + + If 'e_FM_PCD_CC_STATS_MODE_FRAME' and + 'e_FM_PCD_CC_STATS_MODE_BYTE_AND_FRAME' were set for this node, + these counters reflect how many frames were not matched to any + existing key and therefore passed through the miss entry; The + total frames count will be returned in the counter of the + first range (as only one frame length range was defined). + + @Param[in] h_CcNode A handle to the node + @Param[out] p_MissStatistics Statistics counters for 'miss' + + @Return The statistics for 'miss'. + + @Cautions Allowed only following FM_PCD_MatchTableSet(). +*//***************************************************************************/ +t_Error FM_PCD_MatchTableGetMissStatistics(t_Handle h_CcNode, + t_FmPcdCcKeyStatistics *p_MissStatistics); + +/**************************************************************************//** @Function FM_PCD_MatchTableFindNGetKeyStatistics @Description This routine may be used to get statistics counters of specific key @@ -3436,6 +3461,27 @@ t_Error FM_PCD_HashTableFindNGetKeyStatistics(t_Handle h_HashTbl t_FmPcdCcKeyStatistics *p_KeyStatistics); /**************************************************************************//** + @Function FM_PCD_HashTableGetMissStatistics + + @Description This routine may be used to get statistics counters of 'miss' + entry of the a hash table. + + If 'e_FM_PCD_CC_STATS_MODE_FRAME' and + 'e_FM_PCD_CC_STATS_MODE_BYTE_AND_FRAME' were set for this node, + these counters reflect how many frames were not matched to any + existing key and therefore passed through the miss entry; + + @Param[in] h_HashTbl A handle to a hash table + @Param[out] p_MissStatistics Statistics counters for 'miss' + + @Return The statistics for 'miss'. + + @Cautions Allowed only following FM_PCD_HashTableSet(). +*//***************************************************************************/ +t_Error FM_PCD_HashTableGetMissStatistics(t_Handle h_HashTbl, + t_FmPcdCcKeyStatistics *p_MissStatistics); + +/**************************************************************************//** @Function FM_PCD_ManipNodeSet @Description This routine should be called for defining a manipulation diff --git a/drivers/net/ethernet/freescale/fman/inc/integrations/T4240/dpaa_integration_ext.h b/drivers/net/ethernet/freescale/fman/inc/integrations/T4240/dpaa_integration_ext.h index 52ed8f8..b6780b9 100644 --- a/drivers/net/ethernet/freescale/fman/inc/integrations/T4240/dpaa_integration_ext.h +++ b/drivers/net/ethernet/freescale/fman/inc/integrations/T4240/dpaa_integration_ext.h @@ -256,6 +256,9 @@ typedef enum #define FM_DEQ_PIPELINE_PARAMS_FOR_OP #define FM_QMI_NO_SINGLE_ECC_EXCEPTION + +#define FM_NO_GUARANTEED_RESET_VALUES + /* FM errata */ #define FM_HEAVY_TRAFFIC_HANG_ERRATA_FMAN_A005669 #define FM_WRONG_RESET_VALUES_ERRATA_FMAN_A005127 diff --git a/drivers/net/ethernet/freescale/fman/src/inc/wrapper/lnxwrp_exp_sym.h b/drivers/net/ethernet/freescale/fman/src/inc/wrapper/lnxwrp_exp_sym.h index 4c60893..13c61d2 100644 --- a/drivers/net/ethernet/freescale/fman/src/inc/wrapper/lnxwrp_exp_sym.h +++ b/drivers/net/ethernet/freescale/fman/src/inc/wrapper/lnxwrp_exp_sym.h @@ -88,6 +88,8 @@ EXPORT_SYMBOL(FM_PCD_MatchTableGetNextEngine); EXPORT_SYMBOL(FM_PCD_MatchTableGetKeyCounter); EXPORT_SYMBOL(FM_PCD_MatchTableGetKeyStatistics); EXPORT_SYMBOL(FM_PCD_MatchTableFindNGetKeyStatistics); +EXPORT_SYMBOL(FM_PCD_MatchTableGetMissStatistics); +EXPORT_SYMBOL(FM_PCD_HashTableGetMissStatistics); EXPORT_SYMBOL(FM_PCD_HashTableSet); EXPORT_SYMBOL(FM_PCD_HashTableDelete); EXPORT_SYMBOL(FM_PCD_HashTableAddKey); diff --git a/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_ioctls_fm.c b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_ioctls_fm.c index 8121a12..d896b27 100644 --- a/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_ioctls_fm.c +++ b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_ioctls_fm.c @@ -1934,6 +1934,155 @@ invalid_port_id: XX_Free(param); break; } + + +#if defined(CONFIG_COMPAT) + case FM_PCD_IOC_MATCH_TABLE_GET_MISS_STAT_COMPAT: +#endif + case FM_PCD_IOC_MATCH_TABLE_GET_MISS_STAT: + { + ioc_fm_pcd_cc_tbl_get_miss_params_t param; + +#if defined(CONFIG_COMPAT) + if (compat) + { + ioc_compat_fm_pcd_cc_tbl_get_miss_params_t *compat_param; + + compat_param = (ioc_compat_fm_pcd_cc_tbl_get_miss_params_t *) XX_Malloc( + sizeof(ioc_compat_fm_pcd_cc_tbl_get_miss_params_t)); + if (!compat_param) + RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); + + memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_cc_tbl_get_miss_params_t)); + if (copy_from_user(compat_param, + (ioc_compat_fm_pcd_cc_tbl_get_miss_params_t *)compat_ptr(arg), + sizeof(ioc_compat_fm_pcd_cc_tbl_get_miss_params_t))) + { + XX_Free(compat_param); + RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); + } + + compat_copy_fm_pcd_cc_tbl_get_miss(compat_param, ¶m, COMPAT_US_TO_K); + + XX_Free(compat_param); + } + else +#endif + { + if (copy_from_user(¶m, (ioc_fm_pcd_cc_tbl_get_miss_params_t *)arg, + sizeof(ioc_fm_pcd_cc_tbl_get_miss_params_t))) + RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); + } + + + err = FM_PCD_MatchTableGetMissStatistics((t_Handle) param.id, + (t_FmPcdCcKeyStatistics *) ¶m.miss_statistics); + +#if defined(CONFIG_COMPAT) + if (compat) + { + ioc_compat_fm_pcd_cc_tbl_get_miss_params_t *compat_param; + + compat_param = (ioc_compat_fm_pcd_cc_tbl_get_miss_params_t*) XX_Malloc( + sizeof(ioc_compat_fm_pcd_cc_tbl_get_miss_params_t)); + if (!compat_param) + RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); + + memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_cc_tbl_get_miss_params_t)); + compat_copy_fm_pcd_cc_tbl_get_miss(compat_param, ¶m, COMPAT_K_TO_US); + if (copy_to_user((ioc_compat_fm_pcd_cc_tbl_get_miss_params_t*) compat_ptr(arg), + compat_param, + sizeof(ioc_compat_fm_pcd_cc_tbl_get_miss_params_t))) + RETURN_ERROR(MINOR, E_READ_FAILED, NO_MSG); + + XX_Free(compat_param); + } + else +#endif + { + if (copy_to_user((ioc_fm_pcd_hash_table_params_t *)arg, + ¶m, + sizeof(ioc_fm_pcd_cc_tbl_get_miss_params_t))) + RETURN_ERROR(MINOR, E_READ_FAILED, NO_MSG); + } + + break; + } + + +#if defined(CONFIG_COMPAT) + case FM_PCD_IOC_HASH_TABLE_GET_MISS_STAT_COMPAT: +#endif + case FM_PCD_IOC_HASH_TABLE_GET_MISS_STAT: + { + ioc_fm_pcd_cc_tbl_get_miss_params_t param; + +#if defined(CONFIG_COMPAT) + if (compat) + { + ioc_compat_fm_pcd_cc_tbl_get_miss_params_t *compat_param; + + compat_param = (ioc_compat_fm_pcd_cc_tbl_get_miss_params_t *) XX_Malloc( + sizeof(ioc_compat_fm_pcd_cc_tbl_get_miss_params_t)); + if (!compat_param) + RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); + + memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_cc_tbl_get_miss_params_t)); + if (copy_from_user(compat_param, + (ioc_compat_fm_pcd_cc_tbl_get_miss_params_t *)compat_ptr(arg), + sizeof(ioc_compat_fm_pcd_cc_tbl_get_miss_params_t))) + { + XX_Free(compat_param); + RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); + } + + compat_copy_fm_pcd_cc_tbl_get_miss(compat_param, ¶m, COMPAT_US_TO_K); + + XX_Free(compat_param); + } + else +#endif + { + if (copy_from_user(¶m, (ioc_fm_pcd_cc_tbl_get_miss_params_t *)arg, + sizeof(ioc_fm_pcd_cc_tbl_get_miss_params_t))) + RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); + } + + + err = FM_PCD_HashTableGetMissStatistics((t_Handle) param.id, + (t_FmPcdCcKeyStatistics *) ¶m.miss_statistics); + +#if defined(CONFIG_COMPAT) + if (compat) + { + ioc_compat_fm_pcd_cc_tbl_get_miss_params_t *compat_param; + + compat_param = (ioc_compat_fm_pcd_cc_tbl_get_miss_params_t*) XX_Malloc( + sizeof(ioc_compat_fm_pcd_cc_tbl_get_miss_params_t)); + if (!compat_param) + RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); + + memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_cc_tbl_get_miss_params_t)); + compat_copy_fm_pcd_cc_tbl_get_miss(compat_param, ¶m, COMPAT_K_TO_US); + if (copy_to_user((ioc_compat_fm_pcd_cc_tbl_get_miss_params_t*) compat_ptr(arg), + compat_param, + sizeof(ioc_compat_fm_pcd_cc_tbl_get_miss_params_t))) + RETURN_ERROR(MINOR, E_READ_FAILED, NO_MSG); + + XX_Free(compat_param); + } + else +#endif + { + if (copy_to_user((ioc_fm_pcd_hash_table_params_t *)arg, + ¶m, + sizeof(ioc_fm_pcd_cc_tbl_get_miss_params_t))) + RETURN_ERROR(MINOR, E_READ_FAILED, NO_MSG); + } + + break; + } + #if defined(CONFIG_COMPAT) case FM_PCD_IOC_HASH_TABLE_SET_COMPAT: #endif diff --git a/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_ioctls_fm_compat.c b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_ioctls_fm_compat.c index 68142b6..3c1ac30 100644 --- a/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_ioctls_fm_compat.c +++ b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_ioctls_fm_compat.c @@ -506,7 +506,7 @@ void compat_copy_fm_pcd_hash_table( { if (compat == COMPAT_US_TO_K) { - param-> max_num_of_keys = compat_param->max_num_of_keys; + param->max_num_of_keys = compat_param->max_num_of_keys; param->statistics_mode = compat_param->statistics_mode; param->kg_hash_shift = compat_param->kg_hash_shift; param->hash_res_mask = compat_param->hash_res_mask; @@ -516,7 +516,7 @@ void compat_copy_fm_pcd_hash_table( } else { - compat_param-> max_num_of_keys = param->max_num_of_keys; + compat_param->max_num_of_keys = param->max_num_of_keys; compat_param->statistics_mode = param->statistics_mode; compat_param->kg_hash_shift = param->kg_hash_shift; compat_param->hash_res_mask = param->hash_res_mask; @@ -844,6 +844,22 @@ void compat_copy_fm_port_vsp_alloc_params( } #endif /* (DPAA_VERSION >= 11) */ +void compat_copy_fm_pcd_cc_tbl_get_miss( + ioc_compat_fm_pcd_cc_tbl_get_miss_params_t *compat_param, + ioc_fm_pcd_cc_tbl_get_miss_params_t *param, + uint8_t compat) +{ + if (compat == COMPAT_US_TO_K) + { + param->id = compat_pcd_id2ptr(compat_param->id); + memcpy(¶m->miss_statistics, &compat_param->miss_statistics, sizeof(ioc_fm_pcd_cc_key_statistics_t)); + } else { + compat_param->id = compat_add_ptr2id(param->id, FM_MAP_TYPE_PCD_NODE); + memcpy(&compat_param->miss_statistics, ¶m->miss_statistics, sizeof(ioc_fm_pcd_cc_key_statistics_t)); + } +} + + void compat_copy_fm_pcd_net_env( ioc_compat_fm_pcd_net_env_params_t *compat_param, ioc_fm_pcd_net_env_params_t *param, diff --git a/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_ioctls_fm_compat.h b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_ioctls_fm_compat.h index f8655db..ae19b68 100644 --- a/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_ioctls_fm_compat.h +++ b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_ioctls_fm_compat.h @@ -521,6 +521,12 @@ typedef struct ioc_compat_fm_ctrl_mon_counters_params_t { compat_uptr_t p_mon; } ioc_compat_fm_ctrl_mon_counters_params_t; +typedef struct ioc_compat_fm_pcd_cc_tbl_get_miss_params_t { + compat_uptr_t id; + ioc_fm_pcd_cc_key_statistics_t miss_statistics; +} ioc_compat_fm_pcd_cc_tbl_get_miss_params_t; + + /* } pcd compat structures */ void compat_obj_delete( @@ -568,6 +574,11 @@ void compat_copy_fm_pcd_cc_tree( ioc_fm_pcd_cc_tree_params_t *param, uint8_t compat); +void compat_copy_fm_pcd_cc_tbl_get_miss( + ioc_compat_fm_pcd_cc_tbl_get_miss_params_t *compat_param, + ioc_fm_pcd_cc_tbl_get_miss_params_t *param, + uint8_t compat); + void compat_fm_pcd_prs_sw( ioc_compat_fm_pcd_prs_sw_params_t *compat_param, ioc_fm_pcd_prs_sw_params_t *param, diff --git a/drivers/staging/fsl_dpa_offload/dpa_classifier.c b/drivers/staging/fsl_dpa_offload/dpa_classifier.c index a39fc69..5056b2e 100644 --- a/drivers/staging/fsl_dpa_offload/dpa_classifier.c +++ b/drivers/staging/fsl_dpa_offload/dpa_classifier.c @@ -462,6 +462,9 @@ int dpa_classif_table_modify_miss_action(int td, return -EBUSY; } } + + memcpy(&ptable->miss_action, miss_action, sizeof(*miss_action)); + RELEASE_OBJECT(ptable); dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) <--\n", __func__, @@ -3230,6 +3233,26 @@ static inline void key_apply_mask(const struct dpa_offload_lookup_key *key, new_key[i] = key->byte[i] & key->mask[i]; } +int dpa_classif_get_miss_action(int td, struct dpa_cls_tbl_action *miss_action) +{ + struct dpa_cls_table *ptable; + + if (!miss_action) + return -EINVAL; + + LOCK_OBJECT(table_array, td, ptable, -EINVAL); + if (ptable->miss_action.type == DPA_CLS_TBL_ACTION_NONE) { + /* No miss action was specified for this table */ + RELEASE_OBJECT(ptable); + return -ENODEV; + } else + memcpy(miss_action, &ptable->miss_action, sizeof(*miss_action)); + + RELEASE_OBJECT(ptable); + + return 0; +} + static int nat_hm_check_params(const struct dpa_cls_hm_nat_params *nat_params) { unsigned int ip_ver = 0; diff --git a/drivers/staging/fsl_dpa_offload/dpa_classifier.h b/drivers/staging/fsl_dpa_offload/dpa_classifier.h index 0667782..659e1b7 100644 --- a/drivers/staging/fsl_dpa_offload/dpa_classifier.h +++ b/drivers/staging/fsl_dpa_offload/dpa_classifier.h @@ -206,6 +206,9 @@ struct dpa_cls_table { /* (Initial) parameters of the DPA Classifier table. */ struct dpa_cls_tbl_params params; + /* Table miss action. */ + struct dpa_cls_tbl_action miss_action; + /* Access control object for this table to avoid race conditions. */ struct mutex access; }; @@ -675,6 +678,12 @@ int dpa_classif_import_static_hm(void *hm, int next_hmd, int *hmd); void *dpa_classif_get_static_hm_handle(int hmd); /* + * Provides details about the miss action configured on a classification + * table. + */ +int dpa_classif_get_miss_action(int td, struct dpa_cls_tbl_action *miss_action); + +/* * Locks a header manipulation chain (marks as "used"). The header manipulation * operations cannot be removed as long as they are locked. The function * provides the FMan driver handle of the manip node which is chain head. diff --git a/drivers/staging/fsl_dpa_offload/dts/b4860qds-usdpaa-shared-interfaces.dts b/drivers/staging/fsl_dpa_offload/dts/b4860qds-usdpaa-shared-interfaces.dts index 537d3f2..7baa9b1 100644 --- a/drivers/staging/fsl_dpa_offload/dts/b4860qds-usdpaa-shared-interfaces.dts +++ b/drivers/staging/fsl_dpa_offload/dts/b4860qds-usdpaa-shared-interfaces.dts @@ -149,7 +149,7 @@ /* Define frame queues for the OH port*/ /* <OH Rx error, OH Rx default> */ fsl,qman-frame-queues-oh = <0x6e 1 0x6f 1>; - fsl,bman-buffer-pools = <&bp9>; + fsl,bman-buffer-pools = <&bp16>; fsl,fman-oh-port = <&fman0_oh2>; }; dpa_fman0_oh3: dpa-fman0-oh@3 { diff --git a/drivers/staging/fsl_qbman/fsl_usdpaa.c b/drivers/staging/fsl_qbman/fsl_usdpaa.c index 5d0eb4c..633a1a9 100644 --- a/drivers/staging/fsl_qbman/fsl_usdpaa.c +++ b/drivers/staging/fsl_qbman/fsl_usdpaa.c @@ -349,7 +349,8 @@ static int init_qm_portal(struct qm_portal_config *config, } /* Initialize the EQCR */ - if (qm_eqcr_init(portal, qm_eqcr_pvb, qm_eqcr_cce)) { + if (qm_eqcr_init(portal, qm_eqcr_pvb, + portal->eqcr.use_eqcr_ci_stashing ? 3 : 0, 1)) { pr_err("Qman EQCR initialisation failed\n"); return 1; } @@ -486,6 +487,18 @@ __maybe_unused static void dump_frags(void) } +__maybe_unused static void dump_frags(void) +{ + struct mem_fragment *frag; + int i = 0; + list_for_each_entry(frag, &mem_list, list) { + pr_info("FRAG %d: base 0x%llx len 0x%llx root_len 0x%llx\n", + i, frag->base, frag->len, frag->root_len); + ++i; + } +} + + static int usdpaa_release(struct inode *inode, struct file *filp) { struct ctx *ctx = filp->private_data; diff --git a/drivers/staging/fsl_qbman/qman_high.c b/drivers/staging/fsl_qbman/qman_high.c index e5e52b7..c8451f1 100644 --- a/drivers/staging/fsl_qbman/qman_high.c +++ b/drivers/staging/fsl_qbman/qman_high.c @@ -361,9 +361,6 @@ loop: goto loop; } - - - struct qman_portal *qman_create_portal( struct qman_portal *portal, const struct qm_portal_config *config, @@ -382,12 +379,20 @@ struct qman_portal *qman_create_portal( __p = &portal->p; + portal->p.eqcr.use_eqcr_ci_stashing = ((qman_ip_rev >= QMAN_REV30) ? + 1 : 0); + /* prep the low-level portal struct with the mapped addresses from the * config, everything that follows depends on it and "config" is more * for (de)reference... */ __p->addr.addr_ce = config->addr_virt[DPA_PORTAL_CE]; __p->addr.addr_ci = config->addr_virt[DPA_PORTAL_CI]; - if (qm_eqcr_init(__p, qm_eqcr_pvb, qm_eqcr_cce)) { + /* + * If CI-stashing is used, the current defaults use a threshold of 3, + * and stash with high-than-DQRR priority. + */ + if (qm_eqcr_init(__p, qm_eqcr_pvb, + portal->p.eqcr.use_eqcr_ci_stashing ? 3 : 0, 1)) { pr_err("Qman EQCR initialisation failed\n"); goto fail_eqcr; } @@ -1986,10 +1991,23 @@ static inline struct qm_eqcr_entry *try_eq_start(struct qman_portal **p, (*p)->eqci_owned = fq; } #endif - avail = qm_eqcr_get_avail(&(*p)->p); - if (avail < 2) - update_eqcr_ci(*p, avail); - eq = qm_eqcr_start(&(*p)->p); + if ((*p)->p.eqcr.use_eqcr_ci_stashing) { + /* + * The stashing case is easy, only update if we need to in + * order to try and liberate ring entries. + */ + eq = qm_eqcr_start_stash(&(*p)->p); + } else { + /* + * The non-stashing case is harder, need to prefetch ahead of + * time. + */ + avail = qm_eqcr_get_avail(&(*p)->p); + if (avail < 2) + update_eqcr_ci(*p, avail); + eq = qm_eqcr_start_no_stash(&(*p)->p); + } + if (unlikely(!eq)) { #ifdef CONFIG_FSL_DPA_CAN_WAIT_SYNC if (unlikely((flags & QMAN_ENQUEUE_FLAG_WAIT) && diff --git a/drivers/staging/fsl_qbman/qman_low.h b/drivers/staging/fsl_qbman/qman_low.h index d63c722..0b5f16c 100644 --- a/drivers/staging/fsl_qbman/qman_low.h +++ b/drivers/staging/fsl_qbman/qman_low.h @@ -131,10 +131,6 @@ enum qm_eqcr_pmode { /* matches QCSP_CFG::EPM */ qm_eqcr_pce = 1, /* PI index, cache-enabled */ qm_eqcr_pvb = 2 /* valid-bit */ }; -enum qm_eqcr_cmode { /* s/w-only */ - qm_eqcr_cci, /* CI index, cache-inhibited */ - qm_eqcr_cce /* CI index, cache-enabled */ -}; enum qm_dqrr_dmode { /* matches QCSP_CFG::DP */ qm_dqrr_dpush = 0, /* SDQCR + VDQCR */ qm_dqrr_dpull = 1 /* PDQCR */ @@ -170,10 +166,10 @@ enum qm_mr_cmode { /* matches QCSP_CFG::MM */ struct qm_eqcr { struct qm_eqcr_entry *ring, *cursor; u8 ci, available, ithresh, vbit; + u32 use_eqcr_ci_stashing; #ifdef CONFIG_FSL_DPA_CHECKING u32 busy; enum qm_eqcr_pmode pmode; - enum qm_eqcr_cmode cmode; #endif }; @@ -283,7 +279,8 @@ static inline void EQCR_INC(struct qm_eqcr *eqcr) static inline int qm_eqcr_init(struct qm_portal *portal, enum qm_eqcr_pmode pmode, - __maybe_unused enum qm_eqcr_cmode cmode) + unsigned int eq_stash_thresh, + int eq_stash_prio) { /* This use of 'register', as well as all other occurances, is because * it has been observed to generate much faster code with gcc than is @@ -305,9 +302,10 @@ static inline int qm_eqcr_init(struct qm_portal *portal, #ifdef CONFIG_FSL_DPA_CHECKING eqcr->busy = 0; eqcr->pmode = pmode; - eqcr->cmode = cmode; #endif cfg = (qm_in(CFG) & 0x00ffffff) | + (eq_stash_thresh << 28) | /* QCSP_CFG: EST */ + (eq_stash_prio << 26) | /* QCSP_CFG: EP */ ((pmode & 0x3) << 24); /* QCSP_CFG::EPM */ qm_out(CFG, cfg); return 0; @@ -328,7 +326,8 @@ static inline void qm_eqcr_finish(struct qm_portal *portal) pr_crit("EQCR destroyed unquiesced\n"); } -static inline struct qm_eqcr_entry *qm_eqcr_start(struct qm_portal *portal) +static inline struct qm_eqcr_entry *qm_eqcr_start_no_stash(struct qm_portal + *portal) { register struct qm_eqcr *eqcr = &portal->eqcr; DPA_ASSERT(!eqcr->busy); @@ -343,6 +342,28 @@ static inline struct qm_eqcr_entry *qm_eqcr_start(struct qm_portal *portal) return eqcr->cursor; } +static inline struct qm_eqcr_entry *qm_eqcr_start_stash(struct qm_portal + *portal) +{ + register struct qm_eqcr *eqcr = &portal->eqcr; + u8 diff, old_ci; + + DPA_ASSERT(!eqcr->busy); + if (!eqcr->available) { + old_ci = eqcr->ci; + eqcr->ci = qm_cl_in(EQCR_CI) & (QM_EQCR_SIZE - 1); + diff = qm_cyc_diff(QM_EQCR_SIZE, old_ci, eqcr->ci); + eqcr->available += diff; + if (!diff) + return NULL; + } +#ifdef CONFIG_FSL_DPA_CHECKING + eqcr->busy = 1; +#endif + dcbz_64(eqcr->cursor); + return eqcr->cursor; +} + static inline void qm_eqcr_abort(struct qm_portal *portal) { __maybe_unused register struct qm_eqcr *eqcr = &portal->eqcr; @@ -436,7 +457,6 @@ static inline u8 qm_eqcr_cci_update(struct qm_portal *portal) { register struct qm_eqcr *eqcr = &portal->eqcr; u8 diff, old_ci = eqcr->ci; - DPA_ASSERT(eqcr->cmode == qm_eqcr_cci); eqcr->ci = qm_in(EQCR_CI_CINH) & (QM_EQCR_SIZE - 1); diff = qm_cyc_diff(QM_EQCR_SIZE, old_ci, eqcr->ci); eqcr->available += diff; @@ -446,7 +466,6 @@ static inline u8 qm_eqcr_cci_update(struct qm_portal *portal) static inline void qm_eqcr_cce_prefetch(struct qm_portal *portal) { __maybe_unused register struct qm_eqcr *eqcr = &portal->eqcr; - DPA_ASSERT(eqcr->cmode == qm_eqcr_cce); qm_cl_touch_ro(EQCR_CI); } @@ -454,7 +473,6 @@ static inline u8 qm_eqcr_cce_update(struct qm_portal *portal) { register struct qm_eqcr *eqcr = &portal->eqcr; u8 diff, old_ci = eqcr->ci; - DPA_ASSERT(eqcr->cmode == qm_eqcr_cce); eqcr->ci = qm_cl_in(EQCR_CI) & (QM_EQCR_SIZE - 1); qm_cl_invalidate(EQCR_CI); diff = qm_cyc_diff(QM_EQCR_SIZE, old_ci, eqcr->ci); diff --git a/include/uapi/linux/fmd/Peripherals/fm_pcd_ioctls.h b/include/uapi/linux/fmd/Peripherals/fm_pcd_ioctls.h index 7925905..542f935 100644 --- a/include/uapi/linux/fmd/Peripherals/fm_pcd_ioctls.h +++ b/include/uapi/linux/fmd/Peripherals/fm_pcd_ioctls.h @@ -2107,6 +2107,80 @@ typedef struct ioc_fm_pcd_frm_replic_member_params_t { } ioc_fm_pcd_frm_replic_member_params_t; #endif /* DPAA_VERSION >= 11 */ + +typedef struct ioc_fm_pcd_cc_key_statistics_t { + uint32_t byte_count; /**< This counter reflects byte count of frames that + were matched by this key. */ + uint32_t frame_count; /**< This counter reflects count of frames that + were matched by this key. */ +#if (DPAA_VERSION >= 11) + uint32_t frame_length_range_count[IOC_FM_PCD_CC_STATS_MAX_NUM_OF_FLR]; + /**< These counters reflect how many frames matched + this key in 'RMON' statistics mode: + Each counter holds the number of frames of a + specific frames length range, according to the + ranges provided at initialization. */ +#endif /* (DPAA_VERSION >= 11) */ +} ioc_fm_pcd_cc_key_statistics_t; + + +typedef struct ioc_fm_pcd_cc_tbl_get_miss_params_t { + void *id; + ioc_fm_pcd_cc_key_statistics_t miss_statistics; +} ioc_fm_pcd_cc_tbl_get_miss_params_t; + + +/**************************************************************************//** + @Function FM_PCD_MatchTableGetMissStatistics + + @Description This routine may be used to get statistics counters of miss entry + in a CC Node. + + If 'e_FM_PCD_CC_STATS_MODE_FRAME' and + 'e_FM_PCD_CC_STATS_MODE_BYTE_AND_FRAME' were set for this node, + these counters reflect how many frames were not matched to any + existing key and therefore passed through the miss entry; The + total frames count will be returned in the counter of the + first range (as only one frame length range was defined). + + @Param[in] h_CcNode A handle to the node + @Param[out] p_MissStatistics Statistics counters for 'miss' + + @Return E_OK on success; Error code otherwise. + + @Cautions Allowed only following FM_PCD_MatchTableSet(). +*//***************************************************************************/ + +#if defined(CONFIG_COMPAT) +#define FM_PCD_IOC_MATCH_TABLE_GET_MISS_STAT_COMPAT _IOWR(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(12), ioc_compat_fm_pcd_cc_tbl_get_miss_params_t) +#endif +#define FM_PCD_IOC_MATCH_TABLE_GET_MISS_STAT _IOWR(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(12), ioc_fm_pcd_cc_tbl_get_miss_params_t) + +/**************************************************************************//** + @Function FM_PCD_HashTableGetMissStatistics + + @Description This routine may be used to get statistics counters of 'miss' + entry of the a hash table. + + If 'e_FM_PCD_CC_STATS_MODE_FRAME' and + 'e_FM_PCD_CC_STATS_MODE_BYTE_AND_FRAME' were set for this node, + these counters reflect how many frames were not matched to any + existing key and therefore passed through the miss entry; + + @Param[in] h_HashTbl A handle to a hash table + @Param[out] p_MissStatistics Statistics counters for 'miss' + + @Return E_OK on success; Error code otherwise. + + @Cautions Allowed only following FM_PCD_HashTableSet(). +*//***************************************************************************/ + +#if defined(CONFIG_COMPAT) +#define FM_PCD_IOC_HASH_TABLE_GET_MISS_STAT_COMPAT _IOWR(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(13), ioc_compat_fm_pcd_cc_tbl_get_miss_params_t) +#endif +#define FM_PCD_IOC_HASH_TABLE_GET_MISS_STAT _IOWR(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(13), ioc_fm_pcd_cc_tbl_get_miss_params_t) + + /**************************************************************************//** @Function FM_PCD_NetEnvCharacteristicsSet |