1 /* 2 * Copyright 2008-2012 Freescale Semiconductor Inc. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are met: 6 * * Redistributions of source code must retain the above copyright 7 * notice, this list of conditions and the following disclaimer. 8 * * Redistributions in binary form must reproduce the above copyright 9 * notice, this list of conditions and the following disclaimer in the 10 * documentation and/or other materials provided with the distribution. 11 * * Neither the name of Freescale Semiconductor nor the 12 * names of its contributors may be used to endorse or promote products 13 * derived from this software without specific prior written permission. 14 * 15 * 16 * ALTERNATIVELY, this software may be distributed under the terms of the 17 * GNU General Public License ("GPL") as published by the Free Software 18 * Foundation, either version 2 of that License or (at your option) any 19 * later version. 20 * 21 * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY 22 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY 25 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 28 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 34 /****************************************************************************** 35 @File fm_plcr.c 36 37 @Description FM PCD POLICER... 38 *//***************************************************************************/ 39 #include <linux/math64.h> 40 #include "std_ext.h" 41 #include "error_ext.h" 42 #include "string_ext.h" 43 #include "debug_ext.h" 44 #include "net_ext.h" 45 #include "fm_ext.h" 46 47 #include "fm_common.h" 48 #include "fm_pcd.h" 49 #include "fm_hc.h" 50 #include "fm_pcd_ipc.h" 51 #include "fm_plcr.h" 52 53 54 /****************************************/ 55 /* static functions */ 56 /****************************************/ 57 58 static uint32_t PlcrProfileLock(t_Handle h_Profile) 59 { 60 ASSERT_COND(h_Profile); 61 return FmPcdLockSpinlock(((t_FmPcdPlcrProfile *)h_Profile)->p_Lock); 62 } 63 64 static void PlcrProfileUnlock(t_Handle h_Profile, uint32_t intFlags) 65 { 66 ASSERT_COND(h_Profile); 67 FmPcdUnlockSpinlock(((t_FmPcdPlcrProfile *)h_Profile)->p_Lock, intFlags); 68 } 69 70 static bool PlcrProfileFlagTryLock(t_Handle h_Profile) 71 { 72 ASSERT_COND(h_Profile); 73 return FmPcdLockTryLock(((t_FmPcdPlcrProfile *)h_Profile)->p_Lock); 74 } 75 76 static void PlcrProfileFlagUnlock(t_Handle h_Profile) 77 { 78 ASSERT_COND(h_Profile); 79 FmPcdLockUnlock(((t_FmPcdPlcrProfile *)h_Profile)->p_Lock); 80 } 81 82 static uint32_t PlcrHwLock(t_Handle h_FmPcdPlcr) 83 { 84 ASSERT_COND(h_FmPcdPlcr); 85 return XX_LockIntrSpinlock(((t_FmPcdPlcr*)h_FmPcdPlcr)->h_HwSpinlock); 86 } 87 88 static void PlcrHwUnlock(t_Handle h_FmPcdPlcr, uint32_t intFlags) 89 { 90 ASSERT_COND(h_FmPcdPlcr); 91 XX_UnlockIntrSpinlock(((t_FmPcdPlcr*)h_FmPcdPlcr)->h_HwSpinlock, intFlags); 92 } 93 94 static uint32_t PlcrSwLock(t_Handle h_FmPcdPlcr) 95 { 96 ASSERT_COND(h_FmPcdPlcr); 97 return XX_LockIntrSpinlock(((t_FmPcdPlcr*)h_FmPcdPlcr)->h_SwSpinlock); 98 } 99 100 static void PlcrSwUnlock(t_Handle h_FmPcdPlcr, uint32_t intFlags) 101 { 102 ASSERT_COND(h_FmPcdPlcr); 103 XX_UnlockIntrSpinlock(((t_FmPcdPlcr*)h_FmPcdPlcr)->h_SwSpinlock, intFlags); 104 } 105 106 static bool IsProfileShared(t_Handle h_FmPcd, uint16_t absoluteProfileId) 107 { 108 t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; 109 uint16_t i; 110 111 SANITY_CHECK_RETURN_VALUE(p_FmPcd, E_INVALID_HANDLE, FALSE); 112 113 for (i=0;i<p_FmPcd->p_FmPcdPlcr->numOfSharedProfiles;i++) 114 if (p_FmPcd->p_FmPcdPlcr->sharedProfilesIds[i] == absoluteProfileId) 115 return TRUE; 116 return FALSE; 117 } 118 119 static t_Error SetProfileNia(t_FmPcd *p_FmPcd, e_FmPcdEngine nextEngine, u_FmPcdPlcrNextEngineParams *p_NextEngineParams, uint32_t *nextAction) 120 { 121 uint32_t nia; 122 uint16_t absoluteProfileId; 123 uint8_t relativeSchemeId, physicalSchemeId; 124 125 nia = FM_PCD_PLCR_NIA_VALID; 126 127 switch (nextEngine) 128 { 129 case e_FM_PCD_DONE : 130 switch (p_NextEngineParams->action) 131 { 132 case e_FM_PCD_DROP_FRAME : 133 nia |= GET_NIA_BMI_AC_DISCARD_FRAME(p_FmPcd); 134 break; 135 case e_FM_PCD_ENQ_FRAME: 136 nia |= GET_NIA_BMI_AC_ENQ_FRAME(p_FmPcd); 137 break; 138 default: 139 RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); 140 } 141 break; 142 case e_FM_PCD_KG: 143 physicalSchemeId = FmPcdKgGetSchemeId(p_NextEngineParams->h_DirectScheme); 144 relativeSchemeId = FmPcdKgGetRelativeSchemeId(p_FmPcd, physicalSchemeId); 145 if (relativeSchemeId >= FM_PCD_KG_NUM_OF_SCHEMES) 146 RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, NO_MSG); 147 if (!FmPcdKgIsSchemeValidSw(p_NextEngineParams->h_DirectScheme)) 148 RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid direct scheme.")); 149 if (!KgIsSchemeAlwaysDirect(p_FmPcd, relativeSchemeId)) 150 RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Policer Profile may point only to a scheme that is always direct.")); 151 nia |= NIA_ENG_KG | NIA_KG_DIRECT | physicalSchemeId; 152 break; 153 case e_FM_PCD_PLCR: 154 absoluteProfileId = ((t_FmPcdPlcrProfile *)p_NextEngineParams->h_Profile)->absoluteProfileId; 155 if (!IsProfileShared(p_FmPcd, absoluteProfileId)) 156 RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Next profile must be a shared profile")); 157 if (!FmPcdPlcrIsProfileValid(p_FmPcd, absoluteProfileId)) 158 RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid profile ")); 159 nia |= NIA_ENG_PLCR | NIA_PLCR_ABSOLUTE | absoluteProfileId; 160 break; 161 default: 162 RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); 163 } 164 165 *nextAction = nia; 166 167 return E_OK; 168 } 169 170 static uint32_t CalcFPP(uint32_t fpp) 171 { 172 if (fpp > 15) 173 return 15 - (0x1f - fpp); 174 else 175 return 16 + fpp; 176 } 177 178 static void GetInfoRateReg(e_FmPcdPlcrRateMode rateMode, 179 uint32_t rate, 180 uint64_t tsuInTenthNano, 181 uint32_t fppShift, 182 uint64_t *p_Integer, 183 uint64_t *p_Fraction) 184 { 185 uint64_t tmp, div; 186 187 if (rateMode == e_FM_PCD_PLCR_BYTE_MODE) 188 { 189 /* now we calculate the initial integer for the bigger rate */ 190 /* from Kbps to Bytes/TSU */ 191 tmp = (uint64_t)rate; 192 tmp *= 1000; /* kb --> b */ 193 tmp *= tsuInTenthNano; /* bps --> bpTsu(in 10nano) */ 194 195 div = 1000000000; /* nano */ 196 div *= 10; /* 10 nano */ 197 div *= 8; /* bit to byte */ 198 } 199 else 200 { 201 /* now we calculate the initial integer for the bigger rate */ 202 /* from Kbps to Bytes/TSU */ 203 tmp = (uint64_t)rate; 204 tmp *= tsuInTenthNano; /* bps --> bpTsu(in 10nano) */ 205 206 div = 1000000000; /* nano */ 207 div *= 10; /* 10 nano */ 208 } 209 *p_Integer = (tmp<<fppShift) / div; 210 211 /* for calculating the fraction, we will recalculate cir and deduct the integer. 212 * For precision, we will multiply by 2^16. we do not divid back, since we write 213 * this value as fraction - see spec. 214 */ 215 *p_Fraction = (((tmp<<fppShift)<<16) - ((*p_Integer<<16)*div)) / div; 216 } 217 218 /* .......... */ 219 220 static void CalcRates(uint32_t bitFor1Micro, 221 t_FmPcdPlcrNonPassthroughAlgParams *p_NonPassthroughAlgParam, 222 uint32_t *cir, 223 uint32_t *cbs, 224 uint32_t *pir_eir, 225 uint32_t *pbs_ebs, 226 uint32_t *fpp) 227 { 228 uint64_t integer, fraction; 229 uint32_t temp, tsuInTenthNanos; 230 uint8_t fppShift=0; 231 232 /* we want the tsu to count 10 nano for better precision normally tsu is 3.9 nano, now we will get 39 */ 233 tsuInTenthNanos = (uint32_t)(1000*10/(1 << bitFor1Micro)); 234 235 /* we choose the faster rate to calibrate fpp */ 236 /* The meaning of this step: 237 * when fppShift is 0 it means all TS bits are treated as integer and TSU is the TS LSB count. 238 * In this configuration we calculate the integer and fraction that represent the higher infoRate 239 * When this is done, we can tell where we have "spare" unused bits and optimize the division of TS 240 * into "integer" and "fraction" where the logic is - as many bits as possible for integer at 241 * high rate, as many bits as possible for fraction at low rate. 242 */ 243 if (p_NonPassthroughAlgParam->committedInfoRate > p_NonPassthroughAlgParam->peakOrExcessInfoRate) 244 GetInfoRateReg(p_NonPassthroughAlgParam->rateMode, p_NonPassthroughAlgParam->committedInfoRate, tsuInTenthNanos, 0, &integer, &fraction); 245 else 246 GetInfoRateReg(p_NonPassthroughAlgParam->rateMode, p_NonPassthroughAlgParam->peakOrExcessInfoRate, tsuInTenthNanos, 0, &integer, &fraction); 247 248 /* we shift integer, as in cir/pir it is represented by the MSB 16 bits, and 249 * the LSB bits are for the fraction */ 250 temp = (uint32_t)((integer<<16) & 0x00000000FFFFFFFF); 251 /* temp is effected by the rate. For low rates it may be as low as 0, and then we'll 252 * take max FP = 31. 253 * For high rates it will never exceed the 32 bit reg (after the 16 shift), as it is 254 * limited by the 10G physical port. 255 */ 256 if (temp != 0) 257 { 258 /* In this case, the largest rate integer is non 0, if it does not occupy all (high) 16 259 * bits of the PIR_EIR we can use this fact and enlarge it to occupy all 16 bits. 260 * The logic is to have as many bits for integer in the higher rates, but if we have "0"s 261 * in the integer part of the cir/pir register, than these bits are wasted. So we want 262 * to use these bits for the fraction. in this way we will have for fraction - the number 263 * of "0" bits and the rest - for integer. 264 * In other words: For each bit we shift it in PIR_EIR, we move the FP in the TS 265 * one bit to the left - preserving the relationship and achieving more bits 266 * for integer in the TS. 267 */ 268 269 /* count zeroes left of the higher used bit (in order to shift the value such that 270 * unused bits may be used for fraction). 271 */ 272 while ((temp & 0x80000000) == 0) 273 { 274 temp = temp << 1; 275 fppShift++; 276 } 277 if (fppShift > 15) 278 { 279 REPORT_ERROR(MAJOR, E_INVALID_SELECTION, ("timeStampPeriod to Information rate ratio is too small")); 280 return; 281 } 282 } 283 else 284 { 285 temp = (uint32_t)fraction; /* fraction will alyas be smaller than 2^16 */ 286 if (!temp) 287 /* integer and fraction are 0, we set FP to its max val */ 288 fppShift = 31; 289 else 290 { 291 /* integer was 0 but fraction is not. FP is 16 for the fraction, 292 * + all left zeroes of the fraction. */ 293 fppShift=16; 294 /* count zeroes left of the higher used bit (in order to shift the value such that 295 * unused bits may be used for fraction). 296 */ 297 while ((temp & 0x8000) == 0) 298 { 299 temp = temp << 1; 300 fppShift++; 301 } 302 } 303 } 304 305 /* 306 * This means that the FM TS register will now be used so that 'fppShift' bits are for 307 * fraction and the rest for integer */ 308 /* now we re-calculate cir and pir_eir with the calculated FP */ 309 GetInfoRateReg(p_NonPassthroughAlgParam->rateMode, p_NonPassthroughAlgParam->committedInfoRate, tsuInTenthNanos, fppShift, &integer, &fraction); 310 *cir = (uint32_t)(integer << 16 | (fraction & 0xFFFF)); 311 GetInfoRateReg(p_NonPassthroughAlgParam->rateMode, p_NonPassthroughAlgParam->peakOrExcessInfoRate, tsuInTenthNanos, fppShift, &integer, &fraction); 312 *pir_eir = (uint32_t)(integer << 16 | (fraction & 0xFFFF)); 313 314 *cbs = p_NonPassthroughAlgParam->committedBurstSize; 315 *pbs_ebs = p_NonPassthroughAlgParam->peakOrExcessBurstSize; 316 317 /* convert FP as it should be written to reg. 318 * 0-15 --> 16-31 319 * 16-31 --> 0-15 320 */ 321 *fpp = CalcFPP(fppShift); 322 } 323 324 static void WritePar(t_FmPcd *p_FmPcd, uint32_t par) 325 { 326 t_FmPcdPlcrRegs *p_FmPcdPlcrRegs = p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs; 327 328 ASSERT_COND(FmIsMaster(p_FmPcd->h_Fm)); 329 WRITE_UINT32(p_FmPcdPlcrRegs->fmpl_par, par); 330 331 while (GET_UINT32(p_FmPcdPlcrRegs->fmpl_par) & FM_PCD_PLCR_PAR_GO) ; 332 } 333 334 static t_Error BuildProfileRegs(t_FmPcd *p_FmPcd, 335 t_FmPcdPlcrProfileParams *p_ProfileParams, 336 t_FmPcdPlcrProfileRegs *p_PlcrRegs) 337 { 338 t_Error err = E_OK; 339 uint32_t pemode, gnia, ynia, rnia, bitFor1Micro; 340 341 ASSERT_COND(p_FmPcd); 342 343 bitFor1Micro = FmGetTimeStampScale(p_FmPcd->h_Fm); 344 if (bitFor1Micro == 0) 345 RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ("Timestamp scale")); 346 347 /* Set G, Y, R Nia */ 348 err = SetProfileNia(p_FmPcd, p_ProfileParams->nextEngineOnGreen, &(p_ProfileParams->paramsOnGreen), &gnia); 349 if (err) 350 RETURN_ERROR(MAJOR, err, NO_MSG); 351 err = SetProfileNia(p_FmPcd, p_ProfileParams->nextEngineOnYellow, &(p_ProfileParams->paramsOnYellow), &ynia); 352 if (err) 353 RETURN_ERROR(MAJOR, err, NO_MSG); 354 err = SetProfileNia(p_FmPcd, p_ProfileParams->nextEngineOnRed, &(p_ProfileParams->paramsOnRed), &rnia); 355 if (err) 356 RETURN_ERROR(MAJOR, err, NO_MSG); 357 358 /* Mode fmpl_pemode */ 359 pemode = FM_PCD_PLCR_PEMODE_PI; 360 361 switch (p_ProfileParams->algSelection) 362 { 363 case e_FM_PCD_PLCR_PASS_THROUGH: 364 p_PlcrRegs->fmpl_pecir = 0; 365 p_PlcrRegs->fmpl_pecbs = 0; 366 p_PlcrRegs->fmpl_pepepir_eir = 0; 367 p_PlcrRegs->fmpl_pepbs_ebs = 0; 368 p_PlcrRegs->fmpl_pelts = 0; 369 p_PlcrRegs->fmpl_pects = 0; 370 p_PlcrRegs->fmpl_pepts_ets = 0; 371 pemode &= ~FM_PCD_PLCR_PEMODE_ALG_MASK; 372 switch (p_ProfileParams->colorMode) 373 { 374 case e_FM_PCD_PLCR_COLOR_BLIND: 375 pemode |= FM_PCD_PLCR_PEMODE_CBLND; 376 switch (p_ProfileParams->color.dfltColor) 377 { 378 case e_FM_PCD_PLCR_GREEN: 379 pemode &= ~FM_PCD_PLCR_PEMODE_DEFC_MASK; 380 break; 381 case e_FM_PCD_PLCR_YELLOW: 382 pemode |= FM_PCD_PLCR_PEMODE_DEFC_Y; 383 break; 384 case e_FM_PCD_PLCR_RED: 385 pemode |= FM_PCD_PLCR_PEMODE_DEFC_R; 386 break; 387 case e_FM_PCD_PLCR_OVERRIDE: 388 pemode |= FM_PCD_PLCR_PEMODE_DEFC_OVERRIDE; 389 break; 390 default: 391 RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); 392 } 393 394 break; 395 case e_FM_PCD_PLCR_COLOR_AWARE: 396 pemode &= ~FM_PCD_PLCR_PEMODE_CBLND; 397 break; 398 default: 399 RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); 400 } 401 break; 402 403 case e_FM_PCD_PLCR_RFC_2698: 404 /* Select algorithm MODE[ALG] = "01" */ 405 pemode |= FM_PCD_PLCR_PEMODE_ALG_RFC2698; 406 if (p_ProfileParams->nonPassthroughAlgParams.committedInfoRate > p_ProfileParams->nonPassthroughAlgParams.peakOrExcessInfoRate) 407 RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("in RFC2698 Peak rate must be equal or larger than committedInfoRate.")); 408 goto cont_rfc; 409 case e_FM_PCD_PLCR_RFC_4115: 410 /* Select algorithm MODE[ALG] = "10" */ 411 pemode |= FM_PCD_PLCR_PEMODE_ALG_RFC4115; 412 cont_rfc: 413 /* Select Color-Blind / Color-Aware operation (MODE[CBLND]) */ 414 switch (p_ProfileParams->colorMode) 415 { 416 case e_FM_PCD_PLCR_COLOR_BLIND: 417 pemode |= FM_PCD_PLCR_PEMODE_CBLND; 418 break; 419 case e_FM_PCD_PLCR_COLOR_AWARE: 420 pemode &= ~FM_PCD_PLCR_PEMODE_CBLND; 421 /*In color aware more select override color interpretation (MODE[OVCLR]) */ 422 switch (p_ProfileParams->color.override) 423 { 424 case e_FM_PCD_PLCR_GREEN: 425 pemode &= ~FM_PCD_PLCR_PEMODE_OVCLR_MASK; 426 break; 427 case e_FM_PCD_PLCR_YELLOW: 428 pemode |= FM_PCD_PLCR_PEMODE_OVCLR_Y; 429 break; 430 case e_FM_PCD_PLCR_RED: 431 pemode |= FM_PCD_PLCR_PEMODE_OVCLR_R; 432 break; 433 case e_FM_PCD_PLCR_OVERRIDE: 434 pemode |= FM_PCD_PLCR_PEMODE_OVCLR_G_NC; 435 break; 436 default: 437 RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); 438 } 439 break; 440 default: 441 RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); 442 } 443 /* Select Measurement Unit Mode to BYTE or PACKET (MODE[PKT]) */ 444 switch (p_ProfileParams->nonPassthroughAlgParams.rateMode) 445 { 446 case e_FM_PCD_PLCR_BYTE_MODE : 447 pemode &= ~FM_PCD_PLCR_PEMODE_PKT; 448 switch (p_ProfileParams->nonPassthroughAlgParams.byteModeParams.frameLengthSelection) 449 { 450 case e_FM_PCD_PLCR_L2_FRM_LEN: 451 pemode |= FM_PCD_PLCR_PEMODE_FLS_L2; 452 break; 453 case e_FM_PCD_PLCR_L3_FRM_LEN: 454 pemode |= FM_PCD_PLCR_PEMODE_FLS_L3; 455 break; 456 case e_FM_PCD_PLCR_L4_FRM_LEN: 457 pemode |= FM_PCD_PLCR_PEMODE_FLS_L4; 458 break; 459 case e_FM_PCD_PLCR_FULL_FRM_LEN: 460 pemode |= FM_PCD_PLCR_PEMODE_FLS_FULL; 461 break; 462 default: 463 RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); 464 } 465 switch (p_ProfileParams->nonPassthroughAlgParams.byteModeParams.rollBackFrameSelection) 466 { 467 case e_FM_PCD_PLCR_ROLLBACK_L2_FRM_LEN: 468 pemode &= ~FM_PCD_PLCR_PEMODE_RBFLS; 469 break; 470 case e_FM_PCD_PLCR_ROLLBACK_FULL_FRM_LEN: 471 pemode |= FM_PCD_PLCR_PEMODE_RBFLS; 472 break; 473 default: 474 RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); 475 } 476 break; 477 case e_FM_PCD_PLCR_PACKET_MODE : 478 pemode |= FM_PCD_PLCR_PEMODE_PKT; 479 break; 480 default: 481 RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); 482 } 483 /* Select timeStamp floating point position (MODE[FPP]) to fit the actual traffic rates. For PACKET 484 mode with low traffic rates move the fixed point to the left to increase fraction accuracy. For BYTE 485 mode with high traffic rates move the fixed point to the right to increase integer accuracy. */ 486 487 /* Configure Traffic Parameters*/ 488 { 489 uint32_t cir=0, cbs=0, pir_eir=0, pbs_ebs=0, fpp=0; 490 491 CalcRates(bitFor1Micro, &p_ProfileParams->nonPassthroughAlgParams, &cir, &cbs, &pir_eir, &pbs_ebs, &fpp); 492 493 /* Set Committed Information Rate (CIR) */ 494 p_PlcrRegs->fmpl_pecir = cir; 495 /* Set Committed Burst Size (CBS). */ 496 p_PlcrRegs->fmpl_pecbs = cbs; 497 /* Set Peak Information Rate (PIR_EIR used as PIR) */ 498 p_PlcrRegs->fmpl_pepepir_eir = pir_eir; 499 /* Set Peak Burst Size (PBS_EBS used as PBS) */ 500 p_PlcrRegs->fmpl_pepbs_ebs = pbs_ebs; 501 502 /* Initialize the Metering Buckets to be full (write them with 0xFFFFFFFF. */ 503 /* Peak Rate Token Bucket Size (PTS_ETS used as PTS) */ 504 p_PlcrRegs->fmpl_pepts_ets = 0xFFFFFFFF; 505 /* Committed Rate Token Bucket Size (CTS) */ 506 p_PlcrRegs->fmpl_pects = 0xFFFFFFFF; 507 508 /* Set the FPP based on calculation */ 509 pemode |= (fpp << FM_PCD_PLCR_PEMODE_FPP_SHIFT); 510 } 511 break; /* FM_PCD_PLCR_PEMODE_ALG_RFC2698 , FM_PCD_PLCR_PEMODE_ALG_RFC4115 */ 512 default: 513 RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); 514 } 515 516 p_PlcrRegs->fmpl_pemode = pemode; 517 518 p_PlcrRegs->fmpl_pegnia = gnia; 519 p_PlcrRegs->fmpl_peynia = ynia; 520 p_PlcrRegs->fmpl_pernia = rnia; 521 522 /* Zero Counters */ 523 p_PlcrRegs->fmpl_pegpc = 0; 524 p_PlcrRegs->fmpl_peypc = 0; 525 p_PlcrRegs->fmpl_perpc = 0; 526 p_PlcrRegs->fmpl_perypc = 0; 527 p_PlcrRegs->fmpl_perrpc = 0; 528 529 return E_OK; 530 } 531 532 static t_Error AllocSharedProfiles(t_FmPcd *p_FmPcd, uint16_t numOfProfiles, uint16_t *profilesIds) 533 { 534 uint32_t profilesFound; 535 uint16_t i, k=0; 536 uint32_t intFlags; 537 538 SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); 539 540 if (!numOfProfiles) 541 return E_OK; 542 543 if (numOfProfiles>FM_PCD_PLCR_NUM_ENTRIES) 544 RETURN_ERROR(MINOR, E_INVALID_VALUE, ("numProfiles is too big.")); 545 546 intFlags = PlcrSwLock(p_FmPcd->p_FmPcdPlcr); 547 /* Find numOfProfiles free profiles (may be spread) */ 548 profilesFound = 0; 549 for (i=0;i<FM_PCD_PLCR_NUM_ENTRIES; i++) 550 if (!p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.allocated) 551 { 552 profilesFound++; 553 profilesIds[k] = i; 554 k++; 555 if (profilesFound == numOfProfiles) 556 break; 557 } 558 559 if (profilesFound != numOfProfiles) 560 { 561 PlcrSwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags); 562 RETURN_ERROR(MAJOR, E_INVALID_STATE,NO_MSG); 563 } 564 565 for (i = 0;i<k;i++) 566 { 567 p_FmPcd->p_FmPcdPlcr->profiles[profilesIds[i]].profilesMng.allocated = TRUE; 568 p_FmPcd->p_FmPcdPlcr->profiles[profilesIds[i]].profilesMng.ownerId = 0; 569 } 570 PlcrSwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags); 571 572 return E_OK; 573 } 574 575 static void FreeSharedProfiles(t_FmPcd *p_FmPcd, uint16_t numOfProfiles, uint16_t *profilesIds) 576 { 577 uint16_t i; 578 579 SANITY_CHECK_RETURN(p_FmPcd, E_INVALID_HANDLE); 580 581 ASSERT_COND(numOfProfiles); 582 583 for (i=0; i < numOfProfiles; i++) 584 { 585 ASSERT_COND(p_FmPcd->p_FmPcdPlcr->profiles[profilesIds[i]].profilesMng.allocated); 586 p_FmPcd->p_FmPcdPlcr->profiles[profilesIds[i]].profilesMng.allocated = FALSE; 587 p_FmPcd->p_FmPcdPlcr->profiles[profilesIds[i]].profilesMng.ownerId = p_FmPcd->guestId; 588 } 589 } 590 591 static void UpdateRequiredActionFlag(t_Handle h_FmPcd, uint16_t absoluteProfileId, bool set) 592 { 593 t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; 594 595 /* this routine is protected by calling routine */ 596 597 ASSERT_COND(p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].valid); 598 599 if (set) 600 p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].requiredActionFlag = TRUE; 601 else 602 { 603 p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].requiredAction = 0; 604 p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].requiredActionFlag = FALSE; 605 } 606 } 607 608 /*********************************************/ 609 /*............Policer Exception..............*/ 610 /*********************************************/ 611 static void EventsCB(t_Handle h_FmPcd) 612 { 613 t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; 614 uint32_t event, mask, force; 615 616 ASSERT_COND(FmIsMaster(p_FmPcd->h_Fm)); 617 event = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_evr); 618 mask = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_ier); 619 620 event &= mask; 621 622 /* clear the forced events */ 623 force = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_ifr); 624 if (force & event) 625 WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_ifr, force & ~event); 626 627 628 WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_evr, event); 629 630 if (event & FM_PCD_PLCR_PRAM_SELF_INIT_COMPLETE) 631 p_FmPcd->f_Exception(p_FmPcd->h_App,e_FM_PCD_PLCR_EXCEPTION_PRAM_SELF_INIT_COMPLETE); 632 if (event & FM_PCD_PLCR_ATOMIC_ACTION_COMPLETE) 633 p_FmPcd->f_Exception(p_FmPcd->h_App,e_FM_PCD_PLCR_EXCEPTION_ATOMIC_ACTION_COMPLETE); 634 } 635 636 /* ..... */ 637 638 static void ErrorExceptionsCB(t_Handle h_FmPcd) 639 { 640 t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; 641 uint32_t event, force, captureReg, mask; 642 643 ASSERT_COND(FmIsMaster(p_FmPcd->h_Fm)); 644 event = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_eevr); 645 mask = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_eier); 646 647 event &= mask; 648 649 /* clear the forced events */ 650 force = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_eifr); 651 if (force & event) 652 WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_eifr, force & ~event); 653 654 WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_eevr, event); 655 656 if (event & FM_PCD_PLCR_DOUBLE_ECC) 657 p_FmPcd->f_Exception(p_FmPcd->h_App,e_FM_PCD_PLCR_EXCEPTION_DOUBLE_ECC); 658 if (event & FM_PCD_PLCR_INIT_ENTRY_ERROR) 659 { 660 captureReg = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_upcr); 661 /*ASSERT_COND(captureReg & PLCR_ERR_UNINIT_CAP); 662 p_UnInitCapt->profileNum = (uint8_t)(captureReg & PLCR_ERR_UNINIT_NUM_MASK); 663 p_UnInitCapt->portId = (uint8_t)((captureReg & PLCR_ERR_UNINIT_PID_MASK) >>PLCR_ERR_UNINIT_PID_SHIFT) ; 664 p_UnInitCapt->absolute = (bool)(captureReg & PLCR_ERR_UNINIT_ABSOLUTE_MASK);*/ 665 p_FmPcd->f_FmPcdIndexedException(p_FmPcd->h_App,e_FM_PCD_PLCR_EXCEPTION_INIT_ENTRY_ERROR,(uint16_t)(captureReg & PLCR_ERR_UNINIT_NUM_MASK)); 666 WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_upcr, PLCR_ERR_UNINIT_CAP); 667 } 668 } 669 670 671 /*****************************************************************************/ 672 /* Inter-module API routines */ 673 /*****************************************************************************/ 674 675 t_Handle PlcrConfig(t_FmPcd *p_FmPcd, t_FmPcdParams *p_FmPcdParams) 676 { 677 t_FmPcdPlcr *p_FmPcdPlcr; 678 uint16_t i=0; 679 680 UNUSED(p_FmPcd); 681 UNUSED(p_FmPcdParams); 682 683 p_FmPcdPlcr = (t_FmPcdPlcr *) XX_Malloc(sizeof(t_FmPcdPlcr)); 684 if (!p_FmPcdPlcr) 685 { 686 REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM Policer structure allocation FAILED")); 687 return NULL; 688 } 689 memset(p_FmPcdPlcr, 0, sizeof(t_FmPcdPlcr)); 690 if (p_FmPcd->guestId == NCSW_MASTER_ID) 691 { 692 p_FmPcdPlcr->p_FmPcdPlcrRegs = (t_FmPcdPlcrRegs *)UINT_TO_PTR(FmGetPcdPlcrBaseAddr(p_FmPcdParams->h_Fm)); 693 p_FmPcd->p_FmPcdDriverParam->plcrAutoRefresh = DEFAULT_plcrAutoRefresh; 694 p_FmPcd->exceptions |= (DEFAULT_fmPcdPlcrExceptions | DEFAULT_fmPcdPlcrErrorExceptions); 695 } 696 697 p_FmPcdPlcr->numOfSharedProfiles = DEFAULT_numOfSharedPlcrProfiles; 698 699 p_FmPcdPlcr->partPlcrProfilesBase = p_FmPcdParams->partPlcrProfilesBase; 700 p_FmPcdPlcr->partNumOfPlcrProfiles = p_FmPcdParams->partNumOfPlcrProfiles; 701 /* for backward compatabilty. if no policer profile, will set automatically to the max */ 702 if ((p_FmPcd->guestId == NCSW_MASTER_ID) && 703 (p_FmPcdPlcr->partNumOfPlcrProfiles == 0)) 704 p_FmPcdPlcr->partNumOfPlcrProfiles = FM_PCD_PLCR_NUM_ENTRIES; 705 706 for (i=0; i<FM_PCD_PLCR_NUM_ENTRIES; i++) 707 p_FmPcdPlcr->profiles[i].profilesMng.ownerId = (uint8_t)ILLEGAL_BASE; 708 709 return p_FmPcdPlcr; 710 } 711 712 t_Error PlcrInit(t_FmPcd *p_FmPcd) 713 { 714 t_FmPcdDriverParam *p_Param = p_FmPcd->p_FmPcdDriverParam; 715 t_FmPcdPlcr *p_FmPcdPlcr = p_FmPcd->p_FmPcdPlcr; 716 t_FmPcdPlcrRegs *p_Regs = p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs; 717 t_Error err = E_OK; 718 uint32_t tmpReg32 = 0; 719 uint16_t base; 720 721 if ((p_FmPcdPlcr->partPlcrProfilesBase + p_FmPcdPlcr->partNumOfPlcrProfiles) > FM_PCD_PLCR_NUM_ENTRIES) 722 RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("partPlcrProfilesBase+partNumOfPlcrProfiles out of range!!!")); 723 724 p_FmPcdPlcr->h_HwSpinlock = XX_InitSpinlock(); 725 if (!p_FmPcdPlcr->h_HwSpinlock) 726 RETURN_ERROR(MAJOR, E_NO_MEMORY, ("FM Policer HW spinlock")); 727 728 p_FmPcdPlcr->h_SwSpinlock = XX_InitSpinlock(); 729 if (!p_FmPcdPlcr->h_SwSpinlock) 730 RETURN_ERROR(MAJOR, E_NO_MEMORY, ("FM Policer SW spinlock")); 731 732 base = PlcrAllocProfilesForPartition(p_FmPcd, 733 p_FmPcdPlcr->partPlcrProfilesBase, 734 p_FmPcdPlcr->partNumOfPlcrProfiles, 735 p_FmPcd->guestId); 736 if (base == (uint16_t)ILLEGAL_BASE) 737 RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG); 738 739 if (p_FmPcdPlcr->numOfSharedProfiles) 740 { 741 err = AllocSharedProfiles(p_FmPcd, 742 p_FmPcdPlcr->numOfSharedProfiles, 743 p_FmPcdPlcr->sharedProfilesIds); 744 if (err) 745 RETURN_ERROR(MAJOR, err,NO_MSG); 746 } 747 748 if (p_FmPcd->guestId != NCSW_MASTER_ID) 749 return E_OK; 750 751 /**********************FMPL_GCR******************/ 752 tmpReg32 = 0; 753 tmpReg32 |= FM_PCD_PLCR_GCR_STEN; 754 if (p_Param->plcrAutoRefresh) 755 tmpReg32 |= FM_PCD_PLCR_GCR_DAR; 756 tmpReg32 |= GET_NIA_BMI_AC_ENQ_FRAME(p_FmPcd); 757 758 WRITE_UINT32(p_Regs->fmpl_gcr, tmpReg32); 759 /**********************FMPL_GCR******************/ 760 761 /**********************FMPL_EEVR******************/ 762 WRITE_UINT32(p_Regs->fmpl_eevr, (FM_PCD_PLCR_DOUBLE_ECC | FM_PCD_PLCR_INIT_ENTRY_ERROR)); 763 /**********************FMPL_EEVR******************/ 764 /**********************FMPL_EIER******************/ 765 tmpReg32 = 0; 766 if (p_FmPcd->exceptions & FM_PCD_EX_PLCR_DOUBLE_ECC) 767 { 768 FmEnableRamsEcc(p_FmPcd->h_Fm); 769 tmpReg32 |= FM_PCD_PLCR_DOUBLE_ECC; 770 } 771 if (p_FmPcd->exceptions & FM_PCD_EX_PLCR_INIT_ENTRY_ERROR) 772 tmpReg32 |= FM_PCD_PLCR_INIT_ENTRY_ERROR; 773 WRITE_UINT32(p_Regs->fmpl_eier, tmpReg32); 774 /**********************FMPL_EIER******************/ 775 776 /**********************FMPL_EVR******************/ 777 WRITE_UINT32(p_Regs->fmpl_evr, (FM_PCD_PLCR_PRAM_SELF_INIT_COMPLETE | FM_PCD_PLCR_ATOMIC_ACTION_COMPLETE)); 778 /**********************FMPL_EVR******************/ 779 /**********************FMPL_IER******************/ 780 tmpReg32 = 0; 781 if (p_FmPcd->exceptions & FM_PCD_EX_PLCR_PRAM_SELF_INIT_COMPLETE) 782 tmpReg32 |= FM_PCD_PLCR_PRAM_SELF_INIT_COMPLETE; 783 if (p_FmPcd->exceptions & FM_PCD_EX_PLCR_ATOMIC_ACTION_COMPLETE) 784 tmpReg32 |= FM_PCD_PLCR_ATOMIC_ACTION_COMPLETE; 785 WRITE_UINT32(p_Regs->fmpl_ier, tmpReg32); 786 /**********************FMPL_IER******************/ 787 788 /* register even if no interrupts enabled, to allow future enablement */ 789 FmRegisterIntr(p_FmPcd->h_Fm, 790 e_FM_MOD_PLCR, 791 0, 792 e_FM_INTR_TYPE_ERR, 793 ErrorExceptionsCB, 794 p_FmPcd); 795 FmRegisterIntr(p_FmPcd->h_Fm, 796 e_FM_MOD_PLCR, 797 0, 798 e_FM_INTR_TYPE_NORMAL, 799 EventsCB, 800 p_FmPcd); 801 802 /* driver initializes one DFLT profile at the last entry*/ 803 /**********************FMPL_DPMR******************/ 804 tmpReg32 = 0; 805 WRITE_UINT32(p_Regs->fmpl_dpmr, tmpReg32); 806 p_FmPcd->p_FmPcdPlcr->profiles[0].profilesMng.allocated = TRUE; 807 808 return E_OK; 809 } 810 811 t_Error PlcrFree(t_FmPcd *p_FmPcd) 812 { 813 FmUnregisterIntr(p_FmPcd->h_Fm, e_FM_MOD_PLCR, 0, e_FM_INTR_TYPE_ERR); 814 FmUnregisterIntr(p_FmPcd->h_Fm, e_FM_MOD_PLCR, 0, e_FM_INTR_TYPE_NORMAL); 815 816 if (p_FmPcd->p_FmPcdPlcr->numOfSharedProfiles) 817 FreeSharedProfiles(p_FmPcd, 818 p_FmPcd->p_FmPcdPlcr->numOfSharedProfiles, 819 p_FmPcd->p_FmPcdPlcr->sharedProfilesIds); 820 821 if (p_FmPcd->p_FmPcdPlcr->partNumOfPlcrProfiles) 822 PlcrFreeProfilesForPartition(p_FmPcd, 823 p_FmPcd->p_FmPcdPlcr->partPlcrProfilesBase, 824 p_FmPcd->p_FmPcdPlcr->partNumOfPlcrProfiles, 825 p_FmPcd->guestId); 826 827 if (p_FmPcd->p_FmPcdPlcr->h_SwSpinlock) 828 XX_FreeSpinlock(p_FmPcd->p_FmPcdPlcr->h_SwSpinlock); 829 830 if (p_FmPcd->p_FmPcdPlcr->h_HwSpinlock) 831 XX_FreeSpinlock(p_FmPcd->p_FmPcdPlcr->h_HwSpinlock); 832 833 return E_OK; 834 } 835 836 void PlcrEnable(t_FmPcd *p_FmPcd) 837 { 838 t_FmPcdPlcrRegs *p_Regs = p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs; 839 840 WRITE_UINT32(p_Regs->fmpl_gcr, GET_UINT32(p_Regs->fmpl_gcr) | FM_PCD_PLCR_GCR_EN); 841 } 842 843 void PlcrDisable(t_FmPcd *p_FmPcd) 844 { 845 t_FmPcdPlcrRegs *p_Regs = p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs; 846 847 WRITE_UINT32(p_Regs->fmpl_gcr, GET_UINT32(p_Regs->fmpl_gcr) & ~FM_PCD_PLCR_GCR_EN); 848 } 849 850 uint16_t PlcrAllocProfilesForPartition(t_FmPcd *p_FmPcd, uint16_t base, uint16_t numOfProfiles, uint8_t guestId) 851 { 852 uint32_t intFlags; 853 uint16_t profilesFound = 0; 854 int i = 0; 855 856 ASSERT_COND(p_FmPcd); 857 ASSERT_COND(p_FmPcd->p_FmPcdPlcr); 858 859 if (!numOfProfiles) 860 return 0; 861 862 if ((numOfProfiles > FM_PCD_PLCR_NUM_ENTRIES) || 863 (base + numOfProfiles > FM_PCD_PLCR_NUM_ENTRIES)) 864 return (uint16_t)ILLEGAL_BASE; 865 866 if (p_FmPcd->h_IpcSession) 867 { 868 t_FmIpcResourceAllocParams ipcAllocParams; 869 t_FmPcdIpcMsg msg; 870 t_FmPcdIpcReply reply; 871 t_Error err; 872 uint32_t replyLength; 873 874 memset(&msg, 0, sizeof(msg)); 875 memset(&reply, 0, sizeof(reply)); 876 memset(&ipcAllocParams, 0, sizeof(t_FmIpcResourceAllocParams)); 877 ipcAllocParams.guestId = p_FmPcd->guestId; 878 ipcAllocParams.num = p_FmPcd->p_FmPcdPlcr->partNumOfPlcrProfiles; 879 ipcAllocParams.base = p_FmPcd->p_FmPcdPlcr->partPlcrProfilesBase; 880 msg.msgId = FM_PCD_ALLOC_PROFILES; 881 memcpy(msg.msgBody, &ipcAllocParams, sizeof(t_FmIpcResourceAllocParams)); 882 replyLength = sizeof(uint32_t) + sizeof(uint16_t); 883 err = XX_IpcSendMessage(p_FmPcd->h_IpcSession, 884 (uint8_t*)&msg, 885 sizeof(msg.msgId) + sizeof(t_FmIpcResourceAllocParams), 886 (uint8_t*)&reply, 887 &replyLength, 888 NULL, 889 NULL); 890 if ((err != E_OK) || 891 (replyLength != (sizeof(uint32_t) + sizeof(uint16_t)))) 892 { 893 REPORT_ERROR(MAJOR, err, NO_MSG); 894 return (uint16_t)ILLEGAL_BASE; 895 } 896 else 897 memcpy((uint8_t*)&p_FmPcd->p_FmPcdPlcr->partPlcrProfilesBase, reply.replyBody, sizeof(uint16_t)); 898 if (p_FmPcd->p_FmPcdPlcr->partPlcrProfilesBase == (uint16_t)ILLEGAL_BASE) 899 { 900 REPORT_ERROR(MAJOR, err, NO_MSG); 901 return (uint16_t)ILLEGAL_BASE; 902 } 903 } 904 else if (p_FmPcd->guestId != NCSW_MASTER_ID) 905 { 906 DBG(WARNING, ("FM Guest mode, without IPC - can't validate Policer-profiles range!")); 907 return (uint16_t)ILLEGAL_BASE; 908 } 909 910 intFlags = XX_LockIntrSpinlock(p_FmPcd->h_Spinlock); 911 for (i=base; i<(base+numOfProfiles); i++) 912 if (p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.ownerId == (uint8_t)ILLEGAL_BASE) 913 profilesFound++; 914 else 915 break; 916 917 if (profilesFound == numOfProfiles) 918 for (i=base; i<(base+numOfProfiles); i++) 919 p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.ownerId = guestId; 920 else 921 { 922 XX_UnlockIntrSpinlock(p_FmPcd->h_Spinlock, intFlags); 923 return (uint16_t)ILLEGAL_BASE; 924 } 925 XX_UnlockIntrSpinlock(p_FmPcd->h_Spinlock, intFlags); 926 927 return base; 928 } 929 930 void PlcrFreeProfilesForPartition(t_FmPcd *p_FmPcd, uint16_t base, uint16_t numOfProfiles, uint8_t guestId) 931 { 932 int i = 0; 933 934 ASSERT_COND(p_FmPcd); 935 ASSERT_COND(p_FmPcd->p_FmPcdPlcr); 936 937 if (p_FmPcd->h_IpcSession) 938 { 939 t_FmIpcResourceAllocParams ipcAllocParams; 940 t_FmPcdIpcMsg msg; 941 t_Error err; 942 943 memset(&msg, 0, sizeof(msg)); 944 memset(&ipcAllocParams, 0, sizeof(t_FmIpcResourceAllocParams)); 945 ipcAllocParams.guestId = p_FmPcd->guestId; 946 ipcAllocParams.num = p_FmPcd->p_FmPcdPlcr->partNumOfPlcrProfiles; 947 ipcAllocParams.base = p_FmPcd->p_FmPcdPlcr->partPlcrProfilesBase; 948 msg.msgId = FM_PCD_FREE_PROFILES; 949 memcpy(msg.msgBody, &ipcAllocParams, sizeof(t_FmIpcResourceAllocParams)); 950 err = XX_IpcSendMessage(p_FmPcd->h_IpcSession, 951 (uint8_t*)&msg, 952 sizeof(msg.msgId) + sizeof(t_FmIpcResourceAllocParams), 953 NULL, 954 NULL, 955 NULL, 956 NULL); 957 if (err != E_OK) 958 REPORT_ERROR(MAJOR, err, NO_MSG); 959 return; 960 } 961 else if (p_FmPcd->guestId != NCSW_MASTER_ID) 962 { 963 DBG(WARNING, ("FM Guest mode, without IPC - can't validate Policer-profiles range!")); 964 return; 965 } 966 967 for (i=base; i<(base+numOfProfiles); i++) 968 { 969 if (p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.ownerId == guestId) 970 p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.ownerId = (uint8_t)ILLEGAL_BASE; 971 else 972 DBG(WARNING, ("Request for freeing storage profile window which wasn't allocated to this partition")); 973 } 974 } 975 976 t_Error PlcrSetPortProfiles(t_FmPcd *p_FmPcd, 977 uint8_t hardwarePortId, 978 uint16_t numOfProfiles, 979 uint16_t base) 980 { 981 t_FmPcdPlcrRegs *p_Regs = p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs; 982 uint32_t log2Num, tmpReg32; 983 984 if ((p_FmPcd->guestId != NCSW_MASTER_ID) && 985 !p_Regs && 986 p_FmPcd->h_IpcSession) 987 { 988 t_FmIpcResourceAllocParams ipcAllocParams; 989 t_FmPcdIpcMsg msg; 990 t_Error err; 991 992 memset(&msg, 0, sizeof(msg)); 993 memset(&ipcAllocParams, 0, sizeof(t_FmIpcResourceAllocParams)); 994 ipcAllocParams.guestId = hardwarePortId; 995 ipcAllocParams.num = numOfProfiles; 996 ipcAllocParams.base = base; 997 msg.msgId = FM_PCD_SET_PORT_PROFILES; 998 memcpy(msg.msgBody, &ipcAllocParams, sizeof(t_FmIpcResourceAllocParams)); 999 err = XX_IpcSendMessage(p_FmPcd->h_IpcSession, 1000 (uint8_t*)&msg, 1001 sizeof(msg.msgId) + sizeof(t_FmIpcResourceAllocParams), 1002 NULL, 1003 NULL, 1004 NULL, 1005 NULL); 1006 if (err != E_OK) 1007 RETURN_ERROR(MAJOR, err, NO_MSG); 1008 return E_OK; 1009 } 1010 else if (!p_Regs) 1011 RETURN_ERROR(MINOR, E_NOT_SUPPORTED, 1012 ("Either IPC or 'baseAddress' is required!")); 1013 1014 ASSERT_COND(IN_RANGE(1, hardwarePortId, 63)); 1015 1016 if (GET_UINT32(p_Regs->fmpl_pmr[hardwarePortId-1]) & FM_PCD_PLCR_PMR_V) 1017 RETURN_ERROR(MAJOR, E_INVALID_VALUE, 1018 ("The requesting port has already an allocated profiles window.")); 1019 1020 /**********************FMPL_PMRx******************/ 1021 LOG2((uint64_t)numOfProfiles, log2Num); 1022 tmpReg32 = base; 1023 tmpReg32 |= log2Num << 16; 1024 tmpReg32 |= FM_PCD_PLCR_PMR_V; 1025 WRITE_UINT32(p_Regs->fmpl_pmr[hardwarePortId-1], tmpReg32); 1026 1027 return E_OK; 1028 } 1029 1030 t_Error PlcrClearPortProfiles(t_FmPcd *p_FmPcd, uint8_t hardwarePortId) 1031 { 1032 t_FmPcdPlcrRegs *p_Regs = p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs; 1033 1034 if ((p_FmPcd->guestId != NCSW_MASTER_ID) && 1035 !p_Regs && 1036 p_FmPcd->h_IpcSession) 1037 { 1038 t_FmIpcResourceAllocParams ipcAllocParams; 1039 t_FmPcdIpcMsg msg; 1040 t_Error err; 1041 1042 memset(&msg, 0, sizeof(msg)); 1043 memset(&ipcAllocParams, 0, sizeof(t_FmIpcResourceAllocParams)); 1044 ipcAllocParams.guestId = hardwarePortId; 1045 msg.msgId = FM_PCD_CLEAR_PORT_PROFILES; 1046 memcpy(msg.msgBody, &ipcAllocParams, sizeof(t_FmIpcResourceAllocParams)); 1047 err = XX_IpcSendMessage(p_FmPcd->h_IpcSession, 1048 (uint8_t*)&msg, 1049 sizeof(msg.msgId) + sizeof(t_FmIpcResourceAllocParams), 1050 NULL, 1051 NULL, 1052 NULL, 1053 NULL); 1054 if (err != E_OK) 1055 RETURN_ERROR(MAJOR, err, NO_MSG); 1056 return E_OK; 1057 } 1058 else if (!p_Regs) 1059 RETURN_ERROR(MINOR, E_NOT_SUPPORTED, 1060 ("Either IPC or 'baseAddress' is required!")); 1061 1062 ASSERT_COND(IN_RANGE(1, hardwarePortId, 63)); 1063 WRITE_UINT32(p_Regs->fmpl_pmr[hardwarePortId-1], 0); 1064 1065 return E_OK; 1066 } 1067 1068 t_Error FmPcdPlcrAllocProfiles(t_Handle h_FmPcd, uint8_t hardwarePortId, uint16_t numOfProfiles) 1069 { 1070 t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; 1071 t_Error err = E_OK; 1072 uint32_t profilesFound; 1073 uint32_t intFlags; 1074 uint16_t i, first, swPortIndex = 0; 1075 1076 SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); 1077 1078 if (!numOfProfiles) 1079 return E_OK; 1080 1081 ASSERT_COND(hardwarePortId); 1082 1083 if (numOfProfiles>FM_PCD_PLCR_NUM_ENTRIES) 1084 RETURN_ERROR(MINOR, E_INVALID_VALUE, ("numProfiles is too big.")); 1085 1086 if (!POWER_OF_2(numOfProfiles)) 1087 RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("numProfiles must be a power of 2.")); 1088 1089 first = 0; 1090 profilesFound = 0; 1091 intFlags = PlcrSwLock(p_FmPcd->p_FmPcdPlcr); 1092 1093 for (i=0; i<FM_PCD_PLCR_NUM_ENTRIES; ) 1094 { 1095 if (!p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.allocated) 1096 { 1097 profilesFound++; 1098 i++; 1099 if (profilesFound == numOfProfiles) 1100 break; 1101 } 1102 else 1103 { 1104 profilesFound = 0; 1105 /* advance i to the next aligned address */ 1106 i = first = (uint16_t)(first + numOfProfiles); 1107 } 1108 } 1109 1110 if (profilesFound == numOfProfiles) 1111 { 1112 for (i=first; i<first + numOfProfiles; i++) 1113 { 1114 p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.allocated = TRUE; 1115 p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.ownerId = hardwarePortId; 1116 } 1117 } 1118 else 1119 { 1120 PlcrSwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags); 1121 RETURN_ERROR(MINOR, E_FULL, ("No profiles.")); 1122 } 1123 PlcrSwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags); 1124 1125 err = PlcrSetPortProfiles(p_FmPcd, hardwarePortId, numOfProfiles, first); 1126 if (err) 1127 { 1128 RETURN_ERROR(MAJOR, err, NO_MSG); 1129 } 1130 1131 HW_PORT_ID_TO_SW_PORT_INDX(swPortIndex, hardwarePortId); 1132 1133 p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].numOfProfiles = numOfProfiles; 1134 p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].profilesBase = first; 1135 1136 return E_OK; 1137 } 1138 1139 t_Error FmPcdPlcrFreeProfiles(t_Handle h_FmPcd, uint8_t hardwarePortId) 1140 { 1141 t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; 1142 t_Error err = E_OK; 1143 uint32_t intFlags; 1144 uint16_t i, swPortIndex = 0; 1145 1146 ASSERT_COND(IN_RANGE(1, hardwarePortId, 63)); 1147 1148 SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); 1149 SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_HANDLE); 1150 1151 HW_PORT_ID_TO_SW_PORT_INDX(swPortIndex, hardwarePortId); 1152 1153 err = PlcrClearPortProfiles(p_FmPcd, hardwarePortId); 1154 if (err) 1155 RETURN_ERROR(MAJOR, err,NO_MSG); 1156 1157 intFlags = PlcrSwLock(p_FmPcd->p_FmPcdPlcr); 1158 for (i=p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].profilesBase; 1159 i<(p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].profilesBase + 1160 p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].numOfProfiles); 1161 i++) 1162 { 1163 ASSERT_COND(p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.ownerId == hardwarePortId); 1164 ASSERT_COND(p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.allocated); 1165 1166 p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.allocated = FALSE; 1167 p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.ownerId = p_FmPcd->guestId; 1168 } 1169 PlcrSwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags); 1170 1171 p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].numOfProfiles = 0; 1172 p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].profilesBase = 0; 1173 1174 return E_OK; 1175 } 1176 1177 t_Error FmPcdPlcrCcGetSetParams(t_Handle h_FmPcd, uint16_t profileIndx ,uint32_t requiredAction) 1178 { 1179 t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; 1180 t_FmPcdPlcr *p_FmPcdPlcr = p_FmPcd->p_FmPcdPlcr; 1181 t_FmPcdPlcrRegs *p_FmPcdPlcrRegs = p_FmPcdPlcr->p_FmPcdPlcrRegs; 1182 uint32_t tmpReg32, intFlags; 1183 t_Error err; 1184 1185 /* Calling function locked all PCD modules, so no need to lock here */ 1186 1187 if (profileIndx >= FM_PCD_PLCR_NUM_ENTRIES) 1188 RETURN_ERROR(MAJOR, E_INVALID_VALUE,("Policer profile out of range")); 1189 1190 if (!FmPcdPlcrIsProfileValid(p_FmPcd, profileIndx)) 1191 RETURN_ERROR(MAJOR, E_INVALID_VALUE,("Policer profile is not valid")); 1192 1193 /*intFlags = PlcrProfileLock(&p_FmPcd->p_FmPcdPlcr->profiles[profileIndx]);*/ 1194 1195 if (p_FmPcd->h_Hc) 1196 { 1197 err = FmHcPcdPlcrCcGetSetParams(p_FmPcd->h_Hc, profileIndx, requiredAction); 1198 1199 UpdateRequiredActionFlag(p_FmPcd, profileIndx, TRUE); 1200 FmPcdPlcrUpdateRequiredAction(p_FmPcd, profileIndx, requiredAction); 1201 1202 /*PlcrProfileUnlock(&p_FmPcd->p_FmPcdPlcr->profiles[profileIndx], intFlags);*/ 1203 return err; 1204 } 1205 1206 /* lock the HW because once we read the registers we don't want them to be changed 1207 * by another access. (We can copy to a tmp location and release the lock!) */ 1208 1209 intFlags = PlcrHwLock(p_FmPcdPlcr); 1210 WritePar(p_FmPcd, FmPcdPlcrBuildReadPlcrActionReg(profileIndx)); 1211 1212 if (!p_FmPcd->p_FmPcdPlcr->profiles[profileIndx].requiredActionFlag || 1213 !(p_FmPcd->p_FmPcdPlcr->profiles[profileIndx].requiredAction & requiredAction)) 1214 { 1215 if (requiredAction & UPDATE_NIA_ENQ_WITHOUT_DMA) 1216 { 1217 if ((p_FmPcd->p_FmPcdPlcr->profiles[profileIndx].nextEngineOnGreen!= e_FM_PCD_DONE) || 1218 (p_FmPcd->p_FmPcdPlcr->profiles[profileIndx].nextEngineOnYellow!= e_FM_PCD_DONE) || 1219 (p_FmPcd->p_FmPcdPlcr->profiles[profileIndx].nextEngineOnRed!= e_FM_PCD_DONE)) 1220 { 1221 PlcrHwUnlock(p_FmPcdPlcr, intFlags); 1222 /*PlcrProfileUnlock(&p_FmPcd->p_FmPcdPlcr->profiles[profileIndx], intFlags);*/ 1223 RETURN_ERROR (MAJOR, E_OK, ("In this case the next engine can be e_FM_PCD_DONE")); 1224 } 1225 1226 if (p_FmPcd->p_FmPcdPlcr->profiles[profileIndx].paramsOnGreen.action == e_FM_PCD_ENQ_FRAME) 1227 { 1228 tmpReg32 = GET_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pegnia); 1229 if (!(tmpReg32 & (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME))) 1230 { 1231 PlcrHwUnlock(p_FmPcdPlcr, intFlags); 1232 /*PlcrProfileUnlock(&p_FmPcd->p_FmPcdPlcr->profiles[profileIndx], intFlags);*/ 1233 RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Next engine of this policer profile has to be assigned to FM_PCD_DONE")); 1234 } 1235 tmpReg32 |= NIA_BMI_AC_ENQ_FRAME_WITHOUT_DMA; 1236 WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pegnia, tmpReg32); 1237 tmpReg32 = FmPcdPlcrBuildWritePlcrActionReg(profileIndx); 1238 tmpReg32 |= FM_PCD_PLCR_PAR_PWSEL_PEGNIA; 1239 WritePar(p_FmPcd, tmpReg32); 1240 } 1241 1242 if (p_FmPcd->p_FmPcdPlcr->profiles[profileIndx].paramsOnYellow.action == e_FM_PCD_ENQ_FRAME) 1243 { 1244 tmpReg32 = GET_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_peynia); 1245 if (!(tmpReg32 & (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME))) 1246 { 1247 PlcrHwUnlock(p_FmPcdPlcr, intFlags); 1248 /*PlcrProfileUnlock(&p_FmPcd->p_FmPcdPlcr->profiles[profileIndx], intFlags);*/ 1249 RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Next engine of this policer profile has to be assigned to FM_PCD_DONE")); 1250 } 1251 tmpReg32 |= NIA_BMI_AC_ENQ_FRAME_WITHOUT_DMA; 1252 WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_peynia, tmpReg32); 1253 tmpReg32 = FmPcdPlcrBuildWritePlcrActionReg(profileIndx); 1254 tmpReg32 |= FM_PCD_PLCR_PAR_PWSEL_PEYNIA; 1255 WritePar(p_FmPcd, tmpReg32); 1256 PlcrHwUnlock(p_FmPcdPlcr, intFlags); 1257 } 1258 1259 if (p_FmPcd->p_FmPcdPlcr->profiles[profileIndx].paramsOnRed.action == e_FM_PCD_ENQ_FRAME) 1260 { 1261 tmpReg32 = GET_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pernia); 1262 if (!(tmpReg32 & (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME))) 1263 { 1264 PlcrHwUnlock(p_FmPcdPlcr, intFlags); 1265 /*PlcrProfileUnlock(&p_FmPcd->p_FmPcdPlcr->profiles[profileIndx], intFlags);*/ 1266 RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Next engine of this policer profile has to be assigned to FM_PCD_DONE")); 1267 } 1268 tmpReg32 |= NIA_BMI_AC_ENQ_FRAME_WITHOUT_DMA; 1269 WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pernia, tmpReg32); 1270 tmpReg32 = FmPcdPlcrBuildWritePlcrActionReg(profileIndx); 1271 tmpReg32 |= FM_PCD_PLCR_PAR_PWSEL_PERNIA; 1272 WritePar(p_FmPcd, tmpReg32); 1273 1274 } 1275 } 1276 } 1277 PlcrHwUnlock(p_FmPcdPlcr, intFlags); 1278 1279 UpdateRequiredActionFlag(p_FmPcd, profileIndx, TRUE); 1280 FmPcdPlcrUpdateRequiredAction(p_FmPcd, profileIndx, requiredAction); 1281 1282 /*PlcrProfileUnlock(&p_FmPcd->p_FmPcdPlcr->profiles[profileIndx], intFlags);*/ 1283 1284 return E_OK; 1285 } 1286 1287 uint32_t FmPcdPlcrGetRequiredActionFlag(t_Handle h_FmPcd, uint16_t absoluteProfileId) 1288 { 1289 t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; 1290 1291 ASSERT_COND(p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].valid); 1292 1293 return p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].requiredActionFlag; 1294 } 1295 1296 uint32_t FmPcdPlcrGetRequiredAction(t_Handle h_FmPcd, uint16_t absoluteProfileId) 1297 { 1298 t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; 1299 1300 ASSERT_COND(p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].valid); 1301 1302 return p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].requiredAction; 1303 } 1304 1305 bool FmPcdPlcrIsProfileValid(t_Handle h_FmPcd, uint16_t absoluteProfileId) 1306 { 1307 t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; 1308 t_FmPcdPlcr *p_FmPcdPlcr = p_FmPcd->p_FmPcdPlcr; 1309 1310 ASSERT_COND(absoluteProfileId < FM_PCD_PLCR_NUM_ENTRIES); 1311 1312 return p_FmPcdPlcr->profiles[absoluteProfileId].valid; 1313 } 1314 1315 void FmPcdPlcrValidateProfileSw(t_Handle h_FmPcd, uint16_t absoluteProfileId) 1316 { 1317 t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; 1318 uint32_t intFlags; 1319 1320 ASSERT_COND(!p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].valid); 1321 1322 intFlags = PlcrProfileLock(&p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId]); 1323 p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].valid = TRUE; 1324 PlcrProfileUnlock(&p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId], intFlags); 1325 } 1326 1327 void FmPcdPlcrInvalidateProfileSw(t_Handle h_FmPcd, uint16_t absoluteProfileId) 1328 { 1329 t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; 1330 uint32_t intFlags; 1331 1332 ASSERT_COND(p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].valid); 1333 1334 intFlags = PlcrProfileLock(&p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId]); 1335 p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].valid = FALSE; 1336 PlcrProfileUnlock(&p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId], intFlags); 1337 } 1338 1339 uint16_t FmPcdPlcrProfileGetAbsoluteId(t_Handle h_Profile) 1340 { 1341 return ((t_FmPcdPlcrProfile*)h_Profile)->absoluteProfileId; 1342 } 1343 1344 t_Error FmPcdPlcrGetAbsoluteIdByProfileParams(t_Handle h_FmPcd, 1345 e_FmPcdProfileTypeSelection profileType, 1346 t_Handle h_FmPort, 1347 uint16_t relativeProfile, 1348 uint16_t *p_AbsoluteId) 1349 { 1350 t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; 1351 t_FmPcdPlcr *p_FmPcdPlcr = p_FmPcd->p_FmPcdPlcr; 1352 uint8_t i; 1353 1354 switch (profileType) 1355 { 1356 case e_FM_PCD_PLCR_PORT_PRIVATE: 1357 /* get port PCD id from port handle */ 1358 for (i=0;i<FM_MAX_NUM_OF_PORTS;i++) 1359 if (p_FmPcd->p_FmPcdPlcr->portsMapping[i].h_FmPort == h_FmPort) 1360 break; 1361 if (i == FM_MAX_NUM_OF_PORTS) 1362 RETURN_ERROR(MAJOR, E_INVALID_STATE , ("Invalid port handle.")); 1363 1364 if (!p_FmPcd->p_FmPcdPlcr->portsMapping[i].numOfProfiles) 1365 RETURN_ERROR(MAJOR, E_INVALID_SELECTION , ("Port has no allocated profiles")); 1366 if (relativeProfile >= p_FmPcd->p_FmPcdPlcr->portsMapping[i].numOfProfiles) 1367 RETURN_ERROR(MAJOR, E_INVALID_SELECTION , ("Profile id is out of range")); 1368 *p_AbsoluteId = (uint16_t)(p_FmPcd->p_FmPcdPlcr->portsMapping[i].profilesBase + relativeProfile); 1369 break; 1370 case e_FM_PCD_PLCR_SHARED: 1371 if (relativeProfile >= p_FmPcdPlcr->numOfSharedProfiles) 1372 RETURN_ERROR(MAJOR, E_INVALID_SELECTION , ("Profile id is out of range")); 1373 *p_AbsoluteId = (uint16_t)(p_FmPcdPlcr->sharedProfilesIds[relativeProfile]); 1374 break; 1375 default: 1376 RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Invalid policer profile type")); 1377 } 1378 1379 return E_OK; 1380 } 1381 1382 uint16_t FmPcdPlcrGetPortProfilesBase(t_Handle h_FmPcd, uint8_t hardwarePortId) 1383 { 1384 t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; 1385 uint16_t swPortIndex = 0; 1386 1387 HW_PORT_ID_TO_SW_PORT_INDX(swPortIndex, hardwarePortId); 1388 1389 return p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].profilesBase; 1390 } 1391 1392 uint16_t FmPcdPlcrGetPortNumOfProfiles(t_Handle h_FmPcd, uint8_t hardwarePortId) 1393 { 1394 t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; 1395 uint16_t swPortIndex = 0; 1396 1397 HW_PORT_ID_TO_SW_PORT_INDX(swPortIndex, hardwarePortId); 1398 1399 return p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].numOfProfiles; 1400 1401 } 1402 uint32_t FmPcdPlcrBuildWritePlcrActionReg(uint16_t absoluteProfileId) 1403 { 1404 return (uint32_t)(FM_PCD_PLCR_PAR_GO | 1405 ((uint32_t)absoluteProfileId << FM_PCD_PLCR_PAR_PNUM_SHIFT)); 1406 } 1407 1408 uint32_t FmPcdPlcrBuildWritePlcrActionRegs(uint16_t absoluteProfileId) 1409 { 1410 return (uint32_t)(FM_PCD_PLCR_PAR_GO | 1411 ((uint32_t)absoluteProfileId << FM_PCD_PLCR_PAR_PNUM_SHIFT) | 1412 FM_PCD_PLCR_PAR_PWSEL_MASK); 1413 } 1414 1415 bool FmPcdPlcrHwProfileIsValid(uint32_t profileModeReg) 1416 { 1417 1418 if (profileModeReg & FM_PCD_PLCR_PEMODE_PI) 1419 return TRUE; 1420 else 1421 return FALSE; 1422 } 1423 1424 uint32_t FmPcdPlcrBuildReadPlcrActionReg(uint16_t absoluteProfileId) 1425 { 1426 return (uint32_t)(FM_PCD_PLCR_PAR_GO | 1427 FM_PCD_PLCR_PAR_R | 1428 ((uint32_t)absoluteProfileId << FM_PCD_PLCR_PAR_PNUM_SHIFT) | 1429 FM_PCD_PLCR_PAR_PWSEL_MASK); 1430 } 1431 1432 uint32_t FmPcdPlcrBuildCounterProfileReg(e_FmPcdPlcrProfileCounters counter) 1433 { 1434 switch (counter) 1435 { 1436 case (e_FM_PCD_PLCR_PROFILE_GREEN_PACKET_TOTAL_COUNTER): 1437 return FM_PCD_PLCR_PAR_PWSEL_PEGPC; 1438 case (e_FM_PCD_PLCR_PROFILE_YELLOW_PACKET_TOTAL_COUNTER): 1439 return FM_PCD_PLCR_PAR_PWSEL_PEYPC; 1440 case (e_FM_PCD_PLCR_PROFILE_RED_PACKET_TOTAL_COUNTER) : 1441 return FM_PCD_PLCR_PAR_PWSEL_PERPC; 1442 case (e_FM_PCD_PLCR_PROFILE_RECOLOURED_YELLOW_PACKET_TOTAL_COUNTER) : 1443 return FM_PCD_PLCR_PAR_PWSEL_PERYPC; 1444 case (e_FM_PCD_PLCR_PROFILE_RECOLOURED_RED_PACKET_TOTAL_COUNTER) : 1445 return FM_PCD_PLCR_PAR_PWSEL_PERRPC; 1446 default: 1447 REPORT_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); 1448 return 0; 1449 } 1450 } 1451 1452 uint32_t FmPcdPlcrBuildNiaProfileReg(bool green, bool yellow, bool red) 1453 { 1454 1455 uint32_t tmpReg32 = 0; 1456 1457 if (green) 1458 tmpReg32 |= FM_PCD_PLCR_PAR_PWSEL_PEGNIA; 1459 if (yellow) 1460 tmpReg32 |= FM_PCD_PLCR_PAR_PWSEL_PEYNIA; 1461 if (red) 1462 tmpReg32 |= FM_PCD_PLCR_PAR_PWSEL_PERNIA; 1463 1464 return tmpReg32; 1465 } 1466 1467 void FmPcdPlcrUpdateRequiredAction(t_Handle h_FmPcd, uint16_t absoluteProfileId, uint32_t requiredAction) 1468 { 1469 t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; 1470 1471 /* this routine is protected by calling routine */ 1472 1473 ASSERT_COND(p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].valid); 1474 1475 p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].requiredAction |= requiredAction; 1476 } 1477 1478 /*********************** End of inter-module routines ************************/ 1479 1480 1481 /**************************************************/ 1482 /*............Policer API.........................*/ 1483 /**************************************************/ 1484 1485 t_Error FM_PCD_ConfigPlcrAutoRefreshMode(t_Handle h_FmPcd, bool enable) 1486 { 1487 t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; 1488 1489 SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); 1490 SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdDriverParam, E_INVALID_HANDLE); 1491 SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdPlcr, E_INVALID_HANDLE); 1492 1493 if (!FmIsMaster(p_FmPcd->h_Fm)) 1494 RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM_PCD_ConfigPlcrAutoRefreshMode - guest mode!")); 1495 1496 p_FmPcd->p_FmPcdDriverParam->plcrAutoRefresh = enable; 1497 1498 return E_OK; 1499 } 1500 1501 t_Error FM_PCD_ConfigPlcrNumOfSharedProfiles(t_Handle h_FmPcd, uint16_t numOfSharedPlcrProfiles) 1502 { 1503 t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; 1504 1505 SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); 1506 SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdDriverParam, E_INVALID_HANDLE); 1507 SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdPlcr, E_INVALID_HANDLE); 1508 1509 p_FmPcd->p_FmPcdPlcr->numOfSharedProfiles = numOfSharedPlcrProfiles; 1510 1511 return E_OK; 1512 } 1513 1514 t_Error FM_PCD_SetPlcrStatistics(t_Handle h_FmPcd, bool enable) 1515 { 1516 t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; 1517 uint32_t tmpReg32; 1518 1519 SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); 1520 SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_HANDLE); 1521 SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdPlcr, E_INVALID_HANDLE); 1522 1523 if (!FmIsMaster(p_FmPcd->h_Fm)) 1524 RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM_PCD_SetPlcrStatistics - guest mode!")); 1525 1526 tmpReg32 = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_gcr); 1527 if (enable) 1528 tmpReg32 |= FM_PCD_PLCR_GCR_STEN; 1529 else 1530 tmpReg32 &= ~FM_PCD_PLCR_GCR_STEN; 1531 1532 WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_gcr, tmpReg32); 1533 return E_OK; 1534 } 1535 1536 t_Handle FM_PCD_PlcrProfileSet(t_Handle h_FmPcd, 1537 t_FmPcdPlcrProfileParams *p_ProfileParams) 1538 { 1539 t_FmPcd *p_FmPcd; 1540 t_FmPcdPlcrRegs *p_FmPcdPlcrRegs; 1541 t_FmPcdPlcrProfileRegs plcrProfileReg; 1542 uint32_t intFlags; 1543 uint16_t absoluteProfileId; 1544 t_Error err = E_OK; 1545 uint32_t tmpReg32; 1546 t_FmPcdPlcrProfile *p_Profile; 1547 1548 SANITY_CHECK_RETURN_VALUE(h_FmPcd, E_INVALID_HANDLE, NULL); 1549 1550 if (p_ProfileParams->modify) 1551 { 1552 p_Profile = (t_FmPcdPlcrProfile *)p_ProfileParams->id.h_Profile; 1553 p_FmPcd = p_Profile->h_FmPcd; 1554 absoluteProfileId = p_Profile->absoluteProfileId; 1555 if (absoluteProfileId >= FM_PCD_PLCR_NUM_ENTRIES) 1556 { 1557 REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("profileId too Big ")); 1558 return NULL; 1559 } 1560 1561 SANITY_CHECK_RETURN_VALUE(p_FmPcd->p_FmPcdPlcr, E_INVALID_HANDLE, NULL); 1562 1563 /* Try lock profile using flag */ 1564 if (!PlcrProfileFlagTryLock(p_Profile)) 1565 { 1566 DBG(TRACE, ("Profile Try Lock - BUSY")); 1567 /* Signal to caller BUSY condition */ 1568 p_ProfileParams->id.h_Profile = NULL; 1569 return NULL; 1570 } 1571 } 1572 else 1573 { 1574 p_FmPcd = (t_FmPcd*)h_FmPcd; 1575 1576 SANITY_CHECK_RETURN_VALUE(p_FmPcd->p_FmPcdPlcr, E_INVALID_HANDLE, NULL); 1577 1578 /* SMP: needs to be protected only if another core now changes the windows */ 1579 err = FmPcdPlcrGetAbsoluteIdByProfileParams(h_FmPcd, 1580 p_ProfileParams->id.newParams.profileType, 1581 p_ProfileParams->id.newParams.h_FmPort, 1582 p_ProfileParams->id.newParams.relativeProfileId, 1583 &absoluteProfileId); 1584 if (err) 1585 { 1586 REPORT_ERROR(MAJOR, err, NO_MSG); 1587 return NULL; 1588 } 1589 1590 if (absoluteProfileId >= FM_PCD_PLCR_NUM_ENTRIES) 1591 { 1592 REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("profileId too Big ")); 1593 return NULL; 1594 } 1595 1596 if (FmPcdPlcrIsProfileValid(p_FmPcd, absoluteProfileId)) 1597 { 1598 REPORT_ERROR(MAJOR, E_ALREADY_EXISTS, ("Policer Profile is already used")); 1599 return NULL; 1600 } 1601 1602 /* initialize profile struct */ 1603 p_Profile = &p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId]; 1604 1605 p_Profile->h_FmPcd = p_FmPcd; 1606 p_Profile->absoluteProfileId = absoluteProfileId; 1607 1608 p_Profile->p_Lock = FmPcdAcquireLock(p_FmPcd); 1609 if (!p_Profile->p_Lock) 1610 REPORT_ERROR(MAJOR, E_NOT_AVAILABLE, ("FM Policer Profile lock obj!")); 1611 } 1612 1613 SANITY_CHECK_RETURN_VALUE(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE, NULL); 1614 1615 p_Profile->nextEngineOnGreen = p_ProfileParams->nextEngineOnGreen; 1616 memcpy(&p_Profile->paramsOnGreen, &(p_ProfileParams->paramsOnGreen), sizeof(u_FmPcdPlcrNextEngineParams)); 1617 1618 p_Profile->nextEngineOnYellow = p_ProfileParams->nextEngineOnYellow; 1619 memcpy(&p_Profile->paramsOnYellow, &(p_ProfileParams->paramsOnYellow), sizeof(u_FmPcdPlcrNextEngineParams)); 1620 1621 p_Profile->nextEngineOnRed = p_ProfileParams->nextEngineOnRed; 1622 memcpy(&p_Profile->paramsOnRed, &(p_ProfileParams->paramsOnRed), sizeof(u_FmPcdPlcrNextEngineParams)); 1623 1624 memset(&plcrProfileReg, 0, sizeof(t_FmPcdPlcrProfileRegs)); 1625 1626 /* build the policer profile registers */ 1627 err = BuildProfileRegs(h_FmPcd, p_ProfileParams, &plcrProfileReg); 1628 if (err) 1629 { 1630 REPORT_ERROR(MAJOR, err, NO_MSG); 1631 if (p_ProfileParams->modify) 1632 /* unlock */ 1633 PlcrProfileFlagUnlock(p_Profile); 1634 if (!p_ProfileParams->modify && 1635 p_Profile->p_Lock) 1636 /* release allocated Profile lock */ 1637 FmPcdReleaseLock(p_FmPcd, p_Profile->p_Lock); 1638 return NULL; 1639 } 1640 1641 if (p_FmPcd->h_Hc) 1642 { 1643 err = FmHcPcdPlcrSetProfile(p_FmPcd->h_Hc, (t_Handle)p_Profile, &plcrProfileReg); 1644 if (p_ProfileParams->modify) 1645 PlcrProfileFlagUnlock(p_Profile); 1646 if (err) 1647 { 1648 /* release the allocated scheme lock */ 1649 if (!p_ProfileParams->modify && 1650 p_Profile->p_Lock) 1651 FmPcdReleaseLock(p_FmPcd, p_Profile->p_Lock); 1652 1653 return NULL; 1654 } 1655 if (!p_ProfileParams->modify) 1656 FmPcdPlcrValidateProfileSw(p_FmPcd,absoluteProfileId); 1657 return (t_Handle)p_Profile; 1658 } 1659 1660 p_FmPcdPlcrRegs = p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs; 1661 SANITY_CHECK_RETURN_VALUE(p_FmPcdPlcrRegs, E_INVALID_HANDLE, NULL); 1662 1663 intFlags = PlcrHwLock(p_FmPcd->p_FmPcdPlcr); 1664 WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pemode , plcrProfileReg.fmpl_pemode); 1665 WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pegnia , plcrProfileReg.fmpl_pegnia); 1666 WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_peynia , plcrProfileReg.fmpl_peynia); 1667 WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pernia , plcrProfileReg.fmpl_pernia); 1668 WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pecir , plcrProfileReg.fmpl_pecir); 1669 WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pecbs , plcrProfileReg.fmpl_pecbs); 1670 WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pepepir_eir,plcrProfileReg.fmpl_pepepir_eir); 1671 WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pepbs_ebs,plcrProfileReg.fmpl_pepbs_ebs); 1672 WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pelts , plcrProfileReg.fmpl_pelts); 1673 WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pects , plcrProfileReg.fmpl_pects); 1674 WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pepts_ets,plcrProfileReg.fmpl_pepts_ets); 1675 WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pegpc , plcrProfileReg.fmpl_pegpc); 1676 WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_peypc , plcrProfileReg.fmpl_peypc); 1677 WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_perpc , plcrProfileReg.fmpl_perpc); 1678 WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_perypc , plcrProfileReg.fmpl_perypc); 1679 WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_perrpc , plcrProfileReg.fmpl_perrpc); 1680 1681 tmpReg32 = FmPcdPlcrBuildWritePlcrActionRegs(absoluteProfileId); 1682 WritePar(p_FmPcd, tmpReg32); 1683 1684 PlcrHwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags); 1685 1686 if (!p_ProfileParams->modify) 1687 FmPcdPlcrValidateProfileSw(p_FmPcd,absoluteProfileId); 1688 else 1689 PlcrProfileFlagUnlock(p_Profile); 1690 1691 return (t_Handle)p_Profile; 1692 } 1693 1694 t_Error FM_PCD_PlcrProfileDelete(t_Handle h_Profile) 1695 { 1696 t_FmPcdPlcrProfile *p_Profile = (t_FmPcdPlcrProfile*)h_Profile; 1697 t_FmPcd *p_FmPcd; 1698 uint16_t profileIndx; 1699 uint32_t tmpReg32, intFlags; 1700 t_Error err; 1701 1702 SANITY_CHECK_RETURN_ERROR(p_Profile, E_INVALID_HANDLE); 1703 p_FmPcd = p_Profile->h_FmPcd; 1704 SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); 1705 1706 profileIndx = p_Profile->absoluteProfileId; 1707 1708 UpdateRequiredActionFlag(p_FmPcd, profileIndx, FALSE); 1709 1710 FmPcdPlcrInvalidateProfileSw(p_FmPcd,profileIndx); 1711 1712 if (p_FmPcd->h_Hc) 1713 { 1714 err = FmHcPcdPlcrDeleteProfile(p_FmPcd->h_Hc, h_Profile); 1715 if (p_Profile->p_Lock) 1716 /* release allocated Profile lock */ 1717 FmPcdReleaseLock(p_FmPcd, p_Profile->p_Lock); 1718 1719 return err; 1720 } 1721 1722 intFlags = PlcrHwLock(p_FmPcd->p_FmPcdPlcr); 1723 WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->profileRegs.fmpl_pemode, ~FM_PCD_PLCR_PEMODE_PI); 1724 1725 tmpReg32 = FmPcdPlcrBuildWritePlcrActionRegs(profileIndx); 1726 WritePar(p_FmPcd, tmpReg32); 1727 PlcrHwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags); 1728 1729 1730 if (p_Profile->p_Lock) 1731 /* release allocated Profile lock */ 1732 FmPcdReleaseLock(p_FmPcd, p_Profile->p_Lock); 1733 1734 /* we do not memset profile as all its fields are being re-initialized at "set", 1735 * plus its allocation information is still valid. */ 1736 return E_OK; 1737 } 1738 1739 /***************************************************/ 1740 /*............Policer Profile Counter..............*/ 1741 /***************************************************/ 1742 uint32_t FM_PCD_PlcrProfileGetCounter(t_Handle h_Profile, e_FmPcdPlcrProfileCounters counter) 1743 { 1744 t_FmPcdPlcrProfile *p_Profile = (t_FmPcdPlcrProfile*)h_Profile; 1745 t_FmPcd *p_FmPcd; 1746 uint16_t profileIndx; 1747 uint32_t intFlags, counterVal = 0; 1748 t_FmPcdPlcrRegs *p_FmPcdPlcrRegs; 1749 1750 SANITY_CHECK_RETURN_ERROR(p_Profile, E_INVALID_HANDLE); 1751 p_FmPcd = p_Profile->h_FmPcd; 1752 SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); 1753 1754 if (p_FmPcd->h_Hc) 1755 return FmHcPcdPlcrGetProfileCounter(p_FmPcd->h_Hc, h_Profile, counter); 1756 1757 p_FmPcdPlcrRegs = p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs; 1758 SANITY_CHECK_RETURN_VALUE(p_FmPcdPlcrRegs, E_INVALID_HANDLE, 0); 1759 1760 profileIndx = p_Profile->absoluteProfileId; 1761 1762 if (profileIndx >= FM_PCD_PLCR_NUM_ENTRIES) 1763 { 1764 REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("profileId too Big ")); 1765 return 0; 1766 } 1767 intFlags = PlcrHwLock(p_FmPcd->p_FmPcdPlcr); 1768 WritePar(p_FmPcd, FmPcdPlcrBuildReadPlcrActionReg(profileIndx)); 1769 1770 switch (counter) 1771 { 1772 case e_FM_PCD_PLCR_PROFILE_GREEN_PACKET_TOTAL_COUNTER: 1773 counterVal = (GET_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pegpc)); 1774 break; 1775 case e_FM_PCD_PLCR_PROFILE_YELLOW_PACKET_TOTAL_COUNTER: 1776 counterVal = GET_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_peypc); 1777 break; 1778 case e_FM_PCD_PLCR_PROFILE_RED_PACKET_TOTAL_COUNTER: 1779 counterVal = GET_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_perpc); 1780 break; 1781 case e_FM_PCD_PLCR_PROFILE_RECOLOURED_YELLOW_PACKET_TOTAL_COUNTER: 1782 counterVal = GET_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_perypc); 1783 break; 1784 case e_FM_PCD_PLCR_PROFILE_RECOLOURED_RED_PACKET_TOTAL_COUNTER: 1785 counterVal = GET_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_perrpc); 1786 break; 1787 default: 1788 REPORT_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); 1789 break; 1790 } 1791 PlcrHwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags); 1792 1793 return counterVal; 1794 } 1795 1796 t_Error FM_PCD_PlcrProfileSetCounter(t_Handle h_Profile, e_FmPcdPlcrProfileCounters counter, uint32_t value) 1797 { 1798 t_FmPcdPlcrProfile *p_Profile = (t_FmPcdPlcrProfile*)h_Profile; 1799 t_FmPcd *p_FmPcd; 1800 uint16_t profileIndx; 1801 uint32_t tmpReg32, intFlags; 1802 t_FmPcdPlcrRegs *p_FmPcdPlcrRegs; 1803 1804 SANITY_CHECK_RETURN_ERROR(p_Profile, E_INVALID_HANDLE); 1805 1806 p_FmPcd = p_Profile->h_FmPcd; 1807 profileIndx = p_Profile->absoluteProfileId; 1808 1809 if (p_FmPcd->h_Hc) 1810 return FmHcPcdPlcrSetProfileCounter(p_FmPcd->h_Hc, h_Profile, counter, value); 1811 1812 p_FmPcdPlcrRegs = p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs; 1813 SANITY_CHECK_RETURN_ERROR(p_FmPcdPlcrRegs, E_INVALID_HANDLE); 1814 1815 intFlags = PlcrHwLock(p_FmPcd->p_FmPcdPlcr); 1816 switch (counter) 1817 { 1818 case e_FM_PCD_PLCR_PROFILE_GREEN_PACKET_TOTAL_COUNTER: 1819 WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pegpc, value); 1820 break; 1821 case e_FM_PCD_PLCR_PROFILE_YELLOW_PACKET_TOTAL_COUNTER: 1822 WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_peypc, value); 1823 break; 1824 case e_FM_PCD_PLCR_PROFILE_RED_PACKET_TOTAL_COUNTER: 1825 WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_perpc, value); 1826 break; 1827 case e_FM_PCD_PLCR_PROFILE_RECOLOURED_YELLOW_PACKET_TOTAL_COUNTER: 1828 WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_perypc ,value); 1829 break; 1830 case e_FM_PCD_PLCR_PROFILE_RECOLOURED_RED_PACKET_TOTAL_COUNTER: 1831 WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_perrpc ,value); 1832 break; 1833 default: 1834 PlcrHwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags); 1835 RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); 1836 } 1837 1838 /* Activate the atomic write action by writing FMPL_PAR with: GO=1, RW=1, PSI=0, PNUM = 1839 * Profile Number, PWSEL=0xFFFF (select all words). 1840 */ 1841 tmpReg32 = FmPcdPlcrBuildWritePlcrActionReg(profileIndx); 1842 tmpReg32 |= FmPcdPlcrBuildCounterProfileReg(counter); 1843 WritePar(p_FmPcd, tmpReg32); 1844 PlcrHwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags); 1845 1846 return E_OK; 1847 } 1848