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_replic.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_replic.c
36
37
@Description FM frame replicator
38
*//***************************************************************************/
39
#include "std_ext.h"
40
#include "error_ext.h"
41
#include "string_ext.h"
42
#include "debug_ext.h"
43
#include "fm_pcd_ext.h"
44
#include "fm_muram_ext.h"
45
#include "fm_common.h"
46
#include "fm_hc.h"
47
#include "fm_replic.h"
48
#include "fm_cc.h"
49
#include "list_ext.h"
50
51
52
/****************************************/
53
/* static functions */
54
/****************************************/
55
static uint8_t GetMemberPosition(t_FmPcdFrmReplicGroup *p_ReplicGroup,
56
uint32_t memberIndex,
57
bool isAddOperation)
58
{
59
uint8_t memberPosition;
60
uint32_t lastMemberIndex;
61
62
ASSERT_COND(p_ReplicGroup);
63
64
/* the last member index is different between add and remove operation -
65
in case of remove - this is exactly the last member index
66
in case of add - this is the last member index + 1 - e.g.
67
if we have 4 members, the index of the actual last member is 3(because the
68
index starts from 0) therefore in order to add a new member as the last
69
member we shall use memberIndex = 4 and not 3
70
*/
71
if (isAddOperation)
72
lastMemberIndex = p_ReplicGroup->numOfEntries;
73
else
74
lastMemberIndex = p_ReplicGroup->numOfEntries-1;
75
76
/* last */
77
if (memberIndex == lastMemberIndex)
78
memberPosition = FRM_REPLIC_LAST_MEMBER_INDEX;
79
else
80
{
81
/* first */
82
if (memberIndex == 0)
83
memberPosition = FRM_REPLIC_FIRST_MEMBER_INDEX;
84
else
85
{
86
/* middle */
87
ASSERT_COND(memberIndex < lastMemberIndex);
88
memberPosition = FRM_REPLIC_MIDDLE_MEMBER_INDEX;
89
}
90
}
91
return memberPosition;
92
}
93
94
static t_Error MemberCheckParams(t_Handle h_FmPcd,
95
t_FmPcdCcNextEngineParams *p_MemberParams)
96
{
97
t_Error err;
98
99
100
if ((p_MemberParams->nextEngine != e_FM_PCD_DONE) &&
101
(p_MemberParams->nextEngine != e_FM_PCD_KG) &&
102
(p_MemberParams->nextEngine != e_FM_PCD_PLCR))
103
RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Next engine of a member should be MatchTable(cc) or Done or Policer"));
104
105
/* check the regular parameters of the next engine */
106
err = ValidateNextEngineParams(h_FmPcd, p_MemberParams, e_FM_PCD_CC_STATS_MODE_NONE);
107
if (err)
108
RETURN_ERROR(MAJOR, err, ("member next engine parameters"));
109
110
return E_OK;
111
}
112
113
static t_Error CheckParams(t_Handle h_FmPcd,
114
t_FmPcdFrmReplicGroupParams *p_ReplicGroupParam)
115
{
116
int i;
117
t_Error err;
118
119
/* check that max num of entries is at least 2 */
120
if (!IN_RANGE(2, p_ReplicGroupParam->maxNumOfEntries, FM_PCD_FRM_REPLIC_MAX_NUM_OF_ENTRIES))
121
RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, ("maxNumOfEntries in the frame replicator parameters should be 2-%d",FM_PCD_FRM_REPLIC_MAX_NUM_OF_ENTRIES));
122
123
/* check that number of entries is greater than zero */
124
if (!p_ReplicGroupParam->numOfEntries)
125
RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("numOFEntries in the frame replicator group should be greater than zero"));
126
127
/* check that max num of entries is equal or greater than number of entries */
128
if (p_ReplicGroupParam->maxNumOfEntries < p_ReplicGroupParam->numOfEntries)
129
RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("maxNumOfEntries should be equal or greater than numOfEntries"));
130
131
for (i=0; i<p_ReplicGroupParam->numOfEntries; i++)
132
{
133
err = MemberCheckParams(h_FmPcd, &p_ReplicGroupParam->nextEngineParams[i]);
134
if (err)
135
RETURN_ERROR(MAJOR, err, ("member check parameters"));
136
}
137
return E_OK;
138
}
139
140
static t_FmPcdFrmReplicMember *GetAvailableMember(t_FmPcdFrmReplicGroup *p_ReplicGroup)
141
{
142
t_FmPcdFrmReplicMember *p_ReplicMember = NULL;
143
t_List *p_Next;
144
145
if (!LIST_IsEmpty(&p_ReplicGroup->availableMembersList))
146
{
147
p_Next = LIST_FIRST(&p_ReplicGroup->availableMembersList);
148
p_ReplicMember = LIST_OBJECT(p_Next, t_FmPcdFrmReplicMember, node);
149
ASSERT_COND(p_ReplicMember);
150
LIST_DelAndInit(p_Next);
151
}
152
return p_ReplicMember;
153
}
154
155
static void PutAvailableMember(t_FmPcdFrmReplicGroup *p_ReplicGroup,
156
t_FmPcdFrmReplicMember *p_ReplicMember)
157
{
158
LIST_AddToTail(&p_ReplicMember->node, &p_ReplicGroup->availableMembersList);
159
}
160
161
static void AddMemberToList(t_FmPcdFrmReplicGroup *p_ReplicGroup,
162
t_FmPcdFrmReplicMember *p_CurrentMember,
163
t_List *p_ListHead)
164
{
165
LIST_Add(&p_CurrentMember->node, p_ListHead);
166
167
p_ReplicGroup->numOfEntries++;
168
}
169
170
static void RemoveMemberFromList(t_FmPcdFrmReplicGroup *p_ReplicGroup,
171
t_FmPcdFrmReplicMember *p_CurrentMember)
172
{
173
ASSERT_COND(p_ReplicGroup->numOfEntries);
174
LIST_DelAndInit(&p_CurrentMember->node);
175
p_ReplicGroup->numOfEntries--;
176
}
177
178
static void LinkSourceToMember(t_FmPcdFrmReplicGroup *p_ReplicGroup,
179
t_AdOfTypeContLookup *p_SourceTd,
180
t_FmPcdFrmReplicMember *p_ReplicMember)
181
{
182
t_FmPcd *p_FmPcd;
183
184
ASSERT_COND(p_SourceTd);
185
ASSERT_COND(p_ReplicMember);
186
ASSERT_COND(p_ReplicGroup);
187
ASSERT_COND(p_ReplicGroup->h_FmPcd);
188
189
/* Link the first member in the group to the source TD */
190
p_FmPcd = p_ReplicGroup->h_FmPcd;
191
192
WRITE_UINT32(p_SourceTd->matchTblPtr,
193
(uint32_t)(XX_VirtToPhys(p_ReplicMember->p_MemberAd) -
194
p_FmPcd->physicalMuramBase));
195
}
196
197
static void LinkMemberToMember(t_FmPcdFrmReplicGroup *p_ReplicGroup,
198
t_FmPcdFrmReplicMember *p_CurrentMember,
199
t_FmPcdFrmReplicMember *p_NextMember)
200
{
201
t_AdOfTypeResult *p_CurrReplicAd = (t_AdOfTypeResult*)p_CurrentMember->p_MemberAd;
202
t_AdOfTypeResult *p_NextReplicAd = NULL;
203
t_FmPcd *p_FmPcd;
204
uint32_t offset = 0;
205
206
/* Check if the next member exists or it's NULL (- means that this is the last member) */
207
if (p_NextMember)
208
{
209
p_NextReplicAd = (t_AdOfTypeResult*)p_NextMember->p_MemberAd;
210
p_FmPcd = p_ReplicGroup->h_FmPcd;
211
offset = (XX_VirtToPhys(p_NextReplicAd) - (p_FmPcd->physicalMuramBase));
212
offset = ((offset>>NEXT_FRM_REPLIC_ADDR_SHIFT)<< NEXT_FRM_REPLIC_MEMBER_INDEX_SHIFT);
213
}
214
215
/* link the current AD to point to the AD of the next member */
216
WRITE_UINT32(p_CurrReplicAd->res, offset);
217
}
218
219
static t_Error ModifyDescriptor(t_FmPcdFrmReplicGroup *p_ReplicGroup,
220
void *p_OldDescriptor,
221
void *p_NewDescriptor)
222
{
223
t_Handle h_Hc;
224
t_Error err;
225
t_FmPcd *p_FmPcd;
226
227
ASSERT_COND(p_ReplicGroup);
228
ASSERT_COND(p_ReplicGroup->h_FmPcd);
229
ASSERT_COND(p_OldDescriptor);
230
ASSERT_COND(p_NewDescriptor);
231
232
p_FmPcd = p_ReplicGroup->h_FmPcd;
233
h_Hc = FmPcdGetHcHandle(p_FmPcd);
234
if (!h_Hc)
235
RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("Host command"));
236
237
err = FmHcPcdCcDoDynamicChange(h_Hc,
238
(uint32_t)(XX_VirtToPhys(p_OldDescriptor) - p_FmPcd->physicalMuramBase),
239
(uint32_t)(XX_VirtToPhys(p_NewDescriptor) - p_FmPcd->physicalMuramBase));
240
if (err)
241
RETURN_ERROR(MAJOR, err, ("Dynamic change host command"));
242
243
return E_OK;
244
}
245
246
static void FillReplicAdOfTypeResult(void *p_ReplicAd, bool last)
247
{
248
t_AdOfTypeResult *p_CurrReplicAd = (t_AdOfTypeResult*)p_ReplicAd;
249
uint32_t tmp;
250
251
tmp = GET_UINT32(p_CurrReplicAd->plcrProfile);
252
if (last)
253
/* clear the NL bit in case it's the last member in the group*/
254
WRITE_UINT32(p_CurrReplicAd->plcrProfile,(tmp & ~FRM_REPLIC_NL_BIT));
255
else
256
/* set the NL bit in case it's not the last member in the group */
257
WRITE_UINT32(p_CurrReplicAd->plcrProfile, (tmp |FRM_REPLIC_NL_BIT));
258
259
/* set FR bit in the action descriptor */
260
tmp = GET_UINT32(p_CurrReplicAd->nia);
261
WRITE_UINT32(p_CurrReplicAd->nia,
262
(tmp | FRM_REPLIC_FR_BIT | FM_PCD_AD_RESULT_EXTENDED_MODE ));
263
}
264
265
static void BuildSourceTd(void *p_Ad)
266
{
267
t_AdOfTypeContLookup *p_SourceTd;
268
269
ASSERT_COND(p_Ad);
270
271
p_SourceTd = (t_AdOfTypeContLookup *)p_Ad;
272
273
IOMemSet32((uint8_t*)p_SourceTd, 0, FM_PCD_CC_AD_ENTRY_SIZE);
274
275
/* initialize the source table descriptor */
276
WRITE_UINT32(p_SourceTd->ccAdBase, FM_PCD_AD_CONT_LOOKUP_TYPE);
277
WRITE_UINT32(p_SourceTd->pcAndOffsets, FRM_REPLIC_SOURCE_TD_OPCODE);
278
}
279
280
static t_Error BuildShadowAndModifyDescriptor(t_FmPcdFrmReplicGroup *p_ReplicGroup,
281
t_FmPcdFrmReplicMember *p_NextMember,
282
t_FmPcdFrmReplicMember *p_CurrentMember,
283
bool sourceDescriptor,
284
bool last)
285
{
286
t_FmPcd *p_FmPcd;
287
t_FmPcdFrmReplicMember shadowMember;
288
t_Error err;
289
290
ASSERT_COND(p_ReplicGroup);
291
ASSERT_COND(p_ReplicGroup->h_FmPcd);
292
293
p_FmPcd = p_ReplicGroup->h_FmPcd;
294
ASSERT_COND(p_FmPcd->p_CcShadow);
295
296
if (!TRY_LOCK(p_FmPcd->h_ShadowSpinlock, &p_FmPcd->shadowLock))
297
return ERROR_CODE(E_BUSY);
298
299
if (sourceDescriptor)
300
{
301
BuildSourceTd(p_FmPcd->p_CcShadow);
302
LinkSourceToMember(p_ReplicGroup, p_FmPcd->p_CcShadow, p_NextMember);
303
304
/* Modify the source table descriptor according to the prepared shadow descriptor */
305
err = ModifyDescriptor(p_ReplicGroup,
306
p_ReplicGroup->p_SourceTd,
307
p_FmPcd->p_CcShadow/* new prepared source td */);
308
309
RELEASE_LOCK(p_FmPcd->shadowLock);
310
if (err)
311
RETURN_ERROR(MAJOR, err, ("Modify source Descriptor in BuildShadowAndModifyDescriptor"));
312
313
}
314
else
315
{
316
IO2IOCpy32(p_FmPcd->p_CcShadow,
317
p_CurrentMember->p_MemberAd,
318
FM_PCD_CC_AD_ENTRY_SIZE);
319
320
/* update the last bit in the shadow ad */
321
FillReplicAdOfTypeResult(p_FmPcd->p_CcShadow, last);
322
323
shadowMember.p_MemberAd = p_FmPcd->p_CcShadow;
324
325
/* update the next FR member index */
326
LinkMemberToMember(p_ReplicGroup, &shadowMember, p_NextMember);
327
328
/* Modify the next member according to the prepared shadow descriptor */
329
err = ModifyDescriptor(p_ReplicGroup,
330
p_CurrentMember->p_MemberAd,
331
p_FmPcd->p_CcShadow);
332
333
RELEASE_LOCK(p_FmPcd->shadowLock);
334
if (err)
335
RETURN_ERROR(MAJOR, err, ("Modify Descriptor in BuildShadowAndModifyDescriptor"));
336
}
337
338
339
return E_OK;
340
}
341
342
static t_FmPcdFrmReplicMember* GetMemberByIndex(t_FmPcdFrmReplicGroup *p_ReplicGroup,
343
uint16_t memberIndex)
344
{
345
int i=0;
346
t_List *p_Pos;
347
t_FmPcdFrmReplicMember *p_Member = NULL;
348
349
LIST_FOR_EACH(p_Pos, &p_ReplicGroup->membersList)
350
{
351
if (i == memberIndex)
352
{
353
p_Member = LIST_OBJECT(p_Pos, t_FmPcdFrmReplicMember, node);
354
return p_Member;
355
}
356
i++;
357
}
358
return p_Member;
359
}
360
361
static t_Error AllocMember(t_FmPcdFrmReplicGroup *p_ReplicGroup)
362
{
363
t_FmPcdFrmReplicMember *p_CurrentMember;
364
t_Handle h_Muram;
365
366
ASSERT_COND(p_ReplicGroup);
367
368
h_Muram = FmPcdGetMuramHandle(p_ReplicGroup->h_FmPcd);
369
ASSERT_COND(h_Muram);
370
371
/* Initialize an internal structure of a member to add to the available members list */
372
p_CurrentMember = (t_FmPcdFrmReplicMember *)XX_Malloc(sizeof(t_FmPcdFrmReplicMember));
373
if (!p_CurrentMember)
374
RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Frame replicator member"));
375
376
memset(p_CurrentMember, 0 ,sizeof(t_FmPcdFrmReplicMember));
377
378
/* Allocate the member AD */
379
p_CurrentMember->p_MemberAd =
380
(t_AdOfTypeResult*)FM_MURAM_AllocMem(h_Muram,
381
FM_PCD_CC_AD_ENTRY_SIZE,
382
FM_PCD_CC_AD_TABLE_ALIGN);
383
if (!p_CurrentMember->p_MemberAd)
384
{
385
XX_Free(p_CurrentMember);
386
RETURN_ERROR(MAJOR, E_NO_MEMORY, ("member AD table"));
387
}
388
IOMemSet32((uint8_t*)p_CurrentMember->p_MemberAd, 0, FM_PCD_CC_AD_ENTRY_SIZE);
389
390
/* Add the new member to the available members list */
391
LIST_AddToTail(&p_CurrentMember->node, &(p_ReplicGroup->availableMembersList));
392
393
return E_OK;
394
}
395
396
static t_FmPcdFrmReplicMember* InitMember(t_FmPcdFrmReplicGroup *p_ReplicGroup,
397
t_FmPcdCcNextEngineParams *p_MemberParams,
398
bool last)
399
{
400
t_FmPcdFrmReplicMember *p_CurrentMember = NULL;
401
402
ASSERT_COND(p_ReplicGroup);
403
404
/* Get an available member from the internal members list */
405
p_CurrentMember = GetAvailableMember(p_ReplicGroup);
406
if (!p_CurrentMember)
407
{
408
REPORT_ERROR(MAJOR, E_NOT_FOUND, ("Available member"));
409
return NULL;
410
}
411
p_CurrentMember->h_Manip = NULL;
412
413
/* clear the Ad of the new member */
414
IOMemSet32((uint8_t*)p_CurrentMember->p_MemberAd, 0, FM_PCD_CC_AD_ENTRY_SIZE);
415
416
INIT_LIST(&p_CurrentMember->node);
417
418
/* Initialize the Ad of the member */
419
NextStepAd(p_CurrentMember->p_MemberAd,
420
NULL,
421
p_MemberParams,
422
p_ReplicGroup->h_FmPcd);
423
424
/* save Manip handle (for free needs) */
425
if (p_MemberParams->h_Manip)
426
p_CurrentMember->h_Manip = p_MemberParams->h_Manip;
427
428
/* Initialize the relevant frame replicator fields in the AD */
429
FillReplicAdOfTypeResult(p_CurrentMember->p_MemberAd, last);
430
431
return p_CurrentMember;
432
}
433
434
static void FreeMember(t_FmPcdFrmReplicGroup *p_ReplicGroup,
435
t_FmPcdFrmReplicMember *p_Member)
436
{
437
/* Note: Can't free the member AD just returns the member to the available
438
member list - therefore only memset the AD */
439
440
/* zero the AD */
441
IOMemSet32(p_Member->p_MemberAd, 0, FM_PCD_CC_AD_ENTRY_SIZE);
442
443
444
/* return the member to the available members list */
445
PutAvailableMember(p_ReplicGroup, p_Member);
446
}
447
448
static t_Error RemoveMember(t_FmPcdFrmReplicGroup *p_ReplicGroup,
449
uint16_t memberIndex)
450
{
451
t_FmPcd *p_FmPcd = NULL;
452
t_FmPcdFrmReplicMember *p_CurrentMember = NULL, *p_PreviousMember = NULL, *p_NextMember = NULL;
453
t_Error err;
454
uint8_t memberPosition;
455
456
p_FmPcd = p_ReplicGroup->h_FmPcd;
457
ASSERT_COND(p_FmPcd);
458
UNUSED(p_FmPcd);
459
460
p_CurrentMember = GetMemberByIndex(p_ReplicGroup, memberIndex);
461
ASSERT_COND(p_CurrentMember);
462
463
/* determine the member position in the group */
464
memberPosition = GetMemberPosition(p_ReplicGroup,
465
memberIndex,
466
FALSE/*remove operation*/);
467
468
switch (memberPosition)
469
{
470
case FRM_REPLIC_FIRST_MEMBER_INDEX:
471
p_NextMember = GetMemberByIndex(p_ReplicGroup, (uint16_t)(memberIndex+1));
472
ASSERT_COND(p_NextMember);
473
474
/* update the source td itself by using a host command */
475
err = BuildShadowAndModifyDescriptor(p_ReplicGroup,
476
p_NextMember,
477
NULL,
478
TRUE/*sourceDescriptor*/,
479
FALSE/*last*/);
480
break;
481
482
case FRM_REPLIC_MIDDLE_MEMBER_INDEX:
483
p_PreviousMember = GetMemberByIndex(p_ReplicGroup, (uint16_t)(memberIndex-1));
484
ASSERT_COND(p_PreviousMember);
485
486
p_NextMember = GetMemberByIndex(p_ReplicGroup, (uint16_t)(memberIndex+1));
487
ASSERT_COND(p_NextMember);
488
489
err = BuildShadowAndModifyDescriptor(p_ReplicGroup,
490
p_NextMember,
491
p_PreviousMember,
492
FALSE/*sourceDescriptor*/,
493
FALSE/*last*/);
494
495
break;
496
497
case FRM_REPLIC_LAST_MEMBER_INDEX:
498
p_PreviousMember = GetMemberByIndex(p_ReplicGroup, (uint16_t)(memberIndex-1));
499
ASSERT_COND(p_PreviousMember);
500
501
err = BuildShadowAndModifyDescriptor(p_ReplicGroup,
502
NULL,
503
p_PreviousMember,
504
FALSE/*sourceDescriptor*/,
505
TRUE/*last*/);
506
break;
507
508
default:
509
RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("member position in remove member"));
510
}
511
512
if (err)
513
RETURN_ERROR(MAJOR, err, NO_MSG);
514
515
if (p_CurrentMember->h_Manip)
516
{
517
FmPcdManipUpdateOwner(p_CurrentMember->h_Manip, FALSE);
518
p_CurrentMember->h_Manip = NULL;
519
}
520
521
/* remove the member from the driver internal members list */
522
RemoveMemberFromList(p_ReplicGroup, p_CurrentMember);
523
524
/* return the member to the available members list */
525
FreeMember(p_ReplicGroup, p_CurrentMember);
526
527
return E_OK;
528
}
529
530
static void DeleteGroup(t_FmPcdFrmReplicGroup *p_ReplicGroup)
531
{
532
int i, j;
533
t_Handle h_Muram;
534
t_FmPcdFrmReplicMember *p_Member, *p_CurrentMember;
535
536
if (p_ReplicGroup)
537
{
538
ASSERT_COND(p_ReplicGroup->h_FmPcd);
539
h_Muram = FmPcdGetMuramHandle(p_ReplicGroup->h_FmPcd);
540
ASSERT_COND(h_Muram);
541
542
/* free the source table descriptor */
543
if (p_ReplicGroup->p_SourceTd)
544
{
545
FM_MURAM_FreeMem(h_Muram, p_ReplicGroup->p_SourceTd);
546
p_ReplicGroup->p_SourceTd = NULL;
547
}
548
549
/* Remove all members from the members linked list (hw and sw) and
550
return the members to the available members list */
551
if (p_ReplicGroup->numOfEntries)
552
{
553
j = p_ReplicGroup->numOfEntries-1;
554
555
/* manually removal of the member because there are no owners of
556
this group */
557
for (i=j; i>=0; i--)
558
{
559
p_CurrentMember = GetMemberByIndex(p_ReplicGroup, (uint16_t)i/*memberIndex*/);
560
ASSERT_COND(p_CurrentMember);
561
562
if (p_CurrentMember->h_Manip)
563
{
564
FmPcdManipUpdateOwner(p_CurrentMember->h_Manip, FALSE);
565
p_CurrentMember->h_Manip = NULL;
566
}
567
568
/* remove the member from the internal driver members list */
569
RemoveMemberFromList(p_ReplicGroup, p_CurrentMember);
570
571
/* return the member to the available members list */
572
FreeMember(p_ReplicGroup, p_CurrentMember);
573
}
574
}
575
576
/* Free members AD */
577
for (i=0; i<p_ReplicGroup->maxNumOfEntries; i++)
578
{
579
p_Member = GetAvailableMember(p_ReplicGroup);
580
ASSERT_COND(p_Member);
581
if (p_Member->p_MemberAd)
582
{
583
FM_MURAM_FreeMem(h_Muram, p_Member->p_MemberAd);
584
p_Member->p_MemberAd = NULL;
585
}
586
XX_Free(p_Member);
587
}
588
589
/* release the group lock */
590
if (p_ReplicGroup->p_Lock)
591
FmPcdReleaseLock(p_ReplicGroup->h_FmPcd, p_ReplicGroup->p_Lock);
592
593
/* free the replicator group */
594
XX_Free(p_ReplicGroup);
595
}
596
}
597
598
599
/*****************************************************************************/
600
/* Inter-module API routines */
601
/*****************************************************************************/
602
603
/* NOTE: the inter-module routines are locked by cc in case of using them */
604
void * FrmReplicGroupGetSourceTableDescriptor(t_Handle h_ReplicGroup)
605
{
606
t_FmPcdFrmReplicGroup *p_ReplicGroup = (t_FmPcdFrmReplicGroup *)h_ReplicGroup;
607
ASSERT_COND(p_ReplicGroup);
608
609
return (p_ReplicGroup->p_SourceTd);
610
}
611
612
void FrmReplicGroupUpdateAd(t_Handle h_ReplicGroup,
613
void *p_Ad,
614
t_Handle *h_AdNew)
615
{
616
t_FmPcdFrmReplicGroup *p_ReplicGroup = (t_FmPcdFrmReplicGroup *)h_ReplicGroup;
617
t_AdOfTypeResult *p_AdResult = (t_AdOfTypeResult*)p_Ad;
618
t_FmPcd *p_FmPcd;
619
620
ASSERT_COND(p_ReplicGroup);
621
p_FmPcd = p_ReplicGroup->h_FmPcd;
622
623
/* build a bypass ad */
624
WRITE_UINT32(p_AdResult->fqid, FM_PCD_AD_BYPASS_TYPE |
625
(uint32_t)((XX_VirtToPhys(p_ReplicGroup->p_SourceTd)) - p_FmPcd->physicalMuramBase));
626
627
*h_AdNew = NULL;
628
}
629
630
void FrmReplicGroupUpdateOwner(t_Handle h_ReplicGroup,
631
bool add)
632
{
633
t_FmPcdFrmReplicGroup *p_ReplicGroup = (t_FmPcdFrmReplicGroup *)h_ReplicGroup;
634
ASSERT_COND(p_ReplicGroup);
635
636
/* update the group owner counter */
637
if (add)
638
p_ReplicGroup->owners++;
639
else
640
{
641
ASSERT_COND(p_ReplicGroup->owners);
642
p_ReplicGroup->owners--;
643
}
644
}
645
646
t_Error FrmReplicGroupTryLock(t_Handle h_ReplicGroup)
647
{
648
t_FmPcdFrmReplicGroup *p_ReplicGroup = (t_FmPcdFrmReplicGroup *)h_ReplicGroup;
649
650
ASSERT_COND(h_ReplicGroup);
651
652
if (FmPcdLockTryLock(p_ReplicGroup->p_Lock))
653
return E_OK;
654
655
return ERROR_CODE(E_BUSY);
656
}
657
658
void FrmReplicGroupUnlock(t_Handle h_ReplicGroup)
659
{
660
t_FmPcdFrmReplicGroup *p_ReplicGroup = (t_FmPcdFrmReplicGroup *)h_ReplicGroup;
661
662
ASSERT_COND(h_ReplicGroup);
663
664
FmPcdLockUnlock(p_ReplicGroup->p_Lock);
665
}
666
/*********************** End of inter-module routines ************************/
667
668
669
/****************************************/
670
/* API Init unit functions */
671
/****************************************/
672
t_Handle FM_PCD_FrmReplicSetGroup(t_Handle h_FmPcd,
673
t_FmPcdFrmReplicGroupParams *p_ReplicGroupParam)
674
{
675
t_FmPcdFrmReplicGroup *p_ReplicGroup;
676
t_FmPcdFrmReplicMember *p_CurrentMember, *p_NextMember = NULL;
677
int i;
678
t_Error err;
679
bool last = FALSE;
680
t_Handle h_Muram;
681
682
SANITY_CHECK_RETURN_VALUE(h_FmPcd, E_INVALID_HANDLE, NULL);
683
SANITY_CHECK_RETURN_VALUE(p_ReplicGroupParam, E_INVALID_HANDLE, NULL);
684
685
if (!FmPcdIsAdvancedOffloadSupported(h_FmPcd))
686
{
687
REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Advanced-offload must be enabled"));
688
return NULL;
689
}
690
691
err = CheckParams(h_FmPcd, p_ReplicGroupParam);
692
if (err)
693
{
694
REPORT_ERROR(MAJOR, err, (NO_MSG));
695
return NULL;
696
}
697
698
p_ReplicGroup = (t_FmPcdFrmReplicGroup*)XX_Malloc(sizeof(t_FmPcdFrmReplicGroup));
699
if (!p_ReplicGroup)
700
{
701
REPORT_ERROR(MAJOR, E_NO_MEMORY, ("No memory"));
702
return NULL;
703
}
704
memset(p_ReplicGroup, 0, sizeof(t_FmPcdFrmReplicGroup));
705
706
/* initialize lists for internal driver use */
707
INIT_LIST(&p_ReplicGroup->availableMembersList);
708
INIT_LIST(&p_ReplicGroup->membersList);
709
710
p_ReplicGroup->h_FmPcd = h_FmPcd;
711
712
h_Muram = FmPcdGetMuramHandle(p_ReplicGroup->h_FmPcd);
713
ASSERT_COND(h_Muram);
714
715
/* initialize the group lock */
716
p_ReplicGroup->p_Lock = FmPcdAcquireLock(p_ReplicGroup->h_FmPcd);
717
if (!p_ReplicGroup->p_Lock)
718
{
719
REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Replic group lock"));
720
DeleteGroup(p_ReplicGroup);
721
return NULL;
722
}
723
724
/* Allocate the frame replicator source table descriptor */
725
p_ReplicGroup->p_SourceTd =
726
(t_Handle)FM_MURAM_AllocMem(h_Muram,
727
FM_PCD_CC_AD_ENTRY_SIZE,
728
FM_PCD_CC_AD_TABLE_ALIGN);
729
if (!p_ReplicGroup->p_SourceTd)
730
{
731
REPORT_ERROR(MAJOR, E_NO_MEMORY, ("frame replicator source table descriptor"));
732
DeleteGroup(p_ReplicGroup);
733
return NULL;
734
}
735
736
/* update the shadow size - required for the host commands */
737
err = FmPcdUpdateCcShadow(p_ReplicGroup->h_FmPcd,
738
FM_PCD_CC_AD_ENTRY_SIZE,
739
FM_PCD_CC_AD_TABLE_ALIGN);
740
if (err)
741
{
742
REPORT_ERROR(MAJOR, err, ("Update CC shadow"));
743
DeleteGroup(p_ReplicGroup);
744
return NULL;
745
}
746
747
p_ReplicGroup->maxNumOfEntries = p_ReplicGroupParam->maxNumOfEntries;
748
749
/* Allocate the maximal number of members ADs and Statistics AD for the group
750
It prevents allocation of Muram in run-time */
751
for (i=0; i<p_ReplicGroup->maxNumOfEntries; i++)
752
{
753
err = AllocMember(p_ReplicGroup);
754
if (err)
755
{
756
REPORT_ERROR(MAJOR, err, ("allocate a new member"));
757
DeleteGroup(p_ReplicGroup);
758
return NULL;
759
}
760
}
761
762
/* Initialize the members linked lists:
763
(hw - the one that is used by the FMan controller and
764
sw - the one that is managed by the driver internally) */
765
for (i=(p_ReplicGroupParam->numOfEntries-1); i>=0; i--)
766
{
767
/* check if this is the last member in the group */
768
if (i == (p_ReplicGroupParam->numOfEntries-1))
769
last = TRUE;
770
else
771
last = FALSE;
772
773
/* Initialize a new member */
774
p_CurrentMember = InitMember(p_ReplicGroup,
775
&(p_ReplicGroupParam->nextEngineParams[i]),
776
last);
777
if (!p_CurrentMember)
778
{
779
REPORT_ERROR(MAJOR, E_INVALID_HANDLE, ("No available member"));
780
DeleteGroup(p_ReplicGroup);
781
return NULL;
782
}
783
784
/* Build the members group - link two consecutive members in the hw linked list */
785
LinkMemberToMember(p_ReplicGroup, p_CurrentMember, p_NextMember);
786
787
/* update the driver internal members list to be compatible to the hw members linked list */
788
AddMemberToList(p_ReplicGroup, p_CurrentMember, &p_ReplicGroup->membersList);
789
790
p_NextMember = p_CurrentMember;
791
}
792
793
/* initialize the source table descriptor */
794
BuildSourceTd(p_ReplicGroup->p_SourceTd);
795
796
/* link the source table descriptor to point to the first member in the group */
797
LinkSourceToMember(p_ReplicGroup, p_ReplicGroup->p_SourceTd, p_NextMember);
798
799
return p_ReplicGroup;
800
}
801
802
t_Error FM_PCD_FrmReplicDeleteGroup(t_Handle h_ReplicGroup)
803
{
804
t_FmPcdFrmReplicGroup *p_ReplicGroup = (t_FmPcdFrmReplicGroup *)h_ReplicGroup;
805
806
SANITY_CHECK_RETURN_ERROR(p_ReplicGroup, E_INVALID_HANDLE);
807
808
if (p_ReplicGroup->owners)
809
RETURN_ERROR(MAJOR,
810
E_INVALID_STATE,
811
("the group has owners and can't be deleted"));
812
813
DeleteGroup(p_ReplicGroup);
814
815
return E_OK;
816
}
817
818
819
/*****************************************************************************/
820
/* API Run-time Frame replicator Control unit functions */
821
/*****************************************************************************/
822
t_Error FM_PCD_FrmReplicAddMember(t_Handle h_ReplicGroup,
823
uint16_t memberIndex,
824
t_FmPcdCcNextEngineParams *p_MemberParams)
825
{
826
t_FmPcdFrmReplicGroup *p_ReplicGroup = (t_FmPcdFrmReplicGroup*) h_ReplicGroup;
827
t_FmPcdFrmReplicMember *p_NewMember, *p_CurrentMember = NULL, *p_PreviousMember = NULL;
828
t_Error err;
829
uint8_t memberPosition;
830
831
SANITY_CHECK_RETURN_ERROR(p_ReplicGroup, E_INVALID_HANDLE);
832
SANITY_CHECK_RETURN_ERROR(p_MemberParams, E_INVALID_HANDLE);
833
834
/* group lock */
835
err = FrmReplicGroupTryLock(p_ReplicGroup);
836
if (GET_ERROR_TYPE(err) == E_BUSY)
837
return ERROR_CODE(E_BUSY);
838
839
if (memberIndex > p_ReplicGroup->numOfEntries)
840
{
841
/* unlock */
842
FrmReplicGroupUnlock(p_ReplicGroup);
843
RETURN_ERROR(MAJOR, E_INVALID_SELECTION,
844
("memberIndex is greater than the members in the list"));
845
}
846
847
if (memberIndex >= p_ReplicGroup->maxNumOfEntries)
848
{
849
/* unlock */
850
FrmReplicGroupUnlock(p_ReplicGroup);
851
RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("memberIndex is greater than the allowed number of members in the group"));
852
}
853
854
if ((p_ReplicGroup->numOfEntries + 1) > FM_PCD_FRM_REPLIC_MAX_NUM_OF_ENTRIES)
855
{
856
/* unlock */
857
FrmReplicGroupUnlock(p_ReplicGroup);
858
RETURN_ERROR(MAJOR, E_INVALID_VALUE,
859
("numOfEntries with new entry can not be larger than %d\n",
860
FM_PCD_FRM_REPLIC_MAX_NUM_OF_ENTRIES));
861
}
862
863
err = MemberCheckParams(p_ReplicGroup->h_FmPcd, p_MemberParams);
864
if (err)
865
{
866
/* unlock */
867
FrmReplicGroupUnlock(p_ReplicGroup);
868
RETURN_ERROR(MAJOR, err, ("member check parameters in add operation"));
869
}
870
/* determine the member position in the group */
871
memberPosition = GetMemberPosition(p_ReplicGroup,
872
memberIndex,
873
TRUE/* add operation */);
874
875
/* Initialize a new member */
876
p_NewMember = InitMember(p_ReplicGroup,
877
p_MemberParams,
878
(memberPosition == FRM_REPLIC_LAST_MEMBER_INDEX ? TRUE : FALSE));
879
if (!p_NewMember)
880
{
881
/* unlock */
882
FrmReplicGroupUnlock(p_ReplicGroup);
883
RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("No available member"));
884
}
885
886
switch (memberPosition)
887
{
888
case FRM_REPLIC_FIRST_MEMBER_INDEX:
889
p_CurrentMember = GetMemberByIndex(p_ReplicGroup, memberIndex);
890
ASSERT_COND(p_CurrentMember);
891
892
LinkMemberToMember(p_ReplicGroup, p_NewMember, p_CurrentMember);
893
894
/* update the internal group source TD */
895
LinkSourceToMember(p_ReplicGroup,
896
p_ReplicGroup->p_SourceTd,
897
p_NewMember);
898
899
/* add member to the internal sw member list */
900
AddMemberToList(p_ReplicGroup,
901
p_NewMember,
902
&p_ReplicGroup->membersList);
903
break;
904
905
case FRM_REPLIC_MIDDLE_MEMBER_INDEX:
906
p_CurrentMember = GetMemberByIndex(p_ReplicGroup, memberIndex);
907
ASSERT_COND(p_CurrentMember);
908
909
p_PreviousMember = GetMemberByIndex(p_ReplicGroup, (uint16_t)(memberIndex-1));
910
ASSERT_COND(p_PreviousMember);
911
912
LinkMemberToMember(p_ReplicGroup, p_NewMember, p_CurrentMember);
913
LinkMemberToMember(p_ReplicGroup, p_PreviousMember, p_NewMember);
914
915
AddMemberToList(p_ReplicGroup, p_NewMember, &p_PreviousMember->node);
916
break;
917
918
case FRM_REPLIC_LAST_MEMBER_INDEX:
919
p_PreviousMember = GetMemberByIndex(p_ReplicGroup, (uint16_t)(memberIndex-1));
920
ASSERT_COND(p_PreviousMember);
921
922
LinkMemberToMember(p_ReplicGroup, p_PreviousMember, p_NewMember);
923
FillReplicAdOfTypeResult(p_PreviousMember->p_MemberAd, FALSE/*last*/);
924
925
/* add the new member to the internal sw member list */
926
AddMemberToList(p_ReplicGroup, p_NewMember, &p_PreviousMember->node);
927
break;
928
929
default:
930
/* unlock */
931
FrmReplicGroupUnlock(p_ReplicGroup);
932
RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("member position in add member"));
933
934
}
935
936
/* unlock */
937
FrmReplicGroupUnlock(p_ReplicGroup);
938
939
return E_OK;
940
}
941
942
t_Error FM_PCD_FrmReplicRemoveMember(t_Handle h_ReplicGroup,
943
uint16_t memberIndex)
944
{
945
t_FmPcdFrmReplicGroup *p_ReplicGroup = (t_FmPcdFrmReplicGroup*) h_ReplicGroup;
946
t_Error err;
947
948
SANITY_CHECK_RETURN_ERROR(p_ReplicGroup, E_INVALID_HANDLE);
949
950
/* lock */
951
err = FrmReplicGroupTryLock(p_ReplicGroup);
952
if (GET_ERROR_TYPE(err) == E_BUSY)
953
return ERROR_CODE(E_BUSY);
954
955
if (memberIndex >= p_ReplicGroup->numOfEntries)
956
RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("member index to remove"));
957
958
/* Design decision: group must contain at least one member
959
No possibility to remove the last member from the group */
960
if (p_ReplicGroup->numOfEntries == 1)
961
RETURN_ERROR(MAJOR, E_CONFLICT, ("Can't remove the last member. At least one member should be related to a group."));
962
963
err = RemoveMember(p_ReplicGroup, memberIndex);
964
965
/* unlock */
966
FrmReplicGroupUnlock(p_ReplicGroup);
967
968
switch (GET_ERROR_TYPE(err))
969
{
970
case E_OK:
971
return E_OK;
972
973
case E_BUSY:
974
DBG(TRACE, ("E_BUSY error"));
975
return ERROR_CODE(E_BUSY);
976
977
default:
978
RETURN_ERROR(MAJOR, err, NO_MSG);
979
}
980
}
981
982
/*********************** End of API routines ************************/
983
984
985
986