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