blob: b64bb2dd9099368d211089ad6c3eb8cee904a7dd [file] [log] [blame]
Wolfgang Denkba94a1b2006-05-30 15:56:48 +02001/**
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
Wolfgang Denkcb3761e2013-07-28 22:12:47 +020023 * SPDX-License-Identifier: BSD-3-Clause
Wolfgang Denkba94a1b2006-05-30 15:56:48 +020024 * @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 */
68typedef 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*/
York Sun472d5462013-04-01 11:29:11 -070073 BOOL isConfigured; /* This flag is true if the queue has
Wolfgang Denkba94a1b2006-05-30 15:56:48 +020074 * been configured
75 */
76} IxQMgrCfgQ;
77
78/*
79 * Variable declarations global to this file. Externs are followed by
80 * statics.
81 */
82
83extern UINT32 * ixQMgrAqmIfQueAccRegAddr[];
84
85/* Store data required to inline read and write access
86 */
87IxQMgrQInlinedReadWriteInfo ixQMgrQInlinedReadWriteInfo[IX_QMGR_MAX_NUM_QUEUES];
88
89static 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 */
94static UINT32 freeSramAddress=0;
95
96/* 4 words of zeroed memory for inline access */
97static UINT32 zeroedPlaceHolder[4] = { 0, 0, 0, 0 };
98
York Sun472d5462013-04-01 11:29:11 -070099static BOOL cfgInitialized = false;
Wolfgang Denkba94a1b2006-05-30 15:56:48 +0200100
101static IxOsalMutex ixQMgrQCfgMutex;
102
103/*
104 * Statistics
105 */
106static IxQMgrQCfgStats stats;
107
108/*
109 * Function declarations
110 */
111PRIVATE BOOL
112watermarkLevelIsOk (IxQMgrQId qId, IxQMgrWMLevel level);
113
114PRIVATE BOOL
115qSizeInWordsIsOk (IxQMgrQSizeInWords qSize);
116
117PRIVATE BOOL
118qEntrySizeInWordsIsOk (IxQMgrQEntrySizeInWords entrySize);
119
120/*
121 * Function definitions.
122 */
123void
124ixQMgrQCfgInit (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;
York Sun472d5462013-04-01 11:29:11 -0700156 cfgQueueInfo[loopIndex].isConfigured = false;
Wolfgang Denkba94a1b2006-05-30 15:56:48 +0200157
158 /* Statistics */
York Sun472d5462013-04-01 11:29:11 -0700159 stats.qStats[loopIndex].isConfigured = false;
Wolfgang Denkba94a1b2006-05-30 15:56:48 +0200160 stats.qStats[loopIndex].qName = cfgQueueInfo[loopIndex].qName;
161 }
162
163 /* Statistics */
164 stats.wmSetCnt = 0;
165
166 ixQMgrAqmIfSramBaseAddressGet (&freeSramAddress);
167
168 ixOsalMutexInit(&ixQMgrQCfgMutex);
169
York Sun472d5462013-04-01 11:29:11 -0700170 cfgInitialized = true;
Wolfgang Denkba94a1b2006-05-30 15:56:48 +0200171}
172
173void
174ixQMgrQCfgUninit (void)
175{
York Sun472d5462013-04-01 11:29:11 -0700176 cfgInitialized = false;
Wolfgang Denkba94a1b2006-05-30 15:56:48 +0200177
178 /* Uninitialise the AqmIf component */
179 ixQMgrAqmIfUninit ();
180}
181
182IX_STATUS
183ixQMgrQConfig (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 */
York Sun472d5462013-04-01 11:29:11 -0700260 cfgQueueInfo[qId].isConfigured = true;
Wolfgang Denkba94a1b2006-05-30 15:56:48 +0200261
262 ixOsalMutexUnlock(&ixQMgrQCfgMutex);
263
264#ifndef NDEBUG
265 /* Update statistics */
York Sun472d5462013-04-01 11:29:11 -0700266 stats.qStats[qId].isConfigured = true;
Wolfgang Denkba94a1b2006-05-30 15:56:48 +0200267 stats.qStats[qId].qName = cfgQueueInfo[qId].qName;
268#endif
269 return IX_SUCCESS;
270}
271
272IxQMgrQSizeInWords
273ixQMgrQSizeInWordsGet (IxQMgrQId qId)
274{
275 /* No parameter checking as this is used on the data path */
276 return (cfgQueueInfo[qId].qSizeInWords);
277}
278
279IX_STATUS
280ixQMgrQSizeInEntriesGet (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
299IxQMgrQEntrySizeInWords
300ixQMgrQEntrySizeInWordsGet (IxQMgrQId qId)
301{
302 /* No parameter checking as this is used on the data path */
303 return (cfgQueueInfo[qId].qEntrySizeInWords);
304}
305
306IX_STATUS
307ixQMgrWatermarkSet (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
353IX_STATUS
354ixQMgrAvailableSramAddressGet (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
391BOOL
392ixQMgrQIsConfigured (IxQMgrQId qId)
393{
394 if (!IX_QMGR_QID_IS_VALID(qId))
395 {
York Sun472d5462013-04-01 11:29:11 -0700396 return false;
Wolfgang Denkba94a1b2006-05-30 15:56:48 +0200397 }
398
399 return cfgQueueInfo[qId].isConfigured;
400}
401
402IxQMgrQCfgStats*
403ixQMgrQCfgStatsGet (void)
404{
405 return &stats;
406}
407
408IxQMgrQCfgStats*
409ixQMgrQCfgQStatsGet (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
449PRIVATE BOOL
450watermarkLevelIsOk (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:
York Sun472d5462013-04-01 11:29:11 -0700466 return false;
Wolfgang Denkba94a1b2006-05-30 15:56:48 +0200467 }
468
469 /* Check watermark is not bigger than the qSizeInEntries */
470 ixQMgrQSizeInEntriesGet(qId, &qSizeInEntries);
471
472 if ((unsigned)level > qSizeInEntries)
473 {
York Sun472d5462013-04-01 11:29:11 -0700474 return false;
Wolfgang Denkba94a1b2006-05-30 15:56:48 +0200475 }
476
York Sun472d5462013-04-01 11:29:11 -0700477 return true;
Wolfgang Denkba94a1b2006-05-30 15:56:48 +0200478}
479
480PRIVATE BOOL
481qSizeInWordsIsOk (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:
York Sun472d5462013-04-01 11:29:11 -0700491 status = true;
Wolfgang Denkba94a1b2006-05-30 15:56:48 +0200492 break;
493 default:
York Sun472d5462013-04-01 11:29:11 -0700494 status = false;
Wolfgang Denkba94a1b2006-05-30 15:56:48 +0200495 break;
496 }
497
498 return status;
499}
500
501PRIVATE BOOL
502qEntrySizeInWordsIsOk (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:
York Sun472d5462013-04-01 11:29:11 -0700511 status = true;
Wolfgang Denkba94a1b2006-05-30 15:56:48 +0200512 break;
513 default:
York Sun472d5462013-04-01 11:29:11 -0700514 status = false;
Wolfgang Denkba94a1b2006-05-30 15:56:48 +0200515 break;
516 }
517
518 return status;
519}