]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/net/npe/IxEthAccCommon.c
Merge branch 'master' of git://www.denx.de/git/u-boot-cfi-flash
[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  * 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
71 extern 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  */
96 IX_ETH_ACC_PRIVATE
97 IxEthAccQregInfo ixEthAccQmgrRxDefaultTemplate =
98   {
99     IX_ETH_ACC_RX_FRAME_ETH_Q,       /**< Queue ID */
100     "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   */
107     IX_QMGR_Q_WM_LEVEL0,             /**< Q Low water mark */
108     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  */
116 IX_ETH_ACC_PRIVATE
117 IxEthAccQregInfo ixEthAccQmgrRxSmallTemplate =
118   {
119     IX_ETH_ACC_RX_FRAME_ETH_Q,       /**< Queue ID */
120     "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   */
127     IX_QMGR_Q_WM_LEVEL0,             /**< Q Low water mark */
128     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  */
137 IX_ETH_ACC_PRIVATE
138 IxEthAccQregInfo 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  */
149     IX_QMGR_Q_WM_LEVEL0,             /***< Q Low water mark */
150     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  */
162     IX_QMGR_Q_WM_LEVEL0,             /**< Q Low water mark */
163     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  */
175     IX_QMGR_Q_WM_LEVEL0,             /**< Q Low water mark */
176     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  */
188     IX_QMGR_Q_WM_LEVEL0,             /**< Q Low water mark */
189     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  */
201     IX_QMGR_Q_WM_LEVEL0,             /**< Q Low water mark */
202     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  */
214     IX_QMGR_Q_WM_LEVEL0,             /* No queues use almost empty */
215     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  */
227     IX_QMGR_Q_WM_LEVEL0,             /**< Q Low water mark */
228     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  */
255 IX_ETH_ACC_PRIVATE
256 IxEthAccQregInfo 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 */
395 IX_ETH_ACC_PRIVATE IxEthAccStatus
396 ixEthAccQMgrQueueSetup(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  */
406 IX_ETH_ACC_PRIVATE IxEthAccStatus
407 ixEthAccQMgrQueueSetup(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  */
491 IX_ETH_ACC_PUBLIC
492 IxEthAccStatus 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  */
914 IX_ETH_ACC_PUBLIC
915 void 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  */
951 IX_ETH_ACC_PUBLIC
952 IxEthAccStatus 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  */
992 IX_ETH_ACC_PUBLIC
993 IxEthAccStatus 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  */
1036 void 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