Path: blob/main/sys/contrib/ncsw/Peripherals/QM/qm_portal_fqr.c
48378 views
/******************************************************************************12� 1995-2003, 2004, 2005-2011 Freescale Semiconductor, Inc.3All rights reserved.45This is proprietary source code of Freescale Semiconductor Inc.,6and its use is subject to the NetComm Device Drivers EULA.7The copyright notice above does not evidence any actual or intended8publication of such source code.910ALTERNATIVELY, redistribution and use in source and binary forms, with11or without modification, are permitted provided that the following12conditions are met:13* Redistributions of source code must retain the above copyright14notice, this list of conditions and the following disclaimer.15* Redistributions in binary form must reproduce the above copyright16notice, this list of conditions and the following disclaimer in the17documentation and/or other materials provided with the distribution.18* Neither the name of Freescale Semiconductor nor the19names of its contributors may be used to endorse or promote products20derived from this software without specific prior written permission.2122THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY23EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED24WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE25DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY26DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES27(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;28LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND29ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT30(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS31SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.32*3334**************************************************************************/35/******************************************************************************36@File qm.c3738@Description QM & Portal implementation39*//***************************************************************************/40#include <sys/cdefs.h>41#include <sys/types.h>42#include <machine/atomic.h>4344#include "error_ext.h"45#include "std_ext.h"46#include "string_ext.h"47#include "mm_ext.h"48#include "qm.h"49#include "qman_low.h"5051#include <machine/vmparam.h>5253/****************************************/54/* static functions */55/****************************************/5657#define SLOW_POLL_IDLE 100058#define SLOW_POLL_BUSY 105960/*61* Context entries are 32-bit. The qman driver uses the pointer to the queue as62* its context, and the pointer is 64-byte aligned, per the XX_MallocSmart()63* call. Take advantage of this fact to shove a 64-bit kernel pointer into a64* 32-bit context integer, and back.65*66* XXX: This depends on the fact that VM_MAX_KERNEL_ADDRESS is less than 38-bit67* count from VM_MIN_KERNEL_ADDRESS. If this ever changes, this needs to be68* updated.69*/70CTASSERT((VM_MAX_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS) < (1ULL << 35));71static inline uint32_t72aligned_int_from_ptr(const void *p)73{74uintptr_t ctx;7576ctx = (uintptr_t)p;77KASSERT(ctx >= VM_MIN_KERNEL_ADDRESS, ("%p is too low!\n", p));78ctx -= VM_MIN_KERNEL_ADDRESS;79KASSERT((ctx & 0x07) == 0, ("Pointer %p is not 8-byte aligned!\n", p));8081return (ctx >> 3);82}8384static inline void *85ptr_from_aligned_int(uint32_t ctx)86{87uintptr_t p;8889p = ctx;90p = VM_MIN_KERNEL_ADDRESS + (p << 3);9192return ((void *)p);93}9495static t_Error qman_volatile_dequeue(t_QmPortal *p_QmPortal,96struct qman_fq *p_Fq,97uint32_t vdqcr)98{99ASSERT_COND((p_Fq->state == qman_fq_state_parked) ||100(p_Fq->state == qman_fq_state_retired));101ASSERT_COND(!(vdqcr & QM_VDQCR_FQID_MASK));102ASSERT_COND(!(p_Fq->flags & QMAN_FQ_STATE_VDQCR));103104vdqcr = (vdqcr & ~QM_VDQCR_FQID_MASK) | p_Fq->fqid;105NCSW_PLOCK(p_QmPortal);106FQLOCK(p_Fq);107p_Fq->flags |= QMAN_FQ_STATE_VDQCR;108qm_dqrr_vdqcr_set(p_QmPortal->p_LowQmPortal, vdqcr);109FQUNLOCK(p_Fq);110PUNLOCK(p_QmPortal);111112return E_OK;113}114115static const char *mcr_result_str(uint8_t result)116{117switch (result) {118case QM_MCR_RESULT_NULL:119return "QM_MCR_RESULT_NULL";120case QM_MCR_RESULT_OK:121return "QM_MCR_RESULT_OK";122case QM_MCR_RESULT_ERR_FQID:123return "QM_MCR_RESULT_ERR_FQID";124case QM_MCR_RESULT_ERR_FQSTATE:125return "QM_MCR_RESULT_ERR_FQSTATE";126case QM_MCR_RESULT_ERR_NOTEMPTY:127return "QM_MCR_RESULT_ERR_NOTEMPTY";128case QM_MCR_RESULT_PENDING:129return "QM_MCR_RESULT_PENDING";130}131return "<unknown MCR result>";132}133134static t_Error qman_create_fq(t_QmPortal *p_QmPortal,135uint32_t fqid,136uint32_t flags,137struct qman_fq *p_Fq)138{139struct qm_fqd fqd;140struct qm_mcr_queryfq_np np;141struct qm_mc_command *p_Mcc;142struct qm_mc_result *p_Mcr;143144p_Fq->fqid = fqid;145p_Fq->flags = flags;146p_Fq->state = qman_fq_state_oos;147p_Fq->cgr_groupid = 0;148if (!(flags & QMAN_FQ_FLAG_RECOVER) ||149(flags & QMAN_FQ_FLAG_NO_MODIFY))150return E_OK;151/* Everything else is RECOVER support */152NCSW_PLOCK(p_QmPortal);153p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal);154p_Mcc->queryfq.fqid = fqid;155qm_mc_commit(p_QmPortal->p_LowQmPortal, QM_MCC_VERB_QUERYFQ);156while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ;157ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) == QM_MCC_VERB_QUERYFQ);158if (p_Mcr->result != QM_MCR_RESULT_OK) {159PUNLOCK(p_QmPortal);160RETURN_ERROR(MAJOR, E_INVALID_STATE, ("QUERYFQ failed: %s", mcr_result_str(p_Mcr->result)));161}162fqd = p_Mcr->queryfq.fqd;163p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal);164p_Mcc->queryfq_np.fqid = fqid;165qm_mc_commit(p_QmPortal->p_LowQmPortal, QM_MCC_VERB_QUERYFQ_NP);166while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ;167ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) == QM_MCC_VERB_QUERYFQ_NP);168if (p_Mcr->result != QM_MCR_RESULT_OK) {169PUNLOCK(p_QmPortal);170RETURN_ERROR(MAJOR, E_INVALID_STATE, ("UERYFQ_NP failed: %s", mcr_result_str(p_Mcr->result)));171}172np = p_Mcr->queryfq_np;173/* Phew, have queryfq and queryfq_np results, stitch together174* the FQ object from those. */175p_Fq->cgr_groupid = fqd.cgid;176switch (np.state & QM_MCR_NP_STATE_MASK) {177case QM_MCR_NP_STATE_OOS:178break;179case QM_MCR_NP_STATE_RETIRED:180p_Fq->state = qman_fq_state_retired;181if (np.frm_cnt)182p_Fq->flags |= QMAN_FQ_STATE_NE;183break;184case QM_MCR_NP_STATE_TEN_SCHED:185case QM_MCR_NP_STATE_TRU_SCHED:186case QM_MCR_NP_STATE_ACTIVE:187p_Fq->state = qman_fq_state_sched;188if (np.state & QM_MCR_NP_STATE_R)189p_Fq->flags |= QMAN_FQ_STATE_CHANGING;190break;191case QM_MCR_NP_STATE_PARKED:192p_Fq->state = qman_fq_state_parked;193break;194default:195ASSERT_COND(FALSE);196}197if (fqd.fq_ctrl & QM_FQCTRL_CGE)198p_Fq->state |= QMAN_FQ_STATE_CGR_EN;199PUNLOCK(p_QmPortal);200201return E_OK;202}203204static void qman_destroy_fq(struct qman_fq *p_Fq, uint32_t flags)205{206/* We don't need to lock the FQ as it is a pre-condition that the FQ be207* quiesced. Instead, run some checks. */208UNUSED(flags);209switch (p_Fq->state) {210case qman_fq_state_parked:211ASSERT_COND(flags & QMAN_FQ_DESTROY_PARKED);212case qman_fq_state_oos:213return;214default:215break;216}217ASSERT_COND(FALSE);218}219220static t_Error qman_init_fq(t_QmPortal *p_QmPortal,221struct qman_fq *p_Fq,222uint32_t flags,223struct qm_mcc_initfq *p_Opts)224{225struct qm_mc_command *p_Mcc;226struct qm_mc_result *p_Mcr;227uint8_t res, myverb = (uint8_t)((flags & QMAN_INITFQ_FLAG_SCHED) ?228QM_MCC_VERB_INITFQ_SCHED : QM_MCC_VERB_INITFQ_PARKED);229230SANITY_CHECK_RETURN_ERROR((p_Fq->state == qman_fq_state_oos) ||231(p_Fq->state == qman_fq_state_parked),232E_INVALID_STATE);233234if (p_Fq->flags & QMAN_FQ_FLAG_NO_MODIFY)235return ERROR_CODE(E_INVALID_VALUE);236/* Issue an INITFQ_[PARKED|SCHED] management command */237NCSW_PLOCK(p_QmPortal);238FQLOCK(p_Fq);239if ((p_Fq->flags & QMAN_FQ_STATE_CHANGING) ||240((p_Fq->state != qman_fq_state_oos) &&241(p_Fq->state != qman_fq_state_parked))) {242FQUNLOCK(p_Fq);243PUNLOCK(p_QmPortal);244return ERROR_CODE(E_BUSY);245}246p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal);247Mem2IOCpy32((void*)&p_Mcc->initfq, p_Opts, sizeof(struct qm_mcc_initfq));248qm_mc_commit(p_QmPortal->p_LowQmPortal, myverb);249while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ;250ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) == myverb);251res = p_Mcr->result;252if (res != QM_MCR_RESULT_OK) {253FQUNLOCK(p_Fq);254PUNLOCK(p_QmPortal);255RETURN_ERROR(MINOR, E_INVALID_STATE,("INITFQ failed: %s", mcr_result_str(res)));256}257258if (p_Mcc->initfq.we_mask & QM_INITFQ_WE_FQCTRL) {259if (p_Mcc->initfq.fqd.fq_ctrl & QM_FQCTRL_CGE)260p_Fq->flags |= QMAN_FQ_STATE_CGR_EN;261else262p_Fq->flags &= ~QMAN_FQ_STATE_CGR_EN;263}264if (p_Mcc->initfq.we_mask & QM_INITFQ_WE_CGID)265p_Fq->cgr_groupid = p_Mcc->initfq.fqd.cgid;266p_Fq->state = (flags & QMAN_INITFQ_FLAG_SCHED) ?267qman_fq_state_sched : qman_fq_state_parked;268FQUNLOCK(p_Fq);269PUNLOCK(p_QmPortal);270return E_OK;271}272273static t_Error qman_retire_fq(t_QmPortal *p_QmPortal,274struct qman_fq *p_Fq,275uint32_t *p_Flags,276bool drain)277{278struct qm_mc_command *p_Mcc;279struct qm_mc_result *p_Mcr;280t_Error err = E_OK;281uint8_t res;282283SANITY_CHECK_RETURN_ERROR((p_Fq->state == qman_fq_state_parked) ||284(p_Fq->state == qman_fq_state_sched),285E_INVALID_STATE);286287if (p_Fq->flags & QMAN_FQ_FLAG_NO_MODIFY)288return E_INVALID_VALUE;289NCSW_PLOCK(p_QmPortal);290FQLOCK(p_Fq);291if ((p_Fq->flags & QMAN_FQ_STATE_CHANGING) ||292(p_Fq->state == qman_fq_state_retired) ||293(p_Fq->state == qman_fq_state_oos)) {294err = E_BUSY;295goto out;296}297p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal);298p_Mcc->alterfq.fqid = p_Fq->fqid;299if (drain)300p_Mcc->alterfq.context_b = aligned_int_from_ptr(p_Fq);301qm_mc_commit(p_QmPortal->p_LowQmPortal,302(uint8_t)((drain)?QM_MCC_VERB_ALTER_RETIRE_CTXB:QM_MCC_VERB_ALTER_RETIRE));303while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ;304ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) ==305(drain)?QM_MCR_VERB_ALTER_RETIRE_CTXB:QM_MCR_VERB_ALTER_RETIRE);306res = p_Mcr->result;307if (res == QM_MCR_RESULT_OK)308{309/* Process 'fq' right away, we'll ignore FQRNI */310if (p_Mcr->alterfq.fqs & QM_MCR_FQS_NOTEMPTY)311p_Fq->flags |= QMAN_FQ_STATE_NE;312if (p_Mcr->alterfq.fqs & QM_MCR_FQS_ORLPRESENT)313p_Fq->flags |= QMAN_FQ_STATE_ORL;314p_Fq->state = qman_fq_state_retired;315}316else if (res == QM_MCR_RESULT_PENDING)317p_Fq->flags |= QMAN_FQ_STATE_CHANGING;318else {319XX_Print("ALTER_RETIRE failed: %s\n",320mcr_result_str(res));321err = E_INVALID_STATE;322}323if (p_Flags)324*p_Flags = p_Fq->flags;325out:326FQUNLOCK(p_Fq);327PUNLOCK(p_QmPortal);328return err;329}330331static t_Error qman_oos_fq(t_QmPortal *p_QmPortal, struct qman_fq *p_Fq)332{333struct qm_mc_command *p_Mcc;334struct qm_mc_result *p_Mcr;335uint8_t res;336337ASSERT_COND(p_Fq->state == qman_fq_state_retired);338if (p_Fq->flags & QMAN_FQ_FLAG_NO_MODIFY)339return ERROR_CODE(E_INVALID_VALUE);340NCSW_PLOCK(p_QmPortal);341FQLOCK(p_Fq);342if ((p_Fq->flags & QMAN_FQ_STATE_BLOCKOOS) ||343(p_Fq->state != qman_fq_state_retired)) {344FQUNLOCK(p_Fq);345PUNLOCK(p_QmPortal);346return ERROR_CODE(E_BUSY);347}348p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal);349p_Mcc->alterfq.fqid = p_Fq->fqid;350qm_mc_commit(p_QmPortal->p_LowQmPortal, QM_MCC_VERB_ALTER_OOS);351while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ;352ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) == QM_MCR_VERB_ALTER_OOS);353res = p_Mcr->result;354if (res != QM_MCR_RESULT_OK) {355FQUNLOCK(p_Fq);356PUNLOCK(p_QmPortal);357RETURN_ERROR(MINOR, E_INVALID_STATE, ("ALTER_OOS failed: %s\n", mcr_result_str(res)));358}359p_Fq->state = qman_fq_state_oos;360361FQUNLOCK(p_Fq);362PUNLOCK(p_QmPortal);363return E_OK;364}365366static t_Error qman_schedule_fq(t_QmPortal *p_QmPortal, struct qman_fq *p_Fq)367{368struct qm_mc_command *p_Mcc;369struct qm_mc_result *p_Mcr;370uint8_t res;371372ASSERT_COND(p_Fq->state == qman_fq_state_parked);373if (p_Fq->flags & QMAN_FQ_FLAG_NO_MODIFY)374return ERROR_CODE(E_INVALID_VALUE);375/* Issue a ALTERFQ_SCHED management command */376NCSW_PLOCK(p_QmPortal);377FQLOCK(p_Fq);378if ((p_Fq->flags & QMAN_FQ_STATE_CHANGING) ||379(p_Fq->state != qman_fq_state_parked)) {380FQUNLOCK(p_Fq);381PUNLOCK(p_QmPortal);382return ERROR_CODE(E_BUSY);383}384p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal);385p_Mcc->alterfq.fqid = p_Fq->fqid;386qm_mc_commit(p_QmPortal->p_LowQmPortal, QM_MCC_VERB_ALTER_SCHED);387while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ;388ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) == QM_MCR_VERB_ALTER_SCHED);389res = p_Mcr->result;390if (res != QM_MCR_RESULT_OK) {391FQUNLOCK(p_Fq);392PUNLOCK(p_QmPortal);393RETURN_ERROR(MINOR, E_INVALID_STATE, ("ALTER_SCHED failed: %s\n", mcr_result_str(res)));394}395p_Fq->state = qman_fq_state_sched;396397FQUNLOCK(p_Fq);398PUNLOCK(p_QmPortal);399return E_OK;400}401402/* Inline helper to reduce nesting in LoopMessageRing() */403static __inline__ void fq_state_change(struct qman_fq *p_Fq,404struct qm_mr_entry *p_Msg,405uint8_t verb)406{407FQLOCK(p_Fq);408switch(verb) {409case QM_MR_VERB_FQRL:410ASSERT_COND(p_Fq->flags & QMAN_FQ_STATE_ORL);411p_Fq->flags &= ~QMAN_FQ_STATE_ORL;412break;413case QM_MR_VERB_FQRN:414ASSERT_COND((p_Fq->state == qman_fq_state_parked) ||415(p_Fq->state == qman_fq_state_sched));416ASSERT_COND(p_Fq->flags & QMAN_FQ_STATE_CHANGING);417p_Fq->flags &= ~QMAN_FQ_STATE_CHANGING;418if (p_Msg->fq.fqs & QM_MR_FQS_NOTEMPTY)419p_Fq->flags |= QMAN_FQ_STATE_NE;420if (p_Msg->fq.fqs & QM_MR_FQS_ORLPRESENT)421p_Fq->flags |= QMAN_FQ_STATE_ORL;422p_Fq->state = qman_fq_state_retired;423break;424case QM_MR_VERB_FQPN:425ASSERT_COND(p_Fq->state == qman_fq_state_sched);426ASSERT_COND(p_Fq->flags & QMAN_FQ_STATE_CHANGING);427p_Fq->state = qman_fq_state_parked;428}429FQUNLOCK(p_Fq);430}431432static t_Error freeDrainedFq(struct qman_fq *p_Fq)433{434t_QmFqr *p_QmFqr;435uint32_t i;436437ASSERT_COND(p_Fq);438p_QmFqr = (t_QmFqr *)p_Fq->h_QmFqr;439ASSERT_COND(p_QmFqr);440441ASSERT_COND(!p_QmFqr->p_DrainedFqs[p_Fq->fqidOffset]);442p_QmFqr->p_DrainedFqs[p_Fq->fqidOffset] = TRUE;443p_QmFqr->numOfDrainedFqids++;444if (p_QmFqr->numOfDrainedFqids == p_QmFqr->numOfFqids)445{446for (i=0;i<p_QmFqr->numOfFqids;i++)447{448if ((p_QmFqr->p_Fqs[i]->state == qman_fq_state_retired) &&449(qman_oos_fq(p_QmFqr->h_QmPortal, p_QmFqr->p_Fqs[i]) != E_OK))450RETURN_ERROR(MAJOR, E_INVALID_STATE, ("qman_oos_fq() failed!"));451qman_destroy_fq(p_QmFqr->p_Fqs[i], 0);452XX_FreeSmart(p_QmFqr->p_Fqs[i]);453}454XX_Free(p_QmFqr->p_DrainedFqs);455p_QmFqr->p_DrainedFqs = NULL;456457if (p_QmFqr->f_CompletionCB)458{459p_QmFqr->f_CompletionCB(p_QmFqr->h_App, p_QmFqr);460XX_Free(p_QmFqr->p_Fqs);461if (p_QmFqr->fqidBase)462QmFqidPut(p_QmFqr->h_Qm, p_QmFqr->fqidBase);463XX_Free(p_QmFqr);464}465}466467return E_OK;468}469470static t_Error drainRetiredFq(struct qman_fq *p_Fq)471{472t_QmFqr *p_QmFqr;473474ASSERT_COND(p_Fq);475p_QmFqr = (t_QmFqr *)p_Fq->h_QmFqr;476ASSERT_COND(p_QmFqr);477478if (p_Fq->flags & QMAN_FQ_STATE_NE)479{480if (qman_volatile_dequeue(p_QmFqr->h_QmPortal, p_Fq,481(QM_VDQCR_PRECEDENCE_VDQCR | QM_VDQCR_NUMFRAMES_TILLEMPTY)) != E_OK)482483RETURN_ERROR(MAJOR, E_INVALID_STATE, ("drain with volatile failed"));484return E_OK;485}486else487return freeDrainedFq(p_Fq);488}489490static e_RxStoreResponse drainCB(t_Handle h_App,491t_Handle h_QmFqr,492t_Handle h_QmPortal,493uint32_t fqidOffset,494t_DpaaFD *p_Frame)495{496UNUSED(h_App);497UNUSED(h_QmFqr);498UNUSED(h_QmPortal);499UNUSED(fqidOffset);500UNUSED(p_Frame);501502DBG(TRACE,("got fd for fqid %d", ((t_QmFqr *)h_QmFqr)->fqidBase + fqidOffset));503return e_RX_STORE_RESPONSE_CONTINUE;504}505506static void cb_ern_dcErn(t_Handle h_App,507t_Handle h_QmPortal,508struct qman_fq *p_Fq,509const struct qm_mr_entry *p_Msg)510{511static int cnt = 0;512UNUSED(p_Fq);513UNUSED(p_Msg);514UNUSED(h_App);515UNUSED(h_QmPortal);516517XX_Print("cb_ern_dcErn_fqs() unimplemented %d\n", ++cnt);518}519520static void cb_fqs(t_Handle h_App,521t_Handle h_QmPortal,522struct qman_fq *p_Fq,523const struct qm_mr_entry *p_Msg)524{525UNUSED(p_Msg);526UNUSED(h_App);527UNUSED(h_QmPortal);528529if (p_Fq->state == qman_fq_state_retired &&530!(p_Fq->flags & QMAN_FQ_STATE_ORL))531drainRetiredFq(p_Fq);532}533534static void null_cb_mr(t_Handle h_App,535t_Handle h_QmPortal,536struct qman_fq *p_Fq,537const struct qm_mr_entry *p_Msg)538{539t_QmPortal *p_QmPortal = (t_QmPortal *)h_QmPortal;540541UNUSED(p_Fq);UNUSED(h_App);542543if ((p_Msg->verb & QM_MR_VERB_DC_ERN) == QM_MR_VERB_DC_ERN)544XX_Print("Ignoring unowned MR frame on cpu %d, dc-portal 0x%02x.\n",545p_QmPortal->p_LowQmPortal->config.cpu,p_Msg->dcern.portal);546else547XX_Print("Ignoring unowned MR frame on cpu %d, verb 0x%02x.\n",548p_QmPortal->p_LowQmPortal->config.cpu,p_Msg->verb);549}550551static uint32_t LoopMessageRing(t_QmPortal *p_QmPortal, uint32_t is)552{553struct qm_mr_entry *p_Msg;554555if (is & QM_PIRQ_CSCI) {556struct qm_mc_result *p_Mcr;557struct qman_cgrs tmp;558uint32_t mask;559unsigned int i, j;560561NCSW_PLOCK(p_QmPortal);562qm_mc_start(p_QmPortal->p_LowQmPortal);563qm_mc_commit(p_QmPortal->p_LowQmPortal, QM_MCC_VERB_QUERYCONGESTION);564while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ;565566/* cgrs[0] is the portal mask for its cg's, cgrs[1] is the567previous state of cg's */568for (i = 0; i < QM_MAX_NUM_OF_CGS/32; i++)569{570/* get curent state */571tmp.q.__state[i] = p_Mcr->querycongestion.state.__state[i];572/* keep only cg's that are registered for this portal */573tmp.q.__state[i] &= p_QmPortal->cgrs[0].q.__state[i];574/* handle only cg's that changed their state from previous exception */575tmp.q.__state[i] ^= p_QmPortal->cgrs[1].q.__state[i];576/* update previous */577p_QmPortal->cgrs[1].q.__state[i] = p_Mcr->querycongestion.state.__state[i];578}579PUNLOCK(p_QmPortal);580581/* if in interrupt */582/* call the callback routines for any CG with a changed state */583for (i = 0; i < QM_MAX_NUM_OF_CGS/32; i++)584for(j=0, mask = 0x80000000; j<32 ; j++, mask>>=1)585{586if(tmp.q.__state[i] & mask)587{588t_QmCg *p_QmCg = (t_QmCg *)(p_QmPortal->cgsHandles[i*32 + j]);589if(p_QmCg->f_Exception)590p_QmCg->f_Exception(p_QmCg->h_App, e_QM_EX_CG_STATE_CHANGE);591}592}593594}595596597if (is & QM_PIRQ_EQRI) {598NCSW_PLOCK(p_QmPortal);599qmPortalEqcrCceUpdate(p_QmPortal->p_LowQmPortal);600qm_eqcr_set_ithresh(p_QmPortal->p_LowQmPortal, 0);601PUNLOCK(p_QmPortal);602}603604if (is & QM_PIRQ_MRI) {605mr_loop:606qmPortalMrPvbUpdate(p_QmPortal->p_LowQmPortal);607p_Msg = qm_mr_current(p_QmPortal->p_LowQmPortal);608if (p_Msg) {609struct qman_fq *p_FqFqs = ptr_from_aligned_int(p_Msg->fq.contextB);610struct qman_fq *p_FqErn = ptr_from_aligned_int(p_Msg->ern.tag);611uint8_t verb =(uint8_t)(p_Msg->verb & QM_MR_VERB_TYPE_MASK);612t_QmRejectedFrameInfo rejectedFrameInfo;613614memset(&rejectedFrameInfo, 0, sizeof(t_QmRejectedFrameInfo));615if (!(verb & QM_MR_VERB_DC_ERN))616{617switch(p_Msg->ern.rc)618{619case(QM_MR_RC_CGR_TAILDROP):620rejectedFrameInfo.rejectionCode = e_QM_RC_CG_TAILDROP;621rejectedFrameInfo.cg.cgId = (uint8_t)p_FqErn->cgr_groupid;622break;623case(QM_MR_RC_WRED):624rejectedFrameInfo.rejectionCode = e_QM_RC_CG_WRED;625rejectedFrameInfo.cg.cgId = (uint8_t)p_FqErn->cgr_groupid;626break;627case(QM_MR_RC_FQ_TAILDROP):628rejectedFrameInfo.rejectionCode = e_QM_RC_FQ_TAILDROP;629rejectedFrameInfo.cg.cgId = (uint8_t)p_FqErn->cgr_groupid;630break;631case(QM_MR_RC_ERROR):632break;633default:634REPORT_ERROR(MINOR, E_NOT_SUPPORTED, ("Unknown rejection code"));635}636if (!p_FqErn)637p_QmPortal->p_NullCB->ern(p_QmPortal->h_App, NULL, p_QmPortal, 0, (t_DpaaFD*)&p_Msg->ern.fd, &rejectedFrameInfo);638else639p_FqErn->cb.ern(p_FqErn->h_App, p_FqErn->h_QmFqr, p_QmPortal, p_FqErn->fqidOffset, (t_DpaaFD*)&p_Msg->ern.fd, &rejectedFrameInfo);640} else if (verb == QM_MR_VERB_DC_ERN)641{642if (!p_FqErn)643p_QmPortal->p_NullCB->dc_ern(NULL, p_QmPortal, NULL, p_Msg);644else645p_FqErn->cb.dc_ern(p_FqErn->h_App, p_QmPortal, p_FqErn, p_Msg);646} else647{648if (verb == QM_MR_VERB_FQRNI)649; /* we drop FQRNIs on the floor */650else if (!p_FqFqs)651p_QmPortal->p_NullCB->fqs(NULL, p_QmPortal, NULL, p_Msg);652else if ((verb == QM_MR_VERB_FQRN) ||653(verb == QM_MR_VERB_FQRL) ||654(verb == QM_MR_VERB_FQPN))655{656fq_state_change(p_FqFqs, p_Msg, verb);657p_FqFqs->cb.fqs(p_FqFqs->h_App, p_QmPortal, p_FqFqs, p_Msg);658}659}660qm_mr_next(p_QmPortal->p_LowQmPortal);661qmPortalMrCciConsume(p_QmPortal->p_LowQmPortal, 1);662663goto mr_loop;664}665}666667return is & (QM_PIRQ_CSCI | QM_PIRQ_EQCI | QM_PIRQ_EQRI | QM_PIRQ_MRI);668}669670static void LoopDequeueRing(t_Handle h_QmPortal)671{672struct qm_dqrr_entry *p_Dq;673struct qman_fq *p_Fq;674enum qman_cb_dqrr_result res = qman_cb_dqrr_consume;675e_RxStoreResponse tmpRes;676t_QmPortal *p_QmPortal = (t_QmPortal *)h_QmPortal;677int prefetch = !(p_QmPortal->options & QMAN_PORTAL_FLAG_RSTASH);678679while (res != qman_cb_dqrr_pause)680{681if (prefetch)682qmPortalDqrrPvbPrefetch(p_QmPortal->p_LowQmPortal);683qmPortalDqrrPvbUpdate(p_QmPortal->p_LowQmPortal);684p_Dq = qm_dqrr_current(p_QmPortal->p_LowQmPortal);685if (!p_Dq)686break;687p_Fq = ptr_from_aligned_int(p_Dq->contextB);688if (p_Dq->stat & QM_DQRR_STAT_UNSCHEDULED) {689/* We only set QMAN_FQ_STATE_NE when retiring, so we only need690* to check for clearing it when doing volatile dequeues. It's691* one less thing to check in the critical path (SDQCR). */692tmpRes = p_Fq->cb.dqrr(p_Fq->h_App, p_Fq->h_QmFqr, p_QmPortal, p_Fq->fqidOffset, (t_DpaaFD*)&p_Dq->fd);693if (tmpRes == e_RX_STORE_RESPONSE_PAUSE)694res = qman_cb_dqrr_pause;695/* Check for VDQCR completion */696if (p_Dq->stat & QM_DQRR_STAT_DQCR_EXPIRED)697p_Fq->flags &= ~QMAN_FQ_STATE_VDQCR;698if (p_Dq->stat & QM_DQRR_STAT_FQ_EMPTY)699{700p_Fq->flags &= ~QMAN_FQ_STATE_NE;701freeDrainedFq(p_Fq);702}703}704else705{706/* Interpret 'dq' from the owner's perspective. */707/* use portal default handlers */708ASSERT_COND(p_Dq->fqid);709if (p_Fq)710{711tmpRes = p_Fq->cb.dqrr(p_Fq->h_App,712p_Fq->h_QmFqr,713p_QmPortal,714p_Fq->fqidOffset,715(t_DpaaFD*)&p_Dq->fd);716if (tmpRes == e_RX_STORE_RESPONSE_PAUSE)717res = qman_cb_dqrr_pause;718else if (p_Fq->state == qman_fq_state_waiting_parked)719res = qman_cb_dqrr_park;720}721else722{723tmpRes = p_QmPortal->p_NullCB->dqrr(p_QmPortal->h_App,724NULL,725p_QmPortal,726p_Dq->fqid,727(t_DpaaFD*)&p_Dq->fd);728if (tmpRes == e_RX_STORE_RESPONSE_PAUSE)729res = qman_cb_dqrr_pause;730}731}732733/* Parking isn't possible unless HELDACTIVE was set. NB,734* FORCEELIGIBLE implies HELDACTIVE, so we only need to735* check for HELDACTIVE to cover both. */736ASSERT_COND((p_Dq->stat & QM_DQRR_STAT_FQ_HELDACTIVE) ||737(res != qman_cb_dqrr_park));738if (p_QmPortal->options & QMAN_PORTAL_FLAG_DCA) {739/* Defer just means "skip it, I'll consume it myself later on" */740if (res != qman_cb_dqrr_defer)741qmPortalDqrrDcaConsume1ptr(p_QmPortal->p_LowQmPortal,742p_Dq,743(res == qman_cb_dqrr_park));744qm_dqrr_next(p_QmPortal->p_LowQmPortal);745} else {746if (res == qman_cb_dqrr_park)747/* The only thing to do for non-DCA is the park-request */748qm_dqrr_park_ci(p_QmPortal->p_LowQmPortal);749qm_dqrr_next(p_QmPortal->p_LowQmPortal);750qmPortalDqrrCciConsume(p_QmPortal->p_LowQmPortal, 1);751}752}753}754755static void LoopDequeueRingDcaOptimized(t_Handle h_QmPortal)756{757struct qm_dqrr_entry *p_Dq;758struct qman_fq *p_Fq;759enum qman_cb_dqrr_result res = qman_cb_dqrr_consume;760e_RxStoreResponse tmpRes;761t_QmPortal *p_QmPortal = (t_QmPortal *)h_QmPortal;762763while (res != qman_cb_dqrr_pause)764{765qmPortalDqrrPvbUpdate(p_QmPortal->p_LowQmPortal);766p_Dq = qm_dqrr_current(p_QmPortal->p_LowQmPortal);767if (!p_Dq)768break;769p_Fq = ptr_from_aligned_int(p_Dq->contextB);770if (p_Dq->stat & QM_DQRR_STAT_UNSCHEDULED) {771/* We only set QMAN_FQ_STATE_NE when retiring, so we only need772* to check for clearing it when doing volatile dequeues. It's773* one less thing to check in the critical path (SDQCR). */774tmpRes = p_Fq->cb.dqrr(p_Fq->h_App, p_Fq->h_QmFqr, p_QmPortal, p_Fq->fqidOffset, (t_DpaaFD*)&p_Dq->fd);775if (tmpRes == e_RX_STORE_RESPONSE_PAUSE)776res = qman_cb_dqrr_pause;777/* Check for VDQCR completion */778if (p_Dq->stat & QM_DQRR_STAT_DQCR_EXPIRED)779p_Fq->flags &= ~QMAN_FQ_STATE_VDQCR;780if (p_Dq->stat & QM_DQRR_STAT_FQ_EMPTY)781{782p_Fq->flags &= ~QMAN_FQ_STATE_NE;783freeDrainedFq(p_Fq);784}785}786else787{788/* Interpret 'dq' from the owner's perspective. */789/* use portal default handlers */790ASSERT_COND(p_Dq->fqid);791if (p_Fq)792{793tmpRes = p_Fq->cb.dqrr(p_Fq->h_App,794p_Fq->h_QmFqr,795p_QmPortal,796p_Fq->fqidOffset,797(t_DpaaFD*)&p_Dq->fd);798if (tmpRes == e_RX_STORE_RESPONSE_PAUSE)799res = qman_cb_dqrr_pause;800else if (p_Fq->state == qman_fq_state_waiting_parked)801res = qman_cb_dqrr_park;802}803else804{805tmpRes = p_QmPortal->p_NullCB->dqrr(p_QmPortal->h_App,806NULL,807p_QmPortal,808p_Dq->fqid,809(t_DpaaFD*)&p_Dq->fd);810if (tmpRes == e_RX_STORE_RESPONSE_PAUSE)811res = qman_cb_dqrr_pause;812}813}814815/* Parking isn't possible unless HELDACTIVE was set. NB,816* FORCEELIGIBLE implies HELDACTIVE, so we only need to817* check for HELDACTIVE to cover both. */818ASSERT_COND((p_Dq->stat & QM_DQRR_STAT_FQ_HELDACTIVE) ||819(res != qman_cb_dqrr_park));820/* Defer just means "skip it, I'll consume it myself later on" */821if (res != qman_cb_dqrr_defer)822qmPortalDqrrDcaConsume1ptr(p_QmPortal->p_LowQmPortal,823p_Dq,824(res == qman_cb_dqrr_park));825qm_dqrr_next(p_QmPortal->p_LowQmPortal);826}827}828829static void LoopDequeueRingOptimized(t_Handle h_QmPortal)830{831struct qm_dqrr_entry *p_Dq;832struct qman_fq *p_Fq;833enum qman_cb_dqrr_result res = qman_cb_dqrr_consume;834e_RxStoreResponse tmpRes;835t_QmPortal *p_QmPortal = (t_QmPortal *)h_QmPortal;836837while (res != qman_cb_dqrr_pause)838{839qmPortalDqrrPvbUpdate(p_QmPortal->p_LowQmPortal);840p_Dq = qm_dqrr_current(p_QmPortal->p_LowQmPortal);841if (!p_Dq)842break;843p_Fq = ptr_from_aligned_int(p_Dq->contextB);844if (p_Dq->stat & QM_DQRR_STAT_UNSCHEDULED) {845/* We only set QMAN_FQ_STATE_NE when retiring, so we only need846* to check for clearing it when doing volatile dequeues. It's847* one less thing to check in the critical path (SDQCR). */848tmpRes = p_Fq->cb.dqrr(p_Fq->h_App, p_Fq->h_QmFqr, p_QmPortal, p_Fq->fqidOffset, (t_DpaaFD*)&p_Dq->fd);849if (tmpRes == e_RX_STORE_RESPONSE_PAUSE)850res = qman_cb_dqrr_pause;851/* Check for VDQCR completion */852if (p_Dq->stat & QM_DQRR_STAT_DQCR_EXPIRED)853p_Fq->flags &= ~QMAN_FQ_STATE_VDQCR;854if (p_Dq->stat & QM_DQRR_STAT_FQ_EMPTY)855{856p_Fq->flags &= ~QMAN_FQ_STATE_NE;857freeDrainedFq(p_Fq);858}859}860else861{862/* Interpret 'dq' from the owner's perspective. */863/* use portal default handlers */864ASSERT_COND(p_Dq->fqid);865if (p_Fq)866{867tmpRes = p_Fq->cb.dqrr(p_Fq->h_App,868p_Fq->h_QmFqr,869p_QmPortal,870p_Fq->fqidOffset,871(t_DpaaFD*)&p_Dq->fd);872if (tmpRes == e_RX_STORE_RESPONSE_PAUSE)873res = qman_cb_dqrr_pause;874else if (p_Fq->state == qman_fq_state_waiting_parked)875res = qman_cb_dqrr_park;876}877else878{879tmpRes = p_QmPortal->p_NullCB->dqrr(p_QmPortal->h_App,880NULL,881p_QmPortal,882p_Dq->fqid,883(t_DpaaFD*)&p_Dq->fd);884if (tmpRes == e_RX_STORE_RESPONSE_PAUSE)885res = qman_cb_dqrr_pause;886}887}888889/* Parking isn't possible unless HELDACTIVE was set. NB,890* FORCEELIGIBLE implies HELDACTIVE, so we only need to891* check for HELDACTIVE to cover both. */892ASSERT_COND((p_Dq->stat & QM_DQRR_STAT_FQ_HELDACTIVE) ||893(res != qman_cb_dqrr_park));894if (res == qman_cb_dqrr_park)895/* The only thing to do for non-DCA is the park-request */896qm_dqrr_park_ci(p_QmPortal->p_LowQmPortal);897qm_dqrr_next(p_QmPortal->p_LowQmPortal);898qmPortalDqrrCciConsume(p_QmPortal->p_LowQmPortal, 1);899}900}901902/* Portal interrupt handler */903static void portal_isr(void *ptr)904{905t_QmPortal *p_QmPortal = ptr;906uint32_t event = 0;907uint32_t enableEvents = qm_isr_enable_read(p_QmPortal->p_LowQmPortal);908909DBG(TRACE, ("software-portal %d got interrupt", p_QmPortal->p_LowQmPortal->config.cpu));910911event |= (qm_isr_status_read(p_QmPortal->p_LowQmPortal) &912enableEvents);913914qm_isr_status_clear(p_QmPortal->p_LowQmPortal, event);915/* Only do fast-path handling if it's required */916if (/*(event & QM_PIRQ_DQRI) &&*/917(p_QmPortal->options & QMAN_PORTAL_FLAG_IRQ_FAST))918p_QmPortal->f_LoopDequeueRingCB(p_QmPortal);919if (p_QmPortal->options & QMAN_PORTAL_FLAG_IRQ_SLOW)920LoopMessageRing(p_QmPortal, event);921}922923924static t_Error qman_query_fq_np(t_QmPortal *p_QmPortal, struct qman_fq *p_Fq, struct qm_mcr_queryfq_np *p_Np)925{926struct qm_mc_command *p_Mcc;927struct qm_mc_result *p_Mcr;928uint8_t res;929930NCSW_PLOCK(p_QmPortal);931p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal);932p_Mcc->queryfq_np.fqid = p_Fq->fqid;933qm_mc_commit(p_QmPortal->p_LowQmPortal, QM_MCC_VERB_QUERYFQ_NP);934while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ;935ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) == QM_MCR_VERB_QUERYFQ_NP);936res = p_Mcr->result;937if (res == QM_MCR_RESULT_OK)938*p_Np = p_Mcr->queryfq_np;939PUNLOCK(p_QmPortal);940if (res != QM_MCR_RESULT_OK)941RETURN_ERROR(MINOR, E_INVALID_STATE, ("QUERYFQ_NP failed: %s\n", mcr_result_str(res)));942return E_OK;943}944945static uint8_t QmCgGetCgId(t_Handle h_QmCg)946{947t_QmCg *p_QmCg = (t_QmCg *)h_QmCg;948949return p_QmCg->id;950951}952953static t_Error qm_new_fq(t_QmPortal *p_QmPortal,954uint32_t fqid,955uint32_t fqidOffset,956uint32_t channel,957uint32_t wqid,958uint16_t count,959uint32_t flags,960t_QmFqrCongestionAvoidanceParams *p_CgParams,961t_QmContextA *p_ContextA,962t_QmContextB *p_ContextB,963bool initParked,964t_Handle h_QmFqr,965struct qman_fq **p_Fqs)966{967struct qman_fq *p_Fq = NULL;968struct qm_mcc_initfq fq_opts;969uint32_t i;970t_Error err = E_OK;971int gap, tmp;972uint32_t tmpA, tmpN, ta=0, tn=0, initFqFlag;973974ASSERT_COND(p_QmPortal);975ASSERT_COND(count);976977for(i=0;i<count;i++)978{979p_Fq = (struct qman_fq *)XX_MallocSmart(sizeof(struct qman_fq), 0, 64);980if (!p_Fq)981RETURN_ERROR(MAJOR, E_NO_MEMORY, ("FQ obj!!!"));982memset(p_Fq, 0, sizeof(struct qman_fq));983p_Fq->cb.dqrr = p_QmPortal->f_DfltFrame;984p_Fq->cb.ern = p_QmPortal->f_RejectedFrame;985p_Fq->cb.dc_ern = cb_ern_dcErn;986p_Fq->cb.fqs = cb_fqs;987p_Fq->h_App = p_QmPortal->h_App;988p_Fq->h_QmFqr = h_QmFqr;989p_Fq->fqidOffset = fqidOffset;990p_Fqs[i] = p_Fq;991if ((err = qman_create_fq(p_QmPortal,(uint32_t)(fqid + i), 0, p_Fqs[i])) != E_OK)992break;993}994995if (err != E_OK)996{997for(i=0;i<count;i++)998if (p_Fqs[i])999{1000XX_FreeSmart(p_Fqs[i]);1001p_Fqs[i] = NULL;1002}1003RETURN_ERROR(MINOR, err, ("Failed to create Fqs"));1004}10051006memset(&fq_opts,0,sizeof(fq_opts));1007fq_opts.fqid = fqid;1008fq_opts.count = (uint16_t)(count-1);1009fq_opts.we_mask |= QM_INITFQ_WE_DESTWQ;1010fq_opts.fqd.dest.channel = channel;1011fq_opts.fqd.dest.wq = wqid;1012fq_opts.we_mask |= QM_INITFQ_WE_FQCTRL;1013fq_opts.fqd.fq_ctrl = (uint16_t)flags;10141015if ((flags & QM_FQCTRL_CGE) || (flags & QM_FQCTRL_TDE))1016ASSERT_COND(p_CgParams);10171018if(flags & QM_FQCTRL_CGE)1019{1020ASSERT_COND(p_CgParams->h_QmCg);10211022/* CG OAC and FQ TD may not be configured at the same time. if both are required,1023than we configure CG first, and the FQ TD later - see below. */1024fq_opts.fqd.cgid = QmCgGetCgId(p_CgParams->h_QmCg);1025fq_opts.we_mask |= QM_INITFQ_WE_CGID;1026if(p_CgParams->overheadAccountingLength)1027{1028fq_opts.we_mask |= QM_INITFQ_WE_OAC;1029fq_opts.we_mask &= ~QM_INITFQ_WE_TDTHRESH;1030fq_opts.fqd.td_thresh = (uint16_t)(QM_FQD_TD_THRESH_OAC_EN | p_CgParams->overheadAccountingLength);1031}1032}1033if((flags & QM_FQCTRL_TDE) && (!p_CgParams->overheadAccountingLength))1034{1035ASSERT_COND(p_CgParams->fqTailDropThreshold);10361037fq_opts.we_mask |= QM_INITFQ_WE_TDTHRESH;10381039/* express thresh as ta*2^tn */1040gap = (int)p_CgParams->fqTailDropThreshold;1041for (tmpA=0 ; tmpA<256; tmpA++ )1042for (tmpN=0 ; tmpN<32; tmpN++ )1043{1044tmp = ABS((int)(p_CgParams->fqTailDropThreshold - tmpA*(1<<tmpN)));1045if (tmp < gap)1046{1047ta = tmpA;1048tn = tmpN;1049gap = tmp;1050}1051}1052fq_opts.fqd.td.exp = tn;1053fq_opts.fqd.td.mant = ta;1054}10551056if (p_ContextA)1057{1058fq_opts.we_mask |= QM_INITFQ_WE_CONTEXTA;1059memcpy((void*)&fq_opts.fqd.context_a, p_ContextA, sizeof(t_QmContextA));1060}1061/* If this FQ will not be used for tx, we can use contextB field */1062if (fq_opts.fqd.dest.channel < e_QM_FQ_CHANNEL_FMAN0_SP0)1063{1064fq_opts.we_mask |= QM_INITFQ_WE_CONTEXTB;1065fq_opts.fqd.context_b = aligned_int_from_ptr(p_Fqs[0]);1066}1067else if (p_ContextB) /* Tx-Queue */1068{1069fq_opts.we_mask |= QM_INITFQ_WE_CONTEXTB;1070memcpy((void*)&fq_opts.fqd.context_b, p_ContextB, sizeof(t_QmContextB));1071}10721073if((flags & QM_FQCTRL_TDE) && (p_CgParams->overheadAccountingLength))1074initFqFlag = 0;1075else1076initFqFlag = (uint32_t)(initParked?0:QMAN_INITFQ_FLAG_SCHED);10771078if ((err = qman_init_fq(p_QmPortal, p_Fqs[0], initFqFlag, &fq_opts)) != E_OK)1079{1080for(i=0;i<count;i++)1081if (p_Fqs[i])1082{1083XX_FreeSmart(p_Fqs[i]);1084p_Fqs[i] = NULL;1085}1086RETURN_ERROR(MINOR, err, ("Failed to init Fqs [%d-%d]", fqid, fqid+count-1));1087}10881089/* if both CG OAC and FQ TD are needed, we call qman_init_fq again, this time for the FQ TD only */1090if((flags & QM_FQCTRL_TDE) && (p_CgParams->overheadAccountingLength))1091{1092ASSERT_COND(p_CgParams->fqTailDropThreshold);10931094fq_opts.we_mask = QM_INITFQ_WE_TDTHRESH;10951096/* express thresh as ta*2^tn */1097gap = (int)p_CgParams->fqTailDropThreshold;1098for (tmpA=0 ; tmpA<256; tmpA++ )1099for (tmpN=0 ; tmpN<32; tmpN++ )1100{1101tmp = ABS((int)(p_CgParams->fqTailDropThreshold - tmpA*(1<<tmpN)));1102if (tmp < gap)1103{1104ta = tmpA;1105tn = tmpN;1106gap = tmp;1107}1108}1109fq_opts.fqd.td.exp = tn;1110fq_opts.fqd.td.mant = ta;1111if ((err = qman_init_fq(p_QmPortal, p_Fqs[0], (uint32_t)(initParked?0:QMAN_INITFQ_FLAG_SCHED), &fq_opts)) != E_OK)1112{1113for(i=0;i<count;i++)1114if (p_Fqs[i])1115{1116XX_FreeSmart(p_Fqs[i]);1117p_Fqs[i] = NULL;1118}1119RETURN_ERROR(MINOR, err, ("Failed to init Fqs"));1120}1121}112211231124for(i=1;i<count;i++)1125{1126memcpy(p_Fqs[i], p_Fqs[0], sizeof(struct qman_fq));1127p_Fqs[i]->fqid += i;1128}11291130return err;1131}113211331134static t_Error qm_free_fq(t_QmPortal *p_QmPortal, struct qman_fq *p_Fq)1135{1136uint32_t flags=0;11371138if (qman_retire_fq(p_QmPortal, p_Fq, &flags, false) != E_OK)1139RETURN_ERROR(MAJOR, E_INVALID_STATE, ("qman_retire_fq() failed!"));11401141if (flags & QMAN_FQ_STATE_CHANGING)1142RETURN_ERROR(MAJOR, E_INVALID_STATE, ("fq %d currently in use, will be retired", p_Fq->fqid));11431144if (flags & QMAN_FQ_STATE_NE)1145RETURN_ERROR(MAJOR, E_INVALID_STATE, ("qman_retire_fq() failed;" \1146"Frame Queue Not Empty, Need to dequeue"));11471148if (qman_oos_fq(p_QmPortal, p_Fq) != E_OK)1149RETURN_ERROR(MAJOR, E_INVALID_STATE, ("qman_oos_fq() failed!"));11501151qman_destroy_fq(p_Fq,0);11521153return E_OK;1154}11551156static void qman_disable_portal(t_QmPortal *p_QmPortal)1157{1158NCSW_PLOCK(p_QmPortal);1159if (!(p_QmPortal->disable_count++))1160qm_dqrr_set_maxfill(p_QmPortal->p_LowQmPortal, 0);1161PUNLOCK(p_QmPortal);1162}116311641165/* quiesce SDQCR/VDQCR, then drain till h/w wraps up anything it1166* was doing (5ms is more than enough to ensure it's done). */1167static void clean_dqrr_mr(t_QmPortal *p_QmPortal)1168{1169struct qm_dqrr_entry *p_Dq;1170struct qm_mr_entry *p_Msg;1171int idle = 0;11721173qm_dqrr_sdqcr_set(p_QmPortal->p_LowQmPortal, 0);1174qm_dqrr_vdqcr_set(p_QmPortal->p_LowQmPortal, 0);1175drain_loop:1176qmPortalDqrrPvbPrefetch(p_QmPortal->p_LowQmPortal);1177qmPortalDqrrPvbUpdate(p_QmPortal->p_LowQmPortal);1178qmPortalMrPvbUpdate(p_QmPortal->p_LowQmPortal);1179p_Dq = qm_dqrr_current(p_QmPortal->p_LowQmPortal);1180p_Msg = qm_mr_current(p_QmPortal->p_LowQmPortal);1181if (p_Dq) {1182qm_dqrr_next(p_QmPortal->p_LowQmPortal);1183qmPortalDqrrCciConsume(p_QmPortal->p_LowQmPortal, 1);1184}1185if (p_Msg) {1186qm_mr_next(p_QmPortal->p_LowQmPortal);1187qmPortalMrCciConsume(p_QmPortal->p_LowQmPortal, 1);1188}1189if (!p_Dq && !p_Msg) {1190if (++idle < 5) {1191XX_UDelay(1000);1192goto drain_loop;1193}1194} else {1195idle = 0;1196goto drain_loop;1197}1198}11991200static t_Error qman_create_portal(t_QmPortal *p_QmPortal,1201uint32_t flags,1202uint32_t sdqcrFlags,1203uint8_t dqrrSize)1204{1205const struct qm_portal_config *p_Config = &(p_QmPortal->p_LowQmPortal->config);1206int ret = 0;1207t_Error err;1208uint32_t isdr;12091210if ((err = qm_eqcr_init(p_QmPortal->p_LowQmPortal, e_QmPortalPVB, e_QmPortalEqcrCCE)) != E_OK)1211RETURN_ERROR(MINOR, err, ("Qman EQCR initialization failed\n"));12121213if (qm_dqrr_init(p_QmPortal->p_LowQmPortal,1214sdqcrFlags ? e_QmPortalDequeuePushMode : e_QmPortalDequeuePullMode,1215e_QmPortalPVB,1216(flags & QMAN_PORTAL_FLAG_DCA) ? e_QmPortalDqrrDCA : e_QmPortalDqrrCCI,1217dqrrSize,1218(flags & QMAN_PORTAL_FLAG_RSTASH) ? 1 : 0,1219(flags & QMAN_PORTAL_FLAG_DSTASH) ? 1 : 0)) {1220REPORT_ERROR(MAJOR, E_INVALID_STATE, ("DQRR initialization failed"));1221goto fail_dqrr;1222}12231224if (qm_mr_init(p_QmPortal->p_LowQmPortal, e_QmPortalPVB, e_QmPortalMrCCI)) {1225REPORT_ERROR(MAJOR, E_INVALID_STATE, ("MR initialization failed"));1226goto fail_mr;1227}1228if (qm_mc_init(p_QmPortal->p_LowQmPortal)) {1229REPORT_ERROR(MAJOR, E_INVALID_STATE, ("MC initialization failed"));1230goto fail_mc;1231}1232if (qm_isr_init(p_QmPortal->p_LowQmPortal)) {1233REPORT_ERROR(MAJOR, E_INVALID_STATE, ("ISR initialization failed"));1234goto fail_isr;1235}1236/* static interrupt-gating controls */1237qm_dqrr_set_ithresh(p_QmPortal->p_LowQmPortal, 12);1238qm_mr_set_ithresh(p_QmPortal->p_LowQmPortal, 4);1239qm_isr_set_iperiod(p_QmPortal->p_LowQmPortal, 100);1240p_QmPortal->options = flags;1241isdr = 0xffffffff;1242qm_isr_status_clear(p_QmPortal->p_LowQmPortal, 0xffffffff);1243qm_isr_enable_write(p_QmPortal->p_LowQmPortal, DEFAULT_portalExceptions);1244qm_isr_disable_write(p_QmPortal->p_LowQmPortal, isdr);1245if (flags & QMAN_PORTAL_FLAG_IRQ)1246{1247XX_SetIntr(p_Config->irq, portal_isr, p_QmPortal);1248XX_EnableIntr(p_Config->irq);1249qm_isr_uninhibit(p_QmPortal->p_LowQmPortal);1250} else1251/* without IRQ, we can't block */1252flags &= ~QMAN_PORTAL_FLAG_WAIT;1253/* Need EQCR to be empty before continuing */1254isdr ^= QM_PIRQ_EQCI;1255qm_isr_disable_write(p_QmPortal->p_LowQmPortal, isdr);1256ret = qm_eqcr_get_fill(p_QmPortal->p_LowQmPortal);1257if (ret) {1258REPORT_ERROR(MAJOR, E_INVALID_STATE, ("EQCR unclean"));1259goto fail_eqcr_empty;1260}1261isdr ^= (QM_PIRQ_DQRI | QM_PIRQ_MRI);1262qm_isr_disable_write(p_QmPortal->p_LowQmPortal, isdr);1263if (qm_dqrr_current(p_QmPortal->p_LowQmPortal) != NULL)1264{1265REPORT_ERROR(MAJOR, E_INVALID_STATE, ("DQRR unclean"));1266goto fail_dqrr_mr_empty;1267}1268if (qm_mr_current(p_QmPortal->p_LowQmPortal) != NULL)1269{1270REPORT_ERROR(MAJOR, E_INVALID_STATE, ("MR unclean"));1271goto fail_dqrr_mr_empty;1272}1273qm_isr_disable_write(p_QmPortal->p_LowQmPortal, 0);1274qm_dqrr_sdqcr_set(p_QmPortal->p_LowQmPortal, sdqcrFlags);1275return E_OK;1276fail_dqrr_mr_empty:1277fail_eqcr_empty:1278qm_isr_finish(p_QmPortal->p_LowQmPortal);1279fail_isr:1280qm_mc_finish(p_QmPortal->p_LowQmPortal);1281fail_mc:1282qm_mr_finish(p_QmPortal->p_LowQmPortal);1283fail_mr:1284qm_dqrr_finish(p_QmPortal->p_LowQmPortal);1285fail_dqrr:1286qm_eqcr_finish(p_QmPortal->p_LowQmPortal);1287return ERROR_CODE(E_INVALID_STATE);1288}12891290static void qman_destroy_portal(t_QmPortal *p_QmPortal)1291{1292/* NB we do this to "quiesce" EQCR. If we add enqueue-completions or1293* something related to QM_PIRQ_EQCI, this may need fixing. */1294qmPortalEqcrCceUpdate(p_QmPortal->p_LowQmPortal);1295if (p_QmPortal->options & QMAN_PORTAL_FLAG_IRQ)1296{1297XX_DisableIntr(p_QmPortal->p_LowQmPortal->config.irq);1298XX_FreeIntr(p_QmPortal->p_LowQmPortal->config.irq);1299}1300qm_isr_finish(p_QmPortal->p_LowQmPortal);1301qm_mc_finish(p_QmPortal->p_LowQmPortal);1302qm_mr_finish(p_QmPortal->p_LowQmPortal);1303qm_dqrr_finish(p_QmPortal->p_LowQmPortal);1304qm_eqcr_finish(p_QmPortal->p_LowQmPortal);1305}13061307static inline struct qm_eqcr_entry *try_eq_start(t_QmPortal *p_QmPortal)1308{1309struct qm_eqcr_entry *p_Eq;1310uint8_t avail;13111312avail = qm_eqcr_get_avail(p_QmPortal->p_LowQmPortal);1313if (avail == EQCR_THRESH)1314qmPortalEqcrCcePrefetch(p_QmPortal->p_LowQmPortal);1315else if (avail < EQCR_THRESH)1316qmPortalEqcrCceUpdate(p_QmPortal->p_LowQmPortal);1317p_Eq = qm_eqcr_start(p_QmPortal->p_LowQmPortal);13181319return p_Eq;1320}132113221323static t_Error qman_orp_update(t_QmPortal *p_QmPortal,1324uint32_t orpId,1325uint16_t orpSeqnum,1326uint32_t flags)1327{1328struct qm_eqcr_entry *p_Eq;13291330NCSW_PLOCK(p_QmPortal);1331p_Eq = try_eq_start(p_QmPortal);1332if (!p_Eq)1333{1334PUNLOCK(p_QmPortal);1335return ERROR_CODE(E_BUSY);1336}13371338if (flags & QMAN_ENQUEUE_FLAG_NESN)1339orpSeqnum |= QM_EQCR_SEQNUM_NESN;1340else1341/* No need to check 4 QMAN_ENQUEUE_FLAG_HOLE */1342orpSeqnum &= ~QM_EQCR_SEQNUM_NESN;1343p_Eq->seqnum = orpSeqnum;1344p_Eq->orp = orpId;1345qmPortalEqcrPvbCommit(p_QmPortal->p_LowQmPortal, (uint8_t)QM_EQCR_VERB_ORP);13461347PUNLOCK(p_QmPortal);1348return E_OK;1349}13501351static __inline__ t_Error CheckStashParams(t_QmFqrParams *p_QmFqrParams)1352{1353ASSERT_COND(p_QmFqrParams);13541355if (p_QmFqrParams->stashingParams.frameAnnotationSize > QM_CONTEXTA_MAX_STASH_SIZE)1356RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Frame Annotation Size Exceeded Max Stash Size(%d)", QM_CONTEXTA_MAX_STASH_SIZE));1357if (p_QmFqrParams->stashingParams.frameDataSize > QM_CONTEXTA_MAX_STASH_SIZE)1358RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Frame Data Size Exceeded Max Stash Size(%d)", QM_CONTEXTA_MAX_STASH_SIZE));1359if (p_QmFqrParams->stashingParams.fqContextSize > QM_CONTEXTA_MAX_STASH_SIZE)1360RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Frame Context Size Exceeded Max Stash Size(%d)", QM_CONTEXTA_MAX_STASH_SIZE));1361if (p_QmFqrParams->stashingParams.fqContextSize)1362{1363if (!p_QmFqrParams->stashingParams.fqContextAddr)1364RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("FQ Context Address Must be givven"));1365if (!IS_ALIGNED(p_QmFqrParams->stashingParams.fqContextAddr, CACHELINE_SIZE))1366RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("FQ Context Address Must be aligned to %d", CACHELINE_SIZE));1367if (p_QmFqrParams->stashingParams.fqContextAddr & 0xffffff0000000000LL)1368RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("FQ Context Address May be up to 40 bit"));1369}13701371return E_OK;1372}13731374static t_Error QmPortalRegisterCg(t_Handle h_QmPortal, t_Handle h_QmCg, uint8_t cgId)1375{1376t_QmPortal *p_QmPortal = (t_QmPortal *)h_QmPortal;13771378/* cgrs[0] is the mask of registered CG's*/1379if(p_QmPortal->cgrs[0].q.__state[cgId/32] & (0x80000000 >> (cgId % 32)))1380RETURN_ERROR(MINOR, E_BUSY, ("CG already used"));13811382p_QmPortal->cgrs[0].q.__state[cgId/32] |= 0x80000000 >> (cgId % 32);1383p_QmPortal->cgsHandles[cgId] = h_QmCg;13841385return E_OK;1386}13871388static t_Error QmPortalUnregisterCg(t_Handle h_QmPortal, uint8_t cgId)1389{1390t_QmPortal *p_QmPortal = (t_QmPortal *)h_QmPortal;13911392/* cgrs[0] is the mask of registered CG's*/1393if(!(p_QmPortal->cgrs[0].q.__state[cgId/32] & (0x80000000 >> (cgId % 32))))1394RETURN_ERROR(MINOR, E_BUSY, ("CG is not in use"));13951396p_QmPortal->cgrs[0].q.__state[cgId/32] &= ~0x80000000 >> (cgId % 32);1397p_QmPortal->cgsHandles[cgId] = NULL;13981399return E_OK;1400}14011402static e_DpaaSwPortal QmPortalGetSwPortalId(t_Handle h_QmPortal)1403{1404t_QmPortal *p_QmPortal = (t_QmPortal *)h_QmPortal;14051406return (e_DpaaSwPortal)p_QmPortal->p_LowQmPortal->config.cpu;1407}14081409static t_Error CalcWredCurve(t_QmCgWredCurve *p_WredCurve, uint32_t *p_CurveWord)1410{1411uint32_t maxP, roundDown, roundUp, tmpA, tmpN;1412uint32_t ma=0, mn=0, slope, sa=0, sn=0, pn;1413int pres = 1000;1414int gap, tmp;14151416/* TODO - change maxTh to uint64_t?1417if(p_WredCurve->maxTh > (1<<39))1418RETURN_ERROR(MINOR, E_INVALID_VALUE, ("maxTh is not in range"));*/14191420/* express maxTh as ma*2^mn */1421gap = (int)p_WredCurve->maxTh;1422for (tmpA=0 ; tmpA<256; tmpA++ )1423for (tmpN=0 ; tmpN<32; tmpN++ )1424{1425tmp = ABS((int)(p_WredCurve->maxTh - tmpA*(1<<tmpN)));1426if (tmp < gap)1427{1428ma = tmpA;1429mn = tmpN;1430gap = tmp;1431}1432}1433ASSERT_COND(ma <256);1434ASSERT_COND(mn <32);1435p_WredCurve->maxTh = ma*(1<<mn);14361437if(p_WredCurve->maxTh <= p_WredCurve->minTh)1438RETURN_ERROR(MINOR, E_INVALID_VALUE, ("maxTh must be larger than minTh"));1439if(p_WredCurve->probabilityDenominator > 64)1440RETURN_ERROR(MINOR, E_INVALID_VALUE, ("probabilityDenominator mustn't be 1-64"));14411442/* first we translate from Cisco probabilityDenominator1443to 256 fixed denominator, result must be divisible by 4. */1444/* we multiply by a fixed value to get better accuracy (without1445using floating point) */1446maxP = (uint32_t)(256*1000/p_WredCurve->probabilityDenominator);1447if (maxP % 4*pres)1448{1449roundDown = maxP + (maxP % (4*pres));1450roundUp = roundDown + 4*pres;1451if((roundUp - maxP) > (maxP - roundDown))1452maxP = roundDown;1453else1454maxP = roundUp;1455}1456maxP = maxP/pres;1457ASSERT_COND(maxP <= 256);1458pn = (uint8_t)(maxP/4 - 1);14591460if(maxP >= (p_WredCurve->maxTh - p_WredCurve->minTh))1461RETURN_ERROR(MINOR, E_INVALID_VALUE, ("Due to probabilityDenominator selected, maxTh-minTh must be larger than %d", maxP));14621463pres = 1000000;1464slope = maxP*pres/(p_WredCurve->maxTh - p_WredCurve->minTh);1465/* express slope as sa/2^sn */1466gap = (int)slope;1467for (tmpA=(uint32_t)(64*pres) ; tmpA<128*pres; tmpA += pres )1468for (tmpN=7 ; tmpN<64; tmpN++ )1469{1470tmp = ABS((int)(slope - tmpA/(1UL<<(tmpN%32))));1471if (tmp < gap)1472{1473sa = tmpA;1474sn = tmpN;1475gap = tmp;1476}1477}1478sa = sa/pres;1479ASSERT_COND(sa<128 && sa>=64);1480ASSERT_COND(sn<64 && sn>=7);14811482*p_CurveWord = ((ma << 24) |1483(mn << 19) |1484(sa << 12) |1485(sn << 6) |1486pn);14871488return E_OK;1489}14901491static t_Error QmPortalPullFrame(t_Handle h_QmPortal, uint32_t pdqcr, t_DpaaFD *p_Frame)1492{1493t_QmPortal *p_QmPortal = (t_QmPortal *)h_QmPortal;1494struct qm_dqrr_entry *p_Dq;1495int prefetch;1496uint32_t *p_Dst, *p_Src;14971498ASSERT_COND(p_QmPortal);1499ASSERT_COND(p_Frame);1500SANITY_CHECK_RETURN_ERROR(p_QmPortal->pullMode, E_INVALID_STATE);15011502NCSW_PLOCK(p_QmPortal);15031504qm_dqrr_pdqcr_set(p_QmPortal->p_LowQmPortal, pdqcr);1505mb();1506while (qm_dqrr_pdqcr_get(p_QmPortal->p_LowQmPortal)) ;15071508prefetch = !(p_QmPortal->options & QMAN_PORTAL_FLAG_RSTASH);1509while(TRUE)1510{1511if (prefetch)1512qmPortalDqrrPvbPrefetch(p_QmPortal->p_LowQmPortal);1513qmPortalDqrrPvbUpdate(p_QmPortal->p_LowQmPortal);1514p_Dq = qm_dqrr_current(p_QmPortal->p_LowQmPortal);1515if (!p_Dq)1516continue;1517ASSERT_COND(p_Dq->fqid);1518p_Dst = (uint32_t *)p_Frame;1519p_Src = (uint32_t *)&p_Dq->fd;1520p_Dst[0] = p_Src[0];1521p_Dst[1] = p_Src[1];1522p_Dst[2] = p_Src[2];1523p_Dst[3] = p_Src[3];1524if (p_QmPortal->options & QMAN_PORTAL_FLAG_DCA)1525{1526qmPortalDqrrDcaConsume1ptr(p_QmPortal->p_LowQmPortal,1527p_Dq,1528false);1529qm_dqrr_next(p_QmPortal->p_LowQmPortal);1530}1531else1532{1533qm_dqrr_next(p_QmPortal->p_LowQmPortal);1534qmPortalDqrrCciConsume(p_QmPortal->p_LowQmPortal, 1);1535}1536break;1537}15381539PUNLOCK(p_QmPortal);15401541if (!(p_Dq->stat & QM_DQRR_STAT_FD_VALID))1542return ERROR_CODE(E_EMPTY);15431544return E_OK;1545}154615471548/****************************************/1549/* API Init unit functions */1550/****************************************/1551t_Handle QM_PORTAL_Config(t_QmPortalParam *p_QmPortalParam)1552{1553t_QmPortal *p_QmPortal;1554uint32_t i;15551556SANITY_CHECK_RETURN_VALUE(p_QmPortalParam, E_INVALID_HANDLE, NULL);1557SANITY_CHECK_RETURN_VALUE(p_QmPortalParam->swPortalId < DPAA_MAX_NUM_OF_SW_PORTALS, E_INVALID_VALUE, 0);15581559p_QmPortal = (t_QmPortal *)XX_Malloc(sizeof(t_QmPortal));1560if (!p_QmPortal)1561{1562REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Qm Portal obj!!!"));1563return NULL;1564}1565memset(p_QmPortal, 0, sizeof(t_QmPortal));15661567p_QmPortal->p_LowQmPortal = (struct qm_portal *)XX_Malloc(sizeof(struct qm_portal));1568if (!p_QmPortal->p_LowQmPortal)1569{1570XX_Free(p_QmPortal);1571REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Low qm p_QmPortal obj!!!"));1572return NULL;1573}1574memset(p_QmPortal->p_LowQmPortal, 0, sizeof(struct qm_portal));15751576p_QmPortal->p_QmPortalDriverParams = (t_QmPortalDriverParams *)XX_Malloc(sizeof(t_QmPortalDriverParams));1577if (!p_QmPortal->p_QmPortalDriverParams)1578{1579XX_Free(p_QmPortal->p_LowQmPortal);1580XX_Free(p_QmPortal);1581REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Qm Portal driver parameters"));1582return NULL;1583}1584memset(p_QmPortal->p_QmPortalDriverParams, 0, sizeof(t_QmPortalDriverParams));15851586p_QmPortal->p_LowQmPortal->addr.addr_ce = UINT_TO_PTR(p_QmPortalParam->ceBaseAddress);1587p_QmPortal->p_LowQmPortal->addr.addr_ci = UINT_TO_PTR(p_QmPortalParam->ciBaseAddress);1588p_QmPortal->p_LowQmPortal->config.irq = p_QmPortalParam->irq;1589p_QmPortal->p_LowQmPortal->config.bound = 0;1590p_QmPortal->p_LowQmPortal->config.cpu = (int)p_QmPortalParam->swPortalId;1591p_QmPortal->p_LowQmPortal->config.channel = (e_QmFQChannel)(e_QM_FQ_CHANNEL_SWPORTAL0 + p_QmPortalParam->swPortalId);1592p_QmPortal->p_LowQmPortal->bind_lock = XX_InitSpinlock();15931594p_QmPortal->h_Qm = p_QmPortalParam->h_Qm;1595p_QmPortal->f_DfltFrame = p_QmPortalParam->f_DfltFrame;1596p_QmPortal->f_RejectedFrame = p_QmPortalParam->f_RejectedFrame;1597p_QmPortal->h_App = p_QmPortalParam->h_App;15981599p_QmPortal->p_QmPortalDriverParams->fdLiodnOffset = p_QmPortalParam->fdLiodnOffset;1600p_QmPortal->p_QmPortalDriverParams->dequeueDcaMode = DEFAULT_dequeueDcaMode;1601p_QmPortal->p_QmPortalDriverParams->dequeueUpToThreeFrames = DEFAULT_dequeueUpToThreeFrames;1602p_QmPortal->p_QmPortalDriverParams->commandType = DEFAULT_dequeueCommandType;1603p_QmPortal->p_QmPortalDriverParams->userToken = DEFAULT_dequeueUserToken;1604p_QmPortal->p_QmPortalDriverParams->specifiedWq = DEFAULT_dequeueSpecifiedWq;1605p_QmPortal->p_QmPortalDriverParams->dedicatedChannel = DEFAULT_dequeueDedicatedChannel;1606p_QmPortal->p_QmPortalDriverParams->dedicatedChannelHasPrecedenceOverPoolChannels =1607DEFAULT_dequeueDedicatedChannelHasPrecedenceOverPoolChannels;1608p_QmPortal->p_QmPortalDriverParams->poolChannelId = DEFAULT_dequeuePoolChannelId;1609p_QmPortal->p_QmPortalDriverParams->wqId = DEFAULT_dequeueWqId;1610for (i=0;i<QM_MAX_NUM_OF_POOL_CHANNELS;i++)1611p_QmPortal->p_QmPortalDriverParams->poolChannels[i] = FALSE;1612p_QmPortal->p_QmPortalDriverParams->dqrrSize = DEFAULT_dqrrSize;1613p_QmPortal->p_QmPortalDriverParams->pullMode = DEFAULT_pullMode;16141615return p_QmPortal;1616}16171618t_Error QM_PORTAL_Init(t_Handle h_QmPortal)1619{1620t_QmPortal *p_QmPortal = (t_QmPortal *)h_QmPortal;1621uint32_t i, flags=0, sdqcrFlags=0;1622t_Error err;1623t_QmInterModulePortalInitParams qmParams;16241625SANITY_CHECK_RETURN_ERROR(p_QmPortal, E_INVALID_HANDLE);1626SANITY_CHECK_RETURN_ERROR(p_QmPortal->p_QmPortalDriverParams, E_INVALID_HANDLE);16271628memset(&qmParams, 0, sizeof(qmParams));1629qmParams.portalId = (uint8_t)p_QmPortal->p_LowQmPortal->config.cpu;1630qmParams.liodn = p_QmPortal->p_QmPortalDriverParams->fdLiodnOffset;1631qmParams.dqrrLiodn = p_QmPortal->p_QmPortalDriverParams->dqrrLiodn;1632qmParams.fdFqLiodn = p_QmPortal->p_QmPortalDriverParams->fdFqLiodn;1633qmParams.stashDestQueue = p_QmPortal->p_QmPortalDriverParams->stashDestQueue;1634if ((err = QmGetSetPortalParams(p_QmPortal->h_Qm, &qmParams)) != E_OK)1635RETURN_ERROR(MAJOR, err, NO_MSG);16361637flags = (uint32_t)(((p_QmPortal->p_LowQmPortal->config.irq == NO_IRQ) ?16380 :1639(QMAN_PORTAL_FLAG_IRQ |1640QMAN_PORTAL_FLAG_IRQ_FAST |1641QMAN_PORTAL_FLAG_IRQ_SLOW)));1642flags |= ((p_QmPortal->p_QmPortalDriverParams->dequeueDcaMode) ? QMAN_PORTAL_FLAG_DCA : 0);1643flags |= (p_QmPortal->p_QmPortalDriverParams->dqrr)?QMAN_PORTAL_FLAG_RSTASH:0;1644flags |= (p_QmPortal->p_QmPortalDriverParams->fdFq)?QMAN_PORTAL_FLAG_DSTASH:0;16451646p_QmPortal->pullMode = p_QmPortal->p_QmPortalDriverParams->pullMode;1647if (!p_QmPortal->pullMode)1648{1649sdqcrFlags |= (p_QmPortal->p_QmPortalDriverParams->dequeueUpToThreeFrames) ? QM_SDQCR_COUNT_UPTO3 : QM_SDQCR_COUNT_EXACT1;1650sdqcrFlags |= QM_SDQCR_TOKEN_SET(p_QmPortal->p_QmPortalDriverParams->userToken);1651sdqcrFlags |= QM_SDQCR_TYPE_SET(p_QmPortal->p_QmPortalDriverParams->commandType);1652if (!p_QmPortal->p_QmPortalDriverParams->specifiedWq)1653{1654/* sdqcrFlags |= QM_SDQCR_SOURCE_CHANNELS;*/ /* removed as the macro is '0' */1655sdqcrFlags |= (p_QmPortal->p_QmPortalDriverParams->dedicatedChannelHasPrecedenceOverPoolChannels) ? QM_SDQCR_DEDICATED_PRECEDENCE : 0;1656sdqcrFlags |= (p_QmPortal->p_QmPortalDriverParams->dedicatedChannel) ? QM_SDQCR_CHANNELS_DEDICATED : 0;1657for (i=0;i<QM_MAX_NUM_OF_POOL_CHANNELS;i++)1658sdqcrFlags |= ((p_QmPortal->p_QmPortalDriverParams->poolChannels[i]) ?1659QM_SDQCR_CHANNELS_POOL(i+1) : 0);1660}1661else1662{1663sdqcrFlags |= QM_SDQCR_SOURCE_SPECIFICWQ;1664sdqcrFlags |= (p_QmPortal->p_QmPortalDriverParams->dedicatedChannel) ?1665QM_SDQCR_SPECIFICWQ_DEDICATED : QM_SDQCR_SPECIFICWQ_POOL(p_QmPortal->p_QmPortalDriverParams->poolChannelId);1666sdqcrFlags |= QM_SDQCR_SPECIFICWQ_WQ(p_QmPortal->p_QmPortalDriverParams->wqId);1667}1668}1669if ((flags & QMAN_PORTAL_FLAG_RSTASH) && (flags & QMAN_PORTAL_FLAG_DCA))1670p_QmPortal->f_LoopDequeueRingCB = LoopDequeueRingDcaOptimized;1671else if ((flags & QMAN_PORTAL_FLAG_RSTASH) && !(flags & QMAN_PORTAL_FLAG_DCA))1672p_QmPortal->f_LoopDequeueRingCB = LoopDequeueRingOptimized;1673else1674p_QmPortal->f_LoopDequeueRingCB = LoopDequeueRing;16751676if ((!p_QmPortal->f_RejectedFrame) || (!p_QmPortal->f_DfltFrame))1677RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("f_RejectedFrame or f_DfltFrame callback not provided"));16781679p_QmPortal->p_NullCB = (struct qman_fq_cb *)XX_Malloc(sizeof(struct qman_fq_cb));1680if (!p_QmPortal->p_NullCB)1681RETURN_ERROR(MAJOR, E_NO_MEMORY, ("FQ Null CB obj!!!"));1682memset(p_QmPortal->p_NullCB, 0, sizeof(struct qman_fq_cb));16831684p_QmPortal->p_NullCB->dqrr = p_QmPortal->f_DfltFrame;1685p_QmPortal->p_NullCB->ern = p_QmPortal->f_RejectedFrame;1686p_QmPortal->p_NullCB->dc_ern = p_QmPortal->p_NullCB->fqs = null_cb_mr;16871688if (qman_create_portal(p_QmPortal, flags, sdqcrFlags, p_QmPortal->p_QmPortalDriverParams->dqrrSize) != E_OK)1689{1690RETURN_ERROR(MAJOR, E_NO_MEMORY, ("create portal failed"));1691}16921693QmSetPortalHandle(p_QmPortal->h_Qm, (t_Handle)p_QmPortal, (e_DpaaSwPortal)p_QmPortal->p_LowQmPortal->config.cpu);1694XX_Free(p_QmPortal->p_QmPortalDriverParams);1695p_QmPortal->p_QmPortalDriverParams = NULL;16961697DBG(TRACE, ("Qman-Portal %d @ %p:%p",1698p_QmPortal->p_LowQmPortal->config.cpu,1699p_QmPortal->p_LowQmPortal->addr.addr_ce,1700p_QmPortal->p_LowQmPortal->addr.addr_ci1701));17021703DBG(TRACE, ("Qman-Portal %d phys @ 0x%016llx:0x%016llx",1704p_QmPortal->p_LowQmPortal->config.cpu,1705(uint64_t)XX_VirtToPhys(p_QmPortal->p_LowQmPortal->addr.addr_ce),1706(uint64_t)XX_VirtToPhys(p_QmPortal->p_LowQmPortal->addr.addr_ci)1707));17081709return E_OK;1710}17111712t_Error QM_PORTAL_Free(t_Handle h_QmPortal)1713{1714t_QmPortal *p_QmPortal = (t_QmPortal *)h_QmPortal;17151716if (!p_QmPortal)1717return ERROR_CODE(E_INVALID_HANDLE);17181719ASSERT_COND(p_QmPortal->p_LowQmPortal);1720QmSetPortalHandle(p_QmPortal->h_Qm, NULL, (e_DpaaSwPortal)p_QmPortal->p_LowQmPortal->config.cpu);1721qman_destroy_portal(p_QmPortal);1722if (p_QmPortal->p_NullCB)1723XX_Free(p_QmPortal->p_NullCB);17241725if (p_QmPortal->p_LowQmPortal->bind_lock)1726XX_FreeSpinlock(p_QmPortal->p_LowQmPortal->bind_lock);1727if(p_QmPortal->p_QmPortalDriverParams)1728XX_Free(p_QmPortal->p_QmPortalDriverParams);1729XX_Free(p_QmPortal->p_LowQmPortal);1730XX_Free(p_QmPortal);17311732return E_OK;1733}17341735t_Error QM_PORTAL_ConfigDcaMode(t_Handle h_QmPortal, bool enable)1736{1737t_QmPortal *p_QmPortal = (t_QmPortal *)h_QmPortal;17381739SANITY_CHECK_RETURN_ERROR(p_QmPortal, E_INVALID_HANDLE);1740SANITY_CHECK_RETURN_ERROR(p_QmPortal->p_QmPortalDriverParams, E_INVALID_HANDLE);17411742p_QmPortal->p_QmPortalDriverParams->dequeueDcaMode = enable;17431744return E_OK;1745}17461747t_Error QM_PORTAL_ConfigStash(t_Handle h_QmPortal, t_QmPortalStashParam *p_StashParams)1748{1749t_QmPortal *p_QmPortal = (t_QmPortal *)h_QmPortal;17501751SANITY_CHECK_RETURN_ERROR(p_QmPortal, E_INVALID_HANDLE);1752SANITY_CHECK_RETURN_ERROR(p_QmPortal->p_QmPortalDriverParams, E_NULL_POINTER);1753SANITY_CHECK_RETURN_ERROR(p_StashParams, E_NULL_POINTER);17541755p_QmPortal->p_QmPortalDriverParams->stashDestQueue = p_StashParams->stashDestQueue;1756p_QmPortal->p_QmPortalDriverParams->dqrrLiodn = p_StashParams->dqrrLiodn;1757p_QmPortal->p_QmPortalDriverParams->fdFqLiodn = p_StashParams->fdFqLiodn;1758p_QmPortal->p_QmPortalDriverParams->eqcr = p_StashParams->eqcr;1759p_QmPortal->p_QmPortalDriverParams->eqcrHighPri = p_StashParams->eqcrHighPri;1760p_QmPortal->p_QmPortalDriverParams->dqrr = p_StashParams->dqrr;1761p_QmPortal->p_QmPortalDriverParams->dqrrHighPri = p_StashParams->dqrrHighPri;1762p_QmPortal->p_QmPortalDriverParams->fdFq = p_StashParams->fdFq;1763p_QmPortal->p_QmPortalDriverParams->fdFqHighPri = p_StashParams->fdFqHighPri;1764p_QmPortal->p_QmPortalDriverParams->fdFqDrop = p_StashParams->fdFqDrop;17651766return E_OK;1767}176817691770t_Error QM_PORTAL_ConfigPullMode(t_Handle h_QmPortal, bool pullMode)1771{1772t_QmPortal *p_QmPortal = (t_QmPortal *)h_QmPortal;17731774SANITY_CHECK_RETURN_ERROR(p_QmPortal, E_INVALID_HANDLE);1775SANITY_CHECK_RETURN_ERROR(p_QmPortal->p_QmPortalDriverParams, E_NULL_POINTER);17761777p_QmPortal->p_QmPortalDriverParams->pullMode = pullMode;17781779return E_OK;1780}17811782t_Error QM_PORTAL_AddPoolChannel(t_Handle h_QmPortal, uint8_t poolChannelId)1783{1784t_QmPortal *p_QmPortal = (t_QmPortal *)h_QmPortal;1785uint32_t sdqcrFlags;17861787SANITY_CHECK_RETURN_ERROR(p_QmPortal, E_INVALID_HANDLE);1788SANITY_CHECK_RETURN_ERROR((poolChannelId < QM_MAX_NUM_OF_POOL_CHANNELS), E_INVALID_VALUE);17891790sdqcrFlags = qm_dqrr_sdqcr_get(p_QmPortal->p_LowQmPortal);1791sdqcrFlags |= QM_SDQCR_CHANNELS_POOL(poolChannelId+1);1792qm_dqrr_sdqcr_set(p_QmPortal->p_LowQmPortal, sdqcrFlags);17931794return E_OK;1795}17961797t_Error QM_PORTAL_Poll(t_Handle h_QmPortal, e_QmPortalPollSource source)1798{1799t_QmPortal *p_QmPortal = (t_QmPortal *)h_QmPortal;18001801SANITY_CHECK_RETURN_ERROR(p_QmPortal, E_INVALID_HANDLE);18021803NCSW_PLOCK(p_QmPortal);18041805if ((source == e_QM_PORTAL_POLL_SOURCE_CONTROL_FRAMES) ||1806(source == e_QM_PORTAL_POLL_SOURCE_BOTH))1807{1808uint32_t is = qm_isr_status_read(p_QmPortal->p_LowQmPortal);1809uint32_t active = LoopMessageRing(p_QmPortal, is);1810if (active)1811qm_isr_status_clear(p_QmPortal->p_LowQmPortal, active);1812}1813if ((source == e_QM_PORTAL_POLL_SOURCE_DATA_FRAMES) ||1814(source == e_QM_PORTAL_POLL_SOURCE_BOTH))1815p_QmPortal->f_LoopDequeueRingCB((t_Handle)p_QmPortal);18161817PUNLOCK(p_QmPortal);18181819return E_OK;1820}18211822t_Error QM_PORTAL_PollFrame(t_Handle h_QmPortal, t_QmPortalFrameInfo *p_frameInfo)1823{1824t_QmPortal *p_QmPortal = (t_QmPortal *)h_QmPortal;1825struct qm_dqrr_entry *p_Dq;1826struct qman_fq *p_Fq;1827int prefetch;18281829SANITY_CHECK_RETURN_ERROR(p_QmPortal, E_INVALID_HANDLE);1830SANITY_CHECK_RETURN_ERROR(p_frameInfo, E_NULL_POINTER);18311832NCSW_PLOCK(p_QmPortal);18331834prefetch = !(p_QmPortal->options & QMAN_PORTAL_FLAG_RSTASH);1835if (prefetch)1836qmPortalDqrrPvbPrefetch(p_QmPortal->p_LowQmPortal);1837qmPortalDqrrPvbUpdate(p_QmPortal->p_LowQmPortal);1838p_Dq = qm_dqrr_current(p_QmPortal->p_LowQmPortal);1839if (!p_Dq)1840{1841PUNLOCK(p_QmPortal);1842return ERROR_CODE(E_EMPTY);1843}1844p_Fq = ptr_from_aligned_int(p_Dq->contextB);1845ASSERT_COND(p_Dq->fqid);1846if (p_Fq)1847{1848p_frameInfo->h_App = p_Fq->h_App;1849p_frameInfo->h_QmFqr = p_Fq->h_QmFqr;1850p_frameInfo->fqidOffset = p_Fq->fqidOffset;1851memcpy((void*)&p_frameInfo->frame, (void*)&p_Dq->fd, sizeof(t_DpaaFD));1852}1853else1854{1855p_frameInfo->h_App = p_QmPortal->h_App;1856p_frameInfo->h_QmFqr = NULL;1857p_frameInfo->fqidOffset = p_Dq->fqid;1858memcpy((void*)&p_frameInfo->frame, (void*)&p_Dq->fd, sizeof(t_DpaaFD));1859}1860if (p_QmPortal->options & QMAN_PORTAL_FLAG_DCA) {1861qmPortalDqrrDcaConsume1ptr(p_QmPortal->p_LowQmPortal,1862p_Dq,1863false);1864qm_dqrr_next(p_QmPortal->p_LowQmPortal);1865} else {1866qm_dqrr_next(p_QmPortal->p_LowQmPortal);1867qmPortalDqrrCciConsume(p_QmPortal->p_LowQmPortal, 1);1868}18691870PUNLOCK(p_QmPortal);18711872return E_OK;1873}187418751876t_Handle QM_FQR_Create(t_QmFqrParams *p_QmFqrParams)1877{1878t_QmFqr *p_QmFqr;1879uint32_t i, flags = 0;1880u_QmFqdContextA cnxtA;18811882SANITY_CHECK_RETURN_VALUE(p_QmFqrParams, E_INVALID_HANDLE, NULL);1883SANITY_CHECK_RETURN_VALUE(p_QmFqrParams->h_Qm, E_INVALID_HANDLE, NULL);18841885if (p_QmFqrParams->shadowMode &&1886(!p_QmFqrParams->useForce || p_QmFqrParams->numOfFqids != 1))1887{1888REPORT_ERROR(MAJOR, E_CONFLICT, ("shadowMode must be use with useForce and numOfFqids==1!!!"));1889return NULL;1890}18911892p_QmFqr = (t_QmFqr *)XX_MallocSmart(sizeof(t_QmFqr), 0, 64);1893if (!p_QmFqr)1894{1895REPORT_ERROR(MAJOR, E_NO_MEMORY, ("QM FQR obj!!!"));1896return NULL;1897}1898memset(p_QmFqr, 0, sizeof(t_QmFqr));18991900p_QmFqr->h_Qm = p_QmFqrParams->h_Qm;1901p_QmFqr->h_QmPortal = p_QmFqrParams->h_QmPortal;1902p_QmFqr->shadowMode = p_QmFqrParams->shadowMode;1903p_QmFqr->numOfFqids = (p_QmFqrParams->useForce && !p_QmFqrParams->numOfFqids) ?19041 : p_QmFqrParams->numOfFqids;19051906if (!p_QmFqr->h_QmPortal)1907{1908p_QmFqr->h_QmPortal = QmGetPortalHandle(p_QmFqr->h_Qm);1909SANITY_CHECK_RETURN_VALUE(p_QmFqr->h_QmPortal, E_INVALID_HANDLE, NULL);1910}19111912p_QmFqr->p_Fqs = (struct qman_fq **)XX_Malloc(sizeof(struct qman_fq *) * p_QmFqr->numOfFqids);1913if (!p_QmFqr->p_Fqs)1914{1915REPORT_ERROR(MAJOR, E_NO_MEMORY, ("QM FQs obj!!!"));1916QM_FQR_Free(p_QmFqr);1917return NULL;1918}1919memset(p_QmFqr->p_Fqs, 0, sizeof(struct qman_fq *) * p_QmFqr->numOfFqids);19201921if (p_QmFqr->shadowMode)1922{1923struct qman_fq *p_Fq = NULL;19241925p_QmFqr->fqidBase = p_QmFqrParams->qs.frcQ.fqid;1926p_Fq = (struct qman_fq *)XX_MallocSmart(sizeof(struct qman_fq), 0, 64);1927if (!p_Fq)1928{1929REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FQ obj!!!"));1930QM_FQR_Free(p_QmFqr);1931return NULL;1932}1933memset(p_Fq, 0, sizeof(struct qman_fq));1934p_Fq->cb.dqrr = ((t_QmPortal*)p_QmFqr->h_QmPortal)->f_DfltFrame;1935p_Fq->cb.ern = ((t_QmPortal*)p_QmFqr->h_QmPortal)->f_RejectedFrame;1936p_Fq->cb.dc_ern = cb_ern_dcErn;1937p_Fq->cb.fqs = cb_fqs;1938p_Fq->h_App = ((t_QmPortal*)p_QmFqr->h_QmPortal)->h_App;1939p_Fq->h_QmFqr = p_QmFqr;1940p_Fq->state = qman_fq_state_sched;1941p_Fq->fqid = p_QmFqr->fqidBase;1942p_QmFqr->p_Fqs[0] = p_Fq;1943}1944else1945{1946p_QmFqr->channel = p_QmFqrParams->channel;1947p_QmFqr->workQueue = p_QmFqrParams->wq;19481949p_QmFqr->fqidBase = QmFqidGet(p_QmFqr->h_Qm,1950p_QmFqr->numOfFqids,1951p_QmFqrParams->qs.nonFrcQs.align,1952p_QmFqrParams->useForce,1953p_QmFqrParams->qs.frcQ.fqid);1954if (p_QmFqr->fqidBase == (uint32_t)ILLEGAL_BASE)1955{1956REPORT_ERROR(CRITICAL,E_INVALID_STATE,("can't allocate a fqid"));1957QM_FQR_Free(p_QmFqr);1958return NULL;1959}19601961if(p_QmFqrParams->congestionAvoidanceEnable &&1962(p_QmFqrParams->congestionAvoidanceParams.h_QmCg == NULL) &&1963(p_QmFqrParams->congestionAvoidanceParams.fqTailDropThreshold == 0))1964{1965REPORT_ERROR(CRITICAL,E_INVALID_STATE,("NULL congestion group handle and no FQ Threshold"));1966QM_FQR_Free(p_QmFqr);1967return NULL;1968}1969if(p_QmFqrParams->congestionAvoidanceEnable)1970{1971if(p_QmFqrParams->congestionAvoidanceParams.h_QmCg)1972flags |= QM_FQCTRL_CGE;1973if(p_QmFqrParams->congestionAvoidanceParams.fqTailDropThreshold)1974flags |= QM_FQCTRL_TDE;1975}19761977/*1978flags |= (p_QmFqrParams->holdActive) ? QM_FQCTRL_ORP : 0;1979flags |= (p_QmFqrParams->holdActive) ? QM_FQCTRL_CPCSTASH : 0;1980flags |= (p_QmFqrParams->holdActive) ? QM_FQCTRL_FORCESFDR : 0;1981flags |= (p_QmFqrParams->holdActive) ? QM_FQCTRL_AVOIDBLOCK : 0;1982*/1983flags |= (p_QmFqrParams->holdActive) ? QM_FQCTRL_HOLDACTIVE : 0;1984flags |= (p_QmFqrParams->preferInCache) ? QM_FQCTRL_LOCKINCACHE : 0;19851986if (p_QmFqrParams->useContextAForStash)1987{1988if (CheckStashParams(p_QmFqrParams) != E_OK)1989{1990REPORT_ERROR(CRITICAL,E_INVALID_STATE,NO_MSG);1991QM_FQR_Free(p_QmFqr);1992return NULL;1993}19941995memset(&cnxtA, 0, sizeof(cnxtA));1996cnxtA.stashing.annotation_cl = DIV_CEIL(p_QmFqrParams->stashingParams.frameAnnotationSize, CACHELINE_SIZE);1997cnxtA.stashing.data_cl = DIV_CEIL(p_QmFqrParams->stashingParams.frameDataSize, CACHELINE_SIZE);1998cnxtA.stashing.context_cl = DIV_CEIL(p_QmFqrParams->stashingParams.fqContextSize, CACHELINE_SIZE);1999cnxtA.context_hi = (uint8_t)((p_QmFqrParams->stashingParams.fqContextAddr >> 32) & 0xff);2000cnxtA.context_lo = (uint32_t)(p_QmFqrParams->stashingParams.fqContextAddr);2001flags |= QM_FQCTRL_CTXASTASHING;2002}20032004for(i=0;i<p_QmFqr->numOfFqids;i++)2005if (qm_new_fq(p_QmFqr->h_QmPortal,2006p_QmFqr->fqidBase+i,2007i,2008p_QmFqr->channel,2009p_QmFqr->workQueue,20101/*p_QmFqr->numOfFqids*/,2011flags,2012(p_QmFqrParams->congestionAvoidanceEnable ?2013&p_QmFqrParams->congestionAvoidanceParams : NULL),2014p_QmFqrParams->useContextAForStash ?2015(t_QmContextA *)&cnxtA : p_QmFqrParams->p_ContextA,2016p_QmFqrParams->p_ContextB,2017p_QmFqrParams->initParked,2018p_QmFqr,2019&p_QmFqr->p_Fqs[i]) != E_OK)2020{2021QM_FQR_Free(p_QmFqr);2022return NULL;2023}2024}2025return p_QmFqr;2026}20272028t_Error QM_FQR_Free(t_Handle h_QmFqr)2029{2030t_QmFqr *p_QmFqr = (t_QmFqr *)h_QmFqr;2031uint32_t i;20322033if (!p_QmFqr)2034return ERROR_CODE(E_INVALID_HANDLE);20352036if (p_QmFqr->p_Fqs)2037{2038for (i=0;i<p_QmFqr->numOfFqids;i++)2039if (p_QmFqr->p_Fqs[i])2040{2041if (!p_QmFqr->shadowMode)2042qm_free_fq(p_QmFqr->h_QmPortal, p_QmFqr->p_Fqs[i]);2043XX_FreeSmart(p_QmFqr->p_Fqs[i]);2044}2045XX_Free(p_QmFqr->p_Fqs);2046}20472048if (!p_QmFqr->shadowMode && p_QmFqr->fqidBase)2049QmFqidPut(p_QmFqr->h_Qm, p_QmFqr->fqidBase);20502051XX_FreeSmart(p_QmFqr);20522053return E_OK;2054}20552056t_Error QM_FQR_FreeWDrain(t_Handle h_QmFqr,2057t_QmFqrDrainedCompletionCB *f_CompletionCB,2058bool deliverFrame,2059t_QmReceivedFrameCallback *f_CallBack,2060t_Handle h_App)2061{2062t_QmFqr *p_QmFqr = (t_QmFqr *)h_QmFqr;2063uint32_t i;20642065if (!p_QmFqr)2066return ERROR_CODE(E_INVALID_HANDLE);20672068if (p_QmFqr->shadowMode)2069RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("QM_FQR_FreeWDrain can't be called to shadow FQR!!!. call QM_FQR_Free"));20702071p_QmFqr->p_DrainedFqs = (bool *)XX_Malloc(sizeof(bool) * p_QmFqr->numOfFqids);2072if (!p_QmFqr->p_DrainedFqs)2073RETURN_ERROR(MAJOR, E_NO_MEMORY, ("QM Drained-FQs obj!!!. Try to Free without draining"));2074memset(p_QmFqr->p_DrainedFqs, 0, sizeof(bool) * p_QmFqr->numOfFqids);20752076if (f_CompletionCB)2077{2078p_QmFqr->f_CompletionCB = f_CompletionCB;2079p_QmFqr->h_App = h_App;2080}20812082if (deliverFrame)2083{2084if (!f_CallBack)2085{2086REPORT_ERROR(MAJOR, E_NULL_POINTER, ("f_CallBack must be given."));2087XX_Free(p_QmFqr->p_DrainedFqs);2088return ERROR_CODE(E_NULL_POINTER);2089}2090QM_FQR_RegisterCB(p_QmFqr, f_CallBack, h_App);2091}2092else2093QM_FQR_RegisterCB(p_QmFqr, drainCB, h_App);20942095for (i=0;i<p_QmFqr->numOfFqids;i++)2096{2097if (qman_retire_fq(p_QmFqr->h_QmPortal, p_QmFqr->p_Fqs[i], 0, true) != E_OK)2098RETURN_ERROR(MAJOR, E_INVALID_STATE, ("qman_retire_fq() failed!"));20992100if (p_QmFqr->p_Fqs[i]->flags & QMAN_FQ_STATE_CHANGING)2101DBG(INFO, ("fq %d currently in use, will be retired", p_QmFqr->p_Fqs[i]->fqid));2102else2103drainRetiredFq(p_QmFqr->p_Fqs[i]);2104}21052106if (!p_QmFqr->f_CompletionCB)2107{2108while(p_QmFqr->p_DrainedFqs) ;2109DBG(TRACE, ("QM-FQR with base %d completed", p_QmFqr->fqidBase));2110XX_FreeSmart(p_QmFqr->p_Fqs);2111if (p_QmFqr->fqidBase)2112QmFqidPut(p_QmFqr->h_Qm, p_QmFqr->fqidBase);2113XX_FreeSmart(p_QmFqr);2114}21152116return E_OK;2117}21182119t_Error QM_FQR_RegisterCB(t_Handle h_QmFqr, t_QmReceivedFrameCallback *f_CallBack, t_Handle h_App)2120{2121t_QmFqr *p_QmFqr = (t_QmFqr *)h_QmFqr;2122int i;21232124SANITY_CHECK_RETURN_ERROR(p_QmFqr, E_INVALID_HANDLE);21252126for (i=0;i<p_QmFqr->numOfFqids;i++)2127{2128p_QmFqr->p_Fqs[i]->cb.dqrr = f_CallBack;2129p_QmFqr->p_Fqs[i]->h_App = h_App;2130}21312132return E_OK;2133}21342135t_Error QM_FQR_Enqueue(t_Handle h_QmFqr, t_Handle h_QmPortal, uint32_t fqidOffset, t_DpaaFD *p_Frame)2136{2137t_QmFqr *p_QmFqr = (t_QmFqr *)h_QmFqr;2138t_QmPortal *p_QmPortal;2139struct qm_eqcr_entry *p_Eq;2140uint32_t *p_Dst, *p_Src;2141const struct qman_fq *p_Fq;21422143SANITY_CHECK_RETURN_ERROR(p_QmFqr, E_INVALID_HANDLE);2144SANITY_CHECK_RETURN_ERROR((fqidOffset < p_QmFqr->numOfFqids), E_INVALID_VALUE);21452146if (!h_QmPortal)2147{2148SANITY_CHECK_RETURN_ERROR(p_QmFqr->h_Qm, E_INVALID_HANDLE);2149h_QmPortal = QmGetPortalHandle(p_QmFqr->h_Qm);2150SANITY_CHECK_RETURN_ERROR(h_QmPortal, E_INVALID_HANDLE);2151}2152p_QmPortal = (t_QmPortal *)h_QmPortal;21532154p_Fq = p_QmFqr->p_Fqs[fqidOffset];21552156#ifdef QM_CHECKING2157if (p_Fq->flags & QMAN_FQ_FLAG_NO_ENQUEUE)2158RETURN_ERROR(MINOR, E_INVALID_VALUE, NO_MSG);2159if ((!(p_Fq->flags & QMAN_FQ_FLAG_NO_MODIFY)) &&2160((p_Fq->state == qman_fq_state_retired) ||2161(p_Fq->state == qman_fq_state_oos)))2162return ERROR_CODE(E_BUSY);2163#endif /* QM_CHECKING */21642165NCSW_PLOCK(p_QmPortal);2166p_Eq = try_eq_start(p_QmPortal);2167if (!p_Eq)2168{2169PUNLOCK(p_QmPortal);2170return ERROR_CODE(E_BUSY);2171}21722173p_Eq->fqid = p_Fq->fqid;2174p_Eq->tag = aligned_int_from_ptr(p_Fq);2175/* gcc does a dreadful job of the following;2176* eq->fd = *fd;2177* It causes the entire function to save/restore a wider range of2178* registers, and comes up with instruction-waste galore. This will do2179* until we can rework the function for better code-generation. */2180p_Dst = (uint32_t *)&p_Eq->fd;2181p_Src = (uint32_t *)p_Frame;2182p_Dst[0] = p_Src[0];2183p_Dst[1] = p_Src[1];2184p_Dst[2] = p_Src[2];2185p_Dst[3] = p_Src[3];21862187qmPortalEqcrPvbCommit(p_QmPortal->p_LowQmPortal,2188(uint8_t)(QM_EQCR_VERB_CMD_ENQUEUE/* |2189(flags & (QM_EQCR_VERB_COLOUR_MASK | QM_EQCR_VERB_INTERRUPT))*/));2190PUNLOCK(p_QmPortal);21912192return E_OK;2193}219421952196t_Error QM_FQR_PullFrame(t_Handle h_QmFqr, t_Handle h_QmPortal, uint32_t fqidOffset, t_DpaaFD *p_Frame)2197{2198t_QmFqr *p_QmFqr = (t_QmFqr *)h_QmFqr;2199uint32_t pdqcr = 0;22002201SANITY_CHECK_RETURN_ERROR(p_QmFqr, E_INVALID_HANDLE);2202SANITY_CHECK_RETURN_ERROR((fqidOffset < p_QmFqr->numOfFqids), E_INVALID_VALUE);2203SANITY_CHECK_RETURN_ERROR(p_Frame, E_NULL_POINTER);2204SANITY_CHECK_RETURN_ERROR((p_QmFqr->p_Fqs[fqidOffset]->state == qman_fq_state_oos) ||2205(p_QmFqr->p_Fqs[fqidOffset]->state == qman_fq_state_parked),2206E_INVALID_STATE);2207if (!h_QmPortal)2208{2209SANITY_CHECK_RETURN_ERROR(p_QmFqr->h_Qm, E_INVALID_HANDLE);2210h_QmPortal = QmGetPortalHandle(p_QmFqr->h_Qm);2211SANITY_CHECK_RETURN_ERROR(h_QmPortal, E_INVALID_HANDLE);2212}22132214pdqcr |= QM_PDQCR_MODE_UNSCHEDULED;2215pdqcr |= QM_PDQCR_FQID(p_QmFqr->p_Fqs[fqidOffset]->fqid);2216return QmPortalPullFrame(h_QmPortal, pdqcr, p_Frame);2217}22182219t_Error QM_FQR_Resume(t_Handle h_QmFqr, t_Handle h_QmPortal, uint32_t fqidOffset)2220{2221t_QmFqr *p_QmFqr = (t_QmFqr *)h_QmFqr;22222223SANITY_CHECK_RETURN_ERROR(p_QmFqr, E_INVALID_HANDLE);2224SANITY_CHECK_RETURN_ERROR((fqidOffset < p_QmFqr->numOfFqids), E_INVALID_VALUE);22252226if (!h_QmPortal)2227{2228SANITY_CHECK_RETURN_ERROR(p_QmFqr->h_Qm, E_INVALID_HANDLE);2229h_QmPortal = QmGetPortalHandle(p_QmFqr->h_Qm);2230SANITY_CHECK_RETURN_ERROR(h_QmPortal, E_INVALID_HANDLE);2231}2232return qman_schedule_fq(h_QmPortal, p_QmFqr->p_Fqs[fqidOffset]);2233}22342235t_Error QM_FQR_Suspend(t_Handle h_QmFqr, t_Handle h_QmPortal, uint32_t fqidOffset)2236{2237t_QmFqr *p_QmFqr = (t_QmFqr *)h_QmFqr;22382239SANITY_CHECK_RETURN_ERROR(p_QmFqr, E_INVALID_HANDLE);2240SANITY_CHECK_RETURN_ERROR((fqidOffset < p_QmFqr->numOfFqids), E_INVALID_VALUE);2241SANITY_CHECK_RETURN_ERROR((p_QmFqr->p_Fqs[fqidOffset]->flags & QM_FQCTRL_HOLDACTIVE), E_INVALID_STATE);22422243UNUSED(h_QmPortal);2244p_QmFqr->p_Fqs[fqidOffset]->state = qman_fq_state_waiting_parked;22452246return E_OK;2247}22482249uint32_t QM_FQR_GetFqid(t_Handle h_QmFqr)2250{2251t_QmFqr *p_QmFqr = (t_QmFqr *)h_QmFqr;22522253SANITY_CHECK_RETURN_VALUE(p_QmFqr, E_INVALID_HANDLE, 0);22542255return p_QmFqr->fqidBase;2256}22572258uint32_t QM_FQR_GetCounter(t_Handle h_QmFqr, t_Handle h_QmPortal, uint32_t fqidOffset, e_QmFqrCounters counter)2259{2260t_QmFqr *p_QmFqr = (t_QmFqr *)h_QmFqr;2261struct qm_mcr_queryfq_np queryfq_np;22622263SANITY_CHECK_RETURN_VALUE(p_QmFqr, E_INVALID_HANDLE, 0);2264SANITY_CHECK_RETURN_VALUE((fqidOffset < p_QmFqr->numOfFqids), E_INVALID_VALUE, 0);22652266if (!h_QmPortal)2267{2268SANITY_CHECK_RETURN_VALUE(p_QmFqr->h_Qm, E_INVALID_HANDLE, 0);2269h_QmPortal = QmGetPortalHandle(p_QmFqr->h_Qm);2270SANITY_CHECK_RETURN_VALUE(h_QmPortal, E_INVALID_HANDLE, 0);2271}2272if (qman_query_fq_np(h_QmPortal, p_QmFqr->p_Fqs[fqidOffset], &queryfq_np) != E_OK)2273return 0;2274switch (counter)2275{2276case e_QM_FQR_COUNTERS_FRAME :2277return queryfq_np.frm_cnt;2278case e_QM_FQR_COUNTERS_BYTE :2279return queryfq_np.byte_cnt;2280default :2281break;2282}2283/* should never get here */2284ASSERT_COND(FALSE);22852286return 0;2287}228822892290t_Handle QM_CG_Create(t_QmCgParams *p_CgParams)2291{2292t_QmCg *p_QmCg;2293t_QmPortal *p_QmPortal;2294t_Error err;2295uint32_t wredParams;2296uint32_t tmpA, tmpN, ta=0, tn=0;2297int gap, tmp;2298struct qm_mc_command *p_Mcc;2299struct qm_mc_result *p_Mcr;23002301SANITY_CHECK_RETURN_VALUE(p_CgParams, E_INVALID_HANDLE, NULL);2302SANITY_CHECK_RETURN_VALUE(p_CgParams->h_Qm, E_INVALID_HANDLE, NULL);23032304if(p_CgParams->notifyDcPortal &&2305((p_CgParams->dcPortalId == e_DPAA_DCPORTAL2) || (p_CgParams->dcPortalId == e_DPAA_DCPORTAL3)))2306{2307REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("notifyDcPortal is invalid for this DC Portal"));2308return NULL;2309}23102311if (!p_CgParams->h_QmPortal)2312{2313p_QmPortal = QmGetPortalHandle(p_CgParams->h_Qm);2314SANITY_CHECK_RETURN_VALUE(p_QmPortal, E_INVALID_STATE, NULL);2315}2316else2317p_QmPortal = p_CgParams->h_QmPortal;23182319p_QmCg = (t_QmCg *)XX_Malloc(sizeof(t_QmCg));2320if (!p_QmCg)2321{2322REPORT_ERROR(MAJOR, E_NO_MEMORY, ("QM CG obj!!!"));2323return NULL;2324}2325memset(p_QmCg, 0, sizeof(t_QmCg));23262327/* build CG struct */2328p_QmCg->h_Qm = p_CgParams->h_Qm;2329p_QmCg->h_QmPortal = p_QmPortal;2330p_QmCg->h_App = p_CgParams->h_App;2331err = QmGetCgId(p_CgParams->h_Qm, &p_QmCg->id);2332if (err)2333{2334XX_Free(p_QmCg);2335REPORT_ERROR(MAJOR, E_INVALID_STATE, ("QmGetCgId failed"));2336return NULL;2337}23382339NCSW_PLOCK(p_QmPortal);2340p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal);2341p_Mcc->initcgr.cgid = p_QmCg->id;23422343err = QmPortalRegisterCg(p_QmPortal, p_QmCg, p_QmCg->id);2344if (err)2345{2346XX_Free(p_QmCg);2347PUNLOCK(p_QmPortal);2348REPORT_ERROR(MAJOR, E_INVALID_STATE, ("QmPortalRegisterCg failed"));2349return NULL;2350}23512352/* Build CGR command */2353{2354#ifdef QM_CGS_NO_FRAME_MODE2355t_QmRevisionInfo revInfo;23562357QmGetRevision(p_QmCg->h_Qm, &revInfo);23582359if (!((revInfo.majorRev == 1) && (revInfo.minorRev == 0)))2360#endif /* QM_CGS_NO_FRAME_MODE */2361if (p_CgParams->frameCount)2362{2363p_Mcc->initcgr.we_mask |= QM_CGR_WE_MODE;2364p_Mcc->initcgr.cgr.frame_mode = QM_CGR_EN;2365}2366}23672368if (p_CgParams->wredEnable)2369{2370if (p_CgParams->wredParams.enableGreen)2371{2372err = CalcWredCurve(&p_CgParams->wredParams.greenCurve, &wredParams);2373if(err)2374{2375XX_Free(p_QmCg);2376PUNLOCK(p_QmPortal);2377REPORT_ERROR(MAJOR, err, NO_MSG);2378return NULL;2379}2380p_Mcc->initcgr.we_mask |= QM_CGR_WE_WR_EN_G | QM_CGR_WE_WR_PARM_G;2381p_Mcc->initcgr.cgr.wr_en_g = QM_CGR_EN;2382p_Mcc->initcgr.cgr.wr_parm_g.word = wredParams;2383}2384if (p_CgParams->wredParams.enableYellow)2385{2386err = CalcWredCurve(&p_CgParams->wredParams.yellowCurve, &wredParams);2387if(err)2388{2389XX_Free(p_QmCg);2390PUNLOCK(p_QmPortal);2391REPORT_ERROR(MAJOR, err, NO_MSG);2392return NULL;2393}2394p_Mcc->initcgr.we_mask |= QM_CGR_WE_WR_EN_Y | QM_CGR_WE_WR_PARM_Y;2395p_Mcc->initcgr.cgr.wr_en_y = QM_CGR_EN;2396p_Mcc->initcgr.cgr.wr_parm_y.word = wredParams;2397}2398if (p_CgParams->wredParams.enableRed)2399{2400err = CalcWredCurve(&p_CgParams->wredParams.redCurve, &wredParams);2401if(err)2402{2403XX_Free(p_QmCg);2404PUNLOCK(p_QmPortal);2405REPORT_ERROR(MAJOR, err, NO_MSG);2406return NULL;2407}2408p_Mcc->initcgr.we_mask |= QM_CGR_WE_WR_EN_R | QM_CGR_WE_WR_PARM_R;2409p_Mcc->initcgr.cgr.wr_en_r = QM_CGR_EN;2410p_Mcc->initcgr.cgr.wr_parm_r.word = wredParams;2411}2412}24132414if (p_CgParams->tailDropEnable)2415{2416if (!p_CgParams->threshold)2417{2418XX_Free(p_QmCg);2419PUNLOCK(p_QmPortal);2420REPORT_ERROR(MINOR, E_INVALID_STATE, ("tailDropThreshold must be configured if tailDropEnable "));2421return NULL;2422}2423p_Mcc->initcgr.cgr.cstd_en = QM_CGR_EN;2424p_Mcc->initcgr.we_mask |= QM_CGR_WE_CSTD_EN;2425}24262427if (p_CgParams->threshold)2428{2429p_Mcc->initcgr.we_mask |= QM_CGR_WE_CS_THRES;2430p_QmCg->f_Exception = p_CgParams->f_Exception;2431if (p_QmCg->f_Exception || p_CgParams->notifyDcPortal)2432{2433p_Mcc->initcgr.cgr.cscn_en = QM_CGR_EN;2434p_Mcc->initcgr.we_mask |= QM_CGR_WE_CSCN_EN | QM_CGR_WE_CSCN_TARG;2435/* if SW - set target, if HW - if FM, set HW target, otherwize, set SW target */2436p_Mcc->initcgr.cgr.cscn_targ = 0;2437if (p_QmCg->f_Exception)2438p_Mcc->initcgr.cgr.cscn_targ = (uint32_t)QM_CGR_TARGET_SWP(QmPortalGetSwPortalId(p_QmCg->h_QmPortal));2439if (p_CgParams->notifyDcPortal)2440p_Mcc->initcgr.cgr.cscn_targ |= (uint32_t)QM_CGR_TARGET_DCP(p_CgParams->dcPortalId);2441}24422443/* express thresh as ta*2^tn */2444gap = (int)p_CgParams->threshold;2445for (tmpA=0 ; tmpA<256; tmpA++ )2446for (tmpN=0 ; tmpN<32; tmpN++ )2447{2448tmp = ABS((int)(p_CgParams->threshold - tmpA*(1<<tmpN)));2449if (tmp < gap)2450{2451ta = tmpA;2452tn = tmpN;2453gap = tmp;2454}2455}2456p_Mcc->initcgr.cgr.cs_thres.TA = ta;2457p_Mcc->initcgr.cgr.cs_thres.Tn = tn;2458}2459else if(p_CgParams->f_Exception)2460{2461XX_Free(p_QmCg);2462PUNLOCK(p_QmPortal);2463REPORT_ERROR(MINOR, E_INVALID_STATE, ("No threshold configured, but f_Exception defined"));2464return NULL;2465}24662467qm_mc_commit(p_QmPortal->p_LowQmPortal, QM_MCC_VERB_INITCGR);2468while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ;2469ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) == QM_MCC_VERB_INITCGR);2470if (p_Mcr->result != QM_MCR_RESULT_OK)2471{2472XX_Free(p_QmCg);2473PUNLOCK(p_QmPortal);2474REPORT_ERROR(MINOR, E_INVALID_STATE, ("INITCGR failed: %s", mcr_result_str(p_Mcr->result)));2475return NULL;2476}2477PUNLOCK(p_QmPortal);24782479return p_QmCg;2480}24812482t_Error QM_CG_Free(t_Handle h_QmCg)2483{24842485t_QmCg *p_QmCg = (t_QmCg *)h_QmCg;2486t_Error err;2487struct qm_mc_command *p_Mcc;2488struct qm_mc_result *p_Mcr;2489t_QmPortal *p_QmPortal;24902491SANITY_CHECK_RETURN_ERROR(p_QmCg, E_INVALID_HANDLE);24922493p_QmPortal = (t_QmPortal *)p_QmCg->h_QmPortal;24942495NCSW_PLOCK(p_QmPortal);2496p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal);2497p_Mcc->initcgr.cgid = p_QmCg->id;2498p_Mcc->initcgr.we_mask = QM_CGR_WE_MASK;24992500err = QmFreeCgId(p_QmCg->h_Qm, p_QmCg->id);2501if(err)2502{2503XX_Free(p_QmCg);2504PUNLOCK(p_QmPortal);2505RETURN_ERROR(MAJOR, E_INVALID_STATE, ("QmFreeCgId failed"));2506}25072508err = QmPortalUnregisterCg(p_QmCg->h_QmPortal, p_QmCg->id);2509if(err)2510{2511XX_Free(p_QmCg);2512PUNLOCK(p_QmPortal);2513RETURN_ERROR(MAJOR, E_INVALID_STATE, ("QmPortalUnregisterCg failed"));2514}25152516qm_mc_commit(p_QmPortal->p_LowQmPortal, QM_MCC_VERB_MODIFYCGR);2517while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ;2518ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) == QM_MCC_VERB_MODIFYCGR);2519if (p_Mcr->result != QM_MCR_RESULT_OK)2520{2521PUNLOCK(p_QmPortal);2522RETURN_ERROR(MINOR, E_INVALID_STATE, ("INITCGR failed: %s", mcr_result_str(p_Mcr->result)));2523}2524PUNLOCK(p_QmPortal);25252526XX_Free(p_QmCg);25272528return E_OK;2529}25302531t_Error QM_CG_SetException(t_Handle h_QmCg, e_QmExceptions exception, bool enable)2532{2533t_QmCg *p_QmCg = (t_QmCg *)h_QmCg;2534struct qm_mc_command *p_Mcc;2535struct qm_mc_result *p_Mcr;2536t_QmPortal *p_QmPortal;25372538SANITY_CHECK_RETURN_ERROR(p_QmCg, E_INVALID_HANDLE);25392540p_QmPortal = (t_QmPortal *)p_QmCg->h_QmPortal;2541if (!p_QmCg->f_Exception)2542RETURN_ERROR(MINOR, E_INVALID_VALUE, ("Either threshold or exception callback was not configured."));25432544NCSW_PLOCK(p_QmPortal);2545p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal);2546p_Mcc->initcgr.cgid = p_QmCg->id;2547p_Mcc->initcgr.we_mask = QM_CGR_WE_CSCN_EN;25482549if(exception == e_QM_EX_CG_STATE_CHANGE)2550{2551if(enable)2552p_Mcc->initcgr.cgr.cscn_en = QM_CGR_EN;2553}2554else2555{2556PUNLOCK(p_QmPortal);2557RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal exception"));2558}25592560qm_mc_commit(p_QmPortal->p_LowQmPortal, QM_MCC_VERB_MODIFYCGR);2561while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ;2562ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) == QM_MCC_VERB_MODIFYCGR);2563if (p_Mcr->result != QM_MCR_RESULT_OK)2564{2565PUNLOCK(p_QmPortal);2566RETURN_ERROR(MINOR, E_INVALID_STATE, ("INITCGR failed: %s", mcr_result_str(p_Mcr->result)));2567}2568PUNLOCK(p_QmPortal);25692570return E_OK;2571}25722573t_Error QM_CG_ModifyWredCurve(t_Handle h_QmCg, t_QmCgModifyWredParams *p_QmCgModifyParams)2574{2575t_QmCg *p_QmCg = (t_QmCg *)h_QmCg;2576uint32_t wredParams;2577struct qm_mc_command *p_Mcc;2578struct qm_mc_result *p_Mcr;2579t_QmPortal *p_QmPortal;2580t_Error err = E_OK;25812582SANITY_CHECK_RETURN_ERROR(p_QmCg, E_INVALID_HANDLE);25832584p_QmPortal = (t_QmPortal *)p_QmCg->h_QmPortal;25852586NCSW_PLOCK(p_QmPortal);2587p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal);2588p_Mcc->initcgr.cgid = p_QmCg->id;25892590qm_mc_commit(p_QmPortal->p_LowQmPortal, QM_MCC_VERB_QUERYCGR);2591while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ;2592ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) == QM_MCC_VERB_QUERYCGR);2593if (p_Mcr->result != QM_MCR_RESULT_OK)2594{2595PUNLOCK(p_QmPortal);2596RETURN_ERROR(MINOR, E_INVALID_STATE, ("QM_MCC_VERB_QUERYCGR failed: %s", mcr_result_str(p_Mcr->result)));2597}25982599switch(p_QmCgModifyParams->color)2600{2601case(e_QM_CG_COLOR_GREEN):2602if(!p_Mcr->querycgr.cgr.wr_en_g)2603{2604PUNLOCK(p_QmPortal);2605RETURN_ERROR(MINOR, E_INVALID_STATE, ("WRED is not enabled for green"));2606}2607break;2608case(e_QM_CG_COLOR_YELLOW):2609if(!p_Mcr->querycgr.cgr.wr_en_y)2610{2611PUNLOCK(p_QmPortal);2612RETURN_ERROR(MINOR, E_INVALID_STATE, ("WRED is not enabled for yellow"));2613}2614break;2615case(e_QM_CG_COLOR_RED):2616if(!p_Mcr->querycgr.cgr.wr_en_r)2617{2618PUNLOCK(p_QmPortal);2619RETURN_ERROR(MINOR, E_INVALID_STATE, ("WRED is not enabled for red"));2620}2621break;2622}26232624p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal);2625p_Mcc->initcgr.cgid = p_QmCg->id;26262627switch(p_QmCgModifyParams->color)2628{2629case(e_QM_CG_COLOR_GREEN):2630err = CalcWredCurve(&p_QmCgModifyParams->wredParams, &wredParams);2631p_Mcc->initcgr.we_mask |= QM_CGR_WE_WR_EN_G | QM_CGR_WE_WR_PARM_G;2632p_Mcc->initcgr.cgr.wr_en_g = QM_CGR_EN;2633p_Mcc->initcgr.cgr.wr_parm_g.word = wredParams;2634break;2635case(e_QM_CG_COLOR_YELLOW):2636err = CalcWredCurve(&p_QmCgModifyParams->wredParams, &wredParams);2637p_Mcc->initcgr.we_mask |= QM_CGR_WE_WR_EN_Y | QM_CGR_WE_WR_PARM_Y;2638p_Mcc->initcgr.cgr.wr_en_y = QM_CGR_EN;2639p_Mcc->initcgr.cgr.wr_parm_y.word = wredParams;2640break;2641case(e_QM_CG_COLOR_RED):2642err = CalcWredCurve(&p_QmCgModifyParams->wredParams, &wredParams);2643p_Mcc->initcgr.we_mask |= QM_CGR_WE_WR_EN_R | QM_CGR_WE_WR_PARM_R;2644p_Mcc->initcgr.cgr.wr_en_r = QM_CGR_EN;2645p_Mcc->initcgr.cgr.wr_parm_r.word = wredParams;2646break;2647}2648if (err)2649{2650PUNLOCK(p_QmPortal);2651RETURN_ERROR(MINOR, err, NO_MSG);2652}26532654qm_mc_commit(p_QmPortal->p_LowQmPortal, QM_MCC_VERB_MODIFYCGR);2655while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ;2656ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) == QM_MCC_VERB_MODIFYCGR);2657if (p_Mcr->result != QM_MCR_RESULT_OK)2658{2659PUNLOCK(p_QmPortal);2660RETURN_ERROR(MINOR, E_INVALID_STATE, ("INITCGR failed: %s", mcr_result_str(p_Mcr->result)));2661}2662PUNLOCK(p_QmPortal);26632664return E_OK;2665}26662667t_Error QM_CG_ModifyTailDropThreshold(t_Handle h_QmCg, uint32_t threshold)2668{2669t_QmCg *p_QmCg = (t_QmCg *)h_QmCg;2670struct qm_mc_command *p_Mcc;2671struct qm_mc_result *p_Mcr;2672t_QmPortal *p_QmPortal;2673uint32_t tmpA, tmpN, ta=0, tn=0;2674int gap, tmp;26752676SANITY_CHECK_RETURN_ERROR(p_QmCg, E_INVALID_HANDLE);26772678p_QmPortal = (t_QmPortal *)p_QmCg->h_QmPortal;26792680NCSW_PLOCK(p_QmPortal);2681p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal);2682p_Mcc->initcgr.cgid = p_QmCg->id;26832684qm_mc_commit(p_QmPortal->p_LowQmPortal, QM_MCC_VERB_QUERYCGR);2685while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ;2686ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) == QM_MCC_VERB_QUERYCGR);2687if (p_Mcr->result != QM_MCR_RESULT_OK)2688{2689PUNLOCK(p_QmPortal);2690RETURN_ERROR(MINOR, E_INVALID_STATE, ("QM_MCC_VERB_QUERYCGR failed: %s", mcr_result_str(p_Mcr->result)));2691}26922693if(!p_Mcr->querycgr.cgr.cstd_en)2694{2695PUNLOCK(p_QmPortal);2696RETURN_ERROR(MINOR, E_INVALID_STATE, ("Tail Drop is not enabled!"));2697}26982699p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal);2700p_Mcc->initcgr.cgid = p_QmCg->id;2701p_Mcc->initcgr.we_mask |= QM_CGR_WE_CS_THRES;27022703/* express thresh as ta*2^tn */2704gap = (int)threshold;2705for (tmpA=0 ; tmpA<256; tmpA++ )2706for (tmpN=0 ; tmpN<32; tmpN++ )2707{2708tmp = ABS((int)(threshold - tmpA*(1<<tmpN)));2709if (tmp < gap)2710{2711ta = tmpA;2712tn = tmpN;2713gap = tmp;2714}2715}2716p_Mcc->initcgr.cgr.cs_thres.TA = ta;2717p_Mcc->initcgr.cgr.cs_thres.Tn = tn;27182719qm_mc_commit(p_QmPortal->p_LowQmPortal, QM_MCC_VERB_MODIFYCGR);2720while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ;2721ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) == QM_MCC_VERB_MODIFYCGR);2722if (p_Mcr->result != QM_MCR_RESULT_OK)2723{2724PUNLOCK(p_QmPortal);2725RETURN_ERROR(MINOR, E_INVALID_STATE, ("INITCGR failed: %s", mcr_result_str(p_Mcr->result)));2726}2727PUNLOCK(p_QmPortal);27282729return E_OK;2730}2731273227332734