]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/net/npe/IxEthAccCommon.c
Merge branch 'u-boot-imx/master' into 'u-boot-arm/master'
[karo-tx-uboot.git] / drivers / net / npe / IxEthAccCommon.c
1 /**
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  * SPDX-License-Identifier:     BSD-3-Clause
22  * @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
47 extern 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  */
72 IX_ETH_ACC_PRIVATE
73 IxEthAccQregInfo ixEthAccQmgrRxDefaultTemplate =
74   {
75     IX_ETH_ACC_RX_FRAME_ETH_Q,       /**< Queue ID */
76     "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   */
81     true,                            /**< Enable Q notification at startup */
82     IX_ETH_ACC_RX_FRAME_ETH_Q_SOURCE,/**< Q Condition to drive callback   */
83     IX_QMGR_Q_WM_LEVEL0,             /**< Q Low water mark */
84     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  */
92 IX_ETH_ACC_PRIVATE
93 IxEthAccQregInfo ixEthAccQmgrRxSmallTemplate =
94   {
95     IX_ETH_ACC_RX_FRAME_ETH_Q,       /**< Queue ID */
96     "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   */
101     true,                            /**< Enable Q notification at startup */
102     IX_ETH_ACC_RX_FRAME_ETH_Q_SOURCE,/**< Q Condition to drive callback   */
103     IX_QMGR_Q_WM_LEVEL0,             /**< Q Low water mark */
104     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  */
113 IX_ETH_ACC_PRIVATE
114 IxEthAccQregInfo 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   */
123     false,                           /**< Disable Q notification at startup */
124     IX_ETH_ACC_RX_FREE_BUFF_ENET0_Q_SOURCE, /**< Q Condition to drive callback  */
125     IX_QMGR_Q_WM_LEVEL0,             /***< Q Low water mark */
126     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   */
136     false,                           /**< Disable Q notification at startup */
137     IX_ETH_ACC_RX_FREE_BUFF_ENET1_Q_SOURCE,  /**< Q Condition to drive callback  */
138     IX_QMGR_Q_WM_LEVEL0,             /**< Q Low water mark */
139     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   */
149     false,                           /**< Disable Q notification at startup */
150     IX_ETH_ACC_RX_FREE_BUFF_ENET2_Q_SOURCE,  /**< Q Condition to drive callback  */
151     IX_QMGR_Q_WM_LEVEL0,             /**< Q Low water mark */
152     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   */
162     false,                           /**< Disable Q notification at startup */
163     IX_ETH_ACC_TX_FRAME_ENET0_Q_SOURCE,  /**< Q Condition to drive callback  */
164     IX_QMGR_Q_WM_LEVEL0,             /**< Q Low water mark */
165     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   */
175     false,                           /**< Disable Q notification at startup */
176     IX_ETH_ACC_TX_FRAME_ENET1_Q_SOURCE,      /**< Q Condition to drive callback  */
177     IX_QMGR_Q_WM_LEVEL0,             /**< Q Low water mark */
178     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   */
188     false,                           /** Disable Q notification at startup */
189     IX_ETH_ACC_TX_FRAME_ENET2_Q_SOURCE,      /** Q Condition to drive callback  */
190     IX_QMGR_Q_WM_LEVEL0,             /* No queues use almost empty */
191     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   */
201     true,                            /**< Enable Q notification at startup */
202     IX_ETH_ACC_TX_FRAME_DONE_ETH_Q_SOURCE, /**< Q Condition to drive callback  */
203     IX_QMGR_Q_WM_LEVEL0,             /**< Q Low water mark */
204     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  */
231 IX_ETH_ACC_PRIVATE
232 IxEthAccQregInfo 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 */
371 IX_ETH_ACC_PRIVATE IxEthAccStatus
372 ixEthAccQMgrQueueSetup(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  */
382 IX_ETH_ACC_PRIVATE IxEthAccStatus
383 ixEthAccQMgrQueueSetup(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      */
428     if (qInfoDes->qNotificationEnableAtStartup == true)
429     {
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  */
467 IX_ETH_ACC_PUBLIC
468 IxEthAccStatus 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;
492     BOOL completelySorted = false;
493
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++;
685         completelySorted = true;
686         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;
711                 completelySorted = false;
712             }
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  */
890 IX_ETH_ACC_PUBLIC
891 void 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  */
927 IX_ETH_ACC_PUBLIC
928 IxEthAccStatus 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  */
968 IX_ETH_ACC_PUBLIC
969 IxEthAccStatus 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  */
1012 void 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