]>
Commit | Line | Data |
---|---|---|
ba94a1bb WD |
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 | |
cb3761ea | 21 | * SPDX-License-Identifier: BSD-3-Clause |
ba94a1bb WD |
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 | { | |
53677ef1 | 75 | IX_ETH_ACC_RX_FRAME_ETH_Q, /**< Queue ID */ |
ba94a1bb WD |
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 */ | |
472d5460 | 81 | true, /**< Enable Q notification at startup */ |
ba94a1bb | 82 | IX_ETH_ACC_RX_FRAME_ETH_Q_SOURCE,/**< Q Condition to drive callback */ |
53677ef1 | 83 | IX_QMGR_Q_WM_LEVEL0, /**< Q Low water mark */ |
ba94a1bb WD |
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 | { | |
53677ef1 | 95 | IX_ETH_ACC_RX_FRAME_ETH_Q, /**< Queue ID */ |
ba94a1bb WD |
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 */ | |
472d5460 | 101 | true, /**< Enable Q notification at startup */ |
ba94a1bb | 102 | IX_ETH_ACC_RX_FRAME_ETH_Q_SOURCE,/**< Q Condition to drive callback */ |
53677ef1 | 103 | IX_QMGR_Q_WM_LEVEL0, /**< Q Low water mark */ |
ba94a1bb WD |
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 */ | |
472d5460 | 123 | false, /**< Disable Q notification at startup */ |
ba94a1bb | 124 | IX_ETH_ACC_RX_FREE_BUFF_ENET0_Q_SOURCE, /**< Q Condition to drive callback */ |
53677ef1 | 125 | IX_QMGR_Q_WM_LEVEL0, /***< Q Low water mark */ |
ba94a1bb WD |
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 */ | |
472d5460 | 136 | false, /**< Disable Q notification at startup */ |
ba94a1bb | 137 | IX_ETH_ACC_RX_FREE_BUFF_ENET1_Q_SOURCE, /**< Q Condition to drive callback */ |
53677ef1 | 138 | IX_QMGR_Q_WM_LEVEL0, /**< Q Low water mark */ |
ba94a1bb WD |
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 */ | |
472d5460 | 149 | false, /**< Disable Q notification at startup */ |
ba94a1bb | 150 | IX_ETH_ACC_RX_FREE_BUFF_ENET2_Q_SOURCE, /**< Q Condition to drive callback */ |
53677ef1 | 151 | IX_QMGR_Q_WM_LEVEL0, /**< Q Low water mark */ |
ba94a1bb WD |
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 */ | |
472d5460 | 162 | false, /**< Disable Q notification at startup */ |
ba94a1bb | 163 | IX_ETH_ACC_TX_FRAME_ENET0_Q_SOURCE, /**< Q Condition to drive callback */ |
53677ef1 | 164 | IX_QMGR_Q_WM_LEVEL0, /**< Q Low water mark */ |
ba94a1bb WD |
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 */ | |
472d5460 | 175 | false, /**< Disable Q notification at startup */ |
ba94a1bb | 176 | IX_ETH_ACC_TX_FRAME_ENET1_Q_SOURCE, /**< Q Condition to drive callback */ |
53677ef1 | 177 | IX_QMGR_Q_WM_LEVEL0, /**< Q Low water mark */ |
ba94a1bb WD |
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 */ | |
472d5460 | 188 | false, /** Disable Q notification at startup */ |
ba94a1bb | 189 | IX_ETH_ACC_TX_FRAME_ENET2_Q_SOURCE, /** Q Condition to drive callback */ |
53677ef1 | 190 | IX_QMGR_Q_WM_LEVEL0, /* No queues use almost empty */ |
ba94a1bb WD |
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 */ | |
472d5460 | 201 | true, /**< Enable Q notification at startup */ |
ba94a1bb | 202 | IX_ETH_ACC_TX_FRAME_DONE_ETH_Q_SOURCE, /**< Q Condition to drive callback */ |
53677ef1 | 203 | IX_QMGR_Q_WM_LEVEL0, /**< Q Low water mark */ |
ba94a1bb WD |
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 | */ | |
472d5460 | 428 | if (qInfoDes->qNotificationEnableAtStartup == true) |
ba94a1bb WD |
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; | |
472d5460 | 492 | BOOL completelySorted = false; |
ba94a1bb WD |
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++; | |
472d5460 | 685 | completelySorted = true; |
ba94a1bb WD |
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; | |
472d5460 | 711 | completelySorted = false; |
ba94a1bb WD |
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 |