Path: blob/main/sys/contrib/ncsw/Peripherals/FM/Pcd/fm_plcr.c
48524 views
/*1* Copyright 2008-2012 Freescale Semiconductor Inc.2*3* Redistribution and use in source and binary forms, with or without4* modification, are permitted provided that the following conditions are met:5* * Redistributions of source code must retain the above copyright6* notice, this list of conditions and the following disclaimer.7* * Redistributions in binary form must reproduce the above copyright8* notice, this list of conditions and the following disclaimer in the9* documentation and/or other materials provided with the distribution.10* * Neither the name of Freescale Semiconductor nor the11* names of its contributors may be used to endorse or promote products12* derived from this software without specific prior written permission.13*14*15* ALTERNATIVELY, this software may be distributed under the terms of the16* GNU General Public License ("GPL") as published by the Free Software17* Foundation, either version 2 of that License or (at your option) any18* later version.19*20* THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY21* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED22* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE23* DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY24* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES25* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;26* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND27* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT28* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS29* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.30*/313233/******************************************************************************34@File fm_plcr.c3536@Description FM PCD POLICER...37*//***************************************************************************/38#include <linux/math64.h>39#include "std_ext.h"40#include "error_ext.h"41#include "string_ext.h"42#include "debug_ext.h"43#include "net_ext.h"44#include "fm_ext.h"4546#include "fm_common.h"47#include "fm_pcd.h"48#include "fm_hc.h"49#include "fm_pcd_ipc.h"50#include "fm_plcr.h"515253/****************************************/54/* static functions */55/****************************************/5657static uint32_t PlcrProfileLock(t_Handle h_Profile)58{59ASSERT_COND(h_Profile);60return FmPcdLockSpinlock(((t_FmPcdPlcrProfile *)h_Profile)->p_Lock);61}6263static void PlcrProfileUnlock(t_Handle h_Profile, uint32_t intFlags)64{65ASSERT_COND(h_Profile);66FmPcdUnlockSpinlock(((t_FmPcdPlcrProfile *)h_Profile)->p_Lock, intFlags);67}6869static bool PlcrProfileFlagTryLock(t_Handle h_Profile)70{71ASSERT_COND(h_Profile);72return FmPcdLockTryLock(((t_FmPcdPlcrProfile *)h_Profile)->p_Lock);73}7475static void PlcrProfileFlagUnlock(t_Handle h_Profile)76{77ASSERT_COND(h_Profile);78FmPcdLockUnlock(((t_FmPcdPlcrProfile *)h_Profile)->p_Lock);79}8081static uint32_t PlcrHwLock(t_Handle h_FmPcdPlcr)82{83ASSERT_COND(h_FmPcdPlcr);84return XX_LockIntrSpinlock(((t_FmPcdPlcr*)h_FmPcdPlcr)->h_HwSpinlock);85}8687static void PlcrHwUnlock(t_Handle h_FmPcdPlcr, uint32_t intFlags)88{89ASSERT_COND(h_FmPcdPlcr);90XX_UnlockIntrSpinlock(((t_FmPcdPlcr*)h_FmPcdPlcr)->h_HwSpinlock, intFlags);91}9293static uint32_t PlcrSwLock(t_Handle h_FmPcdPlcr)94{95ASSERT_COND(h_FmPcdPlcr);96return XX_LockIntrSpinlock(((t_FmPcdPlcr*)h_FmPcdPlcr)->h_SwSpinlock);97}9899static void PlcrSwUnlock(t_Handle h_FmPcdPlcr, uint32_t intFlags)100{101ASSERT_COND(h_FmPcdPlcr);102XX_UnlockIntrSpinlock(((t_FmPcdPlcr*)h_FmPcdPlcr)->h_SwSpinlock, intFlags);103}104105static bool IsProfileShared(t_Handle h_FmPcd, uint16_t absoluteProfileId)106{107t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;108uint16_t i;109110SANITY_CHECK_RETURN_VALUE(p_FmPcd, E_INVALID_HANDLE, FALSE);111112for (i=0;i<p_FmPcd->p_FmPcdPlcr->numOfSharedProfiles;i++)113if (p_FmPcd->p_FmPcdPlcr->sharedProfilesIds[i] == absoluteProfileId)114return TRUE;115return FALSE;116}117118static t_Error SetProfileNia(t_FmPcd *p_FmPcd, e_FmPcdEngine nextEngine, u_FmPcdPlcrNextEngineParams *p_NextEngineParams, uint32_t *nextAction)119{120uint32_t nia;121uint16_t absoluteProfileId;122uint8_t relativeSchemeId, physicalSchemeId;123124nia = FM_PCD_PLCR_NIA_VALID;125126switch (nextEngine)127{128case e_FM_PCD_DONE :129switch (p_NextEngineParams->action)130{131case e_FM_PCD_DROP_FRAME :132nia |= GET_NIA_BMI_AC_DISCARD_FRAME(p_FmPcd);133break;134case e_FM_PCD_ENQ_FRAME:135nia |= GET_NIA_BMI_AC_ENQ_FRAME(p_FmPcd);136break;137default:138RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);139}140break;141case e_FM_PCD_KG:142physicalSchemeId = FmPcdKgGetSchemeId(p_NextEngineParams->h_DirectScheme);143relativeSchemeId = FmPcdKgGetRelativeSchemeId(p_FmPcd, physicalSchemeId);144if (relativeSchemeId >= FM_PCD_KG_NUM_OF_SCHEMES)145RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, NO_MSG);146if (!FmPcdKgIsSchemeValidSw(p_NextEngineParams->h_DirectScheme))147RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid direct scheme."));148if (!KgIsSchemeAlwaysDirect(p_FmPcd, relativeSchemeId))149RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Policer Profile may point only to a scheme that is always direct."));150nia |= NIA_ENG_KG | NIA_KG_DIRECT | physicalSchemeId;151break;152case e_FM_PCD_PLCR:153absoluteProfileId = ((t_FmPcdPlcrProfile *)p_NextEngineParams->h_Profile)->absoluteProfileId;154if (!IsProfileShared(p_FmPcd, absoluteProfileId))155RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Next profile must be a shared profile"));156if (!FmPcdPlcrIsProfileValid(p_FmPcd, absoluteProfileId))157RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid profile "));158nia |= NIA_ENG_PLCR | NIA_PLCR_ABSOLUTE | absoluteProfileId;159break;160default:161RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);162}163164*nextAction = nia;165166return E_OK;167}168169static uint32_t CalcFPP(uint32_t fpp)170{171if (fpp > 15)172return 15 - (0x1f - fpp);173else174return 16 + fpp;175}176177static void GetInfoRateReg(e_FmPcdPlcrRateMode rateMode,178uint32_t rate,179uint64_t tsuInTenthNano,180uint32_t fppShift,181uint64_t *p_Integer,182uint64_t *p_Fraction)183{184uint64_t tmp, div;185186if (rateMode == e_FM_PCD_PLCR_BYTE_MODE)187{188/* now we calculate the initial integer for the bigger rate */189/* from Kbps to Bytes/TSU */190tmp = (uint64_t)rate;191tmp *= 1000; /* kb --> b */192tmp *= tsuInTenthNano; /* bps --> bpTsu(in 10nano) */193194div = 1000000000; /* nano */195div *= 10; /* 10 nano */196div *= 8; /* bit to byte */197}198else199{200/* now we calculate the initial integer for the bigger rate */201/* from Kbps to Bytes/TSU */202tmp = (uint64_t)rate;203tmp *= tsuInTenthNano; /* bps --> bpTsu(in 10nano) */204205div = 1000000000; /* nano */206div *= 10; /* 10 nano */207}208*p_Integer = (tmp<<fppShift) / div;209210/* for calculating the fraction, we will recalculate cir and deduct the integer.211* For precision, we will multiply by 2^16. we do not divid back, since we write212* this value as fraction - see spec.213*/214*p_Fraction = (((tmp<<fppShift)<<16) - ((*p_Integer<<16)*div)) / div;215}216217/* .......... */218219static void CalcRates(uint32_t bitFor1Micro,220t_FmPcdPlcrNonPassthroughAlgParams *p_NonPassthroughAlgParam,221uint32_t *cir,222uint32_t *cbs,223uint32_t *pir_eir,224uint32_t *pbs_ebs,225uint32_t *fpp)226{227uint64_t integer, fraction;228uint32_t temp, tsuInTenthNanos;229uint8_t fppShift=0;230231/* we want the tsu to count 10 nano for better precision normally tsu is 3.9 nano, now we will get 39 */232tsuInTenthNanos = (uint32_t)(1000*10/(1 << bitFor1Micro));233234/* we choose the faster rate to calibrate fpp */235/* The meaning of this step:236* when fppShift is 0 it means all TS bits are treated as integer and TSU is the TS LSB count.237* In this configuration we calculate the integer and fraction that represent the higher infoRate238* When this is done, we can tell where we have "spare" unused bits and optimize the division of TS239* into "integer" and "fraction" where the logic is - as many bits as possible for integer at240* high rate, as many bits as possible for fraction at low rate.241*/242if (p_NonPassthroughAlgParam->committedInfoRate > p_NonPassthroughAlgParam->peakOrExcessInfoRate)243GetInfoRateReg(p_NonPassthroughAlgParam->rateMode, p_NonPassthroughAlgParam->committedInfoRate, tsuInTenthNanos, 0, &integer, &fraction);244else245GetInfoRateReg(p_NonPassthroughAlgParam->rateMode, p_NonPassthroughAlgParam->peakOrExcessInfoRate, tsuInTenthNanos, 0, &integer, &fraction);246247/* we shift integer, as in cir/pir it is represented by the MSB 16 bits, and248* the LSB bits are for the fraction */249temp = (uint32_t)((integer<<16) & 0x00000000FFFFFFFF);250/* temp is effected by the rate. For low rates it may be as low as 0, and then we'll251* take max FP = 31.252* For high rates it will never exceed the 32 bit reg (after the 16 shift), as it is253* limited by the 10G physical port.254*/255if (temp != 0)256{257/* In this case, the largest rate integer is non 0, if it does not occupy all (high) 16258* bits of the PIR_EIR we can use this fact and enlarge it to occupy all 16 bits.259* The logic is to have as many bits for integer in the higher rates, but if we have "0"s260* in the integer part of the cir/pir register, than these bits are wasted. So we want261* to use these bits for the fraction. in this way we will have for fraction - the number262* of "0" bits and the rest - for integer.263* In other words: For each bit we shift it in PIR_EIR, we move the FP in the TS264* one bit to the left - preserving the relationship and achieving more bits265* for integer in the TS.266*/267268/* count zeroes left of the higher used bit (in order to shift the value such that269* unused bits may be used for fraction).270*/271while ((temp & 0x80000000) == 0)272{273temp = temp << 1;274fppShift++;275}276if (fppShift > 15)277{278REPORT_ERROR(MAJOR, E_INVALID_SELECTION, ("timeStampPeriod to Information rate ratio is too small"));279return;280}281}282else283{284temp = (uint32_t)fraction; /* fraction will alyas be smaller than 2^16 */285if (!temp)286/* integer and fraction are 0, we set FP to its max val */287fppShift = 31;288else289{290/* integer was 0 but fraction is not. FP is 16 for the fraction,291* + all left zeroes of the fraction. */292fppShift=16;293/* count zeroes left of the higher used bit (in order to shift the value such that294* unused bits may be used for fraction).295*/296while ((temp & 0x8000) == 0)297{298temp = temp << 1;299fppShift++;300}301}302}303304/*305* This means that the FM TS register will now be used so that 'fppShift' bits are for306* fraction and the rest for integer */307/* now we re-calculate cir and pir_eir with the calculated FP */308GetInfoRateReg(p_NonPassthroughAlgParam->rateMode, p_NonPassthroughAlgParam->committedInfoRate, tsuInTenthNanos, fppShift, &integer, &fraction);309*cir = (uint32_t)(integer << 16 | (fraction & 0xFFFF));310GetInfoRateReg(p_NonPassthroughAlgParam->rateMode, p_NonPassthroughAlgParam->peakOrExcessInfoRate, tsuInTenthNanos, fppShift, &integer, &fraction);311*pir_eir = (uint32_t)(integer << 16 | (fraction & 0xFFFF));312313*cbs = p_NonPassthroughAlgParam->committedBurstSize;314*pbs_ebs = p_NonPassthroughAlgParam->peakOrExcessBurstSize;315316/* convert FP as it should be written to reg.317* 0-15 --> 16-31318* 16-31 --> 0-15319*/320*fpp = CalcFPP(fppShift);321}322323static void WritePar(t_FmPcd *p_FmPcd, uint32_t par)324{325t_FmPcdPlcrRegs *p_FmPcdPlcrRegs = p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs;326327ASSERT_COND(FmIsMaster(p_FmPcd->h_Fm));328WRITE_UINT32(p_FmPcdPlcrRegs->fmpl_par, par);329330while (GET_UINT32(p_FmPcdPlcrRegs->fmpl_par) & FM_PCD_PLCR_PAR_GO) ;331}332333static t_Error BuildProfileRegs(t_FmPcd *p_FmPcd,334t_FmPcdPlcrProfileParams *p_ProfileParams,335t_FmPcdPlcrProfileRegs *p_PlcrRegs)336{337t_Error err = E_OK;338uint32_t pemode, gnia, ynia, rnia, bitFor1Micro;339340ASSERT_COND(p_FmPcd);341342bitFor1Micro = FmGetTimeStampScale(p_FmPcd->h_Fm);343if (bitFor1Micro == 0)344RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ("Timestamp scale"));345346/* Set G, Y, R Nia */347err = SetProfileNia(p_FmPcd, p_ProfileParams->nextEngineOnGreen, &(p_ProfileParams->paramsOnGreen), &gnia);348if (err)349RETURN_ERROR(MAJOR, err, NO_MSG);350err = SetProfileNia(p_FmPcd, p_ProfileParams->nextEngineOnYellow, &(p_ProfileParams->paramsOnYellow), &ynia);351if (err)352RETURN_ERROR(MAJOR, err, NO_MSG);353err = SetProfileNia(p_FmPcd, p_ProfileParams->nextEngineOnRed, &(p_ProfileParams->paramsOnRed), &rnia);354if (err)355RETURN_ERROR(MAJOR, err, NO_MSG);356357/* Mode fmpl_pemode */358pemode = FM_PCD_PLCR_PEMODE_PI;359360switch (p_ProfileParams->algSelection)361{362case e_FM_PCD_PLCR_PASS_THROUGH:363p_PlcrRegs->fmpl_pecir = 0;364p_PlcrRegs->fmpl_pecbs = 0;365p_PlcrRegs->fmpl_pepepir_eir = 0;366p_PlcrRegs->fmpl_pepbs_ebs = 0;367p_PlcrRegs->fmpl_pelts = 0;368p_PlcrRegs->fmpl_pects = 0;369p_PlcrRegs->fmpl_pepts_ets = 0;370pemode &= ~FM_PCD_PLCR_PEMODE_ALG_MASK;371switch (p_ProfileParams->colorMode)372{373case e_FM_PCD_PLCR_COLOR_BLIND:374pemode |= FM_PCD_PLCR_PEMODE_CBLND;375switch (p_ProfileParams->color.dfltColor)376{377case e_FM_PCD_PLCR_GREEN:378pemode &= ~FM_PCD_PLCR_PEMODE_DEFC_MASK;379break;380case e_FM_PCD_PLCR_YELLOW:381pemode |= FM_PCD_PLCR_PEMODE_DEFC_Y;382break;383case e_FM_PCD_PLCR_RED:384pemode |= FM_PCD_PLCR_PEMODE_DEFC_R;385break;386case e_FM_PCD_PLCR_OVERRIDE:387pemode |= FM_PCD_PLCR_PEMODE_DEFC_OVERRIDE;388break;389default:390RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);391}392393break;394case e_FM_PCD_PLCR_COLOR_AWARE:395pemode &= ~FM_PCD_PLCR_PEMODE_CBLND;396break;397default:398RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);399}400break;401402case e_FM_PCD_PLCR_RFC_2698:403/* Select algorithm MODE[ALG] = "01" */404pemode |= FM_PCD_PLCR_PEMODE_ALG_RFC2698;405if (p_ProfileParams->nonPassthroughAlgParams.committedInfoRate > p_ProfileParams->nonPassthroughAlgParams.peakOrExcessInfoRate)406RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("in RFC2698 Peak rate must be equal or larger than committedInfoRate."));407goto cont_rfc;408case e_FM_PCD_PLCR_RFC_4115:409/* Select algorithm MODE[ALG] = "10" */410pemode |= FM_PCD_PLCR_PEMODE_ALG_RFC4115;411cont_rfc:412/* Select Color-Blind / Color-Aware operation (MODE[CBLND]) */413switch (p_ProfileParams->colorMode)414{415case e_FM_PCD_PLCR_COLOR_BLIND:416pemode |= FM_PCD_PLCR_PEMODE_CBLND;417break;418case e_FM_PCD_PLCR_COLOR_AWARE:419pemode &= ~FM_PCD_PLCR_PEMODE_CBLND;420/*In color aware more select override color interpretation (MODE[OVCLR]) */421switch (p_ProfileParams->color.override)422{423case e_FM_PCD_PLCR_GREEN:424pemode &= ~FM_PCD_PLCR_PEMODE_OVCLR_MASK;425break;426case e_FM_PCD_PLCR_YELLOW:427pemode |= FM_PCD_PLCR_PEMODE_OVCLR_Y;428break;429case e_FM_PCD_PLCR_RED:430pemode |= FM_PCD_PLCR_PEMODE_OVCLR_R;431break;432case e_FM_PCD_PLCR_OVERRIDE:433pemode |= FM_PCD_PLCR_PEMODE_OVCLR_G_NC;434break;435default:436RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);437}438break;439default:440RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);441}442/* Select Measurement Unit Mode to BYTE or PACKET (MODE[PKT]) */443switch (p_ProfileParams->nonPassthroughAlgParams.rateMode)444{445case e_FM_PCD_PLCR_BYTE_MODE :446pemode &= ~FM_PCD_PLCR_PEMODE_PKT;447switch (p_ProfileParams->nonPassthroughAlgParams.byteModeParams.frameLengthSelection)448{449case e_FM_PCD_PLCR_L2_FRM_LEN:450pemode |= FM_PCD_PLCR_PEMODE_FLS_L2;451break;452case e_FM_PCD_PLCR_L3_FRM_LEN:453pemode |= FM_PCD_PLCR_PEMODE_FLS_L3;454break;455case e_FM_PCD_PLCR_L4_FRM_LEN:456pemode |= FM_PCD_PLCR_PEMODE_FLS_L4;457break;458case e_FM_PCD_PLCR_FULL_FRM_LEN:459pemode |= FM_PCD_PLCR_PEMODE_FLS_FULL;460break;461default:462RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);463}464switch (p_ProfileParams->nonPassthroughAlgParams.byteModeParams.rollBackFrameSelection)465{466case e_FM_PCD_PLCR_ROLLBACK_L2_FRM_LEN:467pemode &= ~FM_PCD_PLCR_PEMODE_RBFLS;468break;469case e_FM_PCD_PLCR_ROLLBACK_FULL_FRM_LEN:470pemode |= FM_PCD_PLCR_PEMODE_RBFLS;471break;472default:473RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);474}475break;476case e_FM_PCD_PLCR_PACKET_MODE :477pemode |= FM_PCD_PLCR_PEMODE_PKT;478break;479default:480RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);481}482/* Select timeStamp floating point position (MODE[FPP]) to fit the actual traffic rates. For PACKET483mode with low traffic rates move the fixed point to the left to increase fraction accuracy. For BYTE484mode with high traffic rates move the fixed point to the right to increase integer accuracy. */485486/* Configure Traffic Parameters*/487{488uint32_t cir=0, cbs=0, pir_eir=0, pbs_ebs=0, fpp=0;489490CalcRates(bitFor1Micro, &p_ProfileParams->nonPassthroughAlgParams, &cir, &cbs, &pir_eir, &pbs_ebs, &fpp);491492/* Set Committed Information Rate (CIR) */493p_PlcrRegs->fmpl_pecir = cir;494/* Set Committed Burst Size (CBS). */495p_PlcrRegs->fmpl_pecbs = cbs;496/* Set Peak Information Rate (PIR_EIR used as PIR) */497p_PlcrRegs->fmpl_pepepir_eir = pir_eir;498/* Set Peak Burst Size (PBS_EBS used as PBS) */499p_PlcrRegs->fmpl_pepbs_ebs = pbs_ebs;500501/* Initialize the Metering Buckets to be full (write them with 0xFFFFFFFF. */502/* Peak Rate Token Bucket Size (PTS_ETS used as PTS) */503p_PlcrRegs->fmpl_pepts_ets = 0xFFFFFFFF;504/* Committed Rate Token Bucket Size (CTS) */505p_PlcrRegs->fmpl_pects = 0xFFFFFFFF;506507/* Set the FPP based on calculation */508pemode |= (fpp << FM_PCD_PLCR_PEMODE_FPP_SHIFT);509}510break; /* FM_PCD_PLCR_PEMODE_ALG_RFC2698 , FM_PCD_PLCR_PEMODE_ALG_RFC4115 */511default:512RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);513}514515p_PlcrRegs->fmpl_pemode = pemode;516517p_PlcrRegs->fmpl_pegnia = gnia;518p_PlcrRegs->fmpl_peynia = ynia;519p_PlcrRegs->fmpl_pernia = rnia;520521/* Zero Counters */522p_PlcrRegs->fmpl_pegpc = 0;523p_PlcrRegs->fmpl_peypc = 0;524p_PlcrRegs->fmpl_perpc = 0;525p_PlcrRegs->fmpl_perypc = 0;526p_PlcrRegs->fmpl_perrpc = 0;527528return E_OK;529}530531static t_Error AllocSharedProfiles(t_FmPcd *p_FmPcd, uint16_t numOfProfiles, uint16_t *profilesIds)532{533uint32_t profilesFound;534uint16_t i, k=0;535uint32_t intFlags;536537SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);538539if (!numOfProfiles)540return E_OK;541542if (numOfProfiles>FM_PCD_PLCR_NUM_ENTRIES)543RETURN_ERROR(MINOR, E_INVALID_VALUE, ("numProfiles is too big."));544545intFlags = PlcrSwLock(p_FmPcd->p_FmPcdPlcr);546/* Find numOfProfiles free profiles (may be spread) */547profilesFound = 0;548for (i=0;i<FM_PCD_PLCR_NUM_ENTRIES; i++)549if (!p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.allocated)550{551profilesFound++;552profilesIds[k] = i;553k++;554if (profilesFound == numOfProfiles)555break;556}557558if (profilesFound != numOfProfiles)559{560PlcrSwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags);561RETURN_ERROR(MAJOR, E_INVALID_STATE,NO_MSG);562}563564for (i = 0;i<k;i++)565{566p_FmPcd->p_FmPcdPlcr->profiles[profilesIds[i]].profilesMng.allocated = TRUE;567p_FmPcd->p_FmPcdPlcr->profiles[profilesIds[i]].profilesMng.ownerId = 0;568}569PlcrSwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags);570571return E_OK;572}573574static void FreeSharedProfiles(t_FmPcd *p_FmPcd, uint16_t numOfProfiles, uint16_t *profilesIds)575{576uint16_t i;577578SANITY_CHECK_RETURN(p_FmPcd, E_INVALID_HANDLE);579580ASSERT_COND(numOfProfiles);581582for (i=0; i < numOfProfiles; i++)583{584ASSERT_COND(p_FmPcd->p_FmPcdPlcr->profiles[profilesIds[i]].profilesMng.allocated);585p_FmPcd->p_FmPcdPlcr->profiles[profilesIds[i]].profilesMng.allocated = FALSE;586p_FmPcd->p_FmPcdPlcr->profiles[profilesIds[i]].profilesMng.ownerId = p_FmPcd->guestId;587}588}589590static void UpdateRequiredActionFlag(t_Handle h_FmPcd, uint16_t absoluteProfileId, bool set)591{592t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;593594/* this routine is protected by calling routine */595596ASSERT_COND(p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].valid);597598if (set)599p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].requiredActionFlag = TRUE;600else601{602p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].requiredAction = 0;603p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].requiredActionFlag = FALSE;604}605}606607/*********************************************/608/*............Policer Exception..............*/609/*********************************************/610static void EventsCB(t_Handle h_FmPcd)611{612t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;613uint32_t event, mask, force;614615ASSERT_COND(FmIsMaster(p_FmPcd->h_Fm));616event = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_evr);617mask = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_ier);618619event &= mask;620621/* clear the forced events */622force = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_ifr);623if (force & event)624WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_ifr, force & ~event);625626627WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_evr, event);628629if (event & FM_PCD_PLCR_PRAM_SELF_INIT_COMPLETE)630p_FmPcd->f_Exception(p_FmPcd->h_App,e_FM_PCD_PLCR_EXCEPTION_PRAM_SELF_INIT_COMPLETE);631if (event & FM_PCD_PLCR_ATOMIC_ACTION_COMPLETE)632p_FmPcd->f_Exception(p_FmPcd->h_App,e_FM_PCD_PLCR_EXCEPTION_ATOMIC_ACTION_COMPLETE);633}634635/* ..... */636637static void ErrorExceptionsCB(t_Handle h_FmPcd)638{639t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;640uint32_t event, force, captureReg, mask;641642ASSERT_COND(FmIsMaster(p_FmPcd->h_Fm));643event = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_eevr);644mask = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_eier);645646event &= mask;647648/* clear the forced events */649force = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_eifr);650if (force & event)651WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_eifr, force & ~event);652653WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_eevr, event);654655if (event & FM_PCD_PLCR_DOUBLE_ECC)656p_FmPcd->f_Exception(p_FmPcd->h_App,e_FM_PCD_PLCR_EXCEPTION_DOUBLE_ECC);657if (event & FM_PCD_PLCR_INIT_ENTRY_ERROR)658{659captureReg = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_upcr);660/*ASSERT_COND(captureReg & PLCR_ERR_UNINIT_CAP);661p_UnInitCapt->profileNum = (uint8_t)(captureReg & PLCR_ERR_UNINIT_NUM_MASK);662p_UnInitCapt->portId = (uint8_t)((captureReg & PLCR_ERR_UNINIT_PID_MASK) >>PLCR_ERR_UNINIT_PID_SHIFT) ;663p_UnInitCapt->absolute = (bool)(captureReg & PLCR_ERR_UNINIT_ABSOLUTE_MASK);*/664p_FmPcd->f_FmPcdIndexedException(p_FmPcd->h_App,e_FM_PCD_PLCR_EXCEPTION_INIT_ENTRY_ERROR,(uint16_t)(captureReg & PLCR_ERR_UNINIT_NUM_MASK));665WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_upcr, PLCR_ERR_UNINIT_CAP);666}667}668669670/*****************************************************************************/671/* Inter-module API routines */672/*****************************************************************************/673674t_Handle PlcrConfig(t_FmPcd *p_FmPcd, t_FmPcdParams *p_FmPcdParams)675{676t_FmPcdPlcr *p_FmPcdPlcr;677uint16_t i=0;678679UNUSED(p_FmPcd);680UNUSED(p_FmPcdParams);681682p_FmPcdPlcr = (t_FmPcdPlcr *) XX_Malloc(sizeof(t_FmPcdPlcr));683if (!p_FmPcdPlcr)684{685REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM Policer structure allocation FAILED"));686return NULL;687}688memset(p_FmPcdPlcr, 0, sizeof(t_FmPcdPlcr));689if (p_FmPcd->guestId == NCSW_MASTER_ID)690{691p_FmPcdPlcr->p_FmPcdPlcrRegs = (t_FmPcdPlcrRegs *)UINT_TO_PTR(FmGetPcdPlcrBaseAddr(p_FmPcdParams->h_Fm));692p_FmPcd->p_FmPcdDriverParam->plcrAutoRefresh = DEFAULT_plcrAutoRefresh;693p_FmPcd->exceptions |= (DEFAULT_fmPcdPlcrExceptions | DEFAULT_fmPcdPlcrErrorExceptions);694}695696p_FmPcdPlcr->numOfSharedProfiles = DEFAULT_numOfSharedPlcrProfiles;697698p_FmPcdPlcr->partPlcrProfilesBase = p_FmPcdParams->partPlcrProfilesBase;699p_FmPcdPlcr->partNumOfPlcrProfiles = p_FmPcdParams->partNumOfPlcrProfiles;700/* for backward compatabilty. if no policer profile, will set automatically to the max */701if ((p_FmPcd->guestId == NCSW_MASTER_ID) &&702(p_FmPcdPlcr->partNumOfPlcrProfiles == 0))703p_FmPcdPlcr->partNumOfPlcrProfiles = FM_PCD_PLCR_NUM_ENTRIES;704705for (i=0; i<FM_PCD_PLCR_NUM_ENTRIES; i++)706p_FmPcdPlcr->profiles[i].profilesMng.ownerId = (uint8_t)ILLEGAL_BASE;707708return p_FmPcdPlcr;709}710711t_Error PlcrInit(t_FmPcd *p_FmPcd)712{713t_FmPcdDriverParam *p_Param = p_FmPcd->p_FmPcdDriverParam;714t_FmPcdPlcr *p_FmPcdPlcr = p_FmPcd->p_FmPcdPlcr;715t_FmPcdPlcrRegs *p_Regs = p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs;716t_Error err = E_OK;717uint32_t tmpReg32 = 0;718uint16_t base;719720if ((p_FmPcdPlcr->partPlcrProfilesBase + p_FmPcdPlcr->partNumOfPlcrProfiles) > FM_PCD_PLCR_NUM_ENTRIES)721RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("partPlcrProfilesBase+partNumOfPlcrProfiles out of range!!!"));722723p_FmPcdPlcr->h_HwSpinlock = XX_InitSpinlock();724if (!p_FmPcdPlcr->h_HwSpinlock)725RETURN_ERROR(MAJOR, E_NO_MEMORY, ("FM Policer HW spinlock"));726727p_FmPcdPlcr->h_SwSpinlock = XX_InitSpinlock();728if (!p_FmPcdPlcr->h_SwSpinlock)729RETURN_ERROR(MAJOR, E_NO_MEMORY, ("FM Policer SW spinlock"));730731base = PlcrAllocProfilesForPartition(p_FmPcd,732p_FmPcdPlcr->partPlcrProfilesBase,733p_FmPcdPlcr->partNumOfPlcrProfiles,734p_FmPcd->guestId);735if (base == (uint16_t)ILLEGAL_BASE)736RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG);737738if (p_FmPcdPlcr->numOfSharedProfiles)739{740err = AllocSharedProfiles(p_FmPcd,741p_FmPcdPlcr->numOfSharedProfiles,742p_FmPcdPlcr->sharedProfilesIds);743if (err)744RETURN_ERROR(MAJOR, err,NO_MSG);745}746747if (p_FmPcd->guestId != NCSW_MASTER_ID)748return E_OK;749750/**********************FMPL_GCR******************/751tmpReg32 = 0;752tmpReg32 |= FM_PCD_PLCR_GCR_STEN;753if (p_Param->plcrAutoRefresh)754tmpReg32 |= FM_PCD_PLCR_GCR_DAR;755tmpReg32 |= GET_NIA_BMI_AC_ENQ_FRAME(p_FmPcd);756757WRITE_UINT32(p_Regs->fmpl_gcr, tmpReg32);758/**********************FMPL_GCR******************/759760/**********************FMPL_EEVR******************/761WRITE_UINT32(p_Regs->fmpl_eevr, (FM_PCD_PLCR_DOUBLE_ECC | FM_PCD_PLCR_INIT_ENTRY_ERROR));762/**********************FMPL_EEVR******************/763/**********************FMPL_EIER******************/764tmpReg32 = 0;765if (p_FmPcd->exceptions & FM_PCD_EX_PLCR_DOUBLE_ECC)766{767FmEnableRamsEcc(p_FmPcd->h_Fm);768tmpReg32 |= FM_PCD_PLCR_DOUBLE_ECC;769}770if (p_FmPcd->exceptions & FM_PCD_EX_PLCR_INIT_ENTRY_ERROR)771tmpReg32 |= FM_PCD_PLCR_INIT_ENTRY_ERROR;772WRITE_UINT32(p_Regs->fmpl_eier, tmpReg32);773/**********************FMPL_EIER******************/774775/**********************FMPL_EVR******************/776WRITE_UINT32(p_Regs->fmpl_evr, (FM_PCD_PLCR_PRAM_SELF_INIT_COMPLETE | FM_PCD_PLCR_ATOMIC_ACTION_COMPLETE));777/**********************FMPL_EVR******************/778/**********************FMPL_IER******************/779tmpReg32 = 0;780if (p_FmPcd->exceptions & FM_PCD_EX_PLCR_PRAM_SELF_INIT_COMPLETE)781tmpReg32 |= FM_PCD_PLCR_PRAM_SELF_INIT_COMPLETE;782if (p_FmPcd->exceptions & FM_PCD_EX_PLCR_ATOMIC_ACTION_COMPLETE)783tmpReg32 |= FM_PCD_PLCR_ATOMIC_ACTION_COMPLETE;784WRITE_UINT32(p_Regs->fmpl_ier, tmpReg32);785/**********************FMPL_IER******************/786787/* register even if no interrupts enabled, to allow future enablement */788FmRegisterIntr(p_FmPcd->h_Fm,789e_FM_MOD_PLCR,7900,791e_FM_INTR_TYPE_ERR,792ErrorExceptionsCB,793p_FmPcd);794FmRegisterIntr(p_FmPcd->h_Fm,795e_FM_MOD_PLCR,7960,797e_FM_INTR_TYPE_NORMAL,798EventsCB,799p_FmPcd);800801/* driver initializes one DFLT profile at the last entry*/802/**********************FMPL_DPMR******************/803tmpReg32 = 0;804WRITE_UINT32(p_Regs->fmpl_dpmr, tmpReg32);805p_FmPcd->p_FmPcdPlcr->profiles[0].profilesMng.allocated = TRUE;806807return E_OK;808}809810t_Error PlcrFree(t_FmPcd *p_FmPcd)811{812FmUnregisterIntr(p_FmPcd->h_Fm, e_FM_MOD_PLCR, 0, e_FM_INTR_TYPE_ERR);813FmUnregisterIntr(p_FmPcd->h_Fm, e_FM_MOD_PLCR, 0, e_FM_INTR_TYPE_NORMAL);814815if (p_FmPcd->p_FmPcdPlcr->numOfSharedProfiles)816FreeSharedProfiles(p_FmPcd,817p_FmPcd->p_FmPcdPlcr->numOfSharedProfiles,818p_FmPcd->p_FmPcdPlcr->sharedProfilesIds);819820if (p_FmPcd->p_FmPcdPlcr->partNumOfPlcrProfiles)821PlcrFreeProfilesForPartition(p_FmPcd,822p_FmPcd->p_FmPcdPlcr->partPlcrProfilesBase,823p_FmPcd->p_FmPcdPlcr->partNumOfPlcrProfiles,824p_FmPcd->guestId);825826if (p_FmPcd->p_FmPcdPlcr->h_SwSpinlock)827XX_FreeSpinlock(p_FmPcd->p_FmPcdPlcr->h_SwSpinlock);828829if (p_FmPcd->p_FmPcdPlcr->h_HwSpinlock)830XX_FreeSpinlock(p_FmPcd->p_FmPcdPlcr->h_HwSpinlock);831832return E_OK;833}834835void PlcrEnable(t_FmPcd *p_FmPcd)836{837t_FmPcdPlcrRegs *p_Regs = p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs;838839WRITE_UINT32(p_Regs->fmpl_gcr, GET_UINT32(p_Regs->fmpl_gcr) | FM_PCD_PLCR_GCR_EN);840}841842void PlcrDisable(t_FmPcd *p_FmPcd)843{844t_FmPcdPlcrRegs *p_Regs = p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs;845846WRITE_UINT32(p_Regs->fmpl_gcr, GET_UINT32(p_Regs->fmpl_gcr) & ~FM_PCD_PLCR_GCR_EN);847}848849uint16_t PlcrAllocProfilesForPartition(t_FmPcd *p_FmPcd, uint16_t base, uint16_t numOfProfiles, uint8_t guestId)850{851uint32_t intFlags;852uint16_t profilesFound = 0;853int i = 0;854855ASSERT_COND(p_FmPcd);856ASSERT_COND(p_FmPcd->p_FmPcdPlcr);857858if (!numOfProfiles)859return 0;860861if ((numOfProfiles > FM_PCD_PLCR_NUM_ENTRIES) ||862(base + numOfProfiles > FM_PCD_PLCR_NUM_ENTRIES))863return (uint16_t)ILLEGAL_BASE;864865if (p_FmPcd->h_IpcSession)866{867t_FmIpcResourceAllocParams ipcAllocParams;868t_FmPcdIpcMsg msg;869t_FmPcdIpcReply reply;870t_Error err;871uint32_t replyLength;872873memset(&msg, 0, sizeof(msg));874memset(&reply, 0, sizeof(reply));875memset(&ipcAllocParams, 0, sizeof(t_FmIpcResourceAllocParams));876ipcAllocParams.guestId = p_FmPcd->guestId;877ipcAllocParams.num = p_FmPcd->p_FmPcdPlcr->partNumOfPlcrProfiles;878ipcAllocParams.base = p_FmPcd->p_FmPcdPlcr->partPlcrProfilesBase;879msg.msgId = FM_PCD_ALLOC_PROFILES;880memcpy(msg.msgBody, &ipcAllocParams, sizeof(t_FmIpcResourceAllocParams));881replyLength = sizeof(uint32_t) + sizeof(uint16_t);882err = XX_IpcSendMessage(p_FmPcd->h_IpcSession,883(uint8_t*)&msg,884sizeof(msg.msgId) + sizeof(t_FmIpcResourceAllocParams),885(uint8_t*)&reply,886&replyLength,887NULL,888NULL);889if ((err != E_OK) ||890(replyLength != (sizeof(uint32_t) + sizeof(uint16_t))))891{892REPORT_ERROR(MAJOR, err, NO_MSG);893return (uint16_t)ILLEGAL_BASE;894}895else896memcpy((uint8_t*)&p_FmPcd->p_FmPcdPlcr->partPlcrProfilesBase, reply.replyBody, sizeof(uint16_t));897if (p_FmPcd->p_FmPcdPlcr->partPlcrProfilesBase == (uint16_t)ILLEGAL_BASE)898{899REPORT_ERROR(MAJOR, err, NO_MSG);900return (uint16_t)ILLEGAL_BASE;901}902}903else if (p_FmPcd->guestId != NCSW_MASTER_ID)904{905DBG(WARNING, ("FM Guest mode, without IPC - can't validate Policer-profiles range!"));906return (uint16_t)ILLEGAL_BASE;907}908909intFlags = XX_LockIntrSpinlock(p_FmPcd->h_Spinlock);910for (i=base; i<(base+numOfProfiles); i++)911if (p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.ownerId == (uint8_t)ILLEGAL_BASE)912profilesFound++;913else914break;915916if (profilesFound == numOfProfiles)917for (i=base; i<(base+numOfProfiles); i++)918p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.ownerId = guestId;919else920{921XX_UnlockIntrSpinlock(p_FmPcd->h_Spinlock, intFlags);922return (uint16_t)ILLEGAL_BASE;923}924XX_UnlockIntrSpinlock(p_FmPcd->h_Spinlock, intFlags);925926return base;927}928929void PlcrFreeProfilesForPartition(t_FmPcd *p_FmPcd, uint16_t base, uint16_t numOfProfiles, uint8_t guestId)930{931int i = 0;932933ASSERT_COND(p_FmPcd);934ASSERT_COND(p_FmPcd->p_FmPcdPlcr);935936if (p_FmPcd->h_IpcSession)937{938t_FmIpcResourceAllocParams ipcAllocParams;939t_FmPcdIpcMsg msg;940t_Error err;941942memset(&msg, 0, sizeof(msg));943memset(&ipcAllocParams, 0, sizeof(t_FmIpcResourceAllocParams));944ipcAllocParams.guestId = p_FmPcd->guestId;945ipcAllocParams.num = p_FmPcd->p_FmPcdPlcr->partNumOfPlcrProfiles;946ipcAllocParams.base = p_FmPcd->p_FmPcdPlcr->partPlcrProfilesBase;947msg.msgId = FM_PCD_FREE_PROFILES;948memcpy(msg.msgBody, &ipcAllocParams, sizeof(t_FmIpcResourceAllocParams));949err = XX_IpcSendMessage(p_FmPcd->h_IpcSession,950(uint8_t*)&msg,951sizeof(msg.msgId) + sizeof(t_FmIpcResourceAllocParams),952NULL,953NULL,954NULL,955NULL);956if (err != E_OK)957REPORT_ERROR(MAJOR, err, NO_MSG);958return;959}960else if (p_FmPcd->guestId != NCSW_MASTER_ID)961{962DBG(WARNING, ("FM Guest mode, without IPC - can't validate Policer-profiles range!"));963return;964}965966for (i=base; i<(base+numOfProfiles); i++)967{968if (p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.ownerId == guestId)969p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.ownerId = (uint8_t)ILLEGAL_BASE;970else971DBG(WARNING, ("Request for freeing storage profile window which wasn't allocated to this partition"));972}973}974975t_Error PlcrSetPortProfiles(t_FmPcd *p_FmPcd,976uint8_t hardwarePortId,977uint16_t numOfProfiles,978uint16_t base)979{980t_FmPcdPlcrRegs *p_Regs = p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs;981uint32_t log2Num, tmpReg32;982983if ((p_FmPcd->guestId != NCSW_MASTER_ID) &&984!p_Regs &&985p_FmPcd->h_IpcSession)986{987t_FmIpcResourceAllocParams ipcAllocParams;988t_FmPcdIpcMsg msg;989t_Error err;990991memset(&msg, 0, sizeof(msg));992memset(&ipcAllocParams, 0, sizeof(t_FmIpcResourceAllocParams));993ipcAllocParams.guestId = hardwarePortId;994ipcAllocParams.num = numOfProfiles;995ipcAllocParams.base = base;996msg.msgId = FM_PCD_SET_PORT_PROFILES;997memcpy(msg.msgBody, &ipcAllocParams, sizeof(t_FmIpcResourceAllocParams));998err = XX_IpcSendMessage(p_FmPcd->h_IpcSession,999(uint8_t*)&msg,1000sizeof(msg.msgId) + sizeof(t_FmIpcResourceAllocParams),1001NULL,1002NULL,1003NULL,1004NULL);1005if (err != E_OK)1006RETURN_ERROR(MAJOR, err, NO_MSG);1007return E_OK;1008}1009else if (!p_Regs)1010RETURN_ERROR(MINOR, E_NOT_SUPPORTED,1011("Either IPC or 'baseAddress' is required!"));10121013ASSERT_COND(IN_RANGE(1, hardwarePortId, 63));10141015if (GET_UINT32(p_Regs->fmpl_pmr[hardwarePortId-1]) & FM_PCD_PLCR_PMR_V)1016RETURN_ERROR(MAJOR, E_INVALID_VALUE,1017("The requesting port has already an allocated profiles window."));10181019/**********************FMPL_PMRx******************/1020LOG2((uint64_t)numOfProfiles, log2Num);1021tmpReg32 = base;1022tmpReg32 |= log2Num << 16;1023tmpReg32 |= FM_PCD_PLCR_PMR_V;1024WRITE_UINT32(p_Regs->fmpl_pmr[hardwarePortId-1], tmpReg32);10251026return E_OK;1027}10281029t_Error PlcrClearPortProfiles(t_FmPcd *p_FmPcd, uint8_t hardwarePortId)1030{1031t_FmPcdPlcrRegs *p_Regs = p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs;10321033if ((p_FmPcd->guestId != NCSW_MASTER_ID) &&1034!p_Regs &&1035p_FmPcd->h_IpcSession)1036{1037t_FmIpcResourceAllocParams ipcAllocParams;1038t_FmPcdIpcMsg msg;1039t_Error err;10401041memset(&msg, 0, sizeof(msg));1042memset(&ipcAllocParams, 0, sizeof(t_FmIpcResourceAllocParams));1043ipcAllocParams.guestId = hardwarePortId;1044msg.msgId = FM_PCD_CLEAR_PORT_PROFILES;1045memcpy(msg.msgBody, &ipcAllocParams, sizeof(t_FmIpcResourceAllocParams));1046err = XX_IpcSendMessage(p_FmPcd->h_IpcSession,1047(uint8_t*)&msg,1048sizeof(msg.msgId) + sizeof(t_FmIpcResourceAllocParams),1049NULL,1050NULL,1051NULL,1052NULL);1053if (err != E_OK)1054RETURN_ERROR(MAJOR, err, NO_MSG);1055return E_OK;1056}1057else if (!p_Regs)1058RETURN_ERROR(MINOR, E_NOT_SUPPORTED,1059("Either IPC or 'baseAddress' is required!"));10601061ASSERT_COND(IN_RANGE(1, hardwarePortId, 63));1062WRITE_UINT32(p_Regs->fmpl_pmr[hardwarePortId-1], 0);10631064return E_OK;1065}10661067t_Error FmPcdPlcrAllocProfiles(t_Handle h_FmPcd, uint8_t hardwarePortId, uint16_t numOfProfiles)1068{1069t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;1070t_Error err = E_OK;1071uint32_t profilesFound;1072uint32_t intFlags;1073uint16_t i, first, swPortIndex = 0;10741075SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);10761077if (!numOfProfiles)1078return E_OK;10791080ASSERT_COND(hardwarePortId);10811082if (numOfProfiles>FM_PCD_PLCR_NUM_ENTRIES)1083RETURN_ERROR(MINOR, E_INVALID_VALUE, ("numProfiles is too big."));10841085if (!POWER_OF_2(numOfProfiles))1086RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("numProfiles must be a power of 2."));10871088first = 0;1089profilesFound = 0;1090intFlags = PlcrSwLock(p_FmPcd->p_FmPcdPlcr);10911092for (i=0; i<FM_PCD_PLCR_NUM_ENTRIES; )1093{1094if (!p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.allocated)1095{1096profilesFound++;1097i++;1098if (profilesFound == numOfProfiles)1099break;1100}1101else1102{1103profilesFound = 0;1104/* advance i to the next aligned address */1105i = first = (uint16_t)(first + numOfProfiles);1106}1107}11081109if (profilesFound == numOfProfiles)1110{1111for (i=first; i<first + numOfProfiles; i++)1112{1113p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.allocated = TRUE;1114p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.ownerId = hardwarePortId;1115}1116}1117else1118{1119PlcrSwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags);1120RETURN_ERROR(MINOR, E_FULL, ("No profiles."));1121}1122PlcrSwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags);11231124err = PlcrSetPortProfiles(p_FmPcd, hardwarePortId, numOfProfiles, first);1125if (err)1126{1127RETURN_ERROR(MAJOR, err, NO_MSG);1128}11291130HW_PORT_ID_TO_SW_PORT_INDX(swPortIndex, hardwarePortId);11311132p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].numOfProfiles = numOfProfiles;1133p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].profilesBase = first;11341135return E_OK;1136}11371138t_Error FmPcdPlcrFreeProfiles(t_Handle h_FmPcd, uint8_t hardwarePortId)1139{1140t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;1141t_Error err = E_OK;1142uint32_t intFlags;1143uint16_t i, swPortIndex = 0;11441145ASSERT_COND(IN_RANGE(1, hardwarePortId, 63));11461147SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);1148SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_HANDLE);11491150HW_PORT_ID_TO_SW_PORT_INDX(swPortIndex, hardwarePortId);11511152err = PlcrClearPortProfiles(p_FmPcd, hardwarePortId);1153if (err)1154RETURN_ERROR(MAJOR, err,NO_MSG);11551156intFlags = PlcrSwLock(p_FmPcd->p_FmPcdPlcr);1157for (i=p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].profilesBase;1158i<(p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].profilesBase +1159p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].numOfProfiles);1160i++)1161{1162ASSERT_COND(p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.ownerId == hardwarePortId);1163ASSERT_COND(p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.allocated);11641165p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.allocated = FALSE;1166p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.ownerId = p_FmPcd->guestId;1167}1168PlcrSwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags);11691170p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].numOfProfiles = 0;1171p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].profilesBase = 0;11721173return E_OK;1174}11751176t_Error FmPcdPlcrCcGetSetParams(t_Handle h_FmPcd, uint16_t profileIndx ,uint32_t requiredAction)1177{1178t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;1179t_FmPcdPlcr *p_FmPcdPlcr = p_FmPcd->p_FmPcdPlcr;1180t_FmPcdPlcrRegs *p_FmPcdPlcrRegs = p_FmPcdPlcr->p_FmPcdPlcrRegs;1181uint32_t tmpReg32, intFlags;1182t_Error err;11831184/* Calling function locked all PCD modules, so no need to lock here */11851186if (profileIndx >= FM_PCD_PLCR_NUM_ENTRIES)1187RETURN_ERROR(MAJOR, E_INVALID_VALUE,("Policer profile out of range"));11881189if (!FmPcdPlcrIsProfileValid(p_FmPcd, profileIndx))1190RETURN_ERROR(MAJOR, E_INVALID_VALUE,("Policer profile is not valid"));11911192/*intFlags = PlcrProfileLock(&p_FmPcd->p_FmPcdPlcr->profiles[profileIndx]);*/11931194if (p_FmPcd->h_Hc)1195{1196err = FmHcPcdPlcrCcGetSetParams(p_FmPcd->h_Hc, profileIndx, requiredAction);11971198UpdateRequiredActionFlag(p_FmPcd, profileIndx, TRUE);1199FmPcdPlcrUpdateRequiredAction(p_FmPcd, profileIndx, requiredAction);12001201/*PlcrProfileUnlock(&p_FmPcd->p_FmPcdPlcr->profiles[profileIndx], intFlags);*/1202return err;1203}12041205/* lock the HW because once we read the registers we don't want them to be changed1206* by another access. (We can copy to a tmp location and release the lock!) */12071208intFlags = PlcrHwLock(p_FmPcdPlcr);1209WritePar(p_FmPcd, FmPcdPlcrBuildReadPlcrActionReg(profileIndx));12101211if (!p_FmPcd->p_FmPcdPlcr->profiles[profileIndx].requiredActionFlag ||1212!(p_FmPcd->p_FmPcdPlcr->profiles[profileIndx].requiredAction & requiredAction))1213{1214if (requiredAction & UPDATE_NIA_ENQ_WITHOUT_DMA)1215{1216if ((p_FmPcd->p_FmPcdPlcr->profiles[profileIndx].nextEngineOnGreen!= e_FM_PCD_DONE) ||1217(p_FmPcd->p_FmPcdPlcr->profiles[profileIndx].nextEngineOnYellow!= e_FM_PCD_DONE) ||1218(p_FmPcd->p_FmPcdPlcr->profiles[profileIndx].nextEngineOnRed!= e_FM_PCD_DONE))1219{1220PlcrHwUnlock(p_FmPcdPlcr, intFlags);1221/*PlcrProfileUnlock(&p_FmPcd->p_FmPcdPlcr->profiles[profileIndx], intFlags);*/1222RETURN_ERROR (MAJOR, E_OK, ("In this case the next engine can be e_FM_PCD_DONE"));1223}12241225if (p_FmPcd->p_FmPcdPlcr->profiles[profileIndx].paramsOnGreen.action == e_FM_PCD_ENQ_FRAME)1226{1227tmpReg32 = GET_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pegnia);1228if (!(tmpReg32 & (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME)))1229{1230PlcrHwUnlock(p_FmPcdPlcr, intFlags);1231/*PlcrProfileUnlock(&p_FmPcd->p_FmPcdPlcr->profiles[profileIndx], intFlags);*/1232RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Next engine of this policer profile has to be assigned to FM_PCD_DONE"));1233}1234tmpReg32 |= NIA_BMI_AC_ENQ_FRAME_WITHOUT_DMA;1235WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pegnia, tmpReg32);1236tmpReg32 = FmPcdPlcrBuildWritePlcrActionReg(profileIndx);1237tmpReg32 |= FM_PCD_PLCR_PAR_PWSEL_PEGNIA;1238WritePar(p_FmPcd, tmpReg32);1239}12401241if (p_FmPcd->p_FmPcdPlcr->profiles[profileIndx].paramsOnYellow.action == e_FM_PCD_ENQ_FRAME)1242{1243tmpReg32 = GET_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_peynia);1244if (!(tmpReg32 & (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME)))1245{1246PlcrHwUnlock(p_FmPcdPlcr, intFlags);1247/*PlcrProfileUnlock(&p_FmPcd->p_FmPcdPlcr->profiles[profileIndx], intFlags);*/1248RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Next engine of this policer profile has to be assigned to FM_PCD_DONE"));1249}1250tmpReg32 |= NIA_BMI_AC_ENQ_FRAME_WITHOUT_DMA;1251WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_peynia, tmpReg32);1252tmpReg32 = FmPcdPlcrBuildWritePlcrActionReg(profileIndx);1253tmpReg32 |= FM_PCD_PLCR_PAR_PWSEL_PEYNIA;1254WritePar(p_FmPcd, tmpReg32);1255PlcrHwUnlock(p_FmPcdPlcr, intFlags);1256}12571258if (p_FmPcd->p_FmPcdPlcr->profiles[profileIndx].paramsOnRed.action == e_FM_PCD_ENQ_FRAME)1259{1260tmpReg32 = GET_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pernia);1261if (!(tmpReg32 & (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME)))1262{1263PlcrHwUnlock(p_FmPcdPlcr, intFlags);1264/*PlcrProfileUnlock(&p_FmPcd->p_FmPcdPlcr->profiles[profileIndx], intFlags);*/1265RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Next engine of this policer profile has to be assigned to FM_PCD_DONE"));1266}1267tmpReg32 |= NIA_BMI_AC_ENQ_FRAME_WITHOUT_DMA;1268WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pernia, tmpReg32);1269tmpReg32 = FmPcdPlcrBuildWritePlcrActionReg(profileIndx);1270tmpReg32 |= FM_PCD_PLCR_PAR_PWSEL_PERNIA;1271WritePar(p_FmPcd, tmpReg32);12721273}1274}1275}1276PlcrHwUnlock(p_FmPcdPlcr, intFlags);12771278UpdateRequiredActionFlag(p_FmPcd, profileIndx, TRUE);1279FmPcdPlcrUpdateRequiredAction(p_FmPcd, profileIndx, requiredAction);12801281/*PlcrProfileUnlock(&p_FmPcd->p_FmPcdPlcr->profiles[profileIndx], intFlags);*/12821283return E_OK;1284}12851286uint32_t FmPcdPlcrGetRequiredActionFlag(t_Handle h_FmPcd, uint16_t absoluteProfileId)1287{1288t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;12891290ASSERT_COND(p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].valid);12911292return p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].requiredActionFlag;1293}12941295uint32_t FmPcdPlcrGetRequiredAction(t_Handle h_FmPcd, uint16_t absoluteProfileId)1296{1297t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;12981299ASSERT_COND(p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].valid);13001301return p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].requiredAction;1302}13031304bool FmPcdPlcrIsProfileValid(t_Handle h_FmPcd, uint16_t absoluteProfileId)1305{1306t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;1307t_FmPcdPlcr *p_FmPcdPlcr = p_FmPcd->p_FmPcdPlcr;13081309ASSERT_COND(absoluteProfileId < FM_PCD_PLCR_NUM_ENTRIES);13101311return p_FmPcdPlcr->profiles[absoluteProfileId].valid;1312}13131314void FmPcdPlcrValidateProfileSw(t_Handle h_FmPcd, uint16_t absoluteProfileId)1315{1316t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;1317uint32_t intFlags;13181319ASSERT_COND(!p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].valid);13201321intFlags = PlcrProfileLock(&p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId]);1322p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].valid = TRUE;1323PlcrProfileUnlock(&p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId], intFlags);1324}13251326void FmPcdPlcrInvalidateProfileSw(t_Handle h_FmPcd, uint16_t absoluteProfileId)1327{1328t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;1329uint32_t intFlags;13301331ASSERT_COND(p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].valid);13321333intFlags = PlcrProfileLock(&p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId]);1334p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].valid = FALSE;1335PlcrProfileUnlock(&p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId], intFlags);1336}13371338uint16_t FmPcdPlcrProfileGetAbsoluteId(t_Handle h_Profile)1339{1340return ((t_FmPcdPlcrProfile*)h_Profile)->absoluteProfileId;1341}13421343t_Error FmPcdPlcrGetAbsoluteIdByProfileParams(t_Handle h_FmPcd,1344e_FmPcdProfileTypeSelection profileType,1345t_Handle h_FmPort,1346uint16_t relativeProfile,1347uint16_t *p_AbsoluteId)1348{1349t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;1350t_FmPcdPlcr *p_FmPcdPlcr = p_FmPcd->p_FmPcdPlcr;1351uint8_t i;13521353switch (profileType)1354{1355case e_FM_PCD_PLCR_PORT_PRIVATE:1356/* get port PCD id from port handle */1357for (i=0;i<FM_MAX_NUM_OF_PORTS;i++)1358if (p_FmPcd->p_FmPcdPlcr->portsMapping[i].h_FmPort == h_FmPort)1359break;1360if (i == FM_MAX_NUM_OF_PORTS)1361RETURN_ERROR(MAJOR, E_INVALID_STATE , ("Invalid port handle."));13621363if (!p_FmPcd->p_FmPcdPlcr->portsMapping[i].numOfProfiles)1364RETURN_ERROR(MAJOR, E_INVALID_SELECTION , ("Port has no allocated profiles"));1365if (relativeProfile >= p_FmPcd->p_FmPcdPlcr->portsMapping[i].numOfProfiles)1366RETURN_ERROR(MAJOR, E_INVALID_SELECTION , ("Profile id is out of range"));1367*p_AbsoluteId = (uint16_t)(p_FmPcd->p_FmPcdPlcr->portsMapping[i].profilesBase + relativeProfile);1368break;1369case e_FM_PCD_PLCR_SHARED:1370if (relativeProfile >= p_FmPcdPlcr->numOfSharedProfiles)1371RETURN_ERROR(MAJOR, E_INVALID_SELECTION , ("Profile id is out of range"));1372*p_AbsoluteId = (uint16_t)(p_FmPcdPlcr->sharedProfilesIds[relativeProfile]);1373break;1374default:1375RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Invalid policer profile type"));1376}13771378return E_OK;1379}13801381uint16_t FmPcdPlcrGetPortProfilesBase(t_Handle h_FmPcd, uint8_t hardwarePortId)1382{1383t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;1384uint16_t swPortIndex = 0;13851386HW_PORT_ID_TO_SW_PORT_INDX(swPortIndex, hardwarePortId);13871388return p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].profilesBase;1389}13901391uint16_t FmPcdPlcrGetPortNumOfProfiles(t_Handle h_FmPcd, uint8_t hardwarePortId)1392{1393t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;1394uint16_t swPortIndex = 0;13951396HW_PORT_ID_TO_SW_PORT_INDX(swPortIndex, hardwarePortId);13971398return p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].numOfProfiles;13991400}1401uint32_t FmPcdPlcrBuildWritePlcrActionReg(uint16_t absoluteProfileId)1402{1403return (uint32_t)(FM_PCD_PLCR_PAR_GO |1404((uint32_t)absoluteProfileId << FM_PCD_PLCR_PAR_PNUM_SHIFT));1405}14061407uint32_t FmPcdPlcrBuildWritePlcrActionRegs(uint16_t absoluteProfileId)1408{1409return (uint32_t)(FM_PCD_PLCR_PAR_GO |1410((uint32_t)absoluteProfileId << FM_PCD_PLCR_PAR_PNUM_SHIFT) |1411FM_PCD_PLCR_PAR_PWSEL_MASK);1412}14131414bool FmPcdPlcrHwProfileIsValid(uint32_t profileModeReg)1415{14161417if (profileModeReg & FM_PCD_PLCR_PEMODE_PI)1418return TRUE;1419else1420return FALSE;1421}14221423uint32_t FmPcdPlcrBuildReadPlcrActionReg(uint16_t absoluteProfileId)1424{1425return (uint32_t)(FM_PCD_PLCR_PAR_GO |1426FM_PCD_PLCR_PAR_R |1427((uint32_t)absoluteProfileId << FM_PCD_PLCR_PAR_PNUM_SHIFT) |1428FM_PCD_PLCR_PAR_PWSEL_MASK);1429}14301431uint32_t FmPcdPlcrBuildCounterProfileReg(e_FmPcdPlcrProfileCounters counter)1432{1433switch (counter)1434{1435case (e_FM_PCD_PLCR_PROFILE_GREEN_PACKET_TOTAL_COUNTER):1436return FM_PCD_PLCR_PAR_PWSEL_PEGPC;1437case (e_FM_PCD_PLCR_PROFILE_YELLOW_PACKET_TOTAL_COUNTER):1438return FM_PCD_PLCR_PAR_PWSEL_PEYPC;1439case (e_FM_PCD_PLCR_PROFILE_RED_PACKET_TOTAL_COUNTER) :1440return FM_PCD_PLCR_PAR_PWSEL_PERPC;1441case (e_FM_PCD_PLCR_PROFILE_RECOLOURED_YELLOW_PACKET_TOTAL_COUNTER) :1442return FM_PCD_PLCR_PAR_PWSEL_PERYPC;1443case (e_FM_PCD_PLCR_PROFILE_RECOLOURED_RED_PACKET_TOTAL_COUNTER) :1444return FM_PCD_PLCR_PAR_PWSEL_PERRPC;1445default:1446REPORT_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);1447return 0;1448}1449}14501451uint32_t FmPcdPlcrBuildNiaProfileReg(bool green, bool yellow, bool red)1452{14531454uint32_t tmpReg32 = 0;14551456if (green)1457tmpReg32 |= FM_PCD_PLCR_PAR_PWSEL_PEGNIA;1458if (yellow)1459tmpReg32 |= FM_PCD_PLCR_PAR_PWSEL_PEYNIA;1460if (red)1461tmpReg32 |= FM_PCD_PLCR_PAR_PWSEL_PERNIA;14621463return tmpReg32;1464}14651466void FmPcdPlcrUpdateRequiredAction(t_Handle h_FmPcd, uint16_t absoluteProfileId, uint32_t requiredAction)1467{1468t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;14691470/* this routine is protected by calling routine */14711472ASSERT_COND(p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].valid);14731474p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].requiredAction |= requiredAction;1475}14761477/*********************** End of inter-module routines ************************/147814791480/**************************************************/1481/*............Policer API.........................*/1482/**************************************************/14831484t_Error FM_PCD_ConfigPlcrAutoRefreshMode(t_Handle h_FmPcd, bool enable)1485{1486t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;14871488SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);1489SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdDriverParam, E_INVALID_HANDLE);1490SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdPlcr, E_INVALID_HANDLE);14911492if (!FmIsMaster(p_FmPcd->h_Fm))1493RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM_PCD_ConfigPlcrAutoRefreshMode - guest mode!"));14941495p_FmPcd->p_FmPcdDriverParam->plcrAutoRefresh = enable;14961497return E_OK;1498}14991500t_Error FM_PCD_ConfigPlcrNumOfSharedProfiles(t_Handle h_FmPcd, uint16_t numOfSharedPlcrProfiles)1501{1502t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;15031504SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);1505SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdDriverParam, E_INVALID_HANDLE);1506SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdPlcr, E_INVALID_HANDLE);15071508p_FmPcd->p_FmPcdPlcr->numOfSharedProfiles = numOfSharedPlcrProfiles;15091510return E_OK;1511}15121513t_Error FM_PCD_SetPlcrStatistics(t_Handle h_FmPcd, bool enable)1514{1515t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;1516uint32_t tmpReg32;15171518SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);1519SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_HANDLE);1520SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdPlcr, E_INVALID_HANDLE);15211522if (!FmIsMaster(p_FmPcd->h_Fm))1523RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM_PCD_SetPlcrStatistics - guest mode!"));15241525tmpReg32 = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_gcr);1526if (enable)1527tmpReg32 |= FM_PCD_PLCR_GCR_STEN;1528else1529tmpReg32 &= ~FM_PCD_PLCR_GCR_STEN;15301531WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_gcr, tmpReg32);1532return E_OK;1533}15341535t_Handle FM_PCD_PlcrProfileSet(t_Handle h_FmPcd,1536t_FmPcdPlcrProfileParams *p_ProfileParams)1537{1538t_FmPcd *p_FmPcd;1539t_FmPcdPlcrRegs *p_FmPcdPlcrRegs;1540t_FmPcdPlcrProfileRegs plcrProfileReg;1541uint32_t intFlags;1542uint16_t absoluteProfileId;1543t_Error err = E_OK;1544uint32_t tmpReg32;1545t_FmPcdPlcrProfile *p_Profile;15461547SANITY_CHECK_RETURN_VALUE(h_FmPcd, E_INVALID_HANDLE, NULL);15481549if (p_ProfileParams->modify)1550{1551p_Profile = (t_FmPcdPlcrProfile *)p_ProfileParams->id.h_Profile;1552p_FmPcd = p_Profile->h_FmPcd;1553absoluteProfileId = p_Profile->absoluteProfileId;1554if (absoluteProfileId >= FM_PCD_PLCR_NUM_ENTRIES)1555{1556REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("profileId too Big "));1557return NULL;1558}15591560SANITY_CHECK_RETURN_VALUE(p_FmPcd->p_FmPcdPlcr, E_INVALID_HANDLE, NULL);15611562/* Try lock profile using flag */1563if (!PlcrProfileFlagTryLock(p_Profile))1564{1565DBG(TRACE, ("Profile Try Lock - BUSY"));1566/* Signal to caller BUSY condition */1567p_ProfileParams->id.h_Profile = NULL;1568return NULL;1569}1570}1571else1572{1573p_FmPcd = (t_FmPcd*)h_FmPcd;15741575SANITY_CHECK_RETURN_VALUE(p_FmPcd->p_FmPcdPlcr, E_INVALID_HANDLE, NULL);15761577/* SMP: needs to be protected only if another core now changes the windows */1578err = FmPcdPlcrGetAbsoluteIdByProfileParams(h_FmPcd,1579p_ProfileParams->id.newParams.profileType,1580p_ProfileParams->id.newParams.h_FmPort,1581p_ProfileParams->id.newParams.relativeProfileId,1582&absoluteProfileId);1583if (err)1584{1585REPORT_ERROR(MAJOR, err, NO_MSG);1586return NULL;1587}15881589if (absoluteProfileId >= FM_PCD_PLCR_NUM_ENTRIES)1590{1591REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("profileId too Big "));1592return NULL;1593}15941595if (FmPcdPlcrIsProfileValid(p_FmPcd, absoluteProfileId))1596{1597REPORT_ERROR(MAJOR, E_ALREADY_EXISTS, ("Policer Profile is already used"));1598return NULL;1599}16001601/* initialize profile struct */1602p_Profile = &p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId];16031604p_Profile->h_FmPcd = p_FmPcd;1605p_Profile->absoluteProfileId = absoluteProfileId;16061607p_Profile->p_Lock = FmPcdAcquireLock(p_FmPcd);1608if (!p_Profile->p_Lock)1609REPORT_ERROR(MAJOR, E_NOT_AVAILABLE, ("FM Policer Profile lock obj!"));1610}16111612SANITY_CHECK_RETURN_VALUE(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE, NULL);16131614p_Profile->nextEngineOnGreen = p_ProfileParams->nextEngineOnGreen;1615memcpy(&p_Profile->paramsOnGreen, &(p_ProfileParams->paramsOnGreen), sizeof(u_FmPcdPlcrNextEngineParams));16161617p_Profile->nextEngineOnYellow = p_ProfileParams->nextEngineOnYellow;1618memcpy(&p_Profile->paramsOnYellow, &(p_ProfileParams->paramsOnYellow), sizeof(u_FmPcdPlcrNextEngineParams));16191620p_Profile->nextEngineOnRed = p_ProfileParams->nextEngineOnRed;1621memcpy(&p_Profile->paramsOnRed, &(p_ProfileParams->paramsOnRed), sizeof(u_FmPcdPlcrNextEngineParams));16221623memset(&plcrProfileReg, 0, sizeof(t_FmPcdPlcrProfileRegs));16241625/* build the policer profile registers */1626err = BuildProfileRegs(h_FmPcd, p_ProfileParams, &plcrProfileReg);1627if (err)1628{1629REPORT_ERROR(MAJOR, err, NO_MSG);1630if (p_ProfileParams->modify)1631/* unlock */1632PlcrProfileFlagUnlock(p_Profile);1633if (!p_ProfileParams->modify &&1634p_Profile->p_Lock)1635/* release allocated Profile lock */1636FmPcdReleaseLock(p_FmPcd, p_Profile->p_Lock);1637return NULL;1638}16391640if (p_FmPcd->h_Hc)1641{1642err = FmHcPcdPlcrSetProfile(p_FmPcd->h_Hc, (t_Handle)p_Profile, &plcrProfileReg);1643if (p_ProfileParams->modify)1644PlcrProfileFlagUnlock(p_Profile);1645if (err)1646{1647/* release the allocated scheme lock */1648if (!p_ProfileParams->modify &&1649p_Profile->p_Lock)1650FmPcdReleaseLock(p_FmPcd, p_Profile->p_Lock);16511652return NULL;1653}1654if (!p_ProfileParams->modify)1655FmPcdPlcrValidateProfileSw(p_FmPcd,absoluteProfileId);1656return (t_Handle)p_Profile;1657}16581659p_FmPcdPlcrRegs = p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs;1660SANITY_CHECK_RETURN_VALUE(p_FmPcdPlcrRegs, E_INVALID_HANDLE, NULL);16611662intFlags = PlcrHwLock(p_FmPcd->p_FmPcdPlcr);1663WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pemode , plcrProfileReg.fmpl_pemode);1664WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pegnia , plcrProfileReg.fmpl_pegnia);1665WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_peynia , plcrProfileReg.fmpl_peynia);1666WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pernia , plcrProfileReg.fmpl_pernia);1667WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pecir , plcrProfileReg.fmpl_pecir);1668WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pecbs , plcrProfileReg.fmpl_pecbs);1669WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pepepir_eir,plcrProfileReg.fmpl_pepepir_eir);1670WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pepbs_ebs,plcrProfileReg.fmpl_pepbs_ebs);1671WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pelts , plcrProfileReg.fmpl_pelts);1672WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pects , plcrProfileReg.fmpl_pects);1673WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pepts_ets,plcrProfileReg.fmpl_pepts_ets);1674WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pegpc , plcrProfileReg.fmpl_pegpc);1675WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_peypc , plcrProfileReg.fmpl_peypc);1676WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_perpc , plcrProfileReg.fmpl_perpc);1677WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_perypc , plcrProfileReg.fmpl_perypc);1678WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_perrpc , plcrProfileReg.fmpl_perrpc);16791680tmpReg32 = FmPcdPlcrBuildWritePlcrActionRegs(absoluteProfileId);1681WritePar(p_FmPcd, tmpReg32);16821683PlcrHwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags);16841685if (!p_ProfileParams->modify)1686FmPcdPlcrValidateProfileSw(p_FmPcd,absoluteProfileId);1687else1688PlcrProfileFlagUnlock(p_Profile);16891690return (t_Handle)p_Profile;1691}16921693t_Error FM_PCD_PlcrProfileDelete(t_Handle h_Profile)1694{1695t_FmPcdPlcrProfile *p_Profile = (t_FmPcdPlcrProfile*)h_Profile;1696t_FmPcd *p_FmPcd;1697uint16_t profileIndx;1698uint32_t tmpReg32, intFlags;1699t_Error err;17001701SANITY_CHECK_RETURN_ERROR(p_Profile, E_INVALID_HANDLE);1702p_FmPcd = p_Profile->h_FmPcd;1703SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);17041705profileIndx = p_Profile->absoluteProfileId;17061707UpdateRequiredActionFlag(p_FmPcd, profileIndx, FALSE);17081709FmPcdPlcrInvalidateProfileSw(p_FmPcd,profileIndx);17101711if (p_FmPcd->h_Hc)1712{1713err = FmHcPcdPlcrDeleteProfile(p_FmPcd->h_Hc, h_Profile);1714if (p_Profile->p_Lock)1715/* release allocated Profile lock */1716FmPcdReleaseLock(p_FmPcd, p_Profile->p_Lock);17171718return err;1719}17201721intFlags = PlcrHwLock(p_FmPcd->p_FmPcdPlcr);1722WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->profileRegs.fmpl_pemode, ~FM_PCD_PLCR_PEMODE_PI);17231724tmpReg32 = FmPcdPlcrBuildWritePlcrActionRegs(profileIndx);1725WritePar(p_FmPcd, tmpReg32);1726PlcrHwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags);172717281729if (p_Profile->p_Lock)1730/* release allocated Profile lock */1731FmPcdReleaseLock(p_FmPcd, p_Profile->p_Lock);17321733/* we do not memset profile as all its fields are being re-initialized at "set",1734* plus its allocation information is still valid. */1735return E_OK;1736}17371738/***************************************************/1739/*............Policer Profile Counter..............*/1740/***************************************************/1741uint32_t FM_PCD_PlcrProfileGetCounter(t_Handle h_Profile, e_FmPcdPlcrProfileCounters counter)1742{1743t_FmPcdPlcrProfile *p_Profile = (t_FmPcdPlcrProfile*)h_Profile;1744t_FmPcd *p_FmPcd;1745uint16_t profileIndx;1746uint32_t intFlags, counterVal = 0;1747t_FmPcdPlcrRegs *p_FmPcdPlcrRegs;17481749SANITY_CHECK_RETURN_ERROR(p_Profile, E_INVALID_HANDLE);1750p_FmPcd = p_Profile->h_FmPcd;1751SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);17521753if (p_FmPcd->h_Hc)1754return FmHcPcdPlcrGetProfileCounter(p_FmPcd->h_Hc, h_Profile, counter);17551756p_FmPcdPlcrRegs = p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs;1757SANITY_CHECK_RETURN_VALUE(p_FmPcdPlcrRegs, E_INVALID_HANDLE, 0);17581759profileIndx = p_Profile->absoluteProfileId;17601761if (profileIndx >= FM_PCD_PLCR_NUM_ENTRIES)1762{1763REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("profileId too Big "));1764return 0;1765}1766intFlags = PlcrHwLock(p_FmPcd->p_FmPcdPlcr);1767WritePar(p_FmPcd, FmPcdPlcrBuildReadPlcrActionReg(profileIndx));17681769switch (counter)1770{1771case e_FM_PCD_PLCR_PROFILE_GREEN_PACKET_TOTAL_COUNTER:1772counterVal = (GET_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pegpc));1773break;1774case e_FM_PCD_PLCR_PROFILE_YELLOW_PACKET_TOTAL_COUNTER:1775counterVal = GET_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_peypc);1776break;1777case e_FM_PCD_PLCR_PROFILE_RED_PACKET_TOTAL_COUNTER:1778counterVal = GET_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_perpc);1779break;1780case e_FM_PCD_PLCR_PROFILE_RECOLOURED_YELLOW_PACKET_TOTAL_COUNTER:1781counterVal = GET_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_perypc);1782break;1783case e_FM_PCD_PLCR_PROFILE_RECOLOURED_RED_PACKET_TOTAL_COUNTER:1784counterVal = GET_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_perrpc);1785break;1786default:1787REPORT_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);1788break;1789}1790PlcrHwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags);17911792return counterVal;1793}17941795t_Error FM_PCD_PlcrProfileSetCounter(t_Handle h_Profile, e_FmPcdPlcrProfileCounters counter, uint32_t value)1796{1797t_FmPcdPlcrProfile *p_Profile = (t_FmPcdPlcrProfile*)h_Profile;1798t_FmPcd *p_FmPcd;1799uint16_t profileIndx;1800uint32_t tmpReg32, intFlags;1801t_FmPcdPlcrRegs *p_FmPcdPlcrRegs;18021803SANITY_CHECK_RETURN_ERROR(p_Profile, E_INVALID_HANDLE);18041805p_FmPcd = p_Profile->h_FmPcd;1806profileIndx = p_Profile->absoluteProfileId;18071808if (p_FmPcd->h_Hc)1809return FmHcPcdPlcrSetProfileCounter(p_FmPcd->h_Hc, h_Profile, counter, value);18101811p_FmPcdPlcrRegs = p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs;1812SANITY_CHECK_RETURN_ERROR(p_FmPcdPlcrRegs, E_INVALID_HANDLE);18131814intFlags = PlcrHwLock(p_FmPcd->p_FmPcdPlcr);1815switch (counter)1816{1817case e_FM_PCD_PLCR_PROFILE_GREEN_PACKET_TOTAL_COUNTER:1818WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pegpc, value);1819break;1820case e_FM_PCD_PLCR_PROFILE_YELLOW_PACKET_TOTAL_COUNTER:1821WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_peypc, value);1822break;1823case e_FM_PCD_PLCR_PROFILE_RED_PACKET_TOTAL_COUNTER:1824WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_perpc, value);1825break;1826case e_FM_PCD_PLCR_PROFILE_RECOLOURED_YELLOW_PACKET_TOTAL_COUNTER:1827WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_perypc ,value);1828break;1829case e_FM_PCD_PLCR_PROFILE_RECOLOURED_RED_PACKET_TOTAL_COUNTER:1830WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_perrpc ,value);1831break;1832default:1833PlcrHwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags);1834RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);1835}18361837/* Activate the atomic write action by writing FMPL_PAR with: GO=1, RW=1, PSI=0, PNUM =1838* Profile Number, PWSEL=0xFFFF (select all words).1839*/1840tmpReg32 = FmPcdPlcrBuildWritePlcrActionReg(profileIndx);1841tmpReg32 |= FmPcdPlcrBuildCounterProfileReg(counter);1842WritePar(p_FmPcd, tmpReg32);1843PlcrHwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags);18441845return E_OK;1846}184718481849