xref: /freebsd/sys/contrib/ncsw/Peripherals/FM/Pcd/fm_plcr.c (revision 924226fba12cc9a228c73b956e1b7fa24c60b055)
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