blob: 211203dffd512e3a9b6d04ceeafe245d59b3833c [file] [log] [blame]
Wolfgang Denk4646d2a2006-05-30 15:56:48 +02001/**
2 * @file IxEthAccCommon.c
3 *
4 * @author Intel Corporation
5 * @date 12-Feb-2002
6 *
7 * @brief This file contains the implementation common support routines for the component
8 *
9 * Design Notes:
10 *
11 * @par
12 * IXP400 SW Release version 2.0
13 *
14 * -- Copyright Notice --
15 *
16 * @par
17 * Copyright 2001-2005, Intel Corporation.
18 * All rights reserved.
19 *
20 * @par
21 * Redistribution and use in source and binary forms, with or without
22 * modification, are permitted provided that the following conditions
23 * are met:
24 * 1. Redistributions of source code must retain the above copyright
25 * notice, this list of conditions and the following disclaimer.
26 * 2. Redistributions in binary form must reproduce the above copyright
27 * notice, this list of conditions and the following disclaimer in the
28 * documentation and/or other materials provided with the distribution.
29 * 3. Neither the name of the Intel Corporation nor the names of its contributors
30 * may be used to endorse or promote products derived from this software
31 * without specific prior written permission.
32 *
33 * @par
34 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
35 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
36 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
37 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
38 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
39 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
40 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
41 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
42 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
43 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
44 * SUCH DAMAGE.
45 *
46 * @par
47 * -- End of Copyright Notice --
48 */
49
50/*
51 * Component header files
52 */
53
54#include "IxOsal.h"
55#include "IxEthAcc.h"
56#include "IxEthDB.h"
57#include "IxNpeMh.h"
58#include "IxEthDBPortDefs.h"
59#include "IxFeatureCtrl.h"
60#include "IxEthAcc_p.h"
61#include "IxEthAccQueueAssign_p.h"
62
63#include "IxEthAccDataPlane_p.h"
64#include "IxEthAccMii_p.h"
65
66/**
67 * @addtogroup IxEthAccPri
68 *@{
69 */
70
71extern IxEthAccInfo ixEthAccDataInfo;
72
73/**
74 *
75 * @brief Maximum number of RX queues set to be the maximum number
76 * of traffic calsses.
77 *
78 */
79#define IX_ETHACC_MAX_RX_QUEUES \
80 (IX_ETH_DB_QOS_TRAFFIC_CLASS_7_RX_QUEUE_PROPERTY \
81 - IX_ETH_DB_QOS_TRAFFIC_CLASS_0_RX_QUEUE_PROPERTY \
82 + 1)
83
84/**
85 *
86 * @brief Maximum number of 128 entry RX queues
87 *
88 */
89#define IX_ETHACC_MAX_LARGE_RX_QUEUES 4
90
91/**
92 *
93 * @brief Data structure template for Default RX Queues
94 *
95 */
96IX_ETH_ACC_PRIVATE
97IxEthAccQregInfo ixEthAccQmgrRxDefaultTemplate =
98 {
Wolfgang Denka1be4762008-05-20 16:00:29 +020099 IX_ETH_ACC_RX_FRAME_ETH_Q, /**< Queue ID */
Wolfgang Denk4646d2a2006-05-30 15:56:48 +0200100 "Eth Rx Q",
101 ixEthRxFrameQMCallback, /**< Functional callback */
102 (IxQMgrCallbackId) 0, /**< Callback tag */
103 IX_QMGR_Q_SIZE128, /**< Allocate Max Size Q */
104 IX_QMGR_Q_ENTRY_SIZE1, /**< Queue Entry Sizes - all Q entries are single word entries */
105 TRUE, /**< Enable Q notification at startup */
106 IX_ETH_ACC_RX_FRAME_ETH_Q_SOURCE,/**< Q Condition to drive callback */
Wolfgang Denka1be4762008-05-20 16:00:29 +0200107 IX_QMGR_Q_WM_LEVEL0, /**< Q Low water mark */
Wolfgang Denk4646d2a2006-05-30 15:56:48 +0200108 IX_QMGR_Q_WM_LEVEL1, /**< Q High water mark - needed by NPE */
109 };
110
111/**
112 *
113 * @brief Data structure template for Small RX Queues
114 *
115 */
116IX_ETH_ACC_PRIVATE
117IxEthAccQregInfo ixEthAccQmgrRxSmallTemplate =
118 {
Wolfgang Denka1be4762008-05-20 16:00:29 +0200119 IX_ETH_ACC_RX_FRAME_ETH_Q, /**< Queue ID */
Wolfgang Denk4646d2a2006-05-30 15:56:48 +0200120 "Eth Rx Q",
121 ixEthRxFrameQMCallback, /**< Functional callback */
122 (IxQMgrCallbackId) 0, /**< Callback tag */
123 IX_QMGR_Q_SIZE64, /**< Allocate Smaller Q */
124 IX_QMGR_Q_ENTRY_SIZE1, /**< Queue Entry Sizes - all Q entries are single word entries */
125 TRUE, /**< Enable Q notification at startup */
126 IX_ETH_ACC_RX_FRAME_ETH_Q_SOURCE,/**< Q Condition to drive callback */
Wolfgang Denka1be4762008-05-20 16:00:29 +0200127 IX_QMGR_Q_WM_LEVEL0, /**< Q Low water mark */
Wolfgang Denk4646d2a2006-05-30 15:56:48 +0200128 IX_QMGR_Q_WM_LEVEL1, /**< Q High water mark - needed by NPE */
129 };
130
131
132/**
133 *
134 * @brief Data structure used to register & initialize the Queues
135 *
136 */
137IX_ETH_ACC_PRIVATE
138IxEthAccQregInfo ixEthAccQmgrStaticInfo[]=
139{
140 {
141 IX_ETH_ACC_RX_FREE_BUFF_ENET0_Q,
142 "Eth Rx Fr Q 1",
143 ixEthRxFreeQMCallback,
144 (IxQMgrCallbackId) IX_ETH_PORT_1,
145 IX_QMGR_Q_SIZE128, /**< Allocate Max Size Q */
146 IX_QMGR_Q_ENTRY_SIZE1, /**< Queue Entry Sizes - all Q entries are single word entries */
147 FALSE, /**< Disable Q notification at startup */
148 IX_ETH_ACC_RX_FREE_BUFF_ENET0_Q_SOURCE, /**< Q Condition to drive callback */
Wolfgang Denka1be4762008-05-20 16:00:29 +0200149 IX_QMGR_Q_WM_LEVEL0, /***< Q Low water mark */
Wolfgang Denk4646d2a2006-05-30 15:56:48 +0200150 IX_QMGR_Q_WM_LEVEL64, /**< Q High water mark */
151 },
152
153 {
154 IX_ETH_ACC_RX_FREE_BUFF_ENET1_Q,
155 "Eth Rx Fr Q 2",
156 ixEthRxFreeQMCallback,
157 (IxQMgrCallbackId) IX_ETH_PORT_2,
158 IX_QMGR_Q_SIZE128, /**< Allocate Max Size Q */
159 IX_QMGR_Q_ENTRY_SIZE1, /**< Queue Entry Sizes - all Q entries are single word entries */
160 FALSE, /**< Disable Q notification at startup */
161 IX_ETH_ACC_RX_FREE_BUFF_ENET1_Q_SOURCE, /**< Q Condition to drive callback */
Wolfgang Denka1be4762008-05-20 16:00:29 +0200162 IX_QMGR_Q_WM_LEVEL0, /**< Q Low water mark */
Wolfgang Denk4646d2a2006-05-30 15:56:48 +0200163 IX_QMGR_Q_WM_LEVEL64, /**< Q High water mark */
164 },
165#ifdef __ixp46X
166 {
167 IX_ETH_ACC_RX_FREE_BUFF_ENET2_Q,
168 "Eth Rx Fr Q 3",
169 ixEthRxFreeQMCallback,
170 (IxQMgrCallbackId) IX_ETH_PORT_3,
171 IX_QMGR_Q_SIZE128, /**< Allocate Max Size Q */
172 IX_QMGR_Q_ENTRY_SIZE1, /**< Queue Entry Sizes - all Q entries are single word entries */
173 FALSE, /**< Disable Q notification at startup */
174 IX_ETH_ACC_RX_FREE_BUFF_ENET2_Q_SOURCE, /**< Q Condition to drive callback */
Wolfgang Denka1be4762008-05-20 16:00:29 +0200175 IX_QMGR_Q_WM_LEVEL0, /**< Q Low water mark */
Wolfgang Denk4646d2a2006-05-30 15:56:48 +0200176 IX_QMGR_Q_WM_LEVEL64, /**< Q High water mark */
177 },
178#endif
179 {
180 IX_ETH_ACC_TX_FRAME_ENET0_Q,
181 "Eth Tx Q 1",
182 ixEthTxFrameQMCallback,
183 (IxQMgrCallbackId) IX_ETH_PORT_1,
184 IX_QMGR_Q_SIZE128, /**< Allocate Max Size Q */
185 IX_QMGR_Q_ENTRY_SIZE1, /**< Queue Entry Sizes - all Q entries are single word entries */
186 FALSE, /**< Disable Q notification at startup */
187 IX_ETH_ACC_TX_FRAME_ENET0_Q_SOURCE, /**< Q Condition to drive callback */
Wolfgang Denka1be4762008-05-20 16:00:29 +0200188 IX_QMGR_Q_WM_LEVEL0, /**< Q Low water mark */
Wolfgang Denk4646d2a2006-05-30 15:56:48 +0200189 IX_QMGR_Q_WM_LEVEL64, /**< Q High water mark */
190 },
191
192 {
193 IX_ETH_ACC_TX_FRAME_ENET1_Q,
194 "Eth Tx Q 2",
195 ixEthTxFrameQMCallback,
196 (IxQMgrCallbackId) IX_ETH_PORT_2,
197 IX_QMGR_Q_SIZE128, /**< Allocate Max Size Q */
198 IX_QMGR_Q_ENTRY_SIZE1, /**< Queue Entry Sizes - all Q entries are single word entries */
199 FALSE, /**< Disable Q notification at startup */
200 IX_ETH_ACC_TX_FRAME_ENET1_Q_SOURCE, /**< Q Condition to drive callback */
Wolfgang Denka1be4762008-05-20 16:00:29 +0200201 IX_QMGR_Q_WM_LEVEL0, /**< Q Low water mark */
Wolfgang Denk4646d2a2006-05-30 15:56:48 +0200202 IX_QMGR_Q_WM_LEVEL64, /**< Q High water mark */
203 },
204#ifdef __ixp46X
205 {
206 IX_ETH_ACC_TX_FRAME_ENET2_Q,
207 "Eth Tx Q 3",
208 ixEthTxFrameQMCallback,
209 (IxQMgrCallbackId) IX_ETH_PORT_3,
210 IX_QMGR_Q_SIZE128, /**< Allocate Max Size Q */
211 IX_QMGR_Q_ENTRY_SIZE1, /** Queue Entry Sizes - all Q entries are single ord entries */
212 FALSE, /** Disable Q notification at startup */
213 IX_ETH_ACC_TX_FRAME_ENET2_Q_SOURCE, /** Q Condition to drive callback */
Wolfgang Denka1be4762008-05-20 16:00:29 +0200214 IX_QMGR_Q_WM_LEVEL0, /* No queues use almost empty */
Wolfgang Denk4646d2a2006-05-30 15:56:48 +0200215 IX_QMGR_Q_WM_LEVEL64, /** Q High water mark - needed used */
216 },
217#endif
218 {
219 IX_ETH_ACC_TX_FRAME_DONE_ETH_Q,
220 "Eth Tx Done Q",
221 ixEthTxFrameDoneQMCallback,
222 (IxQMgrCallbackId) 0,
223 IX_QMGR_Q_SIZE128, /**< Allocate Max Size Q */
224 IX_QMGR_Q_ENTRY_SIZE1, /**< Queue Entry Sizes - all Q entries are single word entries */
225 TRUE, /**< Enable Q notification at startup */
226 IX_ETH_ACC_TX_FRAME_DONE_ETH_Q_SOURCE, /**< Q Condition to drive callback */
Wolfgang Denka1be4762008-05-20 16:00:29 +0200227 IX_QMGR_Q_WM_LEVEL0, /**< Q Low water mark */
Wolfgang Denk4646d2a2006-05-30 15:56:48 +0200228 IX_QMGR_Q_WM_LEVEL2, /**< Q High water mark - needed by NPE */
229 },
230
231 { /* Null Termination entry
232 */
233 (IxQMgrQId)0,
234 (char *) NULL,
235 (IxQMgrCallback) NULL,
236 (IxQMgrCallbackId) 0,
237 0,
238 0,
239 0,
240 0,
241 0,
242 0
243 }
244
245};
246
247/**
248 *
249 * @brief Data structure used to register & initialize the Queues
250 *
251 * The structure will be filled at run time depending on the NPE
252 * image already loaded and the QoS configured in ethDB.
253 *
254 */
255IX_ETH_ACC_PRIVATE
256IxEthAccQregInfo ixEthAccQmgrRxQueuesInfo[IX_ETHACC_MAX_RX_QUEUES+1]=
257{
258 { /* PlaceHolder for rx queues
259 * depending on the QoS configured
260 */
261 (IxQMgrQId)0,
262 (char *) NULL,
263 (IxQMgrCallback) NULL,
264 (IxQMgrCallbackId) 0,
265 0,
266 0,
267 0,
268 0,
269 0,
270 0
271 },
272
273 { /* PlaceHolder for rx queues
274 * depending on the QoS configured
275 */
276 (IxQMgrQId)0,
277 (char *) NULL,
278 (IxQMgrCallback) NULL,
279 (IxQMgrCallbackId) 0,
280 0,
281 0,
282 0,
283 0,
284 0,
285 0
286 },
287
288 { /* PlaceHolder for rx queues
289 * depending on the QoS configured
290 */
291 (IxQMgrQId)0,
292 (char *) NULL,
293 (IxQMgrCallback) NULL,
294 (IxQMgrCallbackId) 0,
295 0,
296 0,
297 0,
298 0,
299 0,
300 0
301 },
302
303 { /* PlaceHolder for rx queues
304 * depending on the QoS configured
305 */
306 (IxQMgrQId)0,
307 (char *) NULL,
308 (IxQMgrCallback) NULL,
309 (IxQMgrCallbackId) 0,
310 0,
311 0,
312 0,
313 0,
314 0,
315 0
316 },
317
318 { /* PlaceHolder for rx queues
319 * depending on the QoS configured
320 */
321 (IxQMgrQId)0,
322 (char *) NULL,
323 (IxQMgrCallback) NULL,
324 (IxQMgrCallbackId) 0,
325 0,
326 0,
327 0,
328 0,
329 0,
330 0
331 },
332
333 { /* PlaceHolder for rx queues
334 * depending on the QoS configured
335 */
336 (IxQMgrQId)0,
337 (char *) NULL,
338 (IxQMgrCallback) NULL,
339 (IxQMgrCallbackId) 0,
340 0,
341 0,
342 0,
343 0,
344 0,
345 0
346 },
347
348 { /* PlaceHolder for rx queues
349 * depending on the QoS configured
350 */
351 (IxQMgrQId)0,
352 (char *) NULL,
353 (IxQMgrCallback) NULL,
354 (IxQMgrCallbackId) 0,
355 0,
356 0,
357 0,
358 0,
359 0,
360 0
361 },
362
363 { /* PlaceHolder for rx queues
364 * depending on the QoS configured
365 */
366 (IxQMgrQId)0,
367 (char *) NULL,
368 (IxQMgrCallback) NULL,
369 (IxQMgrCallbackId) 0,
370 0,
371 0,
372 0,
373 0,
374 0,
375 0
376 },
377
378 { /* Null Termination entry
379 */
380 (IxQMgrQId)0,
381 (char *) NULL,
382 (IxQMgrCallback) NULL,
383 (IxQMgrCallbackId) 0,
384 0,
385 0,
386 0,
387 0,
388 0,
389 0
390 }
391
392};
393
394/* forward declarations */
395IX_ETH_ACC_PRIVATE IxEthAccStatus
396ixEthAccQMgrQueueSetup(IxEthAccQregInfo *qInfoDes);
397
398/**
399 * @fn ixEthAccQMgrQueueSetup(void)
400 *
401 * @brief Setup one queue and its event, and register the callback required
402 * by this component to the QMgr
403 *
404 * @internal
405 */
406IX_ETH_ACC_PRIVATE IxEthAccStatus
407ixEthAccQMgrQueueSetup(IxEthAccQregInfo *qInfoDes)
408{
409 /*
410 * Configure each Q.
411 */
412 if ( ixQMgrQConfig( qInfoDes->qName,
413 qInfoDes->qId,
414 qInfoDes->qSize,
415 qInfoDes->qWords) != IX_SUCCESS)
416 {
417 return IX_ETH_ACC_FAIL;
418 }
419
420 if ( ixQMgrWatermarkSet( qInfoDes->qId,
421 qInfoDes->AlmostEmptyThreshold,
422 qInfoDes->AlmostFullThreshold
423 ) != IX_SUCCESS)
424 {
425 return IX_ETH_ACC_FAIL;
426 }
427
428 /*
429 * Set dispatcher priority.
430 */
431 if ( ixQMgrDispatcherPrioritySet( qInfoDes->qId,
432 IX_ETH_ACC_QM_QUEUE_DISPATCH_PRIORITY)
433 != IX_SUCCESS)
434 {
435 return IX_ETH_ACC_FAIL;
436 }
437
438 /*
439 * Register callbacks for each Q.
440 */
441 if ( ixQMgrNotificationCallbackSet(qInfoDes->qId,
442 qInfoDes->qCallback,
443 qInfoDes->callbackTag)
444 != IX_SUCCESS )
445 {
446 return IX_ETH_ACC_FAIL;
447 }
448
449 /*
450 * Set notification condition for Q
451 */
452 if ( qInfoDes->qNotificationEnableAtStartup == TRUE )
453 {
454 if ( ixQMgrNotificationEnable(qInfoDes->qId,
455 qInfoDes->qConditionSource)
456 != IX_SUCCESS )
457 {
458 return IX_ETH_ACC_FAIL;
459 }
460 }
461
462 return(IX_ETH_ACC_SUCCESS);
463}
464
465/**
466 * @fn ixEthAccQMgrQueuesConfig(void)
467 *
468 * @brief Setup all the queues and register all callbacks required
469 * by this component to the QMgr
470 *
471 * The RxFree queues, tx queues, rx queues are configured statically
472 *
473 * Rx queues configuration is driven by QoS setup.
474 * Many Rx queues may be required when QoS is enabled (this depends
475 * on IxEthDB setup and the images being downloaded). The configuration
476 * of the rxQueues is done in many steps as follows:
477 *
478 * @li select all Rx queues as configured by ethDB for all ports
479 * @li sort the queues by traffic class
480 * @li build the priority dependency for all queues
481 * @li fill the configuration for all rx queues
482 * @li configure all statically configured queues
483 * @li configure all dynamically configured queues
484 *
485 * @param none
486 *
487 * @return IxEthAccStatus
488 *
489 * @internal
490 */
491IX_ETH_ACC_PUBLIC
492IxEthAccStatus ixEthAccQMgrQueuesConfig(void)
493{
494 struct
495 {
496 int npeCount;
497 UINT32 npeId;
498 IxQMgrQId qId;
499 IxEthDBProperty trafficClass;
500 } rxQueues[IX_ETHACC_MAX_RX_QUEUES];
501
502 UINT32 rxQueue = 0;
503 UINT32 rxQueueCount = 0;
504 IxQMgrQId ixQId =IX_QMGR_MAX_NUM_QUEUES;
505 IxEthDBStatus ixEthDBStatus = IX_ETH_DB_SUCCESS;
506 IxEthDBPortId ixEthDbPortId = 0;
507 IxEthAccPortId ixEthAccPortId = 0;
508 UINT32 ixNpeId = 0;
509 UINT32 ixHighestNpeId = 0;
510 UINT32 sortIterations = 0;
511 IxEthAccStatus ret = IX_ETH_ACC_SUCCESS;
512 IxEthAccQregInfo *qInfoDes = NULL;
513 IxEthDBProperty ixEthDBTrafficClass = IX_ETH_DB_QOS_TRAFFIC_CLASS_0_RX_QUEUE_PROPERTY;
514 IxEthDBPropertyType ixEthDBPropertyType = IX_ETH_DB_INTEGER_PROPERTY;
515 UINT32 ixEthDBParameter = 0;
516 BOOL completelySorted = FALSE;
517
518 /* Fill the corspondance between ports and queues
519 * This defines the mapping from port to queue Ids.
520 */
521
522 ixEthAccPortData[IX_ETH_PORT_1].ixEthAccRxData.rxFreeQueue
523 = IX_ETH_ACC_RX_FREE_BUFF_ENET0_Q;
524 ixEthAccPortData[IX_ETH_PORT_2].ixEthAccRxData.rxFreeQueue
525 = IX_ETH_ACC_RX_FREE_BUFF_ENET1_Q;
526#ifdef __ixp46X
527 ixEthAccPortData[IX_ETH_PORT_3].ixEthAccRxData.rxFreeQueue
528 = IX_ETH_ACC_RX_FREE_BUFF_ENET2_Q;
529#endif
530 ixEthAccPortData[IX_ETH_PORT_1].ixEthAccTxData.txQueue
531 = IX_ETH_ACC_TX_FRAME_ENET0_Q;
532 ixEthAccPortData[IX_ETH_PORT_2].ixEthAccTxData.txQueue
533 = IX_ETH_ACC_TX_FRAME_ENET1_Q;
534#ifdef __ixp46X
535 ixEthAccPortData[IX_ETH_PORT_3].ixEthAccTxData.txQueue
536 = IX_ETH_ACC_TX_FRAME_ENET2_Q;
537#endif
538 /* Fill the corspondance between ports and NPEs
539 * This defines the mapping from port to npeIds.
540 */
541
542 ixEthAccPortData[IX_ETH_PORT_1].npeId = IX_NPEMH_NPEID_NPEB;
543 ixEthAccPortData[IX_ETH_PORT_2].npeId = IX_NPEMH_NPEID_NPEC;
544#ifdef __ixp46X
545 ixEthAccPortData[IX_ETH_PORT_3].npeId = IX_NPEMH_NPEID_NPEA;
546#endif
547 /* set the default rx scheduling discipline */
548 ixEthAccDataInfo.schDiscipline = FIFO_NO_PRIORITY;
549
550 /*
551 * Queue Selection step:
552 *
553 * The following code selects all the queues and build
554 * a temporary array which contains for each queue
555 * - the queue Id,
556 * - the highest traffic class (in case of many
557 * priorities configured for the same queue on different
558 * ports)
559 * - the number of different Npes which are
560 * configured to write to this queue.
561 *
562 * The output of this loop is a temporary array of RX queues
563 * in any order.
564 *
565 */
566#ifdef CONFIG_IXP425_COMPONENT_ETHDB
567 for (ixEthAccPortId = 0;
568 (ixEthAccPortId < IX_ETH_ACC_NUMBER_OF_PORTS)
569 && (ret == IX_ETH_ACC_SUCCESS);
570 ixEthAccPortId++)
571 {
572 /* map between ethDb and ethAcc port Ids */
573 ixEthDbPortId = (IxEthDBPortId)ixEthAccPortId;
574
575 /* map between npeId and ethAcc port Ids */
576 ixNpeId = IX_ETH_ACC_PORT_TO_NPE_ID(ixEthAccPortId);
577
578 /* Iterate thru the different priorities */
579 for (ixEthDBTrafficClass = IX_ETH_DB_QOS_TRAFFIC_CLASS_0_RX_QUEUE_PROPERTY;
580 ixEthDBTrafficClass <= IX_ETH_DB_QOS_TRAFFIC_CLASS_7_RX_QUEUE_PROPERTY;
581 ixEthDBTrafficClass++)
582 {
583 ixEthDBStatus = ixEthDBFeaturePropertyGet(
584 ixEthDbPortId,
585 IX_ETH_DB_VLAN_QOS,
586 ixEthDBTrafficClass,
587 &ixEthDBPropertyType,
588 (void *)&ixEthDBParameter);
589
590 if (ixEthDBStatus == IX_ETH_DB_SUCCESS)
591 {
592 /* This port and QoS class are mapped to
593 * a RX queue.
594 */
595 if (ixEthDBPropertyType == IX_ETH_DB_INTEGER_PROPERTY)
596 {
597 /* remember the highest npe Id supporting ethernet */
598 if (ixNpeId > ixHighestNpeId)
599 {
600 ixHighestNpeId = ixNpeId;
601 }
602
603 /* search the queue in the list of queues
604 * already used by an other port or QoS
605 */
606 for (rxQueue = 0;
607 rxQueue < rxQueueCount;
608 rxQueue++)
609 {
610 if (rxQueues[rxQueue].qId == (IxQMgrQId)ixEthDBParameter)
611 {
612 /* found an existing setup, update the number of ports
613 * for this queue if the port maps to
614 * a different NPE.
615 */
616 if (rxQueues[rxQueue].npeId != ixNpeId)
617 {
618 rxQueues[rxQueue].npeCount++;
619 rxQueues[rxQueue].npeId = ixNpeId;
620 }
621 /* get the highest traffic class for this queue */
622 if (rxQueues[rxQueue].trafficClass > ixEthDBTrafficClass)
623 {
624 rxQueues[rxQueue].trafficClass = ixEthDBTrafficClass;
625 }
626 break;
627 }
628 }
629 if (rxQueue == rxQueueCount)
630 {
631 /* new queue not found in the current list,
632 * add a new entry.
633 */
634 IX_OSAL_ASSERT(rxQueueCount < IX_ETHACC_MAX_RX_QUEUES);
635 rxQueues[rxQueueCount].qId = ixEthDBParameter;
636 rxQueues[rxQueueCount].npeCount = 1;
637 rxQueues[rxQueueCount].npeId = ixNpeId;
638 rxQueues[rxQueueCount].trafficClass = ixEthDBTrafficClass;
639 rxQueueCount++;
640 }
641 }
642 else
643 {
644 /* unexpected property type (not Integer) */
645 ret = IX_ETH_ACC_FAIL;
646
647 IX_ETH_ACC_WARNING_LOG("ixEthAccQMgrQueuesConfig: unexpected property type returned by EthDB\n", 0, 0, 0, 0, 0, 0);
648
649 /* no point to continue to iterate */
650 break;
651 }
652 }
653 else
654 {
655 /* No Rx queue configured for this port
656 * and this traffic class. Do nothing.
657 */
658 }
659 }
660
661 /* notify EthDB that queue initialization is complete and traffic class allocation is frozen */
662 ixEthDBFeaturePropertySet(ixEthDbPortId,
663 IX_ETH_DB_VLAN_QOS,
664 IX_ETH_DB_QOS_QUEUE_CONFIGURATION_COMPLETE,
665 NULL /* ignored */);
666 }
667
668#else
669
670 ixNpeId = IX_ETH_ACC_PORT_TO_NPE_ID(ixEthAccPortId);
671 rxQueues[0].qId = 4;
672 rxQueues[0].npeCount = 1;
673 rxQueues[0].npeId = ixNpeId;
674 rxQueues[0].trafficClass = IX_ETH_DB_QOS_TRAFFIC_CLASS_0_RX_QUEUE_PROPERTY;
675 rxQueueCount++;
676
677#endif
678
679 /* check there is at least 1 rx queue : there is no point
680 * to continue if there is no rx queue configured
681 */
682 if ((rxQueueCount == 0) || (ret == IX_ETH_ACC_FAIL))
683 {
684 IX_ETH_ACC_WARNING_LOG("ixEthAccQMgrQueuesConfig: no queues configured, bailing out\n", 0, 0, 0, 0, 0, 0);
685 return (IX_ETH_ACC_FAIL);
686 }
687
688 /* Queue sort step:
689 *
690 * Re-order the array of queues by decreasing traffic class
691 * using a bubble sort. (trafficClass 0 is the lowest
692 * priority traffic, trafficClass 7 is the highest priority traffic)
693 *
694 * Primary sort order is traffic class
695 * Secondary sort order is npeId
696 *
697 * Note that a bubble sort algorithm is not very efficient when
698 * the number of queues grows . However, this is not a very bad choice
699 * considering the very small number of entries to sort. Also, bubble
700 * sort is extremely fast when the list is already sorted.
701 *
702 * The output of this loop is a sorted array of queues.
703 *
704 */
705 sortIterations = 0;
706 do
707 {
708 sortIterations++;
709 completelySorted = TRUE;
710 for (rxQueue = 0;
711 rxQueue < rxQueueCount - sortIterations;
712 rxQueue++)
713 {
714 /* compare adjacent elements */
715 if ((rxQueues[rxQueue].trafficClass <
716 rxQueues[rxQueue+1].trafficClass)
717 || ((rxQueues[rxQueue].trafficClass ==
718 rxQueues[rxQueue+1].trafficClass)
719 &&(rxQueues[rxQueue].npeId <
720 rxQueues[rxQueue+1].npeId)))
721 {
722 /* swap adjacent elements */
723 int npeCount = rxQueues[rxQueue].npeCount;
724 UINT32 npeId = rxQueues[rxQueue].npeId;
725 IxQMgrQId qId = rxQueues[rxQueue].qId;
726 IxEthDBProperty trafficClass = rxQueues[rxQueue].trafficClass;
727 rxQueues[rxQueue].npeCount = rxQueues[rxQueue+1].npeCount;
728 rxQueues[rxQueue].npeId = rxQueues[rxQueue+1].npeId;
729 rxQueues[rxQueue].qId = rxQueues[rxQueue+1].qId;
730 rxQueues[rxQueue].trafficClass = rxQueues[rxQueue+1].trafficClass;
731 rxQueues[rxQueue+1].npeCount = npeCount;
732 rxQueues[rxQueue+1].npeId = npeId;
733 rxQueues[rxQueue+1].qId = qId;
734 rxQueues[rxQueue+1].trafficClass = trafficClass;
735 completelySorted = FALSE;
736 }
737 }
738 }
739 while (!completelySorted);
740
741 /* Queue traffic class list:
742 *
743 * Fill an array of rx queues linked by ascending traffic classes.
744 *
745 * If the queues are configured as follows
746 * qId 6 -> traffic class 0 (lowest)
747 * qId 7 -> traffic class 0
748 * qId 8 -> traffic class 6
749 * qId 12 -> traffic class 7 (highest)
750 *
751 * Then the output of this loop will be
752 *
753 * higherPriorityQueue[6] = 8
754 * higherPriorityQueue[7] = 8
755 * higherPriorityQueue[8] = 12
756 * higherPriorityQueue[12] = Invalid queueId
757 * higherPriorityQueue[...] = Invalid queueId
758 *
759 * Note that this queue ordering does not handle all possibilities
760 * that could result from different rules associated with different
761 * ports, and inconsistencies in the rules. In all cases, the
762 * output of this algorithm is a simple linked list of queues,
763 * without closed circuit.
764
765 * This list is implemented as an array with invalid values initialized
766 * with an "invalid" queue id which is the maximum number of queues.
767 *
768 */
769
770 /*
771 * Initialise the rx queue list.
772 */
773 for (rxQueue = 0; rxQueue < IX_QMGR_MAX_NUM_QUEUES; rxQueue++)
774 {
775 ixEthAccDataInfo.higherPriorityQueue[rxQueue] = IX_QMGR_MAX_NUM_QUEUES;
776 }
777
778 /* build the linked list for this NPE.
779 */
780 for (ixNpeId = 0;
781 ixNpeId <= ixHighestNpeId;
782 ixNpeId++)
783 {
784 /* iterate thru the sorted list of queues
785 */
786 ixQId = IX_QMGR_MAX_NUM_QUEUES;
787 for (rxQueue = 0;
788 rxQueue < rxQueueCount;
789 rxQueue++)
790 {
791 if (rxQueues[rxQueue].npeId == ixNpeId)
792 {
793 ixEthAccDataInfo.higherPriorityQueue[rxQueues[rxQueue].qId] = ixQId;
794 /* iterate thru queues with the same traffic class
795 * than the current queue. (queues are ordered by descending
796 * traffic classes and npeIds).
797 */
798 while ((rxQueue < rxQueueCount - 1)
799 && (rxQueues[rxQueue].trafficClass
800 == rxQueues[rxQueue+1].trafficClass)
801 && (ixNpeId == rxQueues[rxQueue].npeId))
802 {
803 rxQueue++;
804 ixEthAccDataInfo.higherPriorityQueue[rxQueues[rxQueue].qId] = ixQId;
805 }
806 ixQId = rxQueues[rxQueue].qId;
807 }
808 }
809 }
810
811 /* point on the first dynamic queue description */
812 qInfoDes = ixEthAccQmgrRxQueuesInfo;
813
814 /* update the list of queues with the rx queues */
815 for (rxQueue = 0;
816 (rxQueue < rxQueueCount) && (ret == IX_ETH_ACC_SUCCESS);
817 rxQueue++)
818 {
819 /* Don't utilize more than IX_ETHACC_MAX_LARGE_RX_QUEUES queues
820 * with the full 128 entries. For the lower priority queues, use
821 * a smaller number of entries. This ensures queue resources
822 * remain available for other components.
823 */
824 if( (rxQueueCount > IX_ETHACC_MAX_LARGE_RX_QUEUES) &&
825 (rxQueue < rxQueueCount - IX_ETHACC_MAX_LARGE_RX_QUEUES) )
826 {
827 /* add the small RX Queue setup template to the list of queues */
828 memcpy(qInfoDes, &ixEthAccQmgrRxSmallTemplate, sizeof(*qInfoDes));
829 } else {
830 /* add the default RX Queue setup template to the list of queues */
831 memcpy(qInfoDes, &ixEthAccQmgrRxDefaultTemplate, sizeof(*qInfoDes));
832 }
833
834 /* setup the RxQueue ID */
835 qInfoDes->qId = rxQueues[rxQueue].qId;
836
837 /* setup the RxQueue watermark level
838 *
839 * Each queue can be filled by many NPEs. To avoid the
840 * NPEs to write to a full queue, need to set the
841 * high watermark level for nearly full condition.
842 * (the high watermark level are a power of 2
843 * starting from the top of the queue)
844 *
845 * Number of watermark
846 * ports level
847 * 1 0
848 * 2 1
849 * 3 2
850 * 4 4
851 * 5 4
852 * 6 8
853 * n approx. 2**ceil(log2(n))
854 */
855 if (rxQueues[rxQueue].npeCount == 1)
856 {
857 qInfoDes->AlmostFullThreshold = IX_QMGR_Q_WM_LEVEL0;
858 }
859 else if (rxQueues[rxQueue].npeCount == 2)
860 {
861 qInfoDes->AlmostFullThreshold = IX_QMGR_Q_WM_LEVEL1;
862 }
863 else if (rxQueues[rxQueue].npeCount == 3)
864 {
865 qInfoDes->AlmostFullThreshold = IX_QMGR_Q_WM_LEVEL2;
866 }
867 else
868 {
869 /* reach the maximum number for CSR 2.0 */
870 IX_ETH_ACC_WARNING_LOG("ixEthAccQMgrQueuesConfig: maximum number of NPEs per queue reached, bailing out\n", 0, 0, 0, 0, 0, 0);
871 ret = IX_ETH_ACC_FAIL;
872 break;
873 }
874
875 /* move to next queue entry */
876 ++qInfoDes;
877 }
878
879 /* configure the static list (RxFree, Tx and TxDone queues) */
880 for (qInfoDes = ixEthAccQmgrStaticInfo;
881 (qInfoDes->qCallback != (IxQMgrCallback) NULL )
882 && (ret == IX_ETH_ACC_SUCCESS);
883 ++qInfoDes)
884 {
885 ret = ixEthAccQMgrQueueSetup(qInfoDes);
886 }
887
888 /* configure the dynamic list (Rx queues) */
889 for (qInfoDes = ixEthAccQmgrRxQueuesInfo;
890 (qInfoDes->qCallback != (IxQMgrCallback) NULL )
891 && (ret == IX_ETH_ACC_SUCCESS);
892 ++qInfoDes)
893 {
894 ret = ixEthAccQMgrQueueSetup(qInfoDes);
895 }
896
897 return(ret);
898}
899
900/**
901 * @fn ixEthAccQMgrRxQEntryGet(UINT32 *rxQueueEntries)
902 *
903 * @brief Add and return the total number of entries in all Rx queues
904 *
905 * @param UINT32 rxQueueEntries[in] number of entries in all queues
906 *
907 * @return void
908 *
909 * @note Rx queues configuration is driven by Qos Setup. There is a
910 * variable number of rx queues which are set at initialisation.
911 *
912 * @internal
913 */
914IX_ETH_ACC_PUBLIC
915void ixEthAccQMgrRxQEntryGet(UINT32 *numRxQueueEntries)
916{
917 UINT32 rxQueueLevel;
918 IxEthAccQregInfo *qInfoDes;;
919
920 *numRxQueueEntries = 0;
921
922 /* iterate thru rx queues */
923 for (qInfoDes = ixEthAccQmgrRxQueuesInfo;
924 qInfoDes->qCallback != (IxQMgrCallback)NULL;
925 ++qInfoDes)
926 {
927 /* retrieve the rx queue level */
928 rxQueueLevel = 0;
929 ixQMgrQNumEntriesGet(qInfoDes->qId, &rxQueueLevel);
930 (*numRxQueueEntries) += rxQueueLevel;
931 }
932}
933
934/**
935 * @fn ixEthAccQMgrRxCallbacksRegister(IxQMgrCallback ixQMgrCallback)
936 *
937 * @brief Change the callback registered to all rx queues.
938 *
939 * @param IxQMgrCallback ixQMgrCallback[in] QMgr callback to register
940 *
941 * @return IxEthAccStatus
942 *
943 * @note The user may decide to use different Rx mechanisms
944 * (e.g. receive many frames at the same time , or receive
945 * one frame at a time, depending on the overall application
946 * performances). A different QMgr callback is registered. This
947 * way, there is no excessive pointer checks in the datapath.
948 *
949 * @internal
950 */
951IX_ETH_ACC_PUBLIC
952IxEthAccStatus ixEthAccQMgrRxCallbacksRegister(IxQMgrCallback ixQMgrCallback)
953{
954 IxEthAccQregInfo *qInfoDes;
955 IxEthAccStatus ret = IX_ETH_ACC_SUCCESS;
956
957 /* parameter check */
958 if (NULL == ixQMgrCallback)
959 {
960 ret = IX_ETH_ACC_FAIL;
961 }
962
963 /* iterate thru rx queues */
964 for (qInfoDes = ixEthAccQmgrRxQueuesInfo;
965 (qInfoDes->qCallback != (IxQMgrCallback) NULL )
966 && (ret == IX_ETH_ACC_SUCCESS);
967 ++qInfoDes)
968 {
969 /* register the rx callback for all queues */
970 if (ixQMgrNotificationCallbackSet(qInfoDes->qId,
971 ixQMgrCallback,
972 qInfoDes->callbackTag
973 ) != IX_SUCCESS)
974 {
975 ret = IX_ETH_ACC_FAIL;
976 }
977 }
978 return(ret);
979}
980
981/**
982 * @fn ixEthAccSingleEthNpeCheck(IxEthAccPortId portId)
983 *
984 * @brief Check the npe exists for this port
985 *
986 * @param IxEthAccPortId portId[in] port
987 *
988 * @return IxEthAccStatus
989 *
990 * @internal
991 */
992IX_ETH_ACC_PUBLIC
993IxEthAccStatus ixEthAccSingleEthNpeCheck(IxEthAccPortId portId)
994{
995
996 /* If not IXP42X A0 stepping, proceed to check for existence of coprocessors */
997 if ((IX_FEATURE_CTRL_SILICON_TYPE_A0 !=
998 (ixFeatureCtrlProductIdRead() & IX_FEATURE_CTRL_SILICON_STEPPING_MASK))
999 || (IX_FEATURE_CTRL_DEVICE_TYPE_IXP42X != ixFeatureCtrlDeviceRead ()))
1000 {
1001 if ((IX_ETH_PORT_1 == portId) &&
1002 (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_ETH0) ==
1003 IX_FEATURE_CTRL_COMPONENT_ENABLED))
1004 {
1005 return IX_ETH_ACC_SUCCESS;
1006 }
1007
1008 if ((IX_ETH_PORT_2 == portId) &&
1009 (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_ETH1) ==
1010 IX_FEATURE_CTRL_COMPONENT_ENABLED))
1011 {
1012 return IX_ETH_ACC_SUCCESS;
1013 }
1014
1015 if ((IX_ETH_PORT_3 == portId) &&
1016 (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_NPEA_ETH) ==
1017 IX_FEATURE_CTRL_COMPONENT_ENABLED))
1018 {
1019 return IX_ETH_ACC_SUCCESS;
1020 }
1021
1022 return IX_ETH_ACC_FAIL;
1023 }
1024
1025 return IX_ETH_ACC_SUCCESS;
1026}
1027
1028/**
1029 * @fn ixEthAccStatsShow(void)
1030 *
1031 * @brief Displays all EthAcc stats
1032 *
1033 * @return void
1034 *
1035 */
1036void ixEthAccStatsShow(IxEthAccPortId portId)
1037{
1038 ixEthAccMdioShow();
1039
1040 printf("\nPort %u\nUnicast MAC : ", portId);
1041 ixEthAccPortUnicastAddressShow(portId);
1042 ixEthAccPortMulticastAddressShow(portId);
1043 printf("\n");
1044
1045 ixEthAccDataPlaneShow();
1046}
1047
1048
1049