source: SVN/rincon/u-boot/cpu/ixp/npe/IxEthAccCommon.c @ 55

Last change on this file since 55 was 55, checked in by Tim Harvey, 22 months ago

rincon: added latest u-boot source

restored form server backup

Signed-off-by: Tim Harvey <tharvey@…>

File size: 28.9 KB
Line 
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
71extern IxEthAccInfo   ixEthAccDataInfo;
72
73/**
74 *
75 * @brief Maximum number of RX queues set to be the maximum number
76 * of traffic calsses.
77 *
78 */
79#define IX_ETHACC_MAX_RX_QUEUES \
80      (IX_ETH_DB_QOS_TRAFFIC_CLASS_7_RX_QUEUE_PROPERTY \
81      - IX_ETH_DB_QOS_TRAFFIC_CLASS_0_RX_QUEUE_PROPERTY \
82      + 1)
83
84/**
85 *
86 * @brief Maximum number of 128 entry RX queues
87 *
88 */
89#define IX_ETHACC_MAX_LARGE_RX_QUEUES 4
90
91/**
92 *
93 * @brief Data structure template for Default RX Queues
94 *
95 */
96IX_ETH_ACC_PRIVATE
97IxEthAccQregInfo ixEthAccQmgrRxDefaultTemplate =
98  {
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 */
116IX_ETH_ACC_PRIVATE
117IxEthAccQregInfo 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 */
137IX_ETH_ACC_PRIVATE
138IxEthAccQregInfo ixEthAccQmgrStaticInfo[]=
139{
140  {
141    IX_ETH_ACC_RX_FREE_BUFF_ENET0_Q,
142    "Eth Rx Fr Q 1",
143    ixEthRxFreeQMCallback,
144    (IxQMgrCallbackId) IX_ETH_PORT_1,
145    IX_QMGR_Q_SIZE128,               /**< Allocate Max Size Q */
146    IX_QMGR_Q_ENTRY_SIZE1,           /**< Queue Entry Sizes - all Q entries are single word entries   */
147    FALSE,                           /**< Disable Q notification at startup */
148    IX_ETH_ACC_RX_FREE_BUFF_ENET0_Q_SOURCE, /**< Q Condition to drive callback  */
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 */
255IX_ETH_ACC_PRIVATE
256IxEthAccQregInfo ixEthAccQmgrRxQueuesInfo[IX_ETHACC_MAX_RX_QUEUES+1]=
257{
258  {  /* PlaceHolder for rx queues
259      * depending on the QoS configured
260      */
261     (IxQMgrQId)0,
262     (char *) NULL,
263     (IxQMgrCallback) NULL,
264     (IxQMgrCallbackId) 0,
265     0,
266     0,
267     0,
268     0,
269     0,
270     0
271  },
272
273  {  /* PlaceHolder for rx queues
274      * depending on the QoS configured
275      */
276     (IxQMgrQId)0,
277     (char *) NULL,
278     (IxQMgrCallback) NULL,
279     (IxQMgrCallbackId) 0,
280     0,
281     0,
282     0,
283     0,
284     0,
285     0
286  },
287
288  {  /* PlaceHolder for rx queues
289      * depending on the QoS configured
290      */
291     (IxQMgrQId)0,
292     (char *) NULL,
293     (IxQMgrCallback) NULL,
294     (IxQMgrCallbackId) 0,
295     0,
296     0,
297     0,
298     0,
299     0,
300     0
301  },
302
303  {  /* PlaceHolder for rx queues
304      * depending on the QoS configured
305      */
306     (IxQMgrQId)0,
307     (char *) NULL,
308     (IxQMgrCallback) NULL,
309     (IxQMgrCallbackId) 0,
310     0,
311     0,
312     0,
313     0,
314     0,
315     0
316  },
317
318  {  /* PlaceHolder for rx queues
319      * depending on the QoS configured
320      */
321     (IxQMgrQId)0,
322     (char *) NULL,
323     (IxQMgrCallback) NULL,
324     (IxQMgrCallbackId) 0,
325     0,
326     0,
327     0,
328     0,
329     0,
330     0
331  },
332
333  {  /* PlaceHolder for rx queues
334      * depending on the QoS configured
335      */
336      (IxQMgrQId)0,
337     (char *) NULL,
338     (IxQMgrCallback) NULL,
339     (IxQMgrCallbackId) 0,
340     0,
341     0,
342     0,
343     0,
344     0,
345     0
346  },
347
348  {  /* PlaceHolder for rx queues
349      * depending on the QoS configured
350      */
351     (IxQMgrQId)0,
352     (char *) NULL,
353     (IxQMgrCallback) NULL,
354     (IxQMgrCallbackId) 0,
355     0,
356     0,
357     0,
358     0,
359     0,
360     0
361  },
362
363  {  /* PlaceHolder for rx queues
364      * depending on the QoS configured
365      */
366     (IxQMgrQId)0,
367     (char *) NULL,
368     (IxQMgrCallback) NULL,
369     (IxQMgrCallbackId) 0,
370     0,
371     0,
372     0,
373     0,
374     0,
375     0
376  },
377
378  {  /* Null Termination entry
379      */
380     (IxQMgrQId)0,
381     (char *) NULL,
382     (IxQMgrCallback) NULL,
383     (IxQMgrCallbackId) 0,
384     0,
385     0,
386     0,
387     0,
388     0,
389     0
390  }
391
392};
393
394/* forward declarations */
395IX_ETH_ACC_PRIVATE IxEthAccStatus
396ixEthAccQMgrQueueSetup(IxEthAccQregInfo *qInfoDes);
397
398/**
399 * @fn ixEthAccQMgrQueueSetup(void)
400 *
401 * @brief Setup one queue and its event, and register the callback required
402 * by this component to the QMgr
403 *
404 * @internal
405 */
406IX_ETH_ACC_PRIVATE IxEthAccStatus
407ixEthAccQMgrQueueSetup(IxEthAccQregInfo *qInfoDes)
408{
409    /*
410     * Configure each Q.
411     */
412    if ( ixQMgrQConfig( qInfoDes->qName,
413                        qInfoDes->qId,
414                        qInfoDes->qSize,
415                        qInfoDes->qWords) != IX_SUCCESS)
416    {
417        return IX_ETH_ACC_FAIL;
418    }
419
420    if ( ixQMgrWatermarkSet( qInfoDes->qId,
421                             qInfoDes->AlmostEmptyThreshold,
422                             qInfoDes->AlmostFullThreshold
423                             ) != IX_SUCCESS)
424    {
425        return IX_ETH_ACC_FAIL;
426    }
427
428    /*
429     * Set dispatcher priority.
430     */
431    if ( ixQMgrDispatcherPrioritySet( qInfoDes->qId,
432                                      IX_ETH_ACC_QM_QUEUE_DISPATCH_PRIORITY)
433         != IX_SUCCESS)
434    {
435        return IX_ETH_ACC_FAIL;
436    }
437
438    /*
439     * Register callbacks for each Q.
440     */
441    if ( ixQMgrNotificationCallbackSet(qInfoDes->qId,
442                                       qInfoDes->qCallback,
443                                       qInfoDes->callbackTag)
444         != IX_SUCCESS )
445    {
446        return IX_ETH_ACC_FAIL;
447    }
448
449    /*
450     * Set notification condition for Q
451     */
452    if ( qInfoDes->qNotificationEnableAtStartup == TRUE )
453    {
454        if (   ixQMgrNotificationEnable(qInfoDes->qId,
455                                        qInfoDes->qConditionSource)
456               != IX_SUCCESS )
457        {
458            return IX_ETH_ACC_FAIL;
459        }
460    }
461
462    return(IX_ETH_ACC_SUCCESS);
463}
464
465/**
466 * @fn ixEthAccQMgrQueuesConfig(void)
467 *
468 * @brief Setup all the queues and register all callbacks required
469 * by this component to the QMgr
470 *
471 * The RxFree queues, tx queues, rx queues are configured statically
472 *
473 * Rx queues configuration is driven by QoS setup.
474 * Many Rx queues may be required when QoS is enabled (this depends
475 * on IxEthDB setup and the images being downloaded). The configuration
476 * of the rxQueues is done in many steps as follows:
477 *
478 * @li select all Rx queues as configured by ethDB for all ports
479 * @li sort the queues by traffic class
480 * @li build the priority dependency for all queues
481 * @li fill the configuration for all rx queues
482 * @li configure all statically configured queues
483 * @li configure all dynamically configured queues
484 *
485 * @param none
486 *
487 * @return IxEthAccStatus
488 *
489 * @internal
490 */
491IX_ETH_ACC_PUBLIC
492IxEthAccStatus ixEthAccQMgrQueuesConfig(void)
493{
494    struct
495    {
496        int npeCount;
497        UINT32 npeId;
498        IxQMgrQId qId;
499        IxEthDBProperty trafficClass;
500    } rxQueues[IX_ETHACC_MAX_RX_QUEUES];
501
502    UINT32 rxQueue = 0;
503    UINT32 rxQueueCount = 0;
504    IxQMgrQId ixQId =IX_QMGR_MAX_NUM_QUEUES;
505    IxEthDBStatus ixEthDBStatus = IX_ETH_DB_SUCCESS;
506    IxEthDBPortId ixEthDbPortId = 0;
507    IxEthAccPortId ixEthAccPortId = 0;
508    UINT32 ixNpeId = 0;
509    UINT32 ixHighestNpeId = 0;
510    UINT32 sortIterations = 0;
511    IxEthAccStatus ret = IX_ETH_ACC_SUCCESS;
512    IxEthAccQregInfo *qInfoDes = NULL;
513    IxEthDBProperty ixEthDBTrafficClass = IX_ETH_DB_QOS_TRAFFIC_CLASS_0_RX_QUEUE_PROPERTY;
514    IxEthDBPropertyType ixEthDBPropertyType = IX_ETH_DB_INTEGER_PROPERTY;
515    UINT32 ixEthDBParameter = 0;
516    BOOL completelySorted = FALSE;
517
518    /* Fill the corspondance between ports and queues
519     * This defines the mapping from port to queue Ids.
520     */
521
522    ixEthAccPortData[IX_ETH_PORT_1].ixEthAccRxData.rxFreeQueue
523        = IX_ETH_ACC_RX_FREE_BUFF_ENET0_Q;
524    ixEthAccPortData[IX_ETH_PORT_2].ixEthAccRxData.rxFreeQueue
525        = IX_ETH_ACC_RX_FREE_BUFF_ENET1_Q;
526#ifdef __ixp46X
527    ixEthAccPortData[IX_ETH_PORT_3].ixEthAccRxData.rxFreeQueue
528        = IX_ETH_ACC_RX_FREE_BUFF_ENET2_Q;
529#endif
530    ixEthAccPortData[IX_ETH_PORT_1].ixEthAccTxData.txQueue
531        = IX_ETH_ACC_TX_FRAME_ENET0_Q;
532    ixEthAccPortData[IX_ETH_PORT_2].ixEthAccTxData.txQueue
533        = IX_ETH_ACC_TX_FRAME_ENET1_Q;
534#ifdef __ixp46X
535    ixEthAccPortData[IX_ETH_PORT_3].ixEthAccTxData.txQueue
536        = IX_ETH_ACC_TX_FRAME_ENET2_Q;
537#endif
538    /* Fill the corspondance between ports and NPEs
539     * This defines the mapping from port to npeIds.
540     */
541
542    ixEthAccPortData[IX_ETH_PORT_1].npeId = IX_NPEMH_NPEID_NPEB;
543    ixEthAccPortData[IX_ETH_PORT_2].npeId = IX_NPEMH_NPEID_NPEC;
544#ifdef __ixp46X
545    ixEthAccPortData[IX_ETH_PORT_3].npeId = IX_NPEMH_NPEID_NPEA;
546#endif
547    /* set the default rx scheduling discipline */
548    ixEthAccDataInfo.schDiscipline = FIFO_NO_PRIORITY;
549
550    /*
551     * Queue Selection step:
552     *
553     * The following code selects all the queues and build
554     * a temporary array which contains for each queue
555     * - the queue Id,
556     * - the highest traffic class (in case of many
557     * priorities configured for the same queue on different
558     * ports)
559     * - the number of different Npes which are
560     * configured to write to this queue.
561     *
562     * The output of this loop is a temporary array of RX queues
563     * in any order.
564     *
565     */
566#ifdef CONFIG_IXP425_COMPONENT_ETHDB
567    for (ixEthAccPortId = 0;
568         (ixEthAccPortId < IX_ETH_ACC_NUMBER_OF_PORTS)
569             && (ret == IX_ETH_ACC_SUCCESS);
570         ixEthAccPortId++)
571    {
572        /* map between ethDb and ethAcc port Ids */
573        ixEthDbPortId = (IxEthDBPortId)ixEthAccPortId;
574
575        /* map between npeId and ethAcc port Ids */
576        ixNpeId = IX_ETH_ACC_PORT_TO_NPE_ID(ixEthAccPortId);
577
578        /* Iterate thru the different priorities */
579        for (ixEthDBTrafficClass = IX_ETH_DB_QOS_TRAFFIC_CLASS_0_RX_QUEUE_PROPERTY;
580             ixEthDBTrafficClass <= IX_ETH_DB_QOS_TRAFFIC_CLASS_7_RX_QUEUE_PROPERTY;
581             ixEthDBTrafficClass++)
582        {
583            ixEthDBStatus = ixEthDBFeaturePropertyGet(
584              ixEthDbPortId,
585              IX_ETH_DB_VLAN_QOS,
586              ixEthDBTrafficClass,
587              &ixEthDBPropertyType,
588              (void *)&ixEthDBParameter);
589
590            if (ixEthDBStatus == IX_ETH_DB_SUCCESS)
591            {
592                /* This port and QoS class are mapped to
593                 * a RX queue.
594                 */
595                if (ixEthDBPropertyType == IX_ETH_DB_INTEGER_PROPERTY)
596                {
597                    /* remember the highest npe Id supporting ethernet */
598                    if (ixNpeId > ixHighestNpeId)
599                    {
600                        ixHighestNpeId = ixNpeId;
601                    }
602
603                    /* search the queue in the list of queues
604                     * already used by an other port or QoS
605                     */
606                    for (rxQueue = 0;
607                         rxQueue < rxQueueCount;
608                         rxQueue++)
609                    {
610                        if (rxQueues[rxQueue].qId == (IxQMgrQId)ixEthDBParameter)
611                        {
612                            /* found an existing setup, update the number of ports
613                             * for this queue if the port maps to
614                             * a different NPE.
615                             */
616                            if (rxQueues[rxQueue].npeId != ixNpeId)
617                            {
618                                rxQueues[rxQueue].npeCount++;
619                                rxQueues[rxQueue].npeId = ixNpeId;
620                            }
621                            /* get the highest traffic class for this queue */
622                            if (rxQueues[rxQueue].trafficClass > ixEthDBTrafficClass)
623                            {
624                                rxQueues[rxQueue].trafficClass = ixEthDBTrafficClass;
625                            }
626                            break;
627                        }
628                    }
629                    if (rxQueue == rxQueueCount)
630                    {
631                        /* new queue not found in the current list,
632                         * add a new entry.
633                         */
634                        IX_OSAL_ASSERT(rxQueueCount < IX_ETHACC_MAX_RX_QUEUES);
635                        rxQueues[rxQueueCount].qId = ixEthDBParameter;
636                        rxQueues[rxQueueCount].npeCount = 1;
637                        rxQueues[rxQueueCount].npeId = ixNpeId;
638                        rxQueues[rxQueueCount].trafficClass = ixEthDBTrafficClass;
639                        rxQueueCount++;
640                    }
641                }
642                else
643                {
644                    /* unexpected property type (not Integer) */
645                    ret = IX_ETH_ACC_FAIL;
646
647                    IX_ETH_ACC_WARNING_LOG("ixEthAccQMgrQueuesConfig: unexpected property type returned by EthDB\n", 0, 0, 0, 0, 0, 0);
648
649                    /* no point to continue to iterate */
650                    break;
651                }
652            }
653            else
654            {
655                /* No Rx queue configured for this port
656                 * and this traffic class. Do nothing.
657                 */
658            }
659        }
660
661        /* notify EthDB that queue initialization is complete and traffic class allocation is frozen */
662        ixEthDBFeaturePropertySet(ixEthDbPortId,
663            IX_ETH_DB_VLAN_QOS,
664            IX_ETH_DB_QOS_QUEUE_CONFIGURATION_COMPLETE,
665            NULL /* ignored */);
666    }
667
668#else
669
670    ixNpeId = IX_ETH_ACC_PORT_TO_NPE_ID(ixEthAccPortId);
671    rxQueues[0].qId = 4;
672    rxQueues[0].npeCount = 1;
673    rxQueues[0].npeId = ixNpeId;
674    rxQueues[0].trafficClass = IX_ETH_DB_QOS_TRAFFIC_CLASS_0_RX_QUEUE_PROPERTY;
675    rxQueueCount++;
676
677#endif
678
679    /* check there is at least 1 rx queue : there is no point
680     * to continue if there is no rx queue configured
681     */
682    if ((rxQueueCount == 0) || (ret == IX_ETH_ACC_FAIL))
683    {
684        IX_ETH_ACC_WARNING_LOG("ixEthAccQMgrQueuesConfig: no queues configured, bailing out\n", 0, 0, 0, 0, 0, 0);
685        return (IX_ETH_ACC_FAIL);
686    }
687
688    /* Queue sort step:
689     *
690     * Re-order the array of queues by decreasing traffic class
691     * using a bubble sort. (trafficClass 0 is the lowest
692     * priority traffic, trafficClass 7 is the highest priority traffic)
693     *
694     * Primary sort order is traffic class
695     * Secondary sort order is npeId
696     *
697     * Note that a bubble sort algorithm is not very efficient when
698     * the number of queues grows . However, this is not a very bad choice
699     * considering the very small number of entries to sort. Also, bubble
700     * sort is extremely fast when the list is already sorted.
701     *
702     * The output of this loop is a sorted array of queues.
703     *
704     */
705    sortIterations = 0;
706    do
707    {
708        sortIterations++;
709        completelySorted = TRUE;
710        for (rxQueue = 0;
711             rxQueue < rxQueueCount - sortIterations;
712             rxQueue++)
713        {
714            /* compare adjacent elements */
715            if ((rxQueues[rxQueue].trafficClass <
716                rxQueues[rxQueue+1].trafficClass)
717                || ((rxQueues[rxQueue].trafficClass ==
718                     rxQueues[rxQueue+1].trafficClass)
719                    &&(rxQueues[rxQueue].npeId <
720                       rxQueues[rxQueue+1].npeId)))
721            {
722                /* swap adjacent elements */
723                int npeCount = rxQueues[rxQueue].npeCount;
724                UINT32 npeId = rxQueues[rxQueue].npeId;
725                IxQMgrQId qId = rxQueues[rxQueue].qId;
726                IxEthDBProperty trafficClass = rxQueues[rxQueue].trafficClass;
727                rxQueues[rxQueue].npeCount = rxQueues[rxQueue+1].npeCount;
728                rxQueues[rxQueue].npeId = rxQueues[rxQueue+1].npeId;
729                rxQueues[rxQueue].qId = rxQueues[rxQueue+1].qId;
730                rxQueues[rxQueue].trafficClass = rxQueues[rxQueue+1].trafficClass;
731                rxQueues[rxQueue+1].npeCount = npeCount;
732                rxQueues[rxQueue+1].npeId = npeId;
733                rxQueues[rxQueue+1].qId = qId;
734                rxQueues[rxQueue+1].trafficClass = trafficClass;
735                completelySorted = FALSE;
736            }
737        }
738    }
739    while (!completelySorted);
740
741    /* Queue traffic class list:
742     *
743     * Fill an array of rx queues linked by ascending traffic classes.
744     *
745     * If the queues are configured as follows
746     *   qId 6 -> traffic class 0 (lowest)
747     *   qId 7 -> traffic class 0
748     *   qId 8 -> traffic class 6
749     *   qId 12 -> traffic class 7 (highest)
750     *
751     * Then the output of this loop will be
752     *
753     * higherPriorityQueue[6] = 8
754     * higherPriorityQueue[7] = 8
755     * higherPriorityQueue[8] = 12
756     * higherPriorityQueue[12] = Invalid queueId
757     * higherPriorityQueue[...] = Invalid queueId
758     *
759     * Note that this queue ordering does not handle all possibilities
760     * that could result from different rules associated with different
761     * ports, and inconsistencies in the rules. In all cases, the
762     * output of this  algorithm is a simple linked list of queues,
763     * without closed circuit.
764
765     * This list is implemented as an array with invalid values initialized
766     * with an "invalid" queue id which is the maximum number of queues.
767     *
768     */
769
770    /*
771     * Initialise the rx queue list.
772     */
773    for (rxQueue = 0; rxQueue < IX_QMGR_MAX_NUM_QUEUES; rxQueue++)
774    {
775        ixEthAccDataInfo.higherPriorityQueue[rxQueue] = IX_QMGR_MAX_NUM_QUEUES;
776    }
777
778    /* build the linked list for this NPE.
779     */
780    for (ixNpeId = 0;
781         ixNpeId <= ixHighestNpeId;
782         ixNpeId++)
783    {
784        /* iterate thru the sorted list of queues
785         */
786        ixQId = IX_QMGR_MAX_NUM_QUEUES;
787        for (rxQueue = 0;
788             rxQueue < rxQueueCount;
789             rxQueue++)
790        {
791            if (rxQueues[rxQueue].npeId == ixNpeId)
792            {
793                ixEthAccDataInfo.higherPriorityQueue[rxQueues[rxQueue].qId] = ixQId;
794                /* iterate thru queues with the same traffic class
795                 * than the current queue. (queues are ordered by descending
796                 * traffic classes and npeIds).
797                 */
798                while ((rxQueue < rxQueueCount - 1)
799                       && (rxQueues[rxQueue].trafficClass
800                           == rxQueues[rxQueue+1].trafficClass)
801                       && (ixNpeId == rxQueues[rxQueue].npeId))
802                {
803                    rxQueue++;
804                    ixEthAccDataInfo.higherPriorityQueue[rxQueues[rxQueue].qId] = ixQId;
805                }
806                ixQId = rxQueues[rxQueue].qId;
807            }
808        }
809    }
810
811    /* point on the first dynamic queue description */
812    qInfoDes = ixEthAccQmgrRxQueuesInfo;
813
814    /* update the list of queues with the rx queues */
815    for (rxQueue = 0;
816         (rxQueue < rxQueueCount) && (ret == IX_ETH_ACC_SUCCESS);
817         rxQueue++)
818    {
819        /* Don't utilize more than IX_ETHACC_MAX_LARGE_RX_QUEUES queues
820         * with the full 128 entries.  For the lower priority queues, use
821         * a smaller number of entries.  This ensures queue resources
822         * remain available for other components.
823         */
824        if( (rxQueueCount > IX_ETHACC_MAX_LARGE_RX_QUEUES) &&
825            (rxQueue < rxQueueCount - IX_ETHACC_MAX_LARGE_RX_QUEUES) )
826        {
827            /* add the small RX Queue setup template to the list of queues */
828            memcpy(qInfoDes, &ixEthAccQmgrRxSmallTemplate, sizeof(*qInfoDes));
829        } else {
830            /* add the default RX Queue setup template to the list of queues */
831            memcpy(qInfoDes, &ixEthAccQmgrRxDefaultTemplate, sizeof(*qInfoDes));
832        }
833
834        /* setup the RxQueue ID */
835        qInfoDes->qId = rxQueues[rxQueue].qId;
836
837        /* setup the RxQueue watermark level
838         *
839         * Each queue can be filled by many NPEs. To avoid the
840         * NPEs to write to a full queue, need to set the
841         * high watermark level for nearly full condition.
842         * (the high watermark level are a power of 2
843         * starting from the top of the queue)
844         *
845         * Number of     watermark
846         *   ports        level
847         *    1             0
848         *    2             1
849         *    3             2
850         *    4             4
851         *    5             4
852         *    6             8
853         *    n          approx. 2**ceil(log2(n))
854         */
855        if (rxQueues[rxQueue].npeCount == 1)
856        {
857            qInfoDes->AlmostFullThreshold = IX_QMGR_Q_WM_LEVEL0;
858        }
859        else if (rxQueues[rxQueue].npeCount == 2)
860        {
861            qInfoDes->AlmostFullThreshold = IX_QMGR_Q_WM_LEVEL1;
862        }
863        else if (rxQueues[rxQueue].npeCount == 3)
864        {
865            qInfoDes->AlmostFullThreshold = IX_QMGR_Q_WM_LEVEL2;
866        }
867        else
868        {
869            /* reach the maximum number for CSR 2.0 */
870            IX_ETH_ACC_WARNING_LOG("ixEthAccQMgrQueuesConfig: maximum number of NPEs per queue reached, bailing out\n", 0, 0, 0, 0, 0, 0);
871            ret = IX_ETH_ACC_FAIL;
872            break;
873        }
874
875        /* move to next queue entry */
876        ++qInfoDes;
877    }
878
879    /* configure the static list (RxFree, Tx and TxDone queues) */
880    for (qInfoDes = ixEthAccQmgrStaticInfo;
881         (qInfoDes->qCallback != (IxQMgrCallback) NULL )
882             && (ret == IX_ETH_ACC_SUCCESS);
883         ++qInfoDes)
884    {
885        ret = ixEthAccQMgrQueueSetup(qInfoDes);
886    }
887
888    /* configure the dynamic list (Rx queues) */
889    for (qInfoDes = ixEthAccQmgrRxQueuesInfo;
890         (qInfoDes->qCallback != (IxQMgrCallback) NULL )
891             && (ret == IX_ETH_ACC_SUCCESS);
892         ++qInfoDes)
893    {
894        ret = ixEthAccQMgrQueueSetup(qInfoDes);
895    }
896
897    return(ret);
898}
899
900/**
901 * @fn ixEthAccQMgrRxQEntryGet(UINT32 *rxQueueEntries)
902 *
903 * @brief Add and return the total number of entries in all Rx queues
904 *
905 * @param UINT32 rxQueueEntries[in] number of entries in all queues
906 *
907 * @return void
908 *
909 * @note Rx queues configuration is driven by Qos Setup. There is a
910 * variable number of rx queues which are set at initialisation.
911 *
912 * @internal
913 */
914IX_ETH_ACC_PUBLIC
915void ixEthAccQMgrRxQEntryGet(UINT32 *numRxQueueEntries)
916{
917    UINT32 rxQueueLevel;
918    IxEthAccQregInfo *qInfoDes;;
919
920    *numRxQueueEntries = 0;
921
922    /* iterate thru rx queues */
923    for (qInfoDes = ixEthAccQmgrRxQueuesInfo;
924         qInfoDes->qCallback != (IxQMgrCallback)NULL;
925         ++qInfoDes)
926    {
927        /* retrieve the rx queue level */
928        rxQueueLevel = 0;
929        ixQMgrQNumEntriesGet(qInfoDes->qId, &rxQueueLevel);
930        (*numRxQueueEntries) += rxQueueLevel;
931    }
932}
933
934/**
935 * @fn ixEthAccQMgrRxCallbacksRegister(IxQMgrCallback ixQMgrCallback)
936 *
937 * @brief Change the callback registered to all rx queues.
938 *
939 * @param IxQMgrCallback ixQMgrCallback[in] QMgr callback to register
940 *
941 * @return IxEthAccStatus
942 *
943 * @note The user may decide to use different Rx mechanisms
944 * (e.g. receive many frames at the same time , or receive
945 *  one frame at a time, depending on the overall application
946 *  performances). A different QMgr callback is registered. This
947 *  way, there is no excessive pointer checks in the datapath.
948 *
949 * @internal
950 */
951IX_ETH_ACC_PUBLIC
952IxEthAccStatus ixEthAccQMgrRxCallbacksRegister(IxQMgrCallback ixQMgrCallback)
953{
954    IxEthAccQregInfo *qInfoDes;
955    IxEthAccStatus ret = IX_ETH_ACC_SUCCESS;
956
957    /* parameter check */
958    if (NULL == ixQMgrCallback)
959    {
960        ret = IX_ETH_ACC_FAIL;
961    }
962
963    /* iterate thru rx queues */
964    for (qInfoDes = ixEthAccQmgrRxQueuesInfo;
965         (qInfoDes->qCallback != (IxQMgrCallback) NULL )
966             && (ret == IX_ETH_ACC_SUCCESS);
967         ++qInfoDes)
968    {
969        /* register the rx callback for all queues */
970        if (ixQMgrNotificationCallbackSet(qInfoDes->qId,
971                                             ixQMgrCallback,
972                                             qInfoDes->callbackTag
973                                             ) != IX_SUCCESS)
974        {
975            ret = IX_ETH_ACC_FAIL;
976        }
977    }
978    return(ret);
979}
980
981/**
982 * @fn ixEthAccSingleEthNpeCheck(IxEthAccPortId portId)
983 *
984 * @brief Check the npe exists for this port
985 *
986 * @param IxEthAccPortId portId[in] port
987 *
988 * @return IxEthAccStatus
989 *
990 * @internal
991 */
992IX_ETH_ACC_PUBLIC
993IxEthAccStatus ixEthAccSingleEthNpeCheck(IxEthAccPortId portId)
994{
995
996    /* If not IXP42X A0 stepping, proceed to check for existence of coprocessors */
997    if ((IX_FEATURE_CTRL_SILICON_TYPE_A0 !=
998        (ixFeatureCtrlProductIdRead() & IX_FEATURE_CTRL_SILICON_STEPPING_MASK))
999        || (IX_FEATURE_CTRL_DEVICE_TYPE_IXP42X != ixFeatureCtrlDeviceRead ()))
1000      {
1001            if ((IX_ETH_PORT_1 == portId) &&
1002                (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_ETH0) ==
1003                 IX_FEATURE_CTRL_COMPONENT_ENABLED))
1004            {
1005                return IX_ETH_ACC_SUCCESS;
1006            }
1007
1008            if ((IX_ETH_PORT_2 == portId) &&
1009                (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_ETH1) ==
1010                 IX_FEATURE_CTRL_COMPONENT_ENABLED))
1011            {
1012                return IX_ETH_ACC_SUCCESS;
1013            }
1014
1015            if ((IX_ETH_PORT_3 == portId) &&
1016                (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_NPEA_ETH) ==
1017                 IX_FEATURE_CTRL_COMPONENT_ENABLED))
1018            {
1019                return IX_ETH_ACC_SUCCESS;
1020            }
1021
1022            return IX_ETH_ACC_FAIL;
1023      }
1024
1025    return IX_ETH_ACC_SUCCESS;
1026}
1027
1028/**
1029 * @fn ixEthAccStatsShow(void)
1030 *
1031 * @brief Displays all EthAcc stats
1032 *
1033 * @return void
1034 *
1035 */
1036void ixEthAccStatsShow(IxEthAccPortId portId)
1037{
1038    ixEthAccMdioShow();
1039
1040    printf("\nPort %u\nUnicast MAC : ", portId);
1041    ixEthAccPortUnicastAddressShow(portId);
1042    ixEthAccPortMulticastAddressShow(portId);
1043    printf("\n");
1044
1045    ixEthAccDataPlaneShow();
1046}
1047
1048
1049
Note: See TracBrowser for help on using the repository browser.