The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/contrib/ncsw/Peripherals/FM/Pcd/fm_replic.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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 

Cache object: 4c88b90cb7dcc40d8acab2d089bdd034


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.