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
PlcrProfileLock(t_Handle h_Profile)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
PlcrProfileUnlock(t_Handle h_Profile,uint32_t intFlags)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
PlcrProfileFlagTryLock(t_Handle h_Profile)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
PlcrProfileFlagUnlock(t_Handle h_Profile)76 static void PlcrProfileFlagUnlock(t_Handle h_Profile)
77 {
78 ASSERT_COND(h_Profile);
79 FmPcdLockUnlock(((t_FmPcdPlcrProfile *)h_Profile)->p_Lock);
80 }
81
PlcrHwLock(t_Handle h_FmPcdPlcr)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
PlcrHwUnlock(t_Handle h_FmPcdPlcr,uint32_t intFlags)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
PlcrSwLock(t_Handle h_FmPcdPlcr)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
PlcrSwUnlock(t_Handle h_FmPcdPlcr,uint32_t intFlags)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
IsProfileShared(t_Handle h_FmPcd,uint16_t absoluteProfileId)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
SetProfileNia(t_FmPcd * p_FmPcd,e_FmPcdEngine nextEngine,u_FmPcdPlcrNextEngineParams * p_NextEngineParams,uint32_t * nextAction)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
CalcFPP(uint32_t fpp)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
GetInfoRateReg(e_FmPcdPlcrRateMode rateMode,uint32_t rate,uint64_t tsuInTenthNano,uint32_t fppShift,uint64_t * p_Integer,uint64_t * p_Fraction)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
CalcRates(uint32_t bitFor1Micro,t_FmPcdPlcrNonPassthroughAlgParams * p_NonPassthroughAlgParam,uint32_t * cir,uint32_t * cbs,uint32_t * pir_eir,uint32_t * pbs_ebs,uint32_t * fpp)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
WritePar(t_FmPcd * p_FmPcd,uint32_t par)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
BuildProfileRegs(t_FmPcd * p_FmPcd,t_FmPcdPlcrProfileParams * p_ProfileParams,t_FmPcdPlcrProfileRegs * p_PlcrRegs)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
AllocSharedProfiles(t_FmPcd * p_FmPcd,uint16_t numOfProfiles,uint16_t * profilesIds)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
FreeSharedProfiles(t_FmPcd * p_FmPcd,uint16_t numOfProfiles,uint16_t * profilesIds)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
UpdateRequiredActionFlag(t_Handle h_FmPcd,uint16_t absoluteProfileId,bool set)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 /*********************************************/
EventsCB(t_Handle h_FmPcd)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
ErrorExceptionsCB(t_Handle h_FmPcd)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
PlcrConfig(t_FmPcd * p_FmPcd,t_FmPcdParams * p_FmPcdParams)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
PlcrInit(t_FmPcd * p_FmPcd)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
PlcrFree(t_FmPcd * p_FmPcd)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
PlcrEnable(t_FmPcd * p_FmPcd)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
PlcrDisable(t_FmPcd * p_FmPcd)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
PlcrAllocProfilesForPartition(t_FmPcd * p_FmPcd,uint16_t base,uint16_t numOfProfiles,uint8_t guestId)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
PlcrFreeProfilesForPartition(t_FmPcd * p_FmPcd,uint16_t base,uint16_t numOfProfiles,uint8_t guestId)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
PlcrSetPortProfiles(t_FmPcd * p_FmPcd,uint8_t hardwarePortId,uint16_t numOfProfiles,uint16_t base)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
PlcrClearPortProfiles(t_FmPcd * p_FmPcd,uint8_t hardwarePortId)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
FmPcdPlcrAllocProfiles(t_Handle h_FmPcd,uint8_t hardwarePortId,uint16_t numOfProfiles)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
FmPcdPlcrFreeProfiles(t_Handle h_FmPcd,uint8_t hardwarePortId)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
FmPcdPlcrCcGetSetParams(t_Handle h_FmPcd,uint16_t profileIndx,uint32_t requiredAction)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
FmPcdPlcrGetRequiredActionFlag(t_Handle h_FmPcd,uint16_t absoluteProfileId)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
FmPcdPlcrGetRequiredAction(t_Handle h_FmPcd,uint16_t absoluteProfileId)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
FmPcdPlcrIsProfileValid(t_Handle h_FmPcd,uint16_t absoluteProfileId)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
FmPcdPlcrValidateProfileSw(t_Handle h_FmPcd,uint16_t absoluteProfileId)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
FmPcdPlcrInvalidateProfileSw(t_Handle h_FmPcd,uint16_t absoluteProfileId)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
FmPcdPlcrProfileGetAbsoluteId(t_Handle h_Profile)1339 uint16_t FmPcdPlcrProfileGetAbsoluteId(t_Handle h_Profile)
1340 {
1341 return ((t_FmPcdPlcrProfile*)h_Profile)->absoluteProfileId;
1342 }
1343
FmPcdPlcrGetAbsoluteIdByProfileParams(t_Handle h_FmPcd,e_FmPcdProfileTypeSelection profileType,t_Handle h_FmPort,uint16_t relativeProfile,uint16_t * p_AbsoluteId)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
FmPcdPlcrGetPortProfilesBase(t_Handle h_FmPcd,uint8_t hardwarePortId)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
FmPcdPlcrGetPortNumOfProfiles(t_Handle h_FmPcd,uint8_t hardwarePortId)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 }
FmPcdPlcrBuildWritePlcrActionReg(uint16_t absoluteProfileId)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
FmPcdPlcrBuildWritePlcrActionRegs(uint16_t absoluteProfileId)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
FmPcdPlcrHwProfileIsValid(uint32_t profileModeReg)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
FmPcdPlcrBuildReadPlcrActionReg(uint16_t absoluteProfileId)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
FmPcdPlcrBuildCounterProfileReg(e_FmPcdPlcrProfileCounters counter)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
FmPcdPlcrBuildNiaProfileReg(bool green,bool yellow,bool red)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
FmPcdPlcrUpdateRequiredAction(t_Handle h_FmPcd,uint16_t absoluteProfileId,uint32_t requiredAction)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
FM_PCD_ConfigPlcrAutoRefreshMode(t_Handle h_FmPcd,bool enable)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
FM_PCD_ConfigPlcrNumOfSharedProfiles(t_Handle h_FmPcd,uint16_t numOfSharedPlcrProfiles)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
FM_PCD_SetPlcrStatistics(t_Handle h_FmPcd,bool enable)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
FM_PCD_PlcrProfileSet(t_Handle h_FmPcd,t_FmPcdPlcrProfileParams * p_ProfileParams)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
FM_PCD_PlcrProfileDelete(t_Handle h_Profile)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 /***************************************************/
FM_PCD_PlcrProfileGetCounter(t_Handle h_Profile,e_FmPcdPlcrProfileCounters counter)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
FM_PCD_PlcrProfileSetCounter(t_Handle h_Profile,e_FmPcdPlcrProfileCounters counter,uint32_t value)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