]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/net/npe/IxQMgrQCfg.c
Merge branch 'u-boot-imx/master' into 'u-boot-arm/master'
[karo-tx-uboot.git] / drivers / net / npe / IxQMgrQCfg.c
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
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  */
92 typedef 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
107 extern UINT32 * ixQMgrAqmIfQueAccRegAddr[]; 
108
109 /* Store data required to inline read and write access
110  */
111 IxQMgrQInlinedReadWriteInfo ixQMgrQInlinedReadWriteInfo[IX_QMGR_MAX_NUM_QUEUES];
112
113 static 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  */
118 static UINT32 freeSramAddress=0;
119
120 /* 4 words of zeroed memory for inline access */
121 static UINT32 zeroedPlaceHolder[4] = { 0, 0, 0, 0 };
122
123 static BOOL cfgInitialized = false;
124
125 static IxOsalMutex ixQMgrQCfgMutex;
126
127 /*
128  * Statistics
129  */
130 static IxQMgrQCfgStats stats;
131
132 /*
133  * Function declarations
134  */
135 PRIVATE BOOL
136 watermarkLevelIsOk (IxQMgrQId qId, IxQMgrWMLevel level);
137
138 PRIVATE BOOL
139 qSizeInWordsIsOk (IxQMgrQSizeInWords qSize);
140
141 PRIVATE BOOL
142 qEntrySizeInWordsIsOk (IxQMgrQEntrySizeInWords entrySize);
143
144 /*
145  * Function definitions.
146  */
147 void
148 ixQMgrQCfgInit (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
197 void
198 ixQMgrQCfgUninit (void)
199 {
200     cfgInitialized = false;
201
202     /* Uninitialise the AqmIf component */
203     ixQMgrAqmIfUninit ();
204 }
205
206 IX_STATUS
207 ixQMgrQConfig (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
296 IxQMgrQSizeInWords
297 ixQMgrQSizeInWordsGet (IxQMgrQId qId)
298 {
299     /* No parameter checking as this is used on the data path */
300     return (cfgQueueInfo[qId].qSizeInWords);
301 }
302
303 IX_STATUS
304 ixQMgrQSizeInEntriesGet (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
323 IxQMgrQEntrySizeInWords
324 ixQMgrQEntrySizeInWordsGet (IxQMgrQId qId)
325 {
326     /* No parameter checking as this is used on the data path */
327     return (cfgQueueInfo[qId].qEntrySizeInWords);
328 }
329
330 IX_STATUS
331 ixQMgrWatermarkSet (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
377 IX_STATUS
378 ixQMgrAvailableSramAddressGet (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
415 BOOL
416 ixQMgrQIsConfigured (IxQMgrQId qId)
417 {
418     if (!IX_QMGR_QID_IS_VALID(qId))
419     {
420         return false;
421     }
422
423     return cfgQueueInfo[qId].isConfigured;
424 }
425
426 IxQMgrQCfgStats*
427 ixQMgrQCfgStatsGet (void)
428 {
429     return &stats;
430 }
431
432 IxQMgrQCfgStats*
433 ixQMgrQCfgQStatsGet (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
473 PRIVATE BOOL
474 watermarkLevelIsOk (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
504 PRIVATE BOOL
505 qSizeInWordsIsOk (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
525 PRIVATE BOOL
526 qEntrySizeInWordsIsOk (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 }