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 */
71 CTASSERT((VM_MAX_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS) < (1ULL << 35));
72 static inline uint32_t
aligned_int_from_ptr(const void * p)73 aligned_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
85 static inline void *
ptr_from_aligned_int(uint32_t ctx)86 ptr_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
qman_volatile_dequeue(t_QmPortal * p_QmPortal,struct qman_fq * p_Fq,uint32_t vdqcr)96 static 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
mcr_result_str(uint8_t result)116 static 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
qman_create_fq(t_QmPortal * p_QmPortal,uint32_t fqid,uint32_t flags,struct qman_fq * p_Fq)135 static 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
qman_destroy_fq(struct qman_fq * p_Fq,uint32_t flags)205 static 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
qman_init_fq(t_QmPortal * p_QmPortal,struct qman_fq * p_Fq,uint32_t flags,struct qm_mcc_initfq * p_Opts)221 static 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
qman_retire_fq(t_QmPortal * p_QmPortal,struct qman_fq * p_Fq,uint32_t * p_Flags,bool drain)274 static 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;
326 out:
327 FQUNLOCK(p_Fq);
328 PUNLOCK(p_QmPortal);
329 return err;
330 }
331
qman_oos_fq(t_QmPortal * p_QmPortal,struct qman_fq * p_Fq)332 static 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
qman_schedule_fq(t_QmPortal * p_QmPortal,struct qman_fq * p_Fq)367 static 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() */
fq_state_change(struct qman_fq * p_Fq,struct qm_mr_entry * p_Msg,uint8_t verb)404 static __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
freeDrainedFq(struct qman_fq * p_Fq)433 static 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
drainRetiredFq(struct qman_fq * p_Fq)471 static 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
drainCB(t_Handle h_App,t_Handle h_QmFqr,t_Handle h_QmPortal,uint32_t fqidOffset,t_DpaaFD * p_Frame)491 static 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
cb_ern_dcErn(t_Handle h_App,t_Handle h_QmPortal,struct qman_fq * p_Fq,const struct qm_mr_entry * p_Msg)507 static 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
cb_fqs(t_Handle h_App,t_Handle h_QmPortal,struct qman_fq * p_Fq,const struct qm_mr_entry * p_Msg)521 static 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
null_cb_mr(t_Handle h_App,t_Handle h_QmPortal,struct qman_fq * p_Fq,const struct qm_mr_entry * p_Msg)535 static 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
LoopMessageRing(t_QmPortal * p_QmPortal,uint32_t is)552 static 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) {
606 mr_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
LoopDequeueRing(t_Handle h_QmPortal)671 static 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
LoopDequeueRingDcaOptimized(t_Handle h_QmPortal)756 static 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
LoopDequeueRingOptimized(t_Handle h_QmPortal)830 static 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 */
portal_isr(void * ptr)904 static 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
qman_query_fq_np(t_QmPortal * p_QmPortal,struct qman_fq * p_Fq,struct qm_mcr_queryfq_np * p_Np)925 static 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
QmCgGetCgId(t_Handle h_QmCg)946 static 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
qm_new_fq(t_QmPortal * p_QmPortal,uint32_t fqid,uint32_t fqidOffset,uint32_t channel,uint32_t wqid,uint16_t count,uint32_t flags,t_QmFqrCongestionAvoidanceParams * p_CgParams,t_QmContextA * p_ContextA,t_QmContextB * p_ContextB,bool initParked,t_Handle h_QmFqr,struct qman_fq ** p_Fqs)954 static 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
qm_free_fq(t_QmPortal * p_QmPortal,struct qman_fq * p_Fq)1135 static 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
qman_disable_portal(t_QmPortal * p_QmPortal)1157 static 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). */
clean_dqrr_mr(t_QmPortal * p_QmPortal)1168 static 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);
1176 drain_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
qman_create_portal(t_QmPortal * p_QmPortal,uint32_t flags,uint32_t sdqcrFlags,uint8_t dqrrSize)1201 static 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"));
1267 goto 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"));
1272 goto 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;
1277 fail_dqrr_mr_empty:
1278 fail_eqcr_empty:
1279 qm_isr_finish(p_QmPortal->p_LowQmPortal);
1280 fail_isr:
1281 qm_mc_finish(p_QmPortal->p_LowQmPortal);
1282 fail_mc:
1283 qm_mr_finish(p_QmPortal->p_LowQmPortal);
1284 fail_mr:
1285 qm_dqrr_finish(p_QmPortal->p_LowQmPortal);
1286 fail_dqrr:
1287 qm_eqcr_finish(p_QmPortal->p_LowQmPortal);
1288 return ERROR_CODE(E_INVALID_STATE);
1289 }
1290
qman_destroy_portal(t_QmPortal * p_QmPortal)1291 static 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
try_eq_start(t_QmPortal * p_QmPortal)1308 static 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
qman_orp_update(t_QmPortal * p_QmPortal,uint32_t orpId,uint16_t orpSeqnum,uint32_t flags)1324 static 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;
1346 qmPortalEqcrPvbCommit(p_QmPortal->p_LowQmPortal, (uint8_t)QM_EQCR_VERB_ORP);
1347
1348 PUNLOCK(p_QmPortal);
1349 return E_OK;
1350 }
1351
CheckStashParams(t_QmFqrParams * p_QmFqrParams)1352 static __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
QmPortalRegisterCg(t_Handle h_QmPortal,t_Handle h_QmCg,uint8_t cgId)1375 static 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
QmPortalUnregisterCg(t_Handle h_QmPortal,uint8_t cgId)1389 static 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
QmPortalGetSwPortalId(t_Handle h_QmPortal)1403 static 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
CalcWredCurve(t_QmCgWredCurve * p_WredCurve,uint32_t * p_CurveWord)1410 static 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
QmPortalPullFrame(t_Handle h_QmPortal,uint32_t pdqcr,t_DpaaFD * p_Frame)1492 static 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 /****************************************/
QM_PORTAL_Config(t_QmPortalParam * p_QmPortalParam)1552 t_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
QM_PORTAL_Init(t_Handle h_QmPortal)1619 t_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
QM_PORTAL_Free(t_Handle h_QmPortal)1713 t_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
QM_PORTAL_ConfigDcaMode(t_Handle h_QmPortal,bool enable)1736 t_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
QM_PORTAL_ConfigStash(t_Handle h_QmPortal,t_QmPortalStashParam * p_StashParams)1748 t_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
QM_PORTAL_ConfigPullMode(t_Handle h_QmPortal,bool pullMode)1771 t_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
QM_PORTAL_AddPoolChannel(t_Handle h_QmPortal,uint8_t poolChannelId)1783 t_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
QM_PORTAL_Poll(t_Handle h_QmPortal,e_QmPortalPollSource source)1798 t_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
QM_PORTAL_PollFrame(t_Handle h_QmPortal,t_QmPortalFrameInfo * p_frameInfo)1823 t_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
QM_FQR_Create(t_QmFqrParams * p_QmFqrParams)1877 t_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
QM_FQR_Free(t_Handle h_QmFqr)2029 t_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
QM_FQR_FreeWDrain(t_Handle h_QmFqr,t_QmFqrDrainedCompletionCB * f_CompletionCB,bool deliverFrame,t_QmReceivedFrameCallback * f_CallBack,t_Handle h_App)2057 t_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
QM_FQR_RegisterCB(t_Handle h_QmFqr,t_QmReceivedFrameCallback * f_CallBack,t_Handle h_App)2120 t_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
QM_FQR_Enqueue(t_Handle h_QmFqr,t_Handle h_QmPortal,uint32_t fqidOffset,t_DpaaFD * p_Frame)2136 t_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
QM_FQR_PullFrame(t_Handle h_QmFqr,t_Handle h_QmPortal,uint32_t fqidOffset,t_DpaaFD * p_Frame)2197 t_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
QM_FQR_Resume(t_Handle h_QmFqr,t_Handle h_QmPortal,uint32_t fqidOffset)2220 t_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
QM_FQR_Suspend(t_Handle h_QmFqr,t_Handle h_QmPortal,uint32_t fqidOffset)2236 t_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
QM_FQR_GetFqid(t_Handle h_QmFqr)2250 uint32_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
QM_FQR_GetCounter(t_Handle h_QmFqr,t_Handle h_QmPortal,uint32_t fqidOffset,e_QmFqrCounters counter)2259 uint32_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
QM_CG_Create(t_QmCgParams * p_CgParams)2291 t_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
QM_CG_Free(t_Handle h_QmCg)2483 t_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
QM_CG_SetException(t_Handle h_QmCg,e_QmExceptions exception,bool enable)2532 t_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
QM_CG_ModifyWredCurve(t_Handle h_QmCg,t_QmCgModifyWredParams * p_QmCgModifyParams)2574 t_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
QM_CG_ModifyTailDropThreshold(t_Handle h_QmCg,uint32_t threshold)2668 t_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