1/******************************************************************************
2
3 � 1995-2003, 2004, 2005-2011 Freescale Semiconductor, Inc.
4 All rights reserved.
5
6 This is proprietary source code of Freescale Semiconductor Inc.,
7 and its use is subject to the NetComm Device Drivers EULA.
8 The copyright notice above does not evidence any actual or intended
9 publication of such source code.
10
11 ALTERNATIVELY, redistribution and use in source and binary forms, with
12 or without modification, are permitted provided that the following
13 conditions are met:
14     * Redistributions of source code must retain the above copyright
15       notice, this list of conditions and the following disclaimer.
16     * Redistributions in binary form must reproduce the above copyright
17       notice, this list of conditions and the following disclaimer in the
18       documentation and/or other materials provided with the distribution.
19     * Neither the name of Freescale Semiconductor nor the
20       names of its contributors may be used to endorse or promote products
21       derived from this software without specific prior written permission.
22
23 THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
24 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
27 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 *
34
35 **************************************************************************/
36/******************************************************************************
37 @File          qm.c
38
39 @Description   QM & Portal implementation
40*//***************************************************************************/
41#include <sys/cdefs.h>
42#include <sys/types.h>
43#include <machine/atomic.h>
44
45#include "error_ext.h"
46#include "std_ext.h"
47#include "string_ext.h"
48#include "mm_ext.h"
49#include "qm.h"
50#include "qman_low.h"
51
52#include <machine/vmparam.h>
53
54/****************************************/
55/*       static functions               */
56/****************************************/
57
58#define SLOW_POLL_IDLE   1000
59#define SLOW_POLL_BUSY   10
60
61/*
62 * Context entries are 32-bit.  The qman driver uses the pointer to the queue as
63 * its context, and the pointer is 64-byte aligned, per the XX_MallocSmart()
64 * call.  Take advantage of this fact to shove a 64-bit kernel pointer into a
65 * 32-bit context integer, and back.
66 *
67 * XXX: This depends on the fact that VM_MAX_KERNEL_ADDRESS is less than 38-bit
68 * count from VM_MIN_KERNEL_ADDRESS.  If this ever changes, this needs to be
69 * updated.
70 */
71CTASSERT((VM_MAX_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS) < (1ULL << 35));
72static inline uint32_t
73aligned_int_from_ptr(const void *p)
74{
75	uintptr_t ctx;
76
77	ctx = (uintptr_t)p;
78	KASSERT(ctx >= VM_MIN_KERNEL_ADDRESS, ("%p is too low!\n", p));
79	ctx -= VM_MIN_KERNEL_ADDRESS;
80	KASSERT((ctx & 0x07) == 0, ("Pointer %p is not 8-byte aligned!\n", p));
81
82	return (ctx >> 3);
83}
84
85static inline void *
86ptr_from_aligned_int(uint32_t ctx)
87{
88	uintptr_t p;
89
90	p = ctx;
91	p = VM_MIN_KERNEL_ADDRESS + (p << 3);
92
93	return ((void *)p);
94}
95
96static t_Error qman_volatile_dequeue(t_QmPortal     *p_QmPortal,
97                                     struct qman_fq *p_Fq,
98                                     uint32_t       vdqcr)
99{
100    ASSERT_COND((p_Fq->state == qman_fq_state_parked) ||
101                (p_Fq->state == qman_fq_state_retired));
102    ASSERT_COND(!(vdqcr & QM_VDQCR_FQID_MASK));
103    ASSERT_COND(!(p_Fq->flags & QMAN_FQ_STATE_VDQCR));
104
105    vdqcr = (vdqcr & ~QM_VDQCR_FQID_MASK) | p_Fq->fqid;
106    NCSW_PLOCK(p_QmPortal);
107    FQLOCK(p_Fq);
108    p_Fq->flags |= QMAN_FQ_STATE_VDQCR;
109    qm_dqrr_vdqcr_set(p_QmPortal->p_LowQmPortal, vdqcr);
110    FQUNLOCK(p_Fq);
111    PUNLOCK(p_QmPortal);
112
113    return E_OK;
114}
115
116static const char *mcr_result_str(uint8_t result)
117{
118    switch (result) {
119    case QM_MCR_RESULT_NULL:
120        return "QM_MCR_RESULT_NULL";
121    case QM_MCR_RESULT_OK:
122        return "QM_MCR_RESULT_OK";
123    case QM_MCR_RESULT_ERR_FQID:
124        return "QM_MCR_RESULT_ERR_FQID";
125    case QM_MCR_RESULT_ERR_FQSTATE:
126        return "QM_MCR_RESULT_ERR_FQSTATE";
127    case QM_MCR_RESULT_ERR_NOTEMPTY:
128        return "QM_MCR_RESULT_ERR_NOTEMPTY";
129    case QM_MCR_RESULT_PENDING:
130        return "QM_MCR_RESULT_PENDING";
131    }
132    return "<unknown MCR result>";
133}
134
135static t_Error qman_create_fq(t_QmPortal        *p_QmPortal,
136                              uint32_t          fqid,
137                              uint32_t          flags,
138                              struct qman_fq    *p_Fq)
139{
140    struct qm_fqd fqd;
141    struct qm_mcr_queryfq_np np;
142    struct qm_mc_command *p_Mcc;
143    struct qm_mc_result *p_Mcr;
144
145    p_Fq->fqid = fqid;
146    p_Fq->flags = flags;
147    p_Fq->state = qman_fq_state_oos;
148    p_Fq->cgr_groupid = 0;
149    if (!(flags & QMAN_FQ_FLAG_RECOVER) ||
150            (flags & QMAN_FQ_FLAG_NO_MODIFY))
151        return E_OK;
152    /* Everything else is RECOVER support */
153    NCSW_PLOCK(p_QmPortal);
154    p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal);
155    p_Mcc->queryfq.fqid = fqid;
156    qm_mc_commit(p_QmPortal->p_LowQmPortal, QM_MCC_VERB_QUERYFQ);
157    while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ;
158    ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) == QM_MCC_VERB_QUERYFQ);
159    if (p_Mcr->result != QM_MCR_RESULT_OK) {
160        PUNLOCK(p_QmPortal);
161        RETURN_ERROR(MAJOR, E_INVALID_STATE, ("QUERYFQ failed: %s", mcr_result_str(p_Mcr->result)));
162    }
163    fqd = p_Mcr->queryfq.fqd;
164    p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal);
165    p_Mcc->queryfq_np.fqid = fqid;
166    qm_mc_commit(p_QmPortal->p_LowQmPortal, QM_MCC_VERB_QUERYFQ_NP);
167    while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ;
168    ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) == QM_MCC_VERB_QUERYFQ_NP);
169    if (p_Mcr->result != QM_MCR_RESULT_OK) {
170        PUNLOCK(p_QmPortal);
171        RETURN_ERROR(MAJOR, E_INVALID_STATE, ("UERYFQ_NP failed: %s", mcr_result_str(p_Mcr->result)));
172    }
173    np = p_Mcr->queryfq_np;
174    /* Phew, have queryfq and queryfq_np results, stitch together
175     * the FQ object from those. */
176    p_Fq->cgr_groupid = fqd.cgid;
177    switch (np.state & QM_MCR_NP_STATE_MASK) {
178    case QM_MCR_NP_STATE_OOS:
179        break;
180    case QM_MCR_NP_STATE_RETIRED:
181        p_Fq->state = qman_fq_state_retired;
182        if (np.frm_cnt)
183            p_Fq->flags |= QMAN_FQ_STATE_NE;
184        break;
185    case QM_MCR_NP_STATE_TEN_SCHED:
186    case QM_MCR_NP_STATE_TRU_SCHED:
187    case QM_MCR_NP_STATE_ACTIVE:
188        p_Fq->state = qman_fq_state_sched;
189        if (np.state & QM_MCR_NP_STATE_R)
190            p_Fq->flags |= QMAN_FQ_STATE_CHANGING;
191        break;
192    case QM_MCR_NP_STATE_PARKED:
193        p_Fq->state = qman_fq_state_parked;
194        break;
195    default:
196        ASSERT_COND(FALSE);
197    }
198    if (fqd.fq_ctrl & QM_FQCTRL_CGE)
199        p_Fq->state |= QMAN_FQ_STATE_CGR_EN;
200    PUNLOCK(p_QmPortal);
201
202    return E_OK;
203}
204
205static void qman_destroy_fq(struct qman_fq *p_Fq, uint32_t flags)
206{
207    /* We don't need to lock the FQ as it is a pre-condition that the FQ be
208     * quiesced. Instead, run some checks. */
209    UNUSED(flags);
210    switch (p_Fq->state) {
211    case qman_fq_state_parked:
212        ASSERT_COND(flags & QMAN_FQ_DESTROY_PARKED);
213    case qman_fq_state_oos:
214        return;
215    default:
216        break;
217    }
218    ASSERT_COND(FALSE);
219}
220
221static t_Error qman_init_fq(t_QmPortal          *p_QmPortal,
222                            struct qman_fq      *p_Fq,
223                            uint32_t            flags,
224                            struct qm_mcc_initfq *p_Opts)
225{
226    struct qm_mc_command    *p_Mcc;
227    struct qm_mc_result     *p_Mcr;
228    uint8_t res, myverb = (uint8_t)((flags & QMAN_INITFQ_FLAG_SCHED) ?
229        QM_MCC_VERB_INITFQ_SCHED : QM_MCC_VERB_INITFQ_PARKED);
230
231    SANITY_CHECK_RETURN_ERROR((p_Fq->state == qman_fq_state_oos) ||
232                              (p_Fq->state == qman_fq_state_parked),
233                              E_INVALID_STATE);
234
235    if (p_Fq->flags & QMAN_FQ_FLAG_NO_MODIFY)
236        return ERROR_CODE(E_INVALID_VALUE);
237    /* Issue an INITFQ_[PARKED|SCHED] management command */
238    NCSW_PLOCK(p_QmPortal);
239    FQLOCK(p_Fq);
240    if ((p_Fq->flags & QMAN_FQ_STATE_CHANGING) ||
241            ((p_Fq->state != qman_fq_state_oos) &&
242                (p_Fq->state != qman_fq_state_parked))) {
243        FQUNLOCK(p_Fq);
244        PUNLOCK(p_QmPortal);
245        return ERROR_CODE(E_BUSY);
246    }
247    p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal);
248    Mem2IOCpy32((void*)&p_Mcc->initfq, p_Opts, sizeof(struct qm_mcc_initfq));
249    qm_mc_commit(p_QmPortal->p_LowQmPortal, myverb);
250    while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ;
251    ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) == myverb);
252    res = p_Mcr->result;
253    if (res != QM_MCR_RESULT_OK) {
254        FQUNLOCK(p_Fq);
255        PUNLOCK(p_QmPortal);
256        RETURN_ERROR(MINOR, E_INVALID_STATE,("INITFQ failed: %s", mcr_result_str(res)));
257    }
258
259    if (p_Mcc->initfq.we_mask & QM_INITFQ_WE_FQCTRL) {
260        if (p_Mcc->initfq.fqd.fq_ctrl & QM_FQCTRL_CGE)
261            p_Fq->flags |= QMAN_FQ_STATE_CGR_EN;
262        else
263            p_Fq->flags &= ~QMAN_FQ_STATE_CGR_EN;
264    }
265    if (p_Mcc->initfq.we_mask & QM_INITFQ_WE_CGID)
266        p_Fq->cgr_groupid = p_Mcc->initfq.fqd.cgid;
267    p_Fq->state = (flags & QMAN_INITFQ_FLAG_SCHED) ?
268            qman_fq_state_sched : qman_fq_state_parked;
269    FQUNLOCK(p_Fq);
270    PUNLOCK(p_QmPortal);
271    return E_OK;
272}
273
274static t_Error qman_retire_fq(t_QmPortal        *p_QmPortal,
275                              struct qman_fq    *p_Fq,
276                              uint32_t          *p_Flags,
277                              bool              drain)
278{
279    struct qm_mc_command    *p_Mcc;
280    struct qm_mc_result     *p_Mcr;
281    t_Error                 err = E_OK;
282    uint8_t                 res;
283
284    SANITY_CHECK_RETURN_ERROR((p_Fq->state == qman_fq_state_parked) ||
285                              (p_Fq->state == qman_fq_state_sched),
286                              E_INVALID_STATE);
287
288    if (p_Fq->flags & QMAN_FQ_FLAG_NO_MODIFY)
289        return E_INVALID_VALUE;
290    NCSW_PLOCK(p_QmPortal);
291    FQLOCK(p_Fq);
292    if ((p_Fq->flags & QMAN_FQ_STATE_CHANGING) ||
293            (p_Fq->state == qman_fq_state_retired) ||
294                (p_Fq->state == qman_fq_state_oos)) {
295        err = E_BUSY;
296        goto out;
297    }
298    p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal);
299    p_Mcc->alterfq.fqid = p_Fq->fqid;
300    if (drain)
301        p_Mcc->alterfq.context_b = aligned_int_from_ptr(p_Fq);
302    qm_mc_commit(p_QmPortal->p_LowQmPortal,
303                 (uint8_t)((drain)?QM_MCC_VERB_ALTER_RETIRE_CTXB:QM_MCC_VERB_ALTER_RETIRE));
304    while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ;
305    ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) ==
306                (drain)?QM_MCR_VERB_ALTER_RETIRE_CTXB:QM_MCR_VERB_ALTER_RETIRE);
307    res = p_Mcr->result;
308    if (res == QM_MCR_RESULT_OK)
309    {
310        /* Process 'fq' right away, we'll ignore FQRNI */
311        if (p_Mcr->alterfq.fqs & QM_MCR_FQS_NOTEMPTY)
312            p_Fq->flags |= QMAN_FQ_STATE_NE;
313        if (p_Mcr->alterfq.fqs & QM_MCR_FQS_ORLPRESENT)
314            p_Fq->flags |= QMAN_FQ_STATE_ORL;
315        p_Fq->state = qman_fq_state_retired;
316    }
317    else if (res == QM_MCR_RESULT_PENDING)
318        p_Fq->flags |= QMAN_FQ_STATE_CHANGING;
319    else {
320        XX_Print("ALTER_RETIRE failed: %s\n",
321                mcr_result_str(res));
322        err = E_INVALID_STATE;
323    }
324    if (p_Flags)
325        *p_Flags = p_Fq->flags;
326out:
327    FQUNLOCK(p_Fq);
328    PUNLOCK(p_QmPortal);
329    return err;
330}
331
332static t_Error qman_oos_fq(t_QmPortal *p_QmPortal, struct qman_fq *p_Fq)
333{
334    struct qm_mc_command    *p_Mcc;
335    struct qm_mc_result     *p_Mcr;
336    uint8_t                 res;
337
338    ASSERT_COND(p_Fq->state == qman_fq_state_retired);
339    if (p_Fq->flags & QMAN_FQ_FLAG_NO_MODIFY)
340        return ERROR_CODE(E_INVALID_VALUE);
341    NCSW_PLOCK(p_QmPortal);
342    FQLOCK(p_Fq);
343    if ((p_Fq->flags & QMAN_FQ_STATE_BLOCKOOS) ||
344            (p_Fq->state != qman_fq_state_retired)) {
345        FQUNLOCK(p_Fq);
346        PUNLOCK(p_QmPortal);
347        return ERROR_CODE(E_BUSY);
348    }
349    p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal);
350    p_Mcc->alterfq.fqid = p_Fq->fqid;
351    qm_mc_commit(p_QmPortal->p_LowQmPortal, QM_MCC_VERB_ALTER_OOS);
352    while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ;
353    ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) == QM_MCR_VERB_ALTER_OOS);
354    res = p_Mcr->result;
355    if (res != QM_MCR_RESULT_OK) {
356        FQUNLOCK(p_Fq);
357        PUNLOCK(p_QmPortal);
358        RETURN_ERROR(MINOR, E_INVALID_STATE, ("ALTER_OOS failed: %s\n", mcr_result_str(res)));
359    }
360    p_Fq->state = qman_fq_state_oos;
361
362    FQUNLOCK(p_Fq);
363    PUNLOCK(p_QmPortal);
364    return E_OK;
365}
366
367static t_Error qman_schedule_fq(t_QmPortal *p_QmPortal, struct qman_fq *p_Fq)
368{
369    struct qm_mc_command    *p_Mcc;
370    struct qm_mc_result     *p_Mcr;
371    uint8_t                 res;
372
373    ASSERT_COND(p_Fq->state == qman_fq_state_parked);
374    if (p_Fq->flags & QMAN_FQ_FLAG_NO_MODIFY)
375        return ERROR_CODE(E_INVALID_VALUE);
376    /* Issue a ALTERFQ_SCHED management command */
377    NCSW_PLOCK(p_QmPortal);
378    FQLOCK(p_Fq);
379    if ((p_Fq->flags & QMAN_FQ_STATE_CHANGING) ||
380            (p_Fq->state != qman_fq_state_parked)) {
381        FQUNLOCK(p_Fq);
382        PUNLOCK(p_QmPortal);
383        return ERROR_CODE(E_BUSY);
384    }
385    p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal);
386    p_Mcc->alterfq.fqid = p_Fq->fqid;
387    qm_mc_commit(p_QmPortal->p_LowQmPortal, QM_MCC_VERB_ALTER_SCHED);
388    while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ;
389    ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) == QM_MCR_VERB_ALTER_SCHED);
390    res = p_Mcr->result;
391    if (res != QM_MCR_RESULT_OK) {
392        FQUNLOCK(p_Fq);
393        PUNLOCK(p_QmPortal);
394        RETURN_ERROR(MINOR, E_INVALID_STATE, ("ALTER_SCHED failed: %s\n", mcr_result_str(res)));
395    }
396    p_Fq->state = qman_fq_state_sched;
397
398    FQUNLOCK(p_Fq);
399    PUNLOCK(p_QmPortal);
400    return E_OK;
401}
402
403/* Inline helper to reduce nesting in LoopMessageRing() */
404static __inline__ void fq_state_change(struct qman_fq *p_Fq,
405                                       struct qm_mr_entry *p_Msg,
406                                       uint8_t verb)
407{
408    FQLOCK(p_Fq);
409    switch(verb) {
410        case QM_MR_VERB_FQRL:
411            ASSERT_COND(p_Fq->flags & QMAN_FQ_STATE_ORL);
412            p_Fq->flags &= ~QMAN_FQ_STATE_ORL;
413            break;
414        case QM_MR_VERB_FQRN:
415            ASSERT_COND((p_Fq->state == qman_fq_state_parked) ||
416                (p_Fq->state == qman_fq_state_sched));
417            ASSERT_COND(p_Fq->flags & QMAN_FQ_STATE_CHANGING);
418            p_Fq->flags &= ~QMAN_FQ_STATE_CHANGING;
419            if (p_Msg->fq.fqs & QM_MR_FQS_NOTEMPTY)
420                p_Fq->flags |= QMAN_FQ_STATE_NE;
421            if (p_Msg->fq.fqs & QM_MR_FQS_ORLPRESENT)
422                p_Fq->flags |= QMAN_FQ_STATE_ORL;
423            p_Fq->state = qman_fq_state_retired;
424            break;
425        case QM_MR_VERB_FQPN:
426            ASSERT_COND(p_Fq->state == qman_fq_state_sched);
427            ASSERT_COND(p_Fq->flags & QMAN_FQ_STATE_CHANGING);
428            p_Fq->state = qman_fq_state_parked;
429    }
430    FQUNLOCK(p_Fq);
431}
432
433static t_Error freeDrainedFq(struct qman_fq *p_Fq)
434{
435    t_QmFqr     *p_QmFqr;
436    uint32_t    i;
437
438    ASSERT_COND(p_Fq);
439    p_QmFqr = (t_QmFqr *)p_Fq->h_QmFqr;
440    ASSERT_COND(p_QmFqr);
441
442    ASSERT_COND(!p_QmFqr->p_DrainedFqs[p_Fq->fqidOffset]);
443    p_QmFqr->p_DrainedFqs[p_Fq->fqidOffset] = TRUE;
444    p_QmFqr->numOfDrainedFqids++;
445    if (p_QmFqr->numOfDrainedFqids == p_QmFqr->numOfFqids)
446    {
447        for (i=0;i<p_QmFqr->numOfFqids;i++)
448        {
449            if ((p_QmFqr->p_Fqs[i]->state == qman_fq_state_retired) &&
450                    (qman_oos_fq(p_QmFqr->h_QmPortal, p_QmFqr->p_Fqs[i]) != E_OK))
451                RETURN_ERROR(MAJOR, E_INVALID_STATE, ("qman_oos_fq() failed!"));
452            qman_destroy_fq(p_QmFqr->p_Fqs[i], 0);
453            XX_FreeSmart(p_QmFqr->p_Fqs[i]);
454        }
455        XX_Free(p_QmFqr->p_DrainedFqs);
456        p_QmFqr->p_DrainedFqs = NULL;
457
458        if (p_QmFqr->f_CompletionCB)
459        {
460            p_QmFqr->f_CompletionCB(p_QmFqr->h_App, p_QmFqr);
461            XX_Free(p_QmFqr->p_Fqs);
462            if (p_QmFqr->fqidBase)
463                QmFqidPut(p_QmFqr->h_Qm, p_QmFqr->fqidBase);
464            XX_Free(p_QmFqr);
465        }
466    }
467
468    return E_OK;
469}
470
471static t_Error drainRetiredFq(struct qman_fq *p_Fq)
472{
473    t_QmFqr     *p_QmFqr;
474
475    ASSERT_COND(p_Fq);
476    p_QmFqr = (t_QmFqr *)p_Fq->h_QmFqr;
477    ASSERT_COND(p_QmFqr);
478
479    if (p_Fq->flags & QMAN_FQ_STATE_NE)
480    {
481        if (qman_volatile_dequeue(p_QmFqr->h_QmPortal, p_Fq,
482                                (QM_VDQCR_PRECEDENCE_VDQCR | QM_VDQCR_NUMFRAMES_TILLEMPTY)) != E_OK)
483
484            RETURN_ERROR(MAJOR, E_INVALID_STATE, ("drain with volatile failed"));
485        return E_OK;
486    }
487    else
488        return freeDrainedFq(p_Fq);
489}
490
491static e_RxStoreResponse drainCB(t_Handle h_App,
492                                 t_Handle h_QmFqr,
493                                 t_Handle h_QmPortal,
494                                 uint32_t fqidOffset,
495                                 t_DpaaFD *p_Frame)
496{
497    UNUSED(h_App);
498    UNUSED(h_QmFqr);
499    UNUSED(h_QmPortal);
500    UNUSED(fqidOffset);
501    UNUSED(p_Frame);
502
503    DBG(TRACE,("got fd for fqid %d", ((t_QmFqr *)h_QmFqr)->fqidBase + fqidOffset));
504    return e_RX_STORE_RESPONSE_CONTINUE;
505}
506
507static void cb_ern_dcErn(t_Handle                   h_App,
508                         t_Handle                   h_QmPortal,
509                         struct qman_fq             *p_Fq,
510                         const struct qm_mr_entry   *p_Msg)
511{
512    static int cnt = 0;
513    UNUSED(p_Fq);
514    UNUSED(p_Msg);
515    UNUSED(h_App);
516    UNUSED(h_QmPortal);
517
518    XX_Print("cb_ern_dcErn_fqs() unimplemented %d\n", ++cnt);
519}
520
521static void cb_fqs(t_Handle                   h_App,
522                   t_Handle                   h_QmPortal,
523                   struct qman_fq             *p_Fq,
524                   const struct qm_mr_entry   *p_Msg)
525{
526    UNUSED(p_Msg);
527    UNUSED(h_App);
528    UNUSED(h_QmPortal);
529
530    if (p_Fq->state == qman_fq_state_retired &&
531        !(p_Fq->flags & QMAN_FQ_STATE_ORL))
532        drainRetiredFq(p_Fq);
533}
534
535static void null_cb_mr(t_Handle                   h_App,
536                       t_Handle                   h_QmPortal,
537                       struct qman_fq             *p_Fq,
538                       const struct qm_mr_entry   *p_Msg)
539{
540    t_QmPortal      *p_QmPortal = (t_QmPortal *)h_QmPortal;
541
542    UNUSED(p_Fq);UNUSED(h_App);
543
544    if ((p_Msg->verb & QM_MR_VERB_DC_ERN) == QM_MR_VERB_DC_ERN)
545        XX_Print("Ignoring unowned MR frame on cpu %d, dc-portal 0x%02x.\n",
546                 p_QmPortal->p_LowQmPortal->config.cpu,p_Msg->dcern.portal);
547    else
548        XX_Print("Ignoring unowned MR frame on cpu %d, verb 0x%02x.\n",
549                 p_QmPortal->p_LowQmPortal->config.cpu,p_Msg->verb);
550}
551
552static uint32_t LoopMessageRing(t_QmPortal *p_QmPortal, uint32_t is)
553{
554    struct qm_mr_entry          *p_Msg;
555
556    if (is & QM_PIRQ_CSCI) {
557        struct qm_mc_result *p_Mcr;
558        struct qman_cgrs    tmp;
559        uint32_t            mask;
560        unsigned int        i, j;
561
562        NCSW_PLOCK(p_QmPortal);
563        qm_mc_start(p_QmPortal->p_LowQmPortal);
564        qm_mc_commit(p_QmPortal->p_LowQmPortal, QM_MCC_VERB_QUERYCONGESTION);
565        while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ;
566
567        /* cgrs[0] is the portal mask for its cg's, cgrs[1] is the
568           previous state of cg's */
569        for (i = 0; i < QM_MAX_NUM_OF_CGS/32; i++)
570        {
571            /* get curent state */
572            tmp.q.__state[i] = p_Mcr->querycongestion.state.__state[i];
573            /* keep only cg's that are registered for this portal */
574            tmp.q.__state[i] &= p_QmPortal->cgrs[0].q.__state[i];
575            /* handle only cg's that changed their state from previous exception */
576            tmp.q.__state[i] ^= p_QmPortal->cgrs[1].q.__state[i];
577            /* update previous */
578            p_QmPortal->cgrs[1].q.__state[i] = p_Mcr->querycongestion.state.__state[i];
579        }
580        PUNLOCK(p_QmPortal);
581
582        /* if in interrupt */
583        /* call the callback routines for any CG with a changed state */
584        for (i = 0; i < QM_MAX_NUM_OF_CGS/32; i++)
585            for(j=0, mask = 0x80000000; j<32 ; j++, mask>>=1)
586            {
587                if(tmp.q.__state[i] & mask)
588                {
589                    t_QmCg *p_QmCg = (t_QmCg *)(p_QmPortal->cgsHandles[i*32 + j]);
590                    if(p_QmCg->f_Exception)
591                        p_QmCg->f_Exception(p_QmCg->h_App, e_QM_EX_CG_STATE_CHANGE);
592                }
593            }
594
595    }
596
597
598    if (is & QM_PIRQ_EQRI) {
599        NCSW_PLOCK(p_QmPortal);
600        qmPortalEqcrCceUpdate(p_QmPortal->p_LowQmPortal);
601        qm_eqcr_set_ithresh(p_QmPortal->p_LowQmPortal, 0);
602        PUNLOCK(p_QmPortal);
603    }
604
605    if (is & QM_PIRQ_MRI) {
606mr_loop:
607        qmPortalMrPvbUpdate(p_QmPortal->p_LowQmPortal);
608        p_Msg = qm_mr_current(p_QmPortal->p_LowQmPortal);
609        if (p_Msg) {
610            struct qman_fq  *p_FqFqs  = ptr_from_aligned_int(p_Msg->fq.contextB);
611            struct qman_fq  *p_FqErn  = ptr_from_aligned_int(p_Msg->ern.tag);
612            uint8_t         verb    =(uint8_t)(p_Msg->verb & QM_MR_VERB_TYPE_MASK);
613            t_QmRejectedFrameInfo   rejectedFrameInfo;
614
615            memset(&rejectedFrameInfo, 0, sizeof(t_QmRejectedFrameInfo));
616            if (!(verb & QM_MR_VERB_DC_ERN))
617            {
618                switch(p_Msg->ern.rc)
619                {
620                    case(QM_MR_RC_CGR_TAILDROP):
621                        rejectedFrameInfo.rejectionCode = e_QM_RC_CG_TAILDROP;
622                        rejectedFrameInfo.cg.cgId = (uint8_t)p_FqErn->cgr_groupid;
623                        break;
624                    case(QM_MR_RC_WRED):
625                        rejectedFrameInfo.rejectionCode = e_QM_RC_CG_WRED;
626                        rejectedFrameInfo.cg.cgId = (uint8_t)p_FqErn->cgr_groupid;
627                        break;
628                    case(QM_MR_RC_FQ_TAILDROP):
629                        rejectedFrameInfo.rejectionCode = e_QM_RC_FQ_TAILDROP;
630                        rejectedFrameInfo.cg.cgId = (uint8_t)p_FqErn->cgr_groupid;
631                        break;
632                    case(QM_MR_RC_ERROR):
633                        break;
634                    default:
635                        REPORT_ERROR(MINOR, E_NOT_SUPPORTED, ("Unknown rejection code"));
636                }
637                if (!p_FqErn)
638                    p_QmPortal->p_NullCB->ern(p_QmPortal->h_App, NULL, p_QmPortal, 0, (t_DpaaFD*)&p_Msg->ern.fd, &rejectedFrameInfo);
639                else
640                    p_FqErn->cb.ern(p_FqErn->h_App, p_FqErn->h_QmFqr, p_QmPortal, p_FqErn->fqidOffset, (t_DpaaFD*)&p_Msg->ern.fd, &rejectedFrameInfo);
641            } else if (verb == QM_MR_VERB_DC_ERN)
642            {
643                if (!p_FqErn)
644                    p_QmPortal->p_NullCB->dc_ern(NULL, p_QmPortal, NULL, p_Msg);
645                else
646                    p_FqErn->cb.dc_ern(p_FqErn->h_App, p_QmPortal, p_FqErn, p_Msg);
647            } else
648            {
649                if (verb == QM_MR_VERB_FQRNI)
650                    ; /* we drop FQRNIs on the floor */
651                else if (!p_FqFqs)
652                            p_QmPortal->p_NullCB->fqs(NULL, p_QmPortal, NULL, p_Msg);
653                else if ((verb == QM_MR_VERB_FQRN) ||
654                         (verb == QM_MR_VERB_FQRL) ||
655                         (verb == QM_MR_VERB_FQPN))
656                {
657                    fq_state_change(p_FqFqs, p_Msg, verb);
658                    p_FqFqs->cb.fqs(p_FqFqs->h_App, p_QmPortal, p_FqFqs, p_Msg);
659                }
660            }
661            qm_mr_next(p_QmPortal->p_LowQmPortal);
662            qmPortalMrCciConsume(p_QmPortal->p_LowQmPortal, 1);
663
664            goto mr_loop;
665        }
666    }
667
668    return is & (QM_PIRQ_CSCI | QM_PIRQ_EQCI | QM_PIRQ_EQRI | QM_PIRQ_MRI);
669}
670
671static void LoopDequeueRing(t_Handle h_QmPortal)
672{
673    struct qm_dqrr_entry        *p_Dq;
674    struct qman_fq              *p_Fq;
675    enum qman_cb_dqrr_result    res = qman_cb_dqrr_consume;
676    e_RxStoreResponse           tmpRes;
677    t_QmPortal                  *p_QmPortal = (t_QmPortal *)h_QmPortal;
678    int                         prefetch = !(p_QmPortal->options & QMAN_PORTAL_FLAG_RSTASH);
679
680    while (res != qman_cb_dqrr_pause)
681    {
682        if (prefetch)
683            qmPortalDqrrPvbPrefetch(p_QmPortal->p_LowQmPortal);
684        qmPortalDqrrPvbUpdate(p_QmPortal->p_LowQmPortal);
685        p_Dq = qm_dqrr_current(p_QmPortal->p_LowQmPortal);
686        if (!p_Dq)
687            break;
688	p_Fq = ptr_from_aligned_int(p_Dq->contextB);
689        if (p_Dq->stat & QM_DQRR_STAT_UNSCHEDULED) {
690            /* We only set QMAN_FQ_STATE_NE when retiring, so we only need
691             * to check for clearing it when doing volatile dequeues. It's
692             * one less thing to check in the critical path (SDQCR). */
693            tmpRes = p_Fq->cb.dqrr(p_Fq->h_App, p_Fq->h_QmFqr, p_QmPortal, p_Fq->fqidOffset, (t_DpaaFD*)&p_Dq->fd);
694            if (tmpRes == e_RX_STORE_RESPONSE_PAUSE)
695                res = qman_cb_dqrr_pause;
696            /* Check for VDQCR completion */
697            if (p_Dq->stat & QM_DQRR_STAT_DQCR_EXPIRED)
698                p_Fq->flags &= ~QMAN_FQ_STATE_VDQCR;
699            if (p_Dq->stat & QM_DQRR_STAT_FQ_EMPTY)
700            {
701                p_Fq->flags &= ~QMAN_FQ_STATE_NE;
702                freeDrainedFq(p_Fq);
703            }
704        }
705        else
706        {
707            /* Interpret 'dq' from the owner's perspective. */
708            /* use portal default handlers */
709            ASSERT_COND(p_Dq->fqid);
710            if (p_Fq)
711            {
712                tmpRes = p_Fq->cb.dqrr(p_Fq->h_App,
713                                       p_Fq->h_QmFqr,
714                                       p_QmPortal,
715                                       p_Fq->fqidOffset,
716                                       (t_DpaaFD*)&p_Dq->fd);
717                if (tmpRes == e_RX_STORE_RESPONSE_PAUSE)
718                    res = qman_cb_dqrr_pause;
719                else if (p_Fq->state == qman_fq_state_waiting_parked)
720                    res = qman_cb_dqrr_park;
721            }
722            else
723            {
724                tmpRes = p_QmPortal->p_NullCB->dqrr(p_QmPortal->h_App,
725                                                    NULL,
726                                                    p_QmPortal,
727                                                    p_Dq->fqid,
728                                                    (t_DpaaFD*)&p_Dq->fd);
729                if (tmpRes == e_RX_STORE_RESPONSE_PAUSE)
730                    res = qman_cb_dqrr_pause;
731            }
732        }
733
734        /* Parking isn't possible unless HELDACTIVE was set. NB,
735         * FORCEELIGIBLE implies HELDACTIVE, so we only need to
736         * check for HELDACTIVE to cover both. */
737        ASSERT_COND((p_Dq->stat & QM_DQRR_STAT_FQ_HELDACTIVE) ||
738                    (res != qman_cb_dqrr_park));
739        if (p_QmPortal->options & QMAN_PORTAL_FLAG_DCA) {
740            /* Defer just means "skip it, I'll consume it myself later on" */
741            if (res != qman_cb_dqrr_defer)
742                qmPortalDqrrDcaConsume1ptr(p_QmPortal->p_LowQmPortal,
743                                           p_Dq,
744                                           (res == qman_cb_dqrr_park));
745            qm_dqrr_next(p_QmPortal->p_LowQmPortal);
746        } else {
747            if (res == qman_cb_dqrr_park)
748                /* The only thing to do for non-DCA is the park-request */
749                qm_dqrr_park_ci(p_QmPortal->p_LowQmPortal);
750            qm_dqrr_next(p_QmPortal->p_LowQmPortal);
751            qmPortalDqrrCciConsume(p_QmPortal->p_LowQmPortal, 1);
752        }
753    }
754}
755
756static void LoopDequeueRingDcaOptimized(t_Handle h_QmPortal)
757{
758    struct qm_dqrr_entry        *p_Dq;
759    struct qman_fq              *p_Fq;
760    enum qman_cb_dqrr_result    res = qman_cb_dqrr_consume;
761    e_RxStoreResponse           tmpRes;
762    t_QmPortal                  *p_QmPortal = (t_QmPortal *)h_QmPortal;
763
764    while (res != qman_cb_dqrr_pause)
765    {
766        qmPortalDqrrPvbUpdate(p_QmPortal->p_LowQmPortal);
767        p_Dq = qm_dqrr_current(p_QmPortal->p_LowQmPortal);
768        if (!p_Dq)
769            break;
770	p_Fq = ptr_from_aligned_int(p_Dq->contextB);
771        if (p_Dq->stat & QM_DQRR_STAT_UNSCHEDULED) {
772            /* We only set QMAN_FQ_STATE_NE when retiring, so we only need
773             * to check for clearing it when doing volatile dequeues. It's
774             * one less thing to check in the critical path (SDQCR). */
775            tmpRes = p_Fq->cb.dqrr(p_Fq->h_App, p_Fq->h_QmFqr, p_QmPortal, p_Fq->fqidOffset, (t_DpaaFD*)&p_Dq->fd);
776            if (tmpRes == e_RX_STORE_RESPONSE_PAUSE)
777                res = qman_cb_dqrr_pause;
778            /* Check for VDQCR completion */
779            if (p_Dq->stat & QM_DQRR_STAT_DQCR_EXPIRED)
780                p_Fq->flags &= ~QMAN_FQ_STATE_VDQCR;
781            if (p_Dq->stat & QM_DQRR_STAT_FQ_EMPTY)
782            {
783                p_Fq->flags &= ~QMAN_FQ_STATE_NE;
784                freeDrainedFq(p_Fq);
785            }
786        }
787        else
788        {
789            /* Interpret 'dq' from the owner's perspective. */
790            /* use portal default handlers */
791            ASSERT_COND(p_Dq->fqid);
792            if (p_Fq)
793            {
794                tmpRes = p_Fq->cb.dqrr(p_Fq->h_App,
795                                       p_Fq->h_QmFqr,
796                                       p_QmPortal,
797                                       p_Fq->fqidOffset,
798                                       (t_DpaaFD*)&p_Dq->fd);
799                if (tmpRes == e_RX_STORE_RESPONSE_PAUSE)
800                    res = qman_cb_dqrr_pause;
801                else if (p_Fq->state == qman_fq_state_waiting_parked)
802                    res = qman_cb_dqrr_park;
803            }
804            else
805            {
806                tmpRes = p_QmPortal->p_NullCB->dqrr(p_QmPortal->h_App,
807                                                    NULL,
808                                                    p_QmPortal,
809                                                    p_Dq->fqid,
810                                                    (t_DpaaFD*)&p_Dq->fd);
811                if (tmpRes == e_RX_STORE_RESPONSE_PAUSE)
812                    res = qman_cb_dqrr_pause;
813            }
814        }
815
816        /* Parking isn't possible unless HELDACTIVE was set. NB,
817         * FORCEELIGIBLE implies HELDACTIVE, so we only need to
818         * check for HELDACTIVE to cover both. */
819        ASSERT_COND((p_Dq->stat & QM_DQRR_STAT_FQ_HELDACTIVE) ||
820                (res != qman_cb_dqrr_park));
821        /* Defer just means "skip it, I'll consume it myself later on" */
822        if (res != qman_cb_dqrr_defer)
823            qmPortalDqrrDcaConsume1ptr(p_QmPortal->p_LowQmPortal,
824                                       p_Dq,
825                                       (res == qman_cb_dqrr_park));
826        qm_dqrr_next(p_QmPortal->p_LowQmPortal);
827    }
828}
829
830static void LoopDequeueRingOptimized(t_Handle h_QmPortal)
831{
832    struct qm_dqrr_entry        *p_Dq;
833    struct qman_fq              *p_Fq;
834    enum qman_cb_dqrr_result    res = qman_cb_dqrr_consume;
835    e_RxStoreResponse           tmpRes;
836    t_QmPortal                  *p_QmPortal = (t_QmPortal *)h_QmPortal;
837
838    while (res != qman_cb_dqrr_pause)
839    {
840        qmPortalDqrrPvbUpdate(p_QmPortal->p_LowQmPortal);
841        p_Dq = qm_dqrr_current(p_QmPortal->p_LowQmPortal);
842        if (!p_Dq)
843            break;
844	p_Fq = ptr_from_aligned_int(p_Dq->contextB);
845        if (p_Dq->stat & QM_DQRR_STAT_UNSCHEDULED) {
846            /* We only set QMAN_FQ_STATE_NE when retiring, so we only need
847             * to check for clearing it when doing volatile dequeues. It's
848             * one less thing to check in the critical path (SDQCR). */
849            tmpRes = p_Fq->cb.dqrr(p_Fq->h_App, p_Fq->h_QmFqr, p_QmPortal, p_Fq->fqidOffset, (t_DpaaFD*)&p_Dq->fd);
850            if (tmpRes == e_RX_STORE_RESPONSE_PAUSE)
851                res = qman_cb_dqrr_pause;
852            /* Check for VDQCR completion */
853            if (p_Dq->stat & QM_DQRR_STAT_DQCR_EXPIRED)
854                p_Fq->flags &= ~QMAN_FQ_STATE_VDQCR;
855            if (p_Dq->stat & QM_DQRR_STAT_FQ_EMPTY)
856            {
857                p_Fq->flags &= ~QMAN_FQ_STATE_NE;
858                freeDrainedFq(p_Fq);
859            }
860        }
861        else
862        {
863            /* Interpret 'dq' from the owner's perspective. */
864            /* use portal default handlers */
865            ASSERT_COND(p_Dq->fqid);
866            if (p_Fq)
867            {
868                tmpRes = p_Fq->cb.dqrr(p_Fq->h_App,
869                                       p_Fq->h_QmFqr,
870                                       p_QmPortal,
871                                       p_Fq->fqidOffset,
872                                       (t_DpaaFD*)&p_Dq->fd);
873                if (tmpRes == e_RX_STORE_RESPONSE_PAUSE)
874                    res = qman_cb_dqrr_pause;
875                else if (p_Fq->state == qman_fq_state_waiting_parked)
876                    res = qman_cb_dqrr_park;
877            }
878            else
879            {
880                tmpRes = p_QmPortal->p_NullCB->dqrr(p_QmPortal->h_App,
881                                                    NULL,
882                                                    p_QmPortal,
883                                                    p_Dq->fqid,
884                                                    (t_DpaaFD*)&p_Dq->fd);
885                if (tmpRes == e_RX_STORE_RESPONSE_PAUSE)
886                    res = qman_cb_dqrr_pause;
887            }
888        }
889
890        /* Parking isn't possible unless HELDACTIVE was set. NB,
891         * FORCEELIGIBLE implies HELDACTIVE, so we only need to
892         * check for HELDACTIVE to cover both. */
893        ASSERT_COND((p_Dq->stat & QM_DQRR_STAT_FQ_HELDACTIVE) ||
894                (res != qman_cb_dqrr_park));
895        if (res == qman_cb_dqrr_park)
896            /* The only thing to do for non-DCA is the park-request */
897            qm_dqrr_park_ci(p_QmPortal->p_LowQmPortal);
898        qm_dqrr_next(p_QmPortal->p_LowQmPortal);
899        qmPortalDqrrCciConsume(p_QmPortal->p_LowQmPortal, 1);
900    }
901}
902
903/* Portal interrupt handler */
904static void portal_isr(void *ptr)
905{
906    t_QmPortal  *p_QmPortal = ptr;
907    uint32_t    event = 0;
908    uint32_t    enableEvents = qm_isr_enable_read(p_QmPortal->p_LowQmPortal);
909
910    DBG(TRACE, ("software-portal %d got interrupt", p_QmPortal->p_LowQmPortal->config.cpu));
911
912    event |= (qm_isr_status_read(p_QmPortal->p_LowQmPortal) &
913            enableEvents);
914
915    qm_isr_status_clear(p_QmPortal->p_LowQmPortal, event);
916    /* Only do fast-path handling if it's required */
917    if (/*(event & QM_PIRQ_DQRI) &&*/
918        (p_QmPortal->options & QMAN_PORTAL_FLAG_IRQ_FAST))
919        p_QmPortal->f_LoopDequeueRingCB(p_QmPortal);
920    if (p_QmPortal->options & QMAN_PORTAL_FLAG_IRQ_SLOW)
921        LoopMessageRing(p_QmPortal, event);
922}
923
924
925static t_Error qman_query_fq_np(t_QmPortal *p_QmPortal, struct qman_fq *p_Fq, struct qm_mcr_queryfq_np *p_Np)
926{
927    struct qm_mc_command    *p_Mcc;
928    struct qm_mc_result     *p_Mcr;
929    uint8_t                 res;
930
931    NCSW_PLOCK(p_QmPortal);
932    p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal);
933    p_Mcc->queryfq_np.fqid = p_Fq->fqid;
934    qm_mc_commit(p_QmPortal->p_LowQmPortal, QM_MCC_VERB_QUERYFQ_NP);
935    while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ;
936    ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) == QM_MCR_VERB_QUERYFQ_NP);
937    res = p_Mcr->result;
938    if (res == QM_MCR_RESULT_OK)
939        *p_Np = p_Mcr->queryfq_np;
940    PUNLOCK(p_QmPortal);
941    if (res != QM_MCR_RESULT_OK)
942        RETURN_ERROR(MINOR, E_INVALID_STATE, ("QUERYFQ_NP failed: %s\n", mcr_result_str(res)));
943    return E_OK;
944}
945
946static uint8_t QmCgGetCgId(t_Handle h_QmCg)
947{
948   t_QmCg *p_QmCg = (t_QmCg *)h_QmCg;
949
950   return p_QmCg->id;
951
952}
953
954static t_Error qm_new_fq(t_QmPortal                         *p_QmPortal,
955                         uint32_t                           fqid,
956                         uint32_t                           fqidOffset,
957                         uint32_t                           channel,
958                         uint32_t                           wqid,
959                         uint16_t                           count,
960                         uint32_t                           flags,
961                         t_QmFqrCongestionAvoidanceParams   *p_CgParams,
962                         t_QmContextA                       *p_ContextA,
963                         t_QmContextB                       *p_ContextB,
964                         bool                               initParked,
965                         t_Handle                           h_QmFqr,
966                         struct qman_fq                     **p_Fqs)
967{
968    struct qman_fq          *p_Fq = NULL;
969    struct qm_mcc_initfq    fq_opts;
970    uint32_t                i;
971    t_Error                 err = E_OK;
972    int         gap, tmp;
973    uint32_t    tmpA, tmpN, ta=0, tn=0, initFqFlag;
974
975    ASSERT_COND(p_QmPortal);
976    ASSERT_COND(count);
977
978    for(i=0;i<count;i++)
979    {
980        p_Fq = (struct qman_fq *)XX_MallocSmart(sizeof(struct qman_fq), 0, 64);
981        if (!p_Fq)
982            RETURN_ERROR(MAJOR, E_NO_MEMORY, ("FQ obj!!!"));
983        memset(p_Fq, 0, sizeof(struct qman_fq));
984        p_Fq->cb.dqrr     = p_QmPortal->f_DfltFrame;
985        p_Fq->cb.ern      = p_QmPortal->f_RejectedFrame;
986        p_Fq->cb.dc_ern   = cb_ern_dcErn;
987        p_Fq->cb.fqs      = cb_fqs;
988        p_Fq->h_App       = p_QmPortal->h_App;
989        p_Fq->h_QmFqr     = h_QmFqr;
990        p_Fq->fqidOffset  = fqidOffset;
991        p_Fqs[i] = p_Fq;
992        if ((err = qman_create_fq(p_QmPortal,(uint32_t)(fqid + i), 0, p_Fqs[i])) != E_OK)
993            break;
994    }
995
996    if (err != E_OK)
997    {
998        for(i=0;i<count;i++)
999            if (p_Fqs[i])
1000            {
1001                XX_FreeSmart(p_Fqs[i]);
1002                p_Fqs[i] = NULL;
1003            }
1004        RETURN_ERROR(MINOR, err, ("Failed to create Fqs"));
1005    }
1006
1007    memset(&fq_opts,0,sizeof(fq_opts));
1008    fq_opts.fqid = fqid;
1009    fq_opts.count = (uint16_t)(count-1);
1010    fq_opts.we_mask |= QM_INITFQ_WE_DESTWQ;
1011    fq_opts.fqd.dest.channel = channel;
1012    fq_opts.fqd.dest.wq = wqid;
1013    fq_opts.we_mask |= QM_INITFQ_WE_FQCTRL;
1014    fq_opts.fqd.fq_ctrl = (uint16_t)flags;
1015
1016    if ((flags & QM_FQCTRL_CGE) || (flags & QM_FQCTRL_TDE))
1017        ASSERT_COND(p_CgParams);
1018
1019    if(flags & QM_FQCTRL_CGE)
1020    {
1021        ASSERT_COND(p_CgParams->h_QmCg);
1022
1023        /* CG OAC and FQ TD may not be configured at the same time. if both are required,
1024           than we configure CG first, and the FQ TD later - see below. */
1025        fq_opts.fqd.cgid = QmCgGetCgId(p_CgParams->h_QmCg);
1026        fq_opts.we_mask |= QM_INITFQ_WE_CGID;
1027        if(p_CgParams->overheadAccountingLength)
1028        {
1029            fq_opts.we_mask |= QM_INITFQ_WE_OAC;
1030            fq_opts.we_mask &= ~QM_INITFQ_WE_TDTHRESH;
1031            fq_opts.fqd.td_thresh = (uint16_t)(QM_FQD_TD_THRESH_OAC_EN | p_CgParams->overheadAccountingLength);
1032        }
1033    }
1034    if((flags & QM_FQCTRL_TDE) && (!p_CgParams->overheadAccountingLength))
1035    {
1036        ASSERT_COND(p_CgParams->fqTailDropThreshold);
1037
1038        fq_opts.we_mask |= QM_INITFQ_WE_TDTHRESH;
1039
1040            /* express thresh as ta*2^tn */
1041            gap = (int)p_CgParams->fqTailDropThreshold;
1042            for (tmpA=0 ; tmpA<256; tmpA++ )
1043                for (tmpN=0 ; tmpN<32; tmpN++ )
1044                {
1045                    tmp = ABS((int)(p_CgParams->fqTailDropThreshold - tmpA*(1<<tmpN)));
1046                    if (tmp < gap)
1047                    {
1048                       ta = tmpA;
1049                       tn = tmpN;
1050                       gap = tmp;
1051                    }
1052                }
1053            fq_opts.fqd.td.exp = tn;
1054            fq_opts.fqd.td.mant = ta;
1055    }
1056
1057    if (p_ContextA)
1058    {
1059        fq_opts.we_mask |= QM_INITFQ_WE_CONTEXTA;
1060        memcpy((void*)&fq_opts.fqd.context_a, p_ContextA, sizeof(t_QmContextA));
1061    }
1062    /* If this FQ will not be used for tx, we can use contextB field */
1063    if (fq_opts.fqd.dest.channel < e_QM_FQ_CHANNEL_FMAN0_SP0)
1064    {
1065            fq_opts.we_mask |= QM_INITFQ_WE_CONTEXTB;
1066            fq_opts.fqd.context_b = aligned_int_from_ptr(p_Fqs[0]);
1067    }
1068    else if (p_ContextB) /* Tx-Queue */
1069    {
1070        fq_opts.we_mask |= QM_INITFQ_WE_CONTEXTB;
1071        memcpy((void*)&fq_opts.fqd.context_b, p_ContextB, sizeof(t_QmContextB));
1072    }
1073
1074    if((flags & QM_FQCTRL_TDE) && (p_CgParams->overheadAccountingLength))
1075        initFqFlag = 0;
1076    else
1077        initFqFlag = (uint32_t)(initParked?0:QMAN_INITFQ_FLAG_SCHED);
1078
1079    if ((err = qman_init_fq(p_QmPortal, p_Fqs[0], initFqFlag, &fq_opts)) != E_OK)
1080    {
1081        for(i=0;i<count;i++)
1082            if (p_Fqs[i])
1083            {
1084                XX_FreeSmart(p_Fqs[i]);
1085                p_Fqs[i] = NULL;
1086            }
1087        RETURN_ERROR(MINOR, err, ("Failed to init Fqs [%d-%d]", fqid, fqid+count-1));
1088    }
1089
1090    /* if both CG OAC and FQ TD are needed, we call qman_init_fq again, this time for the FQ TD only */
1091    if((flags & QM_FQCTRL_TDE) && (p_CgParams->overheadAccountingLength))
1092    {
1093        ASSERT_COND(p_CgParams->fqTailDropThreshold);
1094
1095        fq_opts.we_mask = QM_INITFQ_WE_TDTHRESH;
1096
1097        /* express thresh as ta*2^tn */
1098        gap = (int)p_CgParams->fqTailDropThreshold;
1099        for (tmpA=0 ; tmpA<256; tmpA++ )
1100            for (tmpN=0 ; tmpN<32; tmpN++ )
1101            {
1102                tmp = ABS((int)(p_CgParams->fqTailDropThreshold - tmpA*(1<<tmpN)));
1103                if (tmp < gap)
1104                {
1105                   ta = tmpA;
1106                   tn = tmpN;
1107                   gap = tmp;
1108                }
1109            }
1110        fq_opts.fqd.td.exp = tn;
1111        fq_opts.fqd.td.mant = ta;
1112        if ((err = qman_init_fq(p_QmPortal, p_Fqs[0], (uint32_t)(initParked?0:QMAN_INITFQ_FLAG_SCHED), &fq_opts)) != E_OK)
1113        {
1114            for(i=0;i<count;i++)
1115                if (p_Fqs[i])
1116                {
1117                    XX_FreeSmart(p_Fqs[i]);
1118                    p_Fqs[i] = NULL;
1119                }
1120            RETURN_ERROR(MINOR, err, ("Failed to init Fqs"));
1121        }
1122    }
1123
1124
1125    for(i=1;i<count;i++)
1126    {
1127        memcpy(p_Fqs[i], p_Fqs[0], sizeof(struct qman_fq));
1128        p_Fqs[i]->fqid += i;
1129    }
1130
1131    return err;
1132}
1133
1134
1135static t_Error qm_free_fq(t_QmPortal *p_QmPortal, struct qman_fq *p_Fq)
1136{
1137    uint32_t flags=0;
1138
1139    if (qman_retire_fq(p_QmPortal, p_Fq, &flags, false) != E_OK)
1140        RETURN_ERROR(MAJOR, E_INVALID_STATE, ("qman_retire_fq() failed!"));
1141
1142    if (flags & QMAN_FQ_STATE_CHANGING)
1143        RETURN_ERROR(MAJOR, E_INVALID_STATE, ("fq %d currently in use, will be retired", p_Fq->fqid));
1144
1145    if (flags & QMAN_FQ_STATE_NE)
1146        RETURN_ERROR(MAJOR, E_INVALID_STATE, ("qman_retire_fq() failed;" \
1147                                          "Frame Queue Not Empty, Need to dequeue"));
1148
1149    if (qman_oos_fq(p_QmPortal, p_Fq) != E_OK)
1150        RETURN_ERROR(MAJOR, E_INVALID_STATE, ("qman_oos_fq() failed!"));
1151
1152    qman_destroy_fq(p_Fq,0);
1153
1154    return E_OK;
1155}
1156
1157static void qman_disable_portal(t_QmPortal *p_QmPortal)
1158{
1159    NCSW_PLOCK(p_QmPortal);
1160    if (!(p_QmPortal->disable_count++))
1161        qm_dqrr_set_maxfill(p_QmPortal->p_LowQmPortal, 0);
1162    PUNLOCK(p_QmPortal);
1163}
1164
1165
1166/* quiesce SDQCR/VDQCR, then drain till h/w wraps up anything it
1167 * was doing (5ms is more than enough to ensure it's done). */
1168static void clean_dqrr_mr(t_QmPortal *p_QmPortal)
1169{
1170    struct qm_dqrr_entry    *p_Dq;
1171    struct qm_mr_entry      *p_Msg;
1172    int                     idle = 0;
1173
1174    qm_dqrr_sdqcr_set(p_QmPortal->p_LowQmPortal, 0);
1175    qm_dqrr_vdqcr_set(p_QmPortal->p_LowQmPortal, 0);
1176drain_loop:
1177    qmPortalDqrrPvbPrefetch(p_QmPortal->p_LowQmPortal);
1178    qmPortalDqrrPvbUpdate(p_QmPortal->p_LowQmPortal);
1179    qmPortalMrPvbUpdate(p_QmPortal->p_LowQmPortal);
1180    p_Dq = qm_dqrr_current(p_QmPortal->p_LowQmPortal);
1181    p_Msg = qm_mr_current(p_QmPortal->p_LowQmPortal);
1182    if (p_Dq) {
1183        qm_dqrr_next(p_QmPortal->p_LowQmPortal);
1184        qmPortalDqrrCciConsume(p_QmPortal->p_LowQmPortal, 1);
1185    }
1186    if (p_Msg) {
1187    qm_mr_next(p_QmPortal->p_LowQmPortal);
1188        qmPortalMrCciConsume(p_QmPortal->p_LowQmPortal, 1);
1189    }
1190    if (!p_Dq && !p_Msg) {
1191    if (++idle < 5) {
1192    XX_UDelay(1000);
1193    goto drain_loop;
1194    }
1195    } else {
1196    idle = 0;
1197    goto drain_loop;
1198    }
1199}
1200
1201static t_Error qman_create_portal(t_QmPortal *p_QmPortal,
1202                                   uint32_t flags,
1203                                   uint32_t sdqcrFlags,
1204                                   uint8_t  dqrrSize)
1205{
1206    const struct qm_portal_config   *p_Config = &(p_QmPortal->p_LowQmPortal->config);
1207    int                             ret = 0;
1208    t_Error                         err;
1209    uint32_t                        isdr;
1210
1211    if ((err = qm_eqcr_init(p_QmPortal->p_LowQmPortal, e_QmPortalPVB, e_QmPortalEqcrCCE)) != E_OK)
1212        RETURN_ERROR(MINOR, err, ("Qman EQCR initialization failed\n"));
1213
1214    if (qm_dqrr_init(p_QmPortal->p_LowQmPortal,
1215                     sdqcrFlags ? e_QmPortalDequeuePushMode : e_QmPortalDequeuePullMode,
1216                     e_QmPortalPVB,
1217                     (flags & QMAN_PORTAL_FLAG_DCA) ? e_QmPortalDqrrDCA : e_QmPortalDqrrCCI,
1218                     dqrrSize,
1219                     (flags & QMAN_PORTAL_FLAG_RSTASH) ? 1 : 0,
1220                     (flags & QMAN_PORTAL_FLAG_DSTASH) ? 1 : 0)) {
1221        REPORT_ERROR(MAJOR, E_INVALID_STATE, ("DQRR initialization failed"));
1222        goto fail_dqrr;
1223    }
1224
1225    if (qm_mr_init(p_QmPortal->p_LowQmPortal, e_QmPortalPVB, e_QmPortalMrCCI)) {
1226        REPORT_ERROR(MAJOR, E_INVALID_STATE, ("MR initialization failed"));
1227        goto fail_mr;
1228    }
1229    if (qm_mc_init(p_QmPortal->p_LowQmPortal)) {
1230        REPORT_ERROR(MAJOR, E_INVALID_STATE, ("MC initialization failed"));
1231        goto fail_mc;
1232    }
1233    if (qm_isr_init(p_QmPortal->p_LowQmPortal)) {
1234        REPORT_ERROR(MAJOR, E_INVALID_STATE, ("ISR initialization failed"));
1235        goto fail_isr;
1236    }
1237    /* static interrupt-gating controls */
1238    qm_dqrr_set_ithresh(p_QmPortal->p_LowQmPortal, 12);
1239    qm_mr_set_ithresh(p_QmPortal->p_LowQmPortal, 4);
1240    qm_isr_set_iperiod(p_QmPortal->p_LowQmPortal, 100);
1241    p_QmPortal->options = flags;
1242    isdr = 0xffffffff;
1243    qm_isr_status_clear(p_QmPortal->p_LowQmPortal, 0xffffffff);
1244    qm_isr_enable_write(p_QmPortal->p_LowQmPortal, DEFAULT_portalExceptions);
1245    qm_isr_disable_write(p_QmPortal->p_LowQmPortal, isdr);
1246    if (flags & QMAN_PORTAL_FLAG_IRQ)
1247    {
1248        XX_SetIntr(p_Config->irq, portal_isr, p_QmPortal);
1249        XX_EnableIntr(p_Config->irq);
1250        qm_isr_uninhibit(p_QmPortal->p_LowQmPortal);
1251    } else
1252        /* without IRQ, we can't block */
1253        flags &= ~QMAN_PORTAL_FLAG_WAIT;
1254    /* Need EQCR to be empty before continuing */
1255    isdr ^= QM_PIRQ_EQCI;
1256    qm_isr_disable_write(p_QmPortal->p_LowQmPortal, isdr);
1257    ret = qm_eqcr_get_fill(p_QmPortal->p_LowQmPortal);
1258    if (ret) {
1259        REPORT_ERROR(MAJOR, E_INVALID_STATE, ("EQCR unclean"));
1260        goto fail_eqcr_empty;
1261    }
1262    isdr ^= (QM_PIRQ_DQRI | QM_PIRQ_MRI);
1263    qm_isr_disable_write(p_QmPortal->p_LowQmPortal, isdr);
1264    if (qm_dqrr_current(p_QmPortal->p_LowQmPortal) != NULL)
1265    {
1266        REPORT_ERROR(MAJOR, E_INVALID_STATE, ("DQRR unclean"));
1267goto fail_dqrr_mr_empty;
1268    }
1269    if (qm_mr_current(p_QmPortal->p_LowQmPortal) != NULL)
1270    {
1271        REPORT_ERROR(MAJOR, E_INVALID_STATE, ("MR unclean"));
1272goto fail_dqrr_mr_empty;
1273    }
1274    qm_isr_disable_write(p_QmPortal->p_LowQmPortal, 0);
1275    qm_dqrr_sdqcr_set(p_QmPortal->p_LowQmPortal, sdqcrFlags);
1276    return E_OK;
1277fail_dqrr_mr_empty:
1278fail_eqcr_empty:
1279    qm_isr_finish(p_QmPortal->p_LowQmPortal);
1280fail_isr:
1281    qm_mc_finish(p_QmPortal->p_LowQmPortal);
1282fail_mc:
1283    qm_mr_finish(p_QmPortal->p_LowQmPortal);
1284fail_mr:
1285    qm_dqrr_finish(p_QmPortal->p_LowQmPortal);
1286fail_dqrr:
1287    qm_eqcr_finish(p_QmPortal->p_LowQmPortal);
1288    return ERROR_CODE(E_INVALID_STATE);
1289}
1290
1291static void qman_destroy_portal(t_QmPortal *p_QmPortal)
1292{
1293    /* NB we do this to "quiesce" EQCR. If we add enqueue-completions or
1294     * something related to QM_PIRQ_EQCI, this may need fixing. */
1295    qmPortalEqcrCceUpdate(p_QmPortal->p_LowQmPortal);
1296    if (p_QmPortal->options & QMAN_PORTAL_FLAG_IRQ)
1297    {
1298        XX_DisableIntr(p_QmPortal->p_LowQmPortal->config.irq);
1299        XX_FreeIntr(p_QmPortal->p_LowQmPortal->config.irq);
1300    }
1301    qm_isr_finish(p_QmPortal->p_LowQmPortal);
1302    qm_mc_finish(p_QmPortal->p_LowQmPortal);
1303    qm_mr_finish(p_QmPortal->p_LowQmPortal);
1304    qm_dqrr_finish(p_QmPortal->p_LowQmPortal);
1305    qm_eqcr_finish(p_QmPortal->p_LowQmPortal);
1306}
1307
1308static inline struct qm_eqcr_entry *try_eq_start(t_QmPortal *p_QmPortal)
1309{
1310    struct qm_eqcr_entry    *p_Eq;
1311    uint8_t                 avail;
1312
1313    avail = qm_eqcr_get_avail(p_QmPortal->p_LowQmPortal);
1314    if (avail == EQCR_THRESH)
1315        qmPortalEqcrCcePrefetch(p_QmPortal->p_LowQmPortal);
1316    else if (avail < EQCR_THRESH)
1317            qmPortalEqcrCceUpdate(p_QmPortal->p_LowQmPortal);
1318    p_Eq = qm_eqcr_start(p_QmPortal->p_LowQmPortal);
1319
1320    return p_Eq;
1321}
1322
1323
1324static t_Error qman_orp_update(t_QmPortal   *p_QmPortal,
1325                               uint32_t     orpId,
1326                               uint16_t     orpSeqnum,
1327                               uint32_t     flags)
1328{
1329    struct qm_eqcr_entry *p_Eq;
1330
1331    NCSW_PLOCK(p_QmPortal);
1332    p_Eq = try_eq_start(p_QmPortal);
1333    if (!p_Eq)
1334    {
1335        PUNLOCK(p_QmPortal);
1336        return ERROR_CODE(E_BUSY);
1337    }
1338
1339    if (flags & QMAN_ENQUEUE_FLAG_NESN)
1340        orpSeqnum |= QM_EQCR_SEQNUM_NESN;
1341    else
1342        /* No need to check 4 QMAN_ENQUEUE_FLAG_HOLE */
1343        orpSeqnum &= ~QM_EQCR_SEQNUM_NESN;
1344    p_Eq->seqnum  = orpSeqnum;
1345    p_Eq->orp     = orpId;
1346qmPortalEqcrPvbCommit(p_QmPortal->p_LowQmPortal, (uint8_t)QM_EQCR_VERB_ORP);
1347
1348    PUNLOCK(p_QmPortal);
1349    return E_OK;
1350}
1351
1352static __inline__ t_Error CheckStashParams(t_QmFqrParams *p_QmFqrParams)
1353{
1354    ASSERT_COND(p_QmFqrParams);
1355
1356    if (p_QmFqrParams->stashingParams.frameAnnotationSize > QM_CONTEXTA_MAX_STASH_SIZE)
1357        RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Frame Annotation Size Exceeded Max Stash Size(%d)", QM_CONTEXTA_MAX_STASH_SIZE));
1358    if (p_QmFqrParams->stashingParams.frameDataSize > QM_CONTEXTA_MAX_STASH_SIZE)
1359        RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Frame Data Size Exceeded Max Stash Size(%d)", QM_CONTEXTA_MAX_STASH_SIZE));
1360    if (p_QmFqrParams->stashingParams.fqContextSize > QM_CONTEXTA_MAX_STASH_SIZE)
1361        RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Frame Context Size Exceeded Max Stash Size(%d)", QM_CONTEXTA_MAX_STASH_SIZE));
1362    if (p_QmFqrParams->stashingParams.fqContextSize)
1363    {
1364        if (!p_QmFqrParams->stashingParams.fqContextAddr)
1365            RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("FQ Context Address Must be givven"));
1366        if (!IS_ALIGNED(p_QmFqrParams->stashingParams.fqContextAddr, CACHELINE_SIZE))
1367            RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("FQ Context Address Must be aligned to %d", CACHELINE_SIZE));
1368        if (p_QmFqrParams->stashingParams.fqContextAddr & 0xffffff0000000000LL)
1369            RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("FQ Context Address May be up to 40 bit"));
1370    }
1371
1372    return E_OK;
1373}
1374
1375static t_Error QmPortalRegisterCg(t_Handle h_QmPortal, t_Handle h_QmCg, uint8_t  cgId)
1376{
1377    t_QmPortal  *p_QmPortal = (t_QmPortal *)h_QmPortal;
1378
1379    /* cgrs[0] is the mask of registered CG's*/
1380    if(p_QmPortal->cgrs[0].q.__state[cgId/32] & (0x80000000 >> (cgId % 32)))
1381        RETURN_ERROR(MINOR, E_BUSY, ("CG already used"));
1382
1383    p_QmPortal->cgrs[0].q.__state[cgId/32] |=  0x80000000 >> (cgId % 32);
1384    p_QmPortal->cgsHandles[cgId] = h_QmCg;
1385
1386    return E_OK;
1387}
1388
1389static t_Error QmPortalUnregisterCg(t_Handle h_QmPortal, uint8_t  cgId)
1390{
1391    t_QmPortal  *p_QmPortal = (t_QmPortal *)h_QmPortal;
1392
1393    /* cgrs[0] is the mask of registered CG's*/
1394    if(!(p_QmPortal->cgrs[0].q.__state[cgId/32] & (0x80000000 >> (cgId % 32))))
1395        RETURN_ERROR(MINOR, E_BUSY, ("CG is not in use"));
1396
1397    p_QmPortal->cgrs[0].q.__state[cgId/32] &=  ~0x80000000 >> (cgId % 32);
1398    p_QmPortal->cgsHandles[cgId] = NULL;
1399
1400    return E_OK;
1401}
1402
1403static e_DpaaSwPortal QmPortalGetSwPortalId(t_Handle h_QmPortal)
1404{
1405    t_QmPortal *p_QmPortal = (t_QmPortal *)h_QmPortal;
1406
1407    return (e_DpaaSwPortal)p_QmPortal->p_LowQmPortal->config.cpu;
1408}
1409
1410static t_Error CalcWredCurve(t_QmCgWredCurve *p_WredCurve, uint32_t  *p_CurveWord)
1411{
1412    uint32_t    maxP, roundDown, roundUp, tmpA, tmpN;
1413    uint32_t    ma=0, mn=0, slope, sa=0, sn=0, pn;
1414    int         pres = 1000;
1415    int         gap, tmp;
1416
1417/*  TODO - change maxTh to uint64_t?
1418   if(p_WredCurve->maxTh > (1<<39))
1419        RETURN_ERROR(MINOR, E_INVALID_VALUE, ("maxTh is not in range"));*/
1420
1421    /* express maxTh as ma*2^mn */
1422     gap = (int)p_WredCurve->maxTh;
1423     for (tmpA=0 ; tmpA<256; tmpA++ )
1424         for (tmpN=0 ; tmpN<32; tmpN++ )
1425         {
1426             tmp = ABS((int)(p_WredCurve->maxTh - tmpA*(1<<tmpN)));
1427             if (tmp < gap)
1428             {
1429                ma = tmpA;
1430                mn = tmpN;
1431                gap = tmp;
1432             }
1433         }
1434     ASSERT_COND(ma <256);
1435     ASSERT_COND(mn <32);
1436     p_WredCurve->maxTh = ma*(1<<mn);
1437
1438     if(p_WredCurve->maxTh <= p_WredCurve->minTh)
1439        RETURN_ERROR(MINOR, E_INVALID_VALUE, ("maxTh must be larger than minTh"));
1440     if(p_WredCurve->probabilityDenominator > 64)
1441        RETURN_ERROR(MINOR, E_INVALID_VALUE, ("probabilityDenominator mustn't be 1-64"));
1442
1443    /* first we translate from Cisco probabilityDenominator
1444       to 256 fixed denominator, result must be divisible by 4. */
1445    /* we multiply by a fixed value to get better accuracy (without
1446       using floating point) */
1447    maxP = (uint32_t)(256*1000/p_WredCurve->probabilityDenominator);
1448    if (maxP % 4*pres)
1449    {
1450        roundDown  = maxP + (maxP % (4*pres));
1451        roundUp = roundDown + 4*pres;
1452        if((roundUp - maxP) > (maxP - roundDown))
1453            maxP = roundDown;
1454        else
1455            maxP = roundUp;
1456    }
1457    maxP = maxP/pres;
1458    ASSERT_COND(maxP <= 256);
1459    pn = (uint8_t)(maxP/4 - 1);
1460
1461    if(maxP >= (p_WredCurve->maxTh - p_WredCurve->minTh))
1462        RETURN_ERROR(MINOR, E_INVALID_VALUE, ("Due to probabilityDenominator selected, maxTh-minTh must be larger than %d", maxP));
1463
1464    pres = 1000000;
1465    slope = maxP*pres/(p_WredCurve->maxTh - p_WredCurve->minTh);
1466    /* express slope as sa/2^sn */
1467    gap = (int)slope;
1468    for (tmpA=(uint32_t)(64*pres) ; tmpA<128*pres; tmpA += pres )
1469        for (tmpN=7 ; tmpN<64; tmpN++ )
1470        {
1471            tmp = ABS((int)(slope - tmpA/(1UL<<(tmpN%32))));
1472            if (tmp < gap)
1473            {
1474               sa = tmpA;
1475               sn = tmpN;
1476               gap = tmp;
1477            }
1478        }
1479    sa = sa/pres;
1480    ASSERT_COND(sa<128 && sa>=64);
1481    ASSERT_COND(sn<64 && sn>=7);
1482
1483    *p_CurveWord = ((ma << 24) |
1484                    (mn << 19) |
1485                    (sa << 12) |
1486                    (sn << 6) |
1487                    pn);
1488
1489    return E_OK;
1490}
1491
1492static t_Error QmPortalPullFrame(t_Handle h_QmPortal, uint32_t pdqcr, t_DpaaFD *p_Frame)
1493{
1494    t_QmPortal              *p_QmPortal = (t_QmPortal *)h_QmPortal;
1495    struct qm_dqrr_entry    *p_Dq;
1496    int                     prefetch;
1497    uint32_t                *p_Dst, *p_Src;
1498
1499    ASSERT_COND(p_QmPortal);
1500    ASSERT_COND(p_Frame);
1501    SANITY_CHECK_RETURN_ERROR(p_QmPortal->pullMode, E_INVALID_STATE);
1502
1503    NCSW_PLOCK(p_QmPortal);
1504
1505    qm_dqrr_pdqcr_set(p_QmPortal->p_LowQmPortal, pdqcr);
1506    mb();
1507    while (qm_dqrr_pdqcr_get(p_QmPortal->p_LowQmPortal)) ;
1508
1509    prefetch = !(p_QmPortal->options & QMAN_PORTAL_FLAG_RSTASH);
1510    while(TRUE)
1511    {
1512        if (prefetch)
1513            qmPortalDqrrPvbPrefetch(p_QmPortal->p_LowQmPortal);
1514        qmPortalDqrrPvbUpdate(p_QmPortal->p_LowQmPortal);
1515        p_Dq = qm_dqrr_current(p_QmPortal->p_LowQmPortal);
1516        if (!p_Dq)
1517            continue;
1518        ASSERT_COND(p_Dq->fqid);
1519        p_Dst = (uint32_t *)p_Frame;
1520        p_Src = (uint32_t *)&p_Dq->fd;
1521        p_Dst[0] = p_Src[0];
1522        p_Dst[1] = p_Src[1];
1523        p_Dst[2] = p_Src[2];
1524        p_Dst[3] = p_Src[3];
1525        if (p_QmPortal->options & QMAN_PORTAL_FLAG_DCA)
1526        {
1527            qmPortalDqrrDcaConsume1ptr(p_QmPortal->p_LowQmPortal,
1528                                       p_Dq,
1529                                       false);
1530            qm_dqrr_next(p_QmPortal->p_LowQmPortal);
1531        }
1532        else
1533        {
1534            qm_dqrr_next(p_QmPortal->p_LowQmPortal);
1535            qmPortalDqrrCciConsume(p_QmPortal->p_LowQmPortal, 1);
1536        }
1537        break;
1538    }
1539
1540    PUNLOCK(p_QmPortal);
1541
1542    if (!(p_Dq->stat & QM_DQRR_STAT_FD_VALID))
1543        return ERROR_CODE(E_EMPTY);
1544
1545    return E_OK;
1546}
1547
1548
1549/****************************************/
1550/*       API Init unit functions        */
1551/****************************************/
1552t_Handle QM_PORTAL_Config(t_QmPortalParam *p_QmPortalParam)
1553{
1554    t_QmPortal          *p_QmPortal;
1555    uint32_t            i;
1556
1557    SANITY_CHECK_RETURN_VALUE(p_QmPortalParam, E_INVALID_HANDLE, NULL);
1558    SANITY_CHECK_RETURN_VALUE(p_QmPortalParam->swPortalId < DPAA_MAX_NUM_OF_SW_PORTALS, E_INVALID_VALUE, 0);
1559
1560    p_QmPortal = (t_QmPortal *)XX_Malloc(sizeof(t_QmPortal));
1561    if (!p_QmPortal)
1562    {
1563        REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Qm Portal obj!!!"));
1564        return NULL;
1565    }
1566    memset(p_QmPortal, 0, sizeof(t_QmPortal));
1567
1568    p_QmPortal->p_LowQmPortal = (struct qm_portal *)XX_Malloc(sizeof(struct qm_portal));
1569    if (!p_QmPortal->p_LowQmPortal)
1570    {
1571        XX_Free(p_QmPortal);
1572        REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Low qm p_QmPortal obj!!!"));
1573        return NULL;
1574    }
1575    memset(p_QmPortal->p_LowQmPortal, 0, sizeof(struct qm_portal));
1576
1577    p_QmPortal->p_QmPortalDriverParams = (t_QmPortalDriverParams *)XX_Malloc(sizeof(t_QmPortalDriverParams));
1578    if (!p_QmPortal->p_QmPortalDriverParams)
1579    {
1580        XX_Free(p_QmPortal->p_LowQmPortal);
1581        XX_Free(p_QmPortal);
1582        REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Qm Portal driver parameters"));
1583        return NULL;
1584    }
1585    memset(p_QmPortal->p_QmPortalDriverParams, 0, sizeof(t_QmPortalDriverParams));
1586
1587    p_QmPortal->p_LowQmPortal->addr.addr_ce = UINT_TO_PTR(p_QmPortalParam->ceBaseAddress);
1588    p_QmPortal->p_LowQmPortal->addr.addr_ci = UINT_TO_PTR(p_QmPortalParam->ciBaseAddress);
1589    p_QmPortal->p_LowQmPortal->config.irq = p_QmPortalParam->irq;
1590    p_QmPortal->p_LowQmPortal->config.bound = 0;
1591    p_QmPortal->p_LowQmPortal->config.cpu = (int)p_QmPortalParam->swPortalId;
1592    p_QmPortal->p_LowQmPortal->config.channel = (e_QmFQChannel)(e_QM_FQ_CHANNEL_SWPORTAL0 + p_QmPortalParam->swPortalId);
1593    p_QmPortal->p_LowQmPortal->bind_lock = XX_InitSpinlock();
1594
1595    p_QmPortal->h_Qm                = p_QmPortalParam->h_Qm;
1596    p_QmPortal->f_DfltFrame         = p_QmPortalParam->f_DfltFrame;
1597    p_QmPortal->f_RejectedFrame     = p_QmPortalParam->f_RejectedFrame;
1598    p_QmPortal->h_App               = p_QmPortalParam->h_App;
1599
1600    p_QmPortal->p_QmPortalDriverParams->fdLiodnOffset           = p_QmPortalParam->fdLiodnOffset;
1601    p_QmPortal->p_QmPortalDriverParams->dequeueDcaMode          = DEFAULT_dequeueDcaMode;
1602    p_QmPortal->p_QmPortalDriverParams->dequeueUpToThreeFrames  = DEFAULT_dequeueUpToThreeFrames;
1603    p_QmPortal->p_QmPortalDriverParams->commandType             = DEFAULT_dequeueCommandType;
1604    p_QmPortal->p_QmPortalDriverParams->userToken               = DEFAULT_dequeueUserToken;
1605    p_QmPortal->p_QmPortalDriverParams->specifiedWq             = DEFAULT_dequeueSpecifiedWq;
1606    p_QmPortal->p_QmPortalDriverParams->dedicatedChannel        = DEFAULT_dequeueDedicatedChannel;
1607    p_QmPortal->p_QmPortalDriverParams->dedicatedChannelHasPrecedenceOverPoolChannels =
1608        DEFAULT_dequeueDedicatedChannelHasPrecedenceOverPoolChannels;
1609    p_QmPortal->p_QmPortalDriverParams->poolChannelId           = DEFAULT_dequeuePoolChannelId;
1610    p_QmPortal->p_QmPortalDriverParams->wqId                    = DEFAULT_dequeueWqId;
1611    for (i=0;i<QM_MAX_NUM_OF_POOL_CHANNELS;i++)
1612        p_QmPortal->p_QmPortalDriverParams->poolChannels[i] = FALSE;
1613    p_QmPortal->p_QmPortalDriverParams->dqrrSize                = DEFAULT_dqrrSize;
1614    p_QmPortal->p_QmPortalDriverParams->pullMode                = DEFAULT_pullMode;
1615
1616    return p_QmPortal;
1617}
1618
1619t_Error QM_PORTAL_Init(t_Handle h_QmPortal)
1620{
1621    t_QmPortal                          *p_QmPortal = (t_QmPortal *)h_QmPortal;
1622    uint32_t                            i, flags=0, sdqcrFlags=0;
1623    t_Error                             err;
1624    t_QmInterModulePortalInitParams     qmParams;
1625
1626    SANITY_CHECK_RETURN_ERROR(p_QmPortal, E_INVALID_HANDLE);
1627    SANITY_CHECK_RETURN_ERROR(p_QmPortal->p_QmPortalDriverParams, E_INVALID_HANDLE);
1628
1629    memset(&qmParams, 0, sizeof(qmParams));
1630    qmParams.portalId       = (uint8_t)p_QmPortal->p_LowQmPortal->config.cpu;
1631    qmParams.liodn          = p_QmPortal->p_QmPortalDriverParams->fdLiodnOffset;
1632    qmParams.dqrrLiodn      = p_QmPortal->p_QmPortalDriverParams->dqrrLiodn;
1633    qmParams.fdFqLiodn      = p_QmPortal->p_QmPortalDriverParams->fdFqLiodn;
1634    qmParams.stashDestQueue = p_QmPortal->p_QmPortalDriverParams->stashDestQueue;
1635    if ((err = QmGetSetPortalParams(p_QmPortal->h_Qm, &qmParams)) != E_OK)
1636        RETURN_ERROR(MAJOR, err, NO_MSG);
1637
1638    flags = (uint32_t)(((p_QmPortal->p_LowQmPortal->config.irq == NO_IRQ) ?
1639            0 :
1640            (QMAN_PORTAL_FLAG_IRQ |
1641             QMAN_PORTAL_FLAG_IRQ_FAST |
1642             QMAN_PORTAL_FLAG_IRQ_SLOW)));
1643    flags |= ((p_QmPortal->p_QmPortalDriverParams->dequeueDcaMode) ? QMAN_PORTAL_FLAG_DCA : 0);
1644    flags |= (p_QmPortal->p_QmPortalDriverParams->dqrr)?QMAN_PORTAL_FLAG_RSTASH:0;
1645    flags |= (p_QmPortal->p_QmPortalDriverParams->fdFq)?QMAN_PORTAL_FLAG_DSTASH:0;
1646
1647    p_QmPortal->pullMode = p_QmPortal->p_QmPortalDriverParams->pullMode;
1648    if (!p_QmPortal->pullMode)
1649    {
1650        sdqcrFlags |= (p_QmPortal->p_QmPortalDriverParams->dequeueUpToThreeFrames) ? QM_SDQCR_COUNT_UPTO3 : QM_SDQCR_COUNT_EXACT1;
1651        sdqcrFlags |= QM_SDQCR_TOKEN_SET(p_QmPortal->p_QmPortalDriverParams->userToken);
1652        sdqcrFlags |= QM_SDQCR_TYPE_SET(p_QmPortal->p_QmPortalDriverParams->commandType);
1653        if (!p_QmPortal->p_QmPortalDriverParams->specifiedWq)
1654        {
1655            /* sdqcrFlags |= QM_SDQCR_SOURCE_CHANNELS;*/ /* removed as the macro is '0' */
1656            sdqcrFlags |= (p_QmPortal->p_QmPortalDriverParams->dedicatedChannelHasPrecedenceOverPoolChannels) ? QM_SDQCR_DEDICATED_PRECEDENCE : 0;
1657            sdqcrFlags |= (p_QmPortal->p_QmPortalDriverParams->dedicatedChannel) ? QM_SDQCR_CHANNELS_DEDICATED : 0;
1658            for (i=0;i<QM_MAX_NUM_OF_POOL_CHANNELS;i++)
1659                sdqcrFlags |= ((p_QmPortal->p_QmPortalDriverParams->poolChannels[i]) ?
1660                     QM_SDQCR_CHANNELS_POOL(i+1) : 0);
1661        }
1662        else
1663        {
1664            sdqcrFlags |= QM_SDQCR_SOURCE_SPECIFICWQ;
1665            sdqcrFlags |= (p_QmPortal->p_QmPortalDriverParams->dedicatedChannel) ?
1666                            QM_SDQCR_SPECIFICWQ_DEDICATED : QM_SDQCR_SPECIFICWQ_POOL(p_QmPortal->p_QmPortalDriverParams->poolChannelId);
1667            sdqcrFlags |= QM_SDQCR_SPECIFICWQ_WQ(p_QmPortal->p_QmPortalDriverParams->wqId);
1668        }
1669    }
1670    if ((flags & QMAN_PORTAL_FLAG_RSTASH) && (flags & QMAN_PORTAL_FLAG_DCA))
1671        p_QmPortal->f_LoopDequeueRingCB = LoopDequeueRingDcaOptimized;
1672    else if ((flags & QMAN_PORTAL_FLAG_RSTASH) && !(flags & QMAN_PORTAL_FLAG_DCA))
1673        p_QmPortal->f_LoopDequeueRingCB = LoopDequeueRingOptimized;
1674    else
1675        p_QmPortal->f_LoopDequeueRingCB = LoopDequeueRing;
1676
1677    if ((!p_QmPortal->f_RejectedFrame) || (!p_QmPortal->f_DfltFrame))
1678        RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("f_RejectedFrame or f_DfltFrame callback not provided"));
1679
1680    p_QmPortal->p_NullCB = (struct qman_fq_cb *)XX_Malloc(sizeof(struct qman_fq_cb));
1681    if (!p_QmPortal->p_NullCB)
1682        RETURN_ERROR(MAJOR, E_NO_MEMORY, ("FQ Null CB obj!!!"));
1683    memset(p_QmPortal->p_NullCB, 0, sizeof(struct qman_fq_cb));
1684
1685    p_QmPortal->p_NullCB->dqrr      = p_QmPortal->f_DfltFrame;
1686    p_QmPortal->p_NullCB->ern       = p_QmPortal->f_RejectedFrame;
1687    p_QmPortal->p_NullCB->dc_ern    = p_QmPortal->p_NullCB->fqs = null_cb_mr;
1688
1689    if (qman_create_portal(p_QmPortal, flags, sdqcrFlags, p_QmPortal->p_QmPortalDriverParams->dqrrSize) != E_OK)
1690    {
1691        RETURN_ERROR(MAJOR, E_NO_MEMORY, ("create portal failed"));
1692    }
1693
1694    QmSetPortalHandle(p_QmPortal->h_Qm, (t_Handle)p_QmPortal, (e_DpaaSwPortal)p_QmPortal->p_LowQmPortal->config.cpu);
1695    XX_Free(p_QmPortal->p_QmPortalDriverParams);
1696    p_QmPortal->p_QmPortalDriverParams = NULL;
1697
1698    DBG(TRACE, ("Qman-Portal %d @ %p:%p",
1699                p_QmPortal->p_LowQmPortal->config.cpu,
1700                p_QmPortal->p_LowQmPortal->addr.addr_ce,
1701                p_QmPortal->p_LowQmPortal->addr.addr_ci
1702                ));
1703
1704    DBG(TRACE, ("Qman-Portal %d phys @ 0x%016llx:0x%016llx",
1705                p_QmPortal->p_LowQmPortal->config.cpu,
1706                (uint64_t)XX_VirtToPhys(p_QmPortal->p_LowQmPortal->addr.addr_ce),
1707                (uint64_t)XX_VirtToPhys(p_QmPortal->p_LowQmPortal->addr.addr_ci)
1708                ));
1709
1710    return E_OK;
1711}
1712
1713t_Error QM_PORTAL_Free(t_Handle h_QmPortal)
1714{
1715    t_QmPortal  *p_QmPortal = (t_QmPortal *)h_QmPortal;
1716
1717    if (!p_QmPortal)
1718       return ERROR_CODE(E_INVALID_HANDLE);
1719
1720    ASSERT_COND(p_QmPortal->p_LowQmPortal);
1721    QmSetPortalHandle(p_QmPortal->h_Qm, NULL, (e_DpaaSwPortal)p_QmPortal->p_LowQmPortal->config.cpu);
1722    qman_destroy_portal(p_QmPortal);
1723    if (p_QmPortal->p_NullCB)
1724        XX_Free(p_QmPortal->p_NullCB);
1725
1726    if (p_QmPortal->p_LowQmPortal->bind_lock)
1727        XX_FreeSpinlock(p_QmPortal->p_LowQmPortal->bind_lock);
1728    if(p_QmPortal->p_QmPortalDriverParams)
1729        XX_Free(p_QmPortal->p_QmPortalDriverParams);
1730    XX_Free(p_QmPortal->p_LowQmPortal);
1731    XX_Free(p_QmPortal);
1732
1733    return E_OK;
1734}
1735
1736t_Error QM_PORTAL_ConfigDcaMode(t_Handle h_QmPortal, bool enable)
1737{
1738    t_QmPortal  *p_QmPortal = (t_QmPortal *)h_QmPortal;
1739
1740    SANITY_CHECK_RETURN_ERROR(p_QmPortal, E_INVALID_HANDLE);
1741    SANITY_CHECK_RETURN_ERROR(p_QmPortal->p_QmPortalDriverParams, E_INVALID_HANDLE);
1742
1743    p_QmPortal->p_QmPortalDriverParams->dequeueDcaMode = enable;
1744
1745    return E_OK;
1746}
1747
1748t_Error QM_PORTAL_ConfigStash(t_Handle h_QmPortal, t_QmPortalStashParam *p_StashParams)
1749{
1750    t_QmPortal  *p_QmPortal = (t_QmPortal *)h_QmPortal;
1751
1752    SANITY_CHECK_RETURN_ERROR(p_QmPortal, E_INVALID_HANDLE);
1753    SANITY_CHECK_RETURN_ERROR(p_QmPortal->p_QmPortalDriverParams, E_NULL_POINTER);
1754    SANITY_CHECK_RETURN_ERROR(p_StashParams, E_NULL_POINTER);
1755
1756    p_QmPortal->p_QmPortalDriverParams->stashDestQueue  = p_StashParams->stashDestQueue;
1757    p_QmPortal->p_QmPortalDriverParams->dqrrLiodn       = p_StashParams->dqrrLiodn;
1758    p_QmPortal->p_QmPortalDriverParams->fdFqLiodn       = p_StashParams->fdFqLiodn;
1759    p_QmPortal->p_QmPortalDriverParams->eqcr            = p_StashParams->eqcr;
1760    p_QmPortal->p_QmPortalDriverParams->eqcrHighPri     = p_StashParams->eqcrHighPri;
1761    p_QmPortal->p_QmPortalDriverParams->dqrr            = p_StashParams->dqrr;
1762    p_QmPortal->p_QmPortalDriverParams->dqrrHighPri     = p_StashParams->dqrrHighPri;
1763    p_QmPortal->p_QmPortalDriverParams->fdFq            = p_StashParams->fdFq;
1764    p_QmPortal->p_QmPortalDriverParams->fdFqHighPri     = p_StashParams->fdFqHighPri;
1765    p_QmPortal->p_QmPortalDriverParams->fdFqDrop        = p_StashParams->fdFqDrop;
1766
1767    return E_OK;
1768}
1769
1770
1771t_Error QM_PORTAL_ConfigPullMode(t_Handle h_QmPortal, bool pullMode)
1772{
1773    t_QmPortal  *p_QmPortal = (t_QmPortal *)h_QmPortal;
1774
1775    SANITY_CHECK_RETURN_ERROR(p_QmPortal, E_INVALID_HANDLE);
1776    SANITY_CHECK_RETURN_ERROR(p_QmPortal->p_QmPortalDriverParams, E_NULL_POINTER);
1777
1778    p_QmPortal->p_QmPortalDriverParams->pullMode  = pullMode;
1779
1780    return E_OK;
1781}
1782
1783t_Error QM_PORTAL_AddPoolChannel(t_Handle h_QmPortal, uint8_t poolChannelId)
1784{
1785    t_QmPortal  *p_QmPortal = (t_QmPortal *)h_QmPortal;
1786    uint32_t    sdqcrFlags;
1787
1788    SANITY_CHECK_RETURN_ERROR(p_QmPortal, E_INVALID_HANDLE);
1789    SANITY_CHECK_RETURN_ERROR((poolChannelId < QM_MAX_NUM_OF_POOL_CHANNELS), E_INVALID_VALUE);
1790
1791    sdqcrFlags = qm_dqrr_sdqcr_get(p_QmPortal->p_LowQmPortal);
1792    sdqcrFlags |= QM_SDQCR_CHANNELS_POOL(poolChannelId+1);
1793    qm_dqrr_sdqcr_set(p_QmPortal->p_LowQmPortal, sdqcrFlags);
1794
1795    return E_OK;
1796}
1797
1798t_Error QM_PORTAL_Poll(t_Handle h_QmPortal, e_QmPortalPollSource source)
1799{
1800    t_QmPortal  *p_QmPortal = (t_QmPortal *)h_QmPortal;
1801
1802    SANITY_CHECK_RETURN_ERROR(p_QmPortal, E_INVALID_HANDLE);
1803
1804    NCSW_PLOCK(p_QmPortal);
1805
1806    if ((source == e_QM_PORTAL_POLL_SOURCE_CONTROL_FRAMES) ||
1807        (source == e_QM_PORTAL_POLL_SOURCE_BOTH))
1808    {
1809        uint32_t is = qm_isr_status_read(p_QmPortal->p_LowQmPortal);
1810        uint32_t active = LoopMessageRing(p_QmPortal, is);
1811        if (active)
1812            qm_isr_status_clear(p_QmPortal->p_LowQmPortal, active);
1813    }
1814    if ((source == e_QM_PORTAL_POLL_SOURCE_DATA_FRAMES) ||
1815        (source == e_QM_PORTAL_POLL_SOURCE_BOTH))
1816        p_QmPortal->f_LoopDequeueRingCB((t_Handle)p_QmPortal);
1817
1818    PUNLOCK(p_QmPortal);
1819
1820    return E_OK;
1821}
1822
1823t_Error QM_PORTAL_PollFrame(t_Handle h_QmPortal, t_QmPortalFrameInfo *p_frameInfo)
1824{
1825    t_QmPortal              *p_QmPortal     = (t_QmPortal *)h_QmPortal;
1826    struct qm_dqrr_entry    *p_Dq;
1827    struct qman_fq          *p_Fq;
1828    int                     prefetch;
1829
1830    SANITY_CHECK_RETURN_ERROR(p_QmPortal, E_INVALID_HANDLE);
1831    SANITY_CHECK_RETURN_ERROR(p_frameInfo, E_NULL_POINTER);
1832
1833    NCSW_PLOCK(p_QmPortal);
1834
1835    prefetch = !(p_QmPortal->options & QMAN_PORTAL_FLAG_RSTASH);
1836    if (prefetch)
1837        qmPortalDqrrPvbPrefetch(p_QmPortal->p_LowQmPortal);
1838    qmPortalDqrrPvbUpdate(p_QmPortal->p_LowQmPortal);
1839    p_Dq = qm_dqrr_current(p_QmPortal->p_LowQmPortal);
1840    if (!p_Dq)
1841    {
1842        PUNLOCK(p_QmPortal);
1843        return ERROR_CODE(E_EMPTY);
1844    }
1845    p_Fq = ptr_from_aligned_int(p_Dq->contextB);
1846    ASSERT_COND(p_Dq->fqid);
1847    if (p_Fq)
1848    {
1849        p_frameInfo->h_App = p_Fq->h_App;
1850        p_frameInfo->h_QmFqr = p_Fq->h_QmFqr;
1851        p_frameInfo->fqidOffset = p_Fq->fqidOffset;
1852        memcpy((void*)&p_frameInfo->frame, (void*)&p_Dq->fd, sizeof(t_DpaaFD));
1853    }
1854    else
1855    {
1856        p_frameInfo->h_App = p_QmPortal->h_App;
1857        p_frameInfo->h_QmFqr = NULL;
1858        p_frameInfo->fqidOffset = p_Dq->fqid;
1859        memcpy((void*)&p_frameInfo->frame, (void*)&p_Dq->fd, sizeof(t_DpaaFD));
1860    }
1861    if (p_QmPortal->options & QMAN_PORTAL_FLAG_DCA) {
1862        qmPortalDqrrDcaConsume1ptr(p_QmPortal->p_LowQmPortal,
1863                                   p_Dq,
1864                                   false);
1865        qm_dqrr_next(p_QmPortal->p_LowQmPortal);
1866    } else {
1867        qm_dqrr_next(p_QmPortal->p_LowQmPortal);
1868        qmPortalDqrrCciConsume(p_QmPortal->p_LowQmPortal, 1);
1869    }
1870
1871    PUNLOCK(p_QmPortal);
1872
1873    return E_OK;
1874}
1875
1876
1877t_Handle QM_FQR_Create(t_QmFqrParams *p_QmFqrParams)
1878{
1879    t_QmFqr             *p_QmFqr;
1880    uint32_t            i, flags = 0;
1881    u_QmFqdContextA     cnxtA;
1882
1883    SANITY_CHECK_RETURN_VALUE(p_QmFqrParams, E_INVALID_HANDLE, NULL);
1884    SANITY_CHECK_RETURN_VALUE(p_QmFqrParams->h_Qm, E_INVALID_HANDLE, NULL);
1885
1886    if (p_QmFqrParams->shadowMode &&
1887        (!p_QmFqrParams->useForce || p_QmFqrParams->numOfFqids != 1))
1888    {
1889        REPORT_ERROR(MAJOR, E_CONFLICT, ("shadowMode must be use with useForce and numOfFqids==1!!!"));
1890        return NULL;
1891    }
1892
1893    p_QmFqr = (t_QmFqr *)XX_MallocSmart(sizeof(t_QmFqr), 0, 64);
1894    if (!p_QmFqr)
1895    {
1896        REPORT_ERROR(MAJOR, E_NO_MEMORY, ("QM FQR obj!!!"));
1897        return NULL;
1898    }
1899    memset(p_QmFqr, 0, sizeof(t_QmFqr));
1900
1901    p_QmFqr->h_Qm       = p_QmFqrParams->h_Qm;
1902    p_QmFqr->h_QmPortal = p_QmFqrParams->h_QmPortal;
1903    p_QmFqr->shadowMode = p_QmFqrParams->shadowMode;
1904    p_QmFqr->numOfFqids = (p_QmFqrParams->useForce && !p_QmFqrParams->numOfFqids) ?
1905                              1 : p_QmFqrParams->numOfFqids;
1906
1907    if (!p_QmFqr->h_QmPortal)
1908    {
1909        p_QmFqr->h_QmPortal = QmGetPortalHandle(p_QmFqr->h_Qm);
1910        SANITY_CHECK_RETURN_VALUE(p_QmFqr->h_QmPortal, E_INVALID_HANDLE, NULL);
1911    }
1912
1913    p_QmFqr->p_Fqs = (struct qman_fq **)XX_Malloc(sizeof(struct qman_fq *) * p_QmFqr->numOfFqids);
1914    if (!p_QmFqr->p_Fqs)
1915    {
1916        REPORT_ERROR(MAJOR, E_NO_MEMORY, ("QM FQs obj!!!"));
1917        QM_FQR_Free(p_QmFqr);
1918        return NULL;
1919    }
1920    memset(p_QmFqr->p_Fqs, 0, sizeof(struct qman_fq *) * p_QmFqr->numOfFqids);
1921
1922    if (p_QmFqr->shadowMode)
1923    {
1924        struct qman_fq          *p_Fq = NULL;
1925
1926        p_QmFqr->fqidBase = p_QmFqrParams->qs.frcQ.fqid;
1927        p_Fq = (struct qman_fq *)XX_MallocSmart(sizeof(struct qman_fq), 0, 64);
1928        if (!p_Fq)
1929        {
1930            REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FQ obj!!!"));
1931            QM_FQR_Free(p_QmFqr);
1932            return NULL;
1933        }
1934        memset(p_Fq, 0, sizeof(struct qman_fq));
1935        p_Fq->cb.dqrr     = ((t_QmPortal*)p_QmFqr->h_QmPortal)->f_DfltFrame;
1936        p_Fq->cb.ern      = ((t_QmPortal*)p_QmFqr->h_QmPortal)->f_RejectedFrame;
1937        p_Fq->cb.dc_ern   = cb_ern_dcErn;
1938        p_Fq->cb.fqs      = cb_fqs;
1939        p_Fq->h_App       = ((t_QmPortal*)p_QmFqr->h_QmPortal)->h_App;
1940        p_Fq->h_QmFqr     = p_QmFqr;
1941        p_Fq->state       = qman_fq_state_sched;
1942        p_Fq->fqid        = p_QmFqr->fqidBase;
1943        p_QmFqr->p_Fqs[0] = p_Fq;
1944    }
1945    else
1946    {
1947        p_QmFqr->channel    = p_QmFqrParams->channel;
1948        p_QmFqr->workQueue  = p_QmFqrParams->wq;
1949
1950        p_QmFqr->fqidBase = QmFqidGet(p_QmFqr->h_Qm,
1951                                      p_QmFqr->numOfFqids,
1952                                      p_QmFqrParams->qs.nonFrcQs.align,
1953                                      p_QmFqrParams->useForce,
1954                                      p_QmFqrParams->qs.frcQ.fqid);
1955        if (p_QmFqr->fqidBase == (uint32_t)ILLEGAL_BASE)
1956        {
1957            REPORT_ERROR(CRITICAL,E_INVALID_STATE,("can't allocate a fqid"));
1958            QM_FQR_Free(p_QmFqr);
1959            return NULL;
1960        }
1961
1962        if(p_QmFqrParams->congestionAvoidanceEnable &&
1963            (p_QmFqrParams->congestionAvoidanceParams.h_QmCg == NULL) &&
1964            (p_QmFqrParams->congestionAvoidanceParams.fqTailDropThreshold == 0))
1965        {
1966            REPORT_ERROR(CRITICAL,E_INVALID_STATE,("NULL congestion group handle and no FQ Threshold"));
1967            QM_FQR_Free(p_QmFqr);
1968            return NULL;
1969        }
1970        if(p_QmFqrParams->congestionAvoidanceEnable)
1971        {
1972            if(p_QmFqrParams->congestionAvoidanceParams.h_QmCg)
1973                flags |= QM_FQCTRL_CGE;
1974            if(p_QmFqrParams->congestionAvoidanceParams.fqTailDropThreshold)
1975                flags |= QM_FQCTRL_TDE;
1976        }
1977
1978    /*
1979        flags |= (p_QmFqrParams->holdActive)    ? QM_FQCTRL_ORP : 0;
1980        flags |= (p_QmFqrParams->holdActive)    ? QM_FQCTRL_CPCSTASH : 0;
1981        flags |= (p_QmFqrParams->holdActive)    ? QM_FQCTRL_FORCESFDR : 0;
1982        flags |= (p_QmFqrParams->holdActive)    ? QM_FQCTRL_AVOIDBLOCK : 0;
1983    */
1984        flags |= (p_QmFqrParams->holdActive)    ? QM_FQCTRL_HOLDACTIVE : 0;
1985        flags |= (p_QmFqrParams->preferInCache) ? QM_FQCTRL_LOCKINCACHE : 0;
1986
1987        if (p_QmFqrParams->useContextAForStash)
1988        {
1989            if (CheckStashParams(p_QmFqrParams) != E_OK)
1990            {
1991                REPORT_ERROR(CRITICAL,E_INVALID_STATE,NO_MSG);
1992                QM_FQR_Free(p_QmFqr);
1993                return NULL;
1994            }
1995
1996            memset(&cnxtA, 0, sizeof(cnxtA));
1997            cnxtA.stashing.annotation_cl = DIV_CEIL(p_QmFqrParams->stashingParams.frameAnnotationSize, CACHELINE_SIZE);
1998            cnxtA.stashing.data_cl = DIV_CEIL(p_QmFqrParams->stashingParams.frameDataSize, CACHELINE_SIZE);
1999            cnxtA.stashing.context_cl = DIV_CEIL(p_QmFqrParams->stashingParams.fqContextSize, CACHELINE_SIZE);
2000            cnxtA.context_hi = (uint8_t)((p_QmFqrParams->stashingParams.fqContextAddr >> 32) & 0xff);
2001            cnxtA.context_lo = (uint32_t)(p_QmFqrParams->stashingParams.fqContextAddr);
2002            flags |= QM_FQCTRL_CTXASTASHING;
2003        }
2004
2005        for(i=0;i<p_QmFqr->numOfFqids;i++)
2006            if (qm_new_fq(p_QmFqr->h_QmPortal,
2007                          p_QmFqr->fqidBase+i,
2008                          i,
2009                          p_QmFqr->channel,
2010                          p_QmFqr->workQueue,
2011                          1/*p_QmFqr->numOfFqids*/,
2012                          flags,
2013                          (p_QmFqrParams->congestionAvoidanceEnable ?
2014                              &p_QmFqrParams->congestionAvoidanceParams : NULL),
2015                          p_QmFqrParams->useContextAForStash ?
2016                              (t_QmContextA *)&cnxtA : p_QmFqrParams->p_ContextA,
2017                          p_QmFqrParams->p_ContextB,
2018                          p_QmFqrParams->initParked,
2019                          p_QmFqr,
2020                          &p_QmFqr->p_Fqs[i]) != E_OK)
2021            {
2022                QM_FQR_Free(p_QmFqr);
2023                return NULL;
2024            }
2025    }
2026    return p_QmFqr;
2027}
2028
2029t_Error  QM_FQR_Free(t_Handle h_QmFqr)
2030{
2031    t_QmFqr     *p_QmFqr    = (t_QmFqr *)h_QmFqr;
2032    uint32_t    i;
2033
2034    if (!p_QmFqr)
2035        return ERROR_CODE(E_INVALID_HANDLE);
2036
2037    if (p_QmFqr->p_Fqs)
2038    {
2039        for (i=0;i<p_QmFqr->numOfFqids;i++)
2040            if (p_QmFqr->p_Fqs[i])
2041            {
2042                if (!p_QmFqr->shadowMode)
2043                    qm_free_fq(p_QmFqr->h_QmPortal, p_QmFqr->p_Fqs[i]);
2044                XX_FreeSmart(p_QmFqr->p_Fqs[i]);
2045            }
2046        XX_Free(p_QmFqr->p_Fqs);
2047    }
2048
2049    if (!p_QmFqr->shadowMode && p_QmFqr->fqidBase)
2050        QmFqidPut(p_QmFqr->h_Qm, p_QmFqr->fqidBase);
2051
2052    XX_FreeSmart(p_QmFqr);
2053
2054    return E_OK;
2055}
2056
2057t_Error  QM_FQR_FreeWDrain(t_Handle                     h_QmFqr,
2058                           t_QmFqrDrainedCompletionCB   *f_CompletionCB,
2059                           bool                         deliverFrame,
2060                           t_QmReceivedFrameCallback    *f_CallBack,
2061                           t_Handle                     h_App)
2062{
2063    t_QmFqr     *p_QmFqr    = (t_QmFqr *)h_QmFqr;
2064    uint32_t    i;
2065
2066    if (!p_QmFqr)
2067        return ERROR_CODE(E_INVALID_HANDLE);
2068
2069    if (p_QmFqr->shadowMode)
2070        RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("QM_FQR_FreeWDrain can't be called to shadow FQR!!!. call QM_FQR_Free"));
2071
2072    p_QmFqr->p_DrainedFqs = (bool *)XX_Malloc(sizeof(bool) * p_QmFqr->numOfFqids);
2073    if (!p_QmFqr->p_DrainedFqs)
2074        RETURN_ERROR(MAJOR, E_NO_MEMORY, ("QM Drained-FQs obj!!!. Try to Free without draining"));
2075    memset(p_QmFqr->p_DrainedFqs, 0, sizeof(bool) * p_QmFqr->numOfFqids);
2076
2077    if (f_CompletionCB)
2078    {
2079        p_QmFqr->f_CompletionCB = f_CompletionCB;
2080        p_QmFqr->h_App          = h_App;
2081    }
2082
2083    if (deliverFrame)
2084    {
2085        if (!f_CallBack)
2086        {
2087            REPORT_ERROR(MAJOR, E_NULL_POINTER, ("f_CallBack must be given."));
2088            XX_Free(p_QmFqr->p_DrainedFqs);
2089            return ERROR_CODE(E_NULL_POINTER);
2090        }
2091        QM_FQR_RegisterCB(p_QmFqr, f_CallBack, h_App);
2092    }
2093    else
2094        QM_FQR_RegisterCB(p_QmFqr, drainCB, h_App);
2095
2096    for (i=0;i<p_QmFqr->numOfFqids;i++)
2097    {
2098        if (qman_retire_fq(p_QmFqr->h_QmPortal, p_QmFqr->p_Fqs[i], 0, true) != E_OK)
2099            RETURN_ERROR(MAJOR, E_INVALID_STATE, ("qman_retire_fq() failed!"));
2100
2101        if (p_QmFqr->p_Fqs[i]->flags & QMAN_FQ_STATE_CHANGING)
2102            DBG(INFO, ("fq %d currently in use, will be retired", p_QmFqr->p_Fqs[i]->fqid));
2103        else
2104            drainRetiredFq(p_QmFqr->p_Fqs[i]);
2105    }
2106
2107    if (!p_QmFqr->f_CompletionCB)
2108    {
2109        while(p_QmFqr->p_DrainedFqs) ;
2110        DBG(TRACE, ("QM-FQR with base %d completed", p_QmFqr->fqidBase));
2111        XX_FreeSmart(p_QmFqr->p_Fqs);
2112        if (p_QmFqr->fqidBase)
2113            QmFqidPut(p_QmFqr->h_Qm, p_QmFqr->fqidBase);
2114        XX_FreeSmart(p_QmFqr);
2115    }
2116
2117    return E_OK;
2118}
2119
2120t_Error QM_FQR_RegisterCB(t_Handle h_QmFqr, t_QmReceivedFrameCallback *f_CallBack, t_Handle h_App)
2121{
2122    t_QmFqr     *p_QmFqr = (t_QmFqr *)h_QmFqr;
2123    int         i;
2124
2125    SANITY_CHECK_RETURN_ERROR(p_QmFqr, E_INVALID_HANDLE);
2126
2127    for (i=0;i<p_QmFqr->numOfFqids;i++)
2128    {
2129        p_QmFqr->p_Fqs[i]->cb.dqrr = f_CallBack;
2130        p_QmFqr->p_Fqs[i]->h_App   = h_App;
2131    }
2132
2133    return E_OK;
2134}
2135
2136t_Error QM_FQR_Enqueue(t_Handle h_QmFqr, t_Handle h_QmPortal, uint32_t fqidOffset, t_DpaaFD *p_Frame)
2137{
2138    t_QmFqr                 *p_QmFqr = (t_QmFqr *)h_QmFqr;
2139    t_QmPortal              *p_QmPortal;
2140    struct qm_eqcr_entry    *p_Eq;
2141    uint32_t                *p_Dst, *p_Src;
2142    const struct qman_fq    *p_Fq;
2143
2144    SANITY_CHECK_RETURN_ERROR(p_QmFqr, E_INVALID_HANDLE);
2145    SANITY_CHECK_RETURN_ERROR((fqidOffset < p_QmFqr->numOfFqids), E_INVALID_VALUE);
2146
2147    if (!h_QmPortal)
2148    {
2149        SANITY_CHECK_RETURN_ERROR(p_QmFqr->h_Qm, E_INVALID_HANDLE);
2150        h_QmPortal = QmGetPortalHandle(p_QmFqr->h_Qm);
2151        SANITY_CHECK_RETURN_ERROR(h_QmPortal, E_INVALID_HANDLE);
2152    }
2153    p_QmPortal = (t_QmPortal *)h_QmPortal;
2154
2155    p_Fq = p_QmFqr->p_Fqs[fqidOffset];
2156
2157#ifdef QM_CHECKING
2158    if (p_Fq->flags & QMAN_FQ_FLAG_NO_ENQUEUE)
2159        RETURN_ERROR(MINOR, E_INVALID_VALUE, NO_MSG);
2160    if ((!(p_Fq->flags & QMAN_FQ_FLAG_NO_MODIFY)) &&
2161        ((p_Fq->state == qman_fq_state_retired) ||
2162         (p_Fq->state == qman_fq_state_oos)))
2163        return ERROR_CODE(E_BUSY);
2164#endif /* QM_CHECKING */
2165
2166    NCSW_PLOCK(p_QmPortal);
2167    p_Eq = try_eq_start(p_QmPortal);
2168    if (!p_Eq)
2169    {
2170        PUNLOCK(p_QmPortal);
2171        return ERROR_CODE(E_BUSY);
2172    }
2173
2174    p_Eq->fqid = p_Fq->fqid;
2175    p_Eq->tag = aligned_int_from_ptr(p_Fq);
2176    /* gcc does a dreadful job of the following;
2177     *  eq->fd = *fd;
2178     * It causes the entire function to save/restore a wider range of
2179     * registers, and comes up with instruction-waste galore. This will do
2180     * until we can rework the function for better code-generation. */
2181    p_Dst = (uint32_t *)&p_Eq->fd;
2182    p_Src = (uint32_t *)p_Frame;
2183    p_Dst[0] = p_Src[0];
2184    p_Dst[1] = p_Src[1];
2185    p_Dst[2] = p_Src[2];
2186    p_Dst[3] = p_Src[3];
2187
2188    qmPortalEqcrPvbCommit(p_QmPortal->p_LowQmPortal,
2189                          (uint8_t)(QM_EQCR_VERB_CMD_ENQUEUE/* |
2190                          (flags & (QM_EQCR_VERB_COLOUR_MASK | QM_EQCR_VERB_INTERRUPT))*/));
2191    PUNLOCK(p_QmPortal);
2192
2193    return E_OK;
2194}
2195
2196
2197t_Error QM_FQR_PullFrame(t_Handle h_QmFqr, t_Handle h_QmPortal, uint32_t fqidOffset, t_DpaaFD *p_Frame)
2198{
2199    t_QmFqr                 *p_QmFqr = (t_QmFqr *)h_QmFqr;
2200    uint32_t                pdqcr = 0;
2201
2202    SANITY_CHECK_RETURN_ERROR(p_QmFqr, E_INVALID_HANDLE);
2203    SANITY_CHECK_RETURN_ERROR((fqidOffset < p_QmFqr->numOfFqids), E_INVALID_VALUE);
2204    SANITY_CHECK_RETURN_ERROR(p_Frame, E_NULL_POINTER);
2205    SANITY_CHECK_RETURN_ERROR((p_QmFqr->p_Fqs[fqidOffset]->state == qman_fq_state_oos) ||
2206                              (p_QmFqr->p_Fqs[fqidOffset]->state == qman_fq_state_parked),
2207                              E_INVALID_STATE);
2208    if (!h_QmPortal)
2209    {
2210        SANITY_CHECK_RETURN_ERROR(p_QmFqr->h_Qm, E_INVALID_HANDLE);
2211        h_QmPortal = QmGetPortalHandle(p_QmFqr->h_Qm);
2212        SANITY_CHECK_RETURN_ERROR(h_QmPortal, E_INVALID_HANDLE);
2213    }
2214
2215    pdqcr |= QM_PDQCR_MODE_UNSCHEDULED;
2216    pdqcr |= QM_PDQCR_FQID(p_QmFqr->p_Fqs[fqidOffset]->fqid);
2217    return QmPortalPullFrame(h_QmPortal, pdqcr, p_Frame);
2218}
2219
2220t_Error QM_FQR_Resume(t_Handle h_QmFqr, t_Handle h_QmPortal, uint32_t fqidOffset)
2221{
2222    t_QmFqr     *p_QmFqr = (t_QmFqr *)h_QmFqr;
2223
2224    SANITY_CHECK_RETURN_ERROR(p_QmFqr, E_INVALID_HANDLE);
2225    SANITY_CHECK_RETURN_ERROR((fqidOffset < p_QmFqr->numOfFqids), E_INVALID_VALUE);
2226
2227    if (!h_QmPortal)
2228    {
2229        SANITY_CHECK_RETURN_ERROR(p_QmFqr->h_Qm, E_INVALID_HANDLE);
2230        h_QmPortal = QmGetPortalHandle(p_QmFqr->h_Qm);
2231        SANITY_CHECK_RETURN_ERROR(h_QmPortal, E_INVALID_HANDLE);
2232    }
2233    return qman_schedule_fq(h_QmPortal, p_QmFqr->p_Fqs[fqidOffset]);
2234}
2235
2236t_Error  QM_FQR_Suspend(t_Handle h_QmFqr, t_Handle h_QmPortal, uint32_t fqidOffset)
2237{
2238    t_QmFqr     *p_QmFqr = (t_QmFqr *)h_QmFqr;
2239
2240    SANITY_CHECK_RETURN_ERROR(p_QmFqr, E_INVALID_HANDLE);
2241    SANITY_CHECK_RETURN_ERROR((fqidOffset < p_QmFqr->numOfFqids), E_INVALID_VALUE);
2242    SANITY_CHECK_RETURN_ERROR((p_QmFqr->p_Fqs[fqidOffset]->flags & QM_FQCTRL_HOLDACTIVE), E_INVALID_STATE);
2243
2244    UNUSED(h_QmPortal);
2245    p_QmFqr->p_Fqs[fqidOffset]->state = qman_fq_state_waiting_parked;
2246
2247    return E_OK;
2248}
2249
2250uint32_t QM_FQR_GetFqid(t_Handle h_QmFqr)
2251{
2252    t_QmFqr *p_QmFqr = (t_QmFqr *)h_QmFqr;
2253
2254    SANITY_CHECK_RETURN_VALUE(p_QmFqr, E_INVALID_HANDLE, 0);
2255
2256    return p_QmFqr->fqidBase;
2257}
2258
2259uint32_t QM_FQR_GetCounter(t_Handle h_QmFqr, t_Handle h_QmPortal, uint32_t fqidOffset, e_QmFqrCounters counter)
2260{
2261    t_QmFqr *p_QmFqr = (t_QmFqr *)h_QmFqr;
2262    struct qm_mcr_queryfq_np    queryfq_np;
2263
2264    SANITY_CHECK_RETURN_VALUE(p_QmFqr, E_INVALID_HANDLE, 0);
2265    SANITY_CHECK_RETURN_VALUE((fqidOffset < p_QmFqr->numOfFqids), E_INVALID_VALUE, 0);
2266
2267    if (!h_QmPortal)
2268    {
2269        SANITY_CHECK_RETURN_VALUE(p_QmFqr->h_Qm, E_INVALID_HANDLE, 0);
2270        h_QmPortal = QmGetPortalHandle(p_QmFqr->h_Qm);
2271        SANITY_CHECK_RETURN_VALUE(h_QmPortal, E_INVALID_HANDLE, 0);
2272    }
2273    if (qman_query_fq_np(h_QmPortal, p_QmFqr->p_Fqs[fqidOffset], &queryfq_np) != E_OK)
2274        return 0;
2275    switch (counter)
2276    {
2277        case e_QM_FQR_COUNTERS_FRAME :
2278            return queryfq_np.frm_cnt;
2279        case e_QM_FQR_COUNTERS_BYTE :
2280            return queryfq_np.byte_cnt;
2281        default :
2282            break;
2283    }
2284    /* should never get here */
2285    ASSERT_COND(FALSE);
2286
2287    return 0;
2288}
2289
2290
2291t_Handle QM_CG_Create(t_QmCgParams *p_CgParams)
2292{
2293    t_QmCg                          *p_QmCg;
2294    t_QmPortal                      *p_QmPortal;
2295    t_Error                         err;
2296    uint32_t                        wredParams;
2297    uint32_t                        tmpA, tmpN, ta=0, tn=0;
2298    int                             gap, tmp;
2299    struct qm_mc_command            *p_Mcc;
2300    struct qm_mc_result             *p_Mcr;
2301
2302    SANITY_CHECK_RETURN_VALUE(p_CgParams, E_INVALID_HANDLE, NULL);
2303    SANITY_CHECK_RETURN_VALUE(p_CgParams->h_Qm, E_INVALID_HANDLE, NULL);
2304
2305    if(p_CgParams->notifyDcPortal &&
2306       ((p_CgParams->dcPortalId == e_DPAA_DCPORTAL2) || (p_CgParams->dcPortalId == e_DPAA_DCPORTAL3)))
2307    {
2308        REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("notifyDcPortal is invalid for this DC Portal"));
2309        return NULL;
2310    }
2311
2312    if (!p_CgParams->h_QmPortal)
2313    {
2314        p_QmPortal = QmGetPortalHandle(p_CgParams->h_Qm);
2315        SANITY_CHECK_RETURN_VALUE(p_QmPortal, E_INVALID_STATE, NULL);
2316    }
2317    else
2318        p_QmPortal = p_CgParams->h_QmPortal;
2319
2320    p_QmCg = (t_QmCg *)XX_Malloc(sizeof(t_QmCg));
2321    if (!p_QmCg)
2322    {
2323        REPORT_ERROR(MAJOR, E_NO_MEMORY, ("QM CG obj!!!"));
2324        return NULL;
2325    }
2326    memset(p_QmCg, 0, sizeof(t_QmCg));
2327
2328    /* build CG struct */
2329    p_QmCg->h_Qm        = p_CgParams->h_Qm;
2330    p_QmCg->h_QmPortal  = p_QmPortal;
2331    p_QmCg->h_App       = p_CgParams->h_App;
2332    err = QmGetCgId(p_CgParams->h_Qm, &p_QmCg->id);
2333    if (err)
2334    {
2335        XX_Free(p_QmCg);
2336        REPORT_ERROR(MAJOR, E_INVALID_STATE, ("QmGetCgId failed"));
2337        return NULL;
2338    }
2339
2340    NCSW_PLOCK(p_QmPortal);
2341    p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal);
2342    p_Mcc->initcgr.cgid = p_QmCg->id;
2343
2344    err = QmPortalRegisterCg(p_QmPortal, p_QmCg, p_QmCg->id);
2345    if (err)
2346    {
2347        XX_Free(p_QmCg);
2348        PUNLOCK(p_QmPortal);
2349        REPORT_ERROR(MAJOR, E_INVALID_STATE, ("QmPortalRegisterCg failed"));
2350        return NULL;
2351    }
2352
2353    /*  Build CGR command */
2354    {
2355#ifdef QM_CGS_NO_FRAME_MODE
2356    t_QmRevisionInfo    revInfo;
2357
2358    QmGetRevision(p_QmCg->h_Qm, &revInfo);
2359
2360    if (!((revInfo.majorRev == 1) && (revInfo.minorRev == 0)))
2361#endif /* QM_CGS_NO_FRAME_MODE */
2362        if (p_CgParams->frameCount)
2363        {
2364            p_Mcc->initcgr.we_mask |= QM_CGR_WE_MODE;
2365            p_Mcc->initcgr.cgr.frame_mode = QM_CGR_EN;
2366        }
2367    }
2368
2369    if (p_CgParams->wredEnable)
2370    {
2371        if (p_CgParams->wredParams.enableGreen)
2372        {
2373            err = CalcWredCurve(&p_CgParams->wredParams.greenCurve, &wredParams);
2374            if(err)
2375            {
2376                XX_Free(p_QmCg);
2377                PUNLOCK(p_QmPortal);
2378                REPORT_ERROR(MAJOR, err, NO_MSG);
2379                return NULL;
2380            }
2381            p_Mcc->initcgr.we_mask |= QM_CGR_WE_WR_EN_G | QM_CGR_WE_WR_PARM_G;
2382            p_Mcc->initcgr.cgr.wr_en_g = QM_CGR_EN;
2383            p_Mcc->initcgr.cgr.wr_parm_g.word = wredParams;
2384        }
2385        if (p_CgParams->wredParams.enableYellow)
2386        {
2387            err = CalcWredCurve(&p_CgParams->wredParams.yellowCurve, &wredParams);
2388            if(err)
2389            {
2390                XX_Free(p_QmCg);
2391                PUNLOCK(p_QmPortal);
2392                REPORT_ERROR(MAJOR, err, NO_MSG);
2393                return NULL;
2394            }
2395            p_Mcc->initcgr.we_mask |= QM_CGR_WE_WR_EN_Y | QM_CGR_WE_WR_PARM_Y;
2396            p_Mcc->initcgr.cgr.wr_en_y = QM_CGR_EN;
2397            p_Mcc->initcgr.cgr.wr_parm_y.word = wredParams;
2398        }
2399        if (p_CgParams->wredParams.enableRed)
2400        {
2401            err = CalcWredCurve(&p_CgParams->wredParams.redCurve, &wredParams);
2402            if(err)
2403            {
2404                XX_Free(p_QmCg);
2405                PUNLOCK(p_QmPortal);
2406                REPORT_ERROR(MAJOR, err, NO_MSG);
2407                return NULL;
2408            }
2409            p_Mcc->initcgr.we_mask |= QM_CGR_WE_WR_EN_R | QM_CGR_WE_WR_PARM_R;
2410            p_Mcc->initcgr.cgr.wr_en_r = QM_CGR_EN;
2411            p_Mcc->initcgr.cgr.wr_parm_r.word = wredParams;
2412        }
2413    }
2414
2415    if (p_CgParams->tailDropEnable)
2416    {
2417        if (!p_CgParams->threshold)
2418        {
2419            XX_Free(p_QmCg);
2420            PUNLOCK(p_QmPortal);
2421            REPORT_ERROR(MINOR, E_INVALID_STATE, ("tailDropThreshold must be configured if tailDropEnable "));
2422            return NULL;
2423        }
2424        p_Mcc->initcgr.cgr.cstd_en = QM_CGR_EN;
2425        p_Mcc->initcgr.we_mask |= QM_CGR_WE_CSTD_EN;
2426    }
2427
2428    if (p_CgParams->threshold)
2429    {
2430        p_Mcc->initcgr.we_mask |= QM_CGR_WE_CS_THRES;
2431        p_QmCg->f_Exception = p_CgParams->f_Exception;
2432        if (p_QmCg->f_Exception || p_CgParams->notifyDcPortal)
2433        {
2434            p_Mcc->initcgr.cgr.cscn_en = QM_CGR_EN;
2435            p_Mcc->initcgr.we_mask |= QM_CGR_WE_CSCN_EN | QM_CGR_WE_CSCN_TARG;
2436            /* if SW - set target, if HW - if FM, set HW target, otherwize, set SW target */
2437            p_Mcc->initcgr.cgr.cscn_targ = 0;
2438            if (p_QmCg->f_Exception)
2439                p_Mcc->initcgr.cgr.cscn_targ = (uint32_t)QM_CGR_TARGET_SWP(QmPortalGetSwPortalId(p_QmCg->h_QmPortal));
2440            if (p_CgParams->notifyDcPortal)
2441                p_Mcc->initcgr.cgr.cscn_targ |= (uint32_t)QM_CGR_TARGET_DCP(p_CgParams->dcPortalId);
2442        }
2443
2444        /* express thresh as ta*2^tn */
2445        gap = (int)p_CgParams->threshold;
2446        for (tmpA=0 ; tmpA<256; tmpA++ )
2447            for (tmpN=0 ; tmpN<32; tmpN++ )
2448            {
2449                tmp = ABS((int)(p_CgParams->threshold - tmpA*(1<<tmpN)));
2450                if (tmp < gap)
2451                {
2452                   ta = tmpA;
2453                   tn = tmpN;
2454                   gap = tmp;
2455                }
2456            }
2457        p_Mcc->initcgr.cgr.cs_thres.TA = ta;
2458        p_Mcc->initcgr.cgr.cs_thres.Tn = tn;
2459    }
2460    else if(p_CgParams->f_Exception)
2461    {
2462        XX_Free(p_QmCg);
2463        PUNLOCK(p_QmPortal);
2464        REPORT_ERROR(MINOR, E_INVALID_STATE, ("No threshold configured, but f_Exception defined"));
2465        return NULL;
2466    }
2467
2468    qm_mc_commit(p_QmPortal->p_LowQmPortal, QM_MCC_VERB_INITCGR);
2469    while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ;
2470    ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) == QM_MCC_VERB_INITCGR);
2471    if (p_Mcr->result != QM_MCR_RESULT_OK)
2472    {
2473        XX_Free(p_QmCg);
2474        PUNLOCK(p_QmPortal);
2475        REPORT_ERROR(MINOR, E_INVALID_STATE, ("INITCGR failed: %s", mcr_result_str(p_Mcr->result)));
2476        return NULL;
2477    }
2478    PUNLOCK(p_QmPortal);
2479
2480    return p_QmCg;
2481}
2482
2483t_Error QM_CG_Free(t_Handle h_QmCg)
2484{
2485
2486    t_QmCg                  *p_QmCg = (t_QmCg *)h_QmCg;
2487    t_Error                 err;
2488    struct qm_mc_command    *p_Mcc;
2489    struct qm_mc_result     *p_Mcr;
2490    t_QmPortal              *p_QmPortal;
2491
2492    SANITY_CHECK_RETURN_ERROR(p_QmCg, E_INVALID_HANDLE);
2493
2494    p_QmPortal = (t_QmPortal *)p_QmCg->h_QmPortal;
2495
2496    NCSW_PLOCK(p_QmPortal);
2497    p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal);
2498    p_Mcc->initcgr.cgid = p_QmCg->id;
2499    p_Mcc->initcgr.we_mask = QM_CGR_WE_MASK;
2500
2501    err = QmFreeCgId(p_QmCg->h_Qm, p_QmCg->id);
2502    if(err)
2503    {
2504        XX_Free(p_QmCg);
2505        PUNLOCK(p_QmPortal);
2506        RETURN_ERROR(MAJOR, E_INVALID_STATE, ("QmFreeCgId failed"));
2507    }
2508
2509    err = QmPortalUnregisterCg(p_QmCg->h_QmPortal, p_QmCg->id);
2510    if(err)
2511    {
2512        XX_Free(p_QmCg);
2513        PUNLOCK(p_QmPortal);
2514        RETURN_ERROR(MAJOR, E_INVALID_STATE, ("QmPortalUnregisterCg failed"));
2515    }
2516
2517    qm_mc_commit(p_QmPortal->p_LowQmPortal, QM_MCC_VERB_MODIFYCGR);
2518    while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ;
2519    ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) == QM_MCC_VERB_MODIFYCGR);
2520    if (p_Mcr->result != QM_MCR_RESULT_OK)
2521    {
2522        PUNLOCK(p_QmPortal);
2523        RETURN_ERROR(MINOR, E_INVALID_STATE, ("INITCGR failed: %s", mcr_result_str(p_Mcr->result)));
2524    }
2525    PUNLOCK(p_QmPortal);
2526
2527    XX_Free(p_QmCg);
2528
2529    return E_OK;
2530}
2531
2532t_Error QM_CG_SetException(t_Handle h_QmCg, e_QmExceptions exception, bool enable)
2533{
2534    t_QmCg                  *p_QmCg = (t_QmCg *)h_QmCg;
2535    struct qm_mc_command    *p_Mcc;
2536    struct qm_mc_result     *p_Mcr;
2537    t_QmPortal              *p_QmPortal;
2538
2539    SANITY_CHECK_RETURN_ERROR(p_QmCg, E_INVALID_HANDLE);
2540
2541    p_QmPortal = (t_QmPortal *)p_QmCg->h_QmPortal;
2542    if (!p_QmCg->f_Exception)
2543        RETURN_ERROR(MINOR, E_INVALID_VALUE, ("Either threshold or exception callback was not configured."));
2544
2545    NCSW_PLOCK(p_QmPortal);
2546    p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal);
2547    p_Mcc->initcgr.cgid = p_QmCg->id;
2548    p_Mcc->initcgr.we_mask = QM_CGR_WE_CSCN_EN;
2549
2550    if(exception == e_QM_EX_CG_STATE_CHANGE)
2551    {
2552        if(enable)
2553            p_Mcc->initcgr.cgr.cscn_en = QM_CGR_EN;
2554    }
2555    else
2556    {
2557        PUNLOCK(p_QmPortal);
2558        RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal exception"));
2559    }
2560
2561    qm_mc_commit(p_QmPortal->p_LowQmPortal, QM_MCC_VERB_MODIFYCGR);
2562    while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ;
2563    ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) == QM_MCC_VERB_MODIFYCGR);
2564    if (p_Mcr->result != QM_MCR_RESULT_OK)
2565    {
2566        PUNLOCK(p_QmPortal);
2567        RETURN_ERROR(MINOR, E_INVALID_STATE, ("INITCGR failed: %s", mcr_result_str(p_Mcr->result)));
2568    }
2569    PUNLOCK(p_QmPortal);
2570
2571    return E_OK;
2572}
2573
2574t_Error QM_CG_ModifyWredCurve(t_Handle h_QmCg, t_QmCgModifyWredParams *p_QmCgModifyParams)
2575{
2576    t_QmCg                  *p_QmCg = (t_QmCg *)h_QmCg;
2577    uint32_t                wredParams;
2578    struct qm_mc_command    *p_Mcc;
2579    struct qm_mc_result     *p_Mcr;
2580    t_QmPortal              *p_QmPortal;
2581    t_Error                 err = E_OK;
2582
2583    SANITY_CHECK_RETURN_ERROR(p_QmCg, E_INVALID_HANDLE);
2584
2585    p_QmPortal = (t_QmPortal *)p_QmCg->h_QmPortal;
2586
2587    NCSW_PLOCK(p_QmPortal);
2588    p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal);
2589    p_Mcc->initcgr.cgid = p_QmCg->id;
2590
2591    qm_mc_commit(p_QmPortal->p_LowQmPortal, QM_MCC_VERB_QUERYCGR);
2592    while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ;
2593    ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) == QM_MCC_VERB_QUERYCGR);
2594    if (p_Mcr->result != QM_MCR_RESULT_OK)
2595    {
2596        PUNLOCK(p_QmPortal);
2597        RETURN_ERROR(MINOR, E_INVALID_STATE, ("QM_MCC_VERB_QUERYCGR failed: %s", mcr_result_str(p_Mcr->result)));
2598    }
2599
2600    switch(p_QmCgModifyParams->color)
2601    {
2602        case(e_QM_CG_COLOR_GREEN):
2603            if(!p_Mcr->querycgr.cgr.wr_en_g)
2604            {
2605                PUNLOCK(p_QmPortal);
2606                RETURN_ERROR(MINOR, E_INVALID_STATE, ("WRED is not enabled for green"));
2607            }
2608            break;
2609        case(e_QM_CG_COLOR_YELLOW):
2610            if(!p_Mcr->querycgr.cgr.wr_en_y)
2611            {
2612                PUNLOCK(p_QmPortal);
2613                RETURN_ERROR(MINOR, E_INVALID_STATE, ("WRED is not enabled for yellow"));
2614            }
2615            break;
2616        case(e_QM_CG_COLOR_RED):
2617            if(!p_Mcr->querycgr.cgr.wr_en_r)
2618            {
2619                PUNLOCK(p_QmPortal);
2620                RETURN_ERROR(MINOR, E_INVALID_STATE, ("WRED is not enabled for red"));
2621            }
2622            break;
2623    }
2624
2625    p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal);
2626    p_Mcc->initcgr.cgid = p_QmCg->id;
2627
2628    switch(p_QmCgModifyParams->color)
2629    {
2630        case(e_QM_CG_COLOR_GREEN):
2631            err = CalcWredCurve(&p_QmCgModifyParams->wredParams, &wredParams);
2632            p_Mcc->initcgr.we_mask |= QM_CGR_WE_WR_EN_G | QM_CGR_WE_WR_PARM_G;
2633            p_Mcc->initcgr.cgr.wr_en_g = QM_CGR_EN;
2634            p_Mcc->initcgr.cgr.wr_parm_g.word = wredParams;
2635            break;
2636        case(e_QM_CG_COLOR_YELLOW):
2637            err = CalcWredCurve(&p_QmCgModifyParams->wredParams, &wredParams);
2638            p_Mcc->initcgr.we_mask |= QM_CGR_WE_WR_EN_Y | QM_CGR_WE_WR_PARM_Y;
2639            p_Mcc->initcgr.cgr.wr_en_y = QM_CGR_EN;
2640            p_Mcc->initcgr.cgr.wr_parm_y.word = wredParams;
2641            break;
2642        case(e_QM_CG_COLOR_RED):
2643            err = CalcWredCurve(&p_QmCgModifyParams->wredParams, &wredParams);
2644            p_Mcc->initcgr.we_mask |= QM_CGR_WE_WR_EN_R | QM_CGR_WE_WR_PARM_R;
2645            p_Mcc->initcgr.cgr.wr_en_r = QM_CGR_EN;
2646            p_Mcc->initcgr.cgr.wr_parm_r.word = wredParams;
2647            break;
2648    }
2649    if (err)
2650    {
2651        PUNLOCK(p_QmPortal);
2652        RETURN_ERROR(MINOR, err, NO_MSG);
2653    }
2654
2655    qm_mc_commit(p_QmPortal->p_LowQmPortal, QM_MCC_VERB_MODIFYCGR);
2656    while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ;
2657    ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) == QM_MCC_VERB_MODIFYCGR);
2658    if (p_Mcr->result != QM_MCR_RESULT_OK)
2659    {
2660        PUNLOCK(p_QmPortal);
2661        RETURN_ERROR(MINOR, E_INVALID_STATE, ("INITCGR failed: %s", mcr_result_str(p_Mcr->result)));
2662    }
2663    PUNLOCK(p_QmPortal);
2664
2665    return E_OK;
2666}
2667
2668t_Error QM_CG_ModifyTailDropThreshold(t_Handle h_QmCg, uint32_t threshold)
2669{
2670    t_QmCg                  *p_QmCg = (t_QmCg *)h_QmCg;
2671    struct qm_mc_command    *p_Mcc;
2672    struct qm_mc_result     *p_Mcr;
2673    t_QmPortal              *p_QmPortal;
2674    uint32_t                tmpA, tmpN, ta=0, tn=0;
2675    int                     gap, tmp;
2676
2677    SANITY_CHECK_RETURN_ERROR(p_QmCg, E_INVALID_HANDLE);
2678
2679    p_QmPortal = (t_QmPortal *)p_QmCg->h_QmPortal;
2680
2681    NCSW_PLOCK(p_QmPortal);
2682    p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal);
2683    p_Mcc->initcgr.cgid = p_QmCg->id;
2684
2685    qm_mc_commit(p_QmPortal->p_LowQmPortal, QM_MCC_VERB_QUERYCGR);
2686    while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ;
2687    ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) == QM_MCC_VERB_QUERYCGR);
2688    if (p_Mcr->result != QM_MCR_RESULT_OK)
2689    {
2690        PUNLOCK(p_QmPortal);
2691        RETURN_ERROR(MINOR, E_INVALID_STATE, ("QM_MCC_VERB_QUERYCGR failed: %s", mcr_result_str(p_Mcr->result)));
2692    }
2693
2694    if(!p_Mcr->querycgr.cgr.cstd_en)
2695    {
2696        PUNLOCK(p_QmPortal);
2697        RETURN_ERROR(MINOR, E_INVALID_STATE, ("Tail Drop is not enabled!"));
2698    }
2699
2700    p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal);
2701    p_Mcc->initcgr.cgid = p_QmCg->id;
2702    p_Mcc->initcgr.we_mask |= QM_CGR_WE_CS_THRES;
2703
2704    /* express thresh as ta*2^tn */
2705    gap = (int)threshold;
2706    for (tmpA=0 ; tmpA<256; tmpA++ )
2707        for (tmpN=0 ; tmpN<32; tmpN++ )
2708        {
2709            tmp = ABS((int)(threshold - tmpA*(1<<tmpN)));
2710            if (tmp < gap)
2711            {
2712               ta = tmpA;
2713               tn = tmpN;
2714               gap = tmp;
2715            }
2716        }
2717    p_Mcc->initcgr.cgr.cs_thres.TA = ta;
2718    p_Mcc->initcgr.cgr.cs_thres.Tn = tn;
2719
2720    qm_mc_commit(p_QmPortal->p_LowQmPortal, QM_MCC_VERB_MODIFYCGR);
2721    while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ;
2722    ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) == QM_MCC_VERB_MODIFYCGR);
2723    if (p_Mcr->result != QM_MCR_RESULT_OK)
2724    {
2725        PUNLOCK(p_QmPortal);
2726        RETURN_ERROR(MINOR, E_INVALID_STATE, ("INITCGR failed: %s", mcr_result_str(p_Mcr->result)));
2727    }
2728    PUNLOCK(p_QmPortal);
2729
2730    return E_OK;
2731}
2732
2733