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