Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/ncsw/Peripherals/FM/Pcd/fm_plcr.c
48524 views
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
1849