]>
Commit | Line | Data |
---|---|---|
ba94a1bb WD |
1 | /** |
2 | * @file QMgrQCfg.c | |
3 | * | |
4 | * @author Intel Corporation | |
5 | * @date 30-Oct-2001 | |
6 | * | |
7 | * @brief This modules provides an interface for setting up the static | |
8 | * configuration of AQM queues.This file contains the following | |
9 | * functions: | |
10 | * | |
11 | * | |
12 | * | |
13 | * @par | |
14 | * IXP400 SW Release version 2.0 | |
15 | * | |
16 | * -- Copyright Notice -- | |
17 | * | |
18 | * @par | |
19 | * Copyright 2001-2005, Intel Corporation. | |
20 | * All rights reserved. | |
21 | * | |
22 | * @par | |
cb3761ea | 23 | * SPDX-License-Identifier: BSD-3-Clause |
ba94a1bb WD |
24 | * @par |
25 | * -- End of Copyright Notice -- | |
26 | */ | |
27 | ||
28 | /* | |
29 | * System defined include files. | |
30 | */ | |
31 | ||
32 | /* | |
33 | * User defined include files. | |
34 | */ | |
35 | #include "IxOsal.h" | |
36 | #include "IxQMgr.h" | |
37 | #include "IxQMgrAqmIf_p.h" | |
38 | #include "IxQMgrQCfg_p.h" | |
39 | #include "IxQMgrDefines_p.h" | |
40 | ||
41 | /* | |
42 | * #defines and macros used in this file. | |
43 | */ | |
44 | ||
45 | #define IX_QMGR_MIN_ENTRY_SIZE_IN_WORDS 16 | |
46 | ||
47 | /* Total size of SRAM */ | |
48 | #define IX_QMGR_AQM_SRAM_SIZE_IN_BYTES 0x4000 | |
49 | ||
50 | /* | |
51 | * Check that qId is a valid queue identifier. This is provided to | |
52 | * make the code easier to read. | |
53 | */ | |
54 | #define IX_QMGR_QID_IS_VALID(qId) \ | |
55 | (((qId) >= (IX_QMGR_MIN_QID)) && ((qId) <= (IX_QMGR_MAX_QID))) | |
56 | ||
57 | /* | |
58 | * Typedefs whose scope is limited to this file. | |
59 | */ | |
60 | ||
61 | /* | |
62 | * This struct describes an AQM queue. | |
63 | * N.b. bufferSizeInWords and qEntrySizeInWords are stored in the queue | |
64 | * as these are requested by Access in the data path. sizeInEntries is | |
65 | * not required by the data path so it can be calculated dynamically. | |
66 | * | |
67 | */ | |
68 | typedef struct | |
69 | { | |
70 | char qName[IX_QMGR_MAX_QNAME_LEN+1]; /* Textual description of a queue*/ | |
71 | IxQMgrQSizeInWords qSizeInWords; /* The number of words in the queue */ | |
72 | IxQMgrQEntrySizeInWords qEntrySizeInWords; /* Number of words per queue entry*/ | |
472d5460 | 73 | BOOL isConfigured; /* This flag is true if the queue has |
ba94a1bb WD |
74 | * been configured |
75 | */ | |
76 | } IxQMgrCfgQ; | |
77 | ||
78 | /* | |
79 | * Variable declarations global to this file. Externs are followed by | |
80 | * statics. | |
81 | */ | |
82 | ||
83 | extern UINT32 * ixQMgrAqmIfQueAccRegAddr[]; | |
84 | ||
85 | /* Store data required to inline read and write access | |
86 | */ | |
87 | IxQMgrQInlinedReadWriteInfo ixQMgrQInlinedReadWriteInfo[IX_QMGR_MAX_NUM_QUEUES]; | |
88 | ||
89 | static IxQMgrCfgQ cfgQueueInfo[IX_QMGR_MAX_NUM_QUEUES]; | |
90 | ||
91 | /* This pointer holds the starting address of AQM SRAM not used by | |
92 | * the AQM queues. | |
93 | */ | |
94 | static UINT32 freeSramAddress=0; | |
95 | ||
96 | /* 4 words of zeroed memory for inline access */ | |
97 | static UINT32 zeroedPlaceHolder[4] = { 0, 0, 0, 0 }; | |
98 | ||
472d5460 | 99 | static BOOL cfgInitialized = false; |
ba94a1bb WD |
100 | |
101 | static IxOsalMutex ixQMgrQCfgMutex; | |
102 | ||
103 | /* | |
104 | * Statistics | |
105 | */ | |
106 | static IxQMgrQCfgStats stats; | |
107 | ||
108 | /* | |
109 | * Function declarations | |
110 | */ | |
111 | PRIVATE BOOL | |
112 | watermarkLevelIsOk (IxQMgrQId qId, IxQMgrWMLevel level); | |
113 | ||
114 | PRIVATE BOOL | |
115 | qSizeInWordsIsOk (IxQMgrQSizeInWords qSize); | |
116 | ||
117 | PRIVATE BOOL | |
118 | qEntrySizeInWordsIsOk (IxQMgrQEntrySizeInWords entrySize); | |
119 | ||
120 | /* | |
121 | * Function definitions. | |
122 | */ | |
123 | void | |
124 | ixQMgrQCfgInit (void) | |
125 | { | |
126 | int loopIndex; | |
127 | ||
128 | for (loopIndex=0; loopIndex < IX_QMGR_MAX_NUM_QUEUES;loopIndex++) | |
129 | { | |
130 | /* info for code inlining */ | |
131 | ixQMgrAqmIfQueAccRegAddr[loopIndex] = zeroedPlaceHolder; | |
132 | ||
133 | /* info for code inlining */ | |
134 | ixQMgrQInlinedReadWriteInfo[loopIndex].qReadCount = 0; | |
135 | ixQMgrQInlinedReadWriteInfo[loopIndex].qWriteCount = 0; | |
136 | ixQMgrQInlinedReadWriteInfo[loopIndex].qAccRegAddr = zeroedPlaceHolder; | |
137 | ixQMgrQInlinedReadWriteInfo[loopIndex].qUOStatRegAddr = zeroedPlaceHolder; | |
138 | ixQMgrQInlinedReadWriteInfo[loopIndex].qUflowStatBitMask = 0; | |
139 | ixQMgrQInlinedReadWriteInfo[loopIndex].qOflowStatBitMask = 0; | |
140 | ixQMgrQInlinedReadWriteInfo[loopIndex].qEntrySizeInWords = 0; | |
141 | ixQMgrQInlinedReadWriteInfo[loopIndex].qSizeInEntries = 0; | |
142 | ixQMgrQInlinedReadWriteInfo[loopIndex].qConfigRegAddr = zeroedPlaceHolder; | |
143 | } | |
144 | ||
145 | /* Initialise the AqmIf component */ | |
146 | ixQMgrAqmIfInit (); | |
147 | ||
148 | /* Reset all queues to have queue name = NULL, entry size = 0 and | |
149 | * isConfigured = false | |
150 | */ | |
151 | for (loopIndex=0; loopIndex < IX_QMGR_MAX_NUM_QUEUES;loopIndex++) | |
152 | { | |
153 | strcpy (cfgQueueInfo[loopIndex].qName, ""); | |
154 | cfgQueueInfo[loopIndex].qSizeInWords = 0; | |
155 | cfgQueueInfo[loopIndex].qEntrySizeInWords = 0; | |
472d5460 | 156 | cfgQueueInfo[loopIndex].isConfigured = false; |
ba94a1bb WD |
157 | |
158 | /* Statistics */ | |
472d5460 | 159 | stats.qStats[loopIndex].isConfigured = false; |
ba94a1bb WD |
160 | stats.qStats[loopIndex].qName = cfgQueueInfo[loopIndex].qName; |
161 | } | |
162 | ||
163 | /* Statistics */ | |
164 | stats.wmSetCnt = 0; | |
165 | ||
166 | ixQMgrAqmIfSramBaseAddressGet (&freeSramAddress); | |
167 | ||
168 | ixOsalMutexInit(&ixQMgrQCfgMutex); | |
169 | ||
472d5460 | 170 | cfgInitialized = true; |
ba94a1bb WD |
171 | } |
172 | ||
173 | void | |
174 | ixQMgrQCfgUninit (void) | |
175 | { | |
472d5460 | 176 | cfgInitialized = false; |
ba94a1bb WD |
177 | |
178 | /* Uninitialise the AqmIf component */ | |
179 | ixQMgrAqmIfUninit (); | |
180 | } | |
181 | ||
182 | IX_STATUS | |
183 | ixQMgrQConfig (char *qName, | |
184 | IxQMgrQId qId, | |
185 | IxQMgrQSizeInWords qSizeInWords, | |
186 | IxQMgrQEntrySizeInWords qEntrySizeInWords) | |
187 | { | |
188 | UINT32 aqmLocalBaseAddress; | |
189 | ||
190 | if (!cfgInitialized) | |
191 | { | |
192 | return IX_FAIL; | |
193 | } | |
194 | ||
195 | if (!IX_QMGR_QID_IS_VALID(qId)) | |
196 | { | |
197 | return IX_QMGR_INVALID_Q_ID; | |
198 | } | |
199 | ||
200 | else if (NULL == qName) | |
201 | { | |
202 | return IX_QMGR_PARAMETER_ERROR; | |
203 | } | |
204 | ||
205 | else if (strlen (qName) > IX_QMGR_MAX_QNAME_LEN) | |
206 | { | |
207 | return IX_QMGR_PARAMETER_ERROR; | |
208 | } | |
209 | ||
210 | else if (!qSizeInWordsIsOk (qSizeInWords)) | |
211 | { | |
212 | return IX_QMGR_INVALID_QSIZE; | |
213 | } | |
214 | ||
215 | else if (!qEntrySizeInWordsIsOk (qEntrySizeInWords)) | |
216 | { | |
217 | return IX_QMGR_INVALID_Q_ENTRY_SIZE; | |
218 | } | |
219 | ||
220 | else if (cfgQueueInfo[qId].isConfigured) | |
221 | { | |
222 | return IX_QMGR_Q_ALREADY_CONFIGURED; | |
223 | } | |
224 | ||
225 | ixOsalMutexLock(&ixQMgrQCfgMutex, IX_OSAL_WAIT_FOREVER); | |
226 | ||
227 | /* Write the config register */ | |
228 | ixQMgrAqmIfQueCfgWrite (qId, | |
229 | qSizeInWords, | |
230 | qEntrySizeInWords, | |
231 | freeSramAddress); | |
232 | ||
233 | ||
234 | strcpy (cfgQueueInfo[qId].qName, qName); | |
235 | cfgQueueInfo[qId].qSizeInWords = qSizeInWords; | |
236 | cfgQueueInfo[qId].qEntrySizeInWords = qEntrySizeInWords; | |
237 | ||
238 | /* store pre-computed information in the same cache line | |
239 | * to facilitate inlining of QRead and QWrite functions | |
240 | * in IxQMgr.h | |
241 | */ | |
242 | ixQMgrQInlinedReadWriteInfo[qId].qReadCount = 0; | |
243 | ixQMgrQInlinedReadWriteInfo[qId].qWriteCount = 0; | |
244 | ixQMgrQInlinedReadWriteInfo[qId].qEntrySizeInWords = qEntrySizeInWords; | |
245 | ixQMgrQInlinedReadWriteInfo[qId].qSizeInEntries = | |
246 | (UINT32)qSizeInWords / (UINT32)qEntrySizeInWords; | |
247 | ||
248 | /* Calculate the new freeSramAddress from the size of the queue | |
249 | * currently being configured. | |
250 | */ | |
251 | freeSramAddress += (qSizeInWords * IX_QMGR_NUM_BYTES_PER_WORD); | |
252 | ||
253 | /* Get the virtual SRAM address */ | |
254 | ixQMgrAqmIfBaseAddressGet (&aqmLocalBaseAddress); | |
255 | ||
256 | IX_OSAL_ASSERT((freeSramAddress - (aqmLocalBaseAddress + (IX_QMGR_QUEBUFFER_SPACE_OFFSET))) <= | |
257 | IX_QMGR_QUE_BUFFER_SPACE_SIZE); | |
258 | ||
259 | /* The queue is now configured */ | |
472d5460 | 260 | cfgQueueInfo[qId].isConfigured = true; |
ba94a1bb WD |
261 | |
262 | ixOsalMutexUnlock(&ixQMgrQCfgMutex); | |
263 | ||
264 | #ifndef NDEBUG | |
265 | /* Update statistics */ | |
472d5460 | 266 | stats.qStats[qId].isConfigured = true; |
ba94a1bb WD |
267 | stats.qStats[qId].qName = cfgQueueInfo[qId].qName; |
268 | #endif | |
269 | return IX_SUCCESS; | |
270 | } | |
271 | ||
272 | IxQMgrQSizeInWords | |
273 | ixQMgrQSizeInWordsGet (IxQMgrQId qId) | |
274 | { | |
275 | /* No parameter checking as this is used on the data path */ | |
276 | return (cfgQueueInfo[qId].qSizeInWords); | |
277 | } | |
278 | ||
279 | IX_STATUS | |
280 | ixQMgrQSizeInEntriesGet (IxQMgrQId qId, | |
281 | unsigned *qSizeInEntries) | |
282 | { | |
283 | if (!ixQMgrQIsConfigured(qId)) | |
284 | { | |
285 | return IX_QMGR_Q_NOT_CONFIGURED; | |
286 | } | |
287 | ||
288 | if(NULL == qSizeInEntries) | |
289 | { | |
290 | return IX_QMGR_PARAMETER_ERROR; | |
291 | } | |
292 | ||
293 | *qSizeInEntries = (UINT32)(cfgQueueInfo[qId].qSizeInWords) / | |
294 | (UINT32)cfgQueueInfo[qId].qEntrySizeInWords; | |
295 | ||
296 | return IX_SUCCESS; | |
297 | } | |
298 | ||
299 | IxQMgrQEntrySizeInWords | |
300 | ixQMgrQEntrySizeInWordsGet (IxQMgrQId qId) | |
301 | { | |
302 | /* No parameter checking as this is used on the data path */ | |
303 | return (cfgQueueInfo[qId].qEntrySizeInWords); | |
304 | } | |
305 | ||
306 | IX_STATUS | |
307 | ixQMgrWatermarkSet (IxQMgrQId qId, | |
308 | IxQMgrWMLevel ne, | |
309 | IxQMgrWMLevel nf) | |
310 | { | |
311 | IxQMgrQStatus qStatusOnEntry;/* The queue status on entry/exit */ | |
312 | IxQMgrQStatus qStatusOnExit; /* to this function */ | |
313 | ||
314 | if (!ixQMgrQIsConfigured(qId)) | |
315 | { | |
316 | return IX_QMGR_Q_NOT_CONFIGURED; | |
317 | } | |
318 | ||
319 | if (!watermarkLevelIsOk (qId, ne)) | |
320 | { | |
321 | return IX_QMGR_INVALID_Q_WM; | |
322 | } | |
323 | ||
324 | if (!watermarkLevelIsOk (qId, nf)) | |
325 | { | |
326 | return IX_QMGR_INVALID_Q_WM; | |
327 | } | |
328 | ||
329 | /* Get the current queue status */ | |
330 | ixQMgrAqmIfQueStatRead (qId, &qStatusOnEntry); | |
331 | ||
332 | #ifndef NDEBUG | |
333 | /* Update statistics */ | |
334 | stats.wmSetCnt++; | |
335 | #endif | |
336 | ||
337 | ixQMgrAqmIfWatermarkSet (qId, | |
338 | ne, | |
339 | nf); | |
340 | ||
341 | /* Get the current queue status */ | |
342 | ixQMgrAqmIfQueStatRead (qId, &qStatusOnExit); | |
343 | ||
344 | /* If the status has changed return a warning */ | |
345 | if (qStatusOnEntry != qStatusOnExit) | |
346 | { | |
347 | return IX_QMGR_WARNING; | |
348 | } | |
349 | ||
350 | return IX_SUCCESS; | |
351 | } | |
352 | ||
353 | IX_STATUS | |
354 | ixQMgrAvailableSramAddressGet (UINT32 *address, | |
355 | unsigned *sizeOfFreeRam) | |
356 | { | |
357 | UINT32 aqmLocalBaseAddress; | |
358 | ||
359 | if ((NULL == address)||(NULL == sizeOfFreeRam)) | |
360 | { | |
361 | return IX_QMGR_PARAMETER_ERROR; | |
362 | } | |
363 | if (!cfgInitialized) | |
364 | { | |
365 | return IX_FAIL; | |
366 | } | |
367 | ||
368 | *address = freeSramAddress; | |
369 | ||
370 | /* Get the virtual SRAM address */ | |
371 | ixQMgrAqmIfBaseAddressGet (&aqmLocalBaseAddress); | |
372 | ||
373 | /* | |
374 | * Calculate the size in bytes of free sram | |
375 | * i.e. current free SRAM virtual pointer from | |
376 | * (base + total size) | |
377 | */ | |
378 | *sizeOfFreeRam = | |
379 | (aqmLocalBaseAddress + | |
380 | IX_QMGR_AQM_SRAM_SIZE_IN_BYTES) - | |
381 | freeSramAddress; | |
382 | ||
383 | if (0 == *sizeOfFreeRam) | |
384 | { | |
385 | return IX_QMGR_NO_AVAILABLE_SRAM; | |
386 | } | |
387 | ||
388 | return IX_SUCCESS; | |
389 | } | |
390 | ||
391 | BOOL | |
392 | ixQMgrQIsConfigured (IxQMgrQId qId) | |
393 | { | |
394 | if (!IX_QMGR_QID_IS_VALID(qId)) | |
395 | { | |
472d5460 | 396 | return false; |
ba94a1bb WD |
397 | } |
398 | ||
399 | return cfgQueueInfo[qId].isConfigured; | |
400 | } | |
401 | ||
402 | IxQMgrQCfgStats* | |
403 | ixQMgrQCfgStatsGet (void) | |
404 | { | |
405 | return &stats; | |
406 | } | |
407 | ||
408 | IxQMgrQCfgStats* | |
409 | ixQMgrQCfgQStatsGet (IxQMgrQId qId) | |
410 | { | |
411 | unsigned int ne; | |
412 | unsigned int nf; | |
413 | UINT32 baseAddress; | |
414 | UINT32 readPtr; | |
415 | UINT32 writePtr; | |
416 | ||
417 | stats.qStats[qId].qSizeInWords = cfgQueueInfo[qId].qSizeInWords; | |
418 | stats.qStats[qId].qEntrySizeInWords = cfgQueueInfo[qId].qEntrySizeInWords; | |
419 | ||
420 | if (IX_SUCCESS != ixQMgrQNumEntriesGet (qId, &stats.qStats[qId].numEntries)) | |
421 | { | |
422 | if (IX_QMGR_WARNING != ixQMgrQNumEntriesGet (qId, &stats.qStats[qId].numEntries)) | |
423 | { | |
424 | IX_QMGR_LOG_WARNING1("Failed to get the number of entries in queue.... %d\n", qId); | |
425 | } | |
426 | } | |
427 | ||
428 | ixQMgrAqmIfQueCfgRead (qId, | |
429 | stats.qStats[qId].numEntries, | |
430 | &baseAddress, | |
431 | &ne, | |
432 | &nf, | |
433 | &readPtr, | |
434 | &writePtr); | |
435 | ||
436 | stats.qStats[qId].baseAddress = baseAddress; | |
437 | stats.qStats[qId].ne = ne; | |
438 | stats.qStats[qId].nf = nf; | |
439 | stats.qStats[qId].readPtr = readPtr; | |
440 | stats.qStats[qId].writePtr = writePtr; | |
441 | ||
442 | return &stats; | |
443 | } | |
444 | ||
445 | /* | |
446 | * Static function definitions | |
447 | */ | |
448 | ||
449 | PRIVATE BOOL | |
450 | watermarkLevelIsOk (IxQMgrQId qId, IxQMgrWMLevel level) | |
451 | { | |
452 | unsigned qSizeInEntries; | |
453 | ||
454 | switch (level) | |
455 | { | |
456 | case IX_QMGR_Q_WM_LEVEL0: | |
457 | case IX_QMGR_Q_WM_LEVEL1: | |
458 | case IX_QMGR_Q_WM_LEVEL2: | |
459 | case IX_QMGR_Q_WM_LEVEL4: | |
460 | case IX_QMGR_Q_WM_LEVEL8: | |
461 | case IX_QMGR_Q_WM_LEVEL16: | |
462 | case IX_QMGR_Q_WM_LEVEL32: | |
463 | case IX_QMGR_Q_WM_LEVEL64: | |
464 | break; | |
465 | default: | |
472d5460 | 466 | return false; |
ba94a1bb WD |
467 | } |
468 | ||
469 | /* Check watermark is not bigger than the qSizeInEntries */ | |
470 | ixQMgrQSizeInEntriesGet(qId, &qSizeInEntries); | |
471 | ||
472 | if ((unsigned)level > qSizeInEntries) | |
473 | { | |
472d5460 | 474 | return false; |
ba94a1bb WD |
475 | } |
476 | ||
472d5460 | 477 | return true; |
ba94a1bb WD |
478 | } |
479 | ||
480 | PRIVATE BOOL | |
481 | qSizeInWordsIsOk (IxQMgrQSizeInWords qSize) | |
482 | { | |
483 | BOOL status; | |
484 | ||
485 | switch (qSize) | |
486 | { | |
487 | case IX_QMGR_Q_SIZE16: | |
488 | case IX_QMGR_Q_SIZE32: | |
489 | case IX_QMGR_Q_SIZE64: | |
490 | case IX_QMGR_Q_SIZE128: | |
472d5460 | 491 | status = true; |
ba94a1bb WD |
492 | break; |
493 | default: | |
472d5460 | 494 | status = false; |
ba94a1bb WD |
495 | break; |
496 | } | |
497 | ||
498 | return status; | |
499 | } | |
500 | ||
501 | PRIVATE BOOL | |
502 | qEntrySizeInWordsIsOk (IxQMgrQEntrySizeInWords entrySize) | |
503 | { | |
504 | BOOL status; | |
505 | ||
506 | switch (entrySize) | |
507 | { | |
508 | case IX_QMGR_Q_ENTRY_SIZE1: | |
509 | case IX_QMGR_Q_ENTRY_SIZE2: | |
510 | case IX_QMGR_Q_ENTRY_SIZE4: | |
472d5460 | 511 | status = true; |
ba94a1bb WD |
512 | break; |
513 | default: | |
472d5460 | 514 | status = false; |
ba94a1bb WD |
515 | break; |
516 | } | |
517 | ||
518 | return status; | |
519 | } |