e10ba41e9aee396c25250e0f39608e0e0eb5b885
[o-du/l2.git] / src / mt / ss_rbuf.c
1 /*******************************************************************************
2 ################################################################################
3 #   Copyright (c) [2017-2019] [Radisys]                                        #
4 #                                                                              #
5 #   Licensed under the Apache License, Version 2.0 (the "License");            #
6 #   you may not use this file except in compliance with the License.           #
7 #   You may obtain a copy of the License at                                    #
8 #                                                                              #
9 #       http://www.apache.org/licenses/LICENSE-2.0                             #
10 #                                                                              #
11 #   Unless required by applicable law or agreed to in writing, software        #
12 #   distributed under the License is distributed on an "AS IS" BASIS,          #
13 #   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
14 #   See the License for the specific language governing permissions and        #
15 #   limitations under the License.                                             #
16 ################################################################################
17 *******************************************************************************/
18
19 /*
20   Steps to Add a new Ring Buffer
21
22 1. Add Buffer Id to enum in ss_rbuf.h
23 2. Update Static SsRngCfgTbl below for ring and element size. Add a macro in ss_rbuf.h
24 3. typedef a structure for element type if not available in ss_rbuf.h
25 4. Call SCreateSRngBuf for new Buffer id from bcInitRingBuffers() in bc_cpu_init.c
26 5. Call SAttachSRngBuf from producer and consumer ActvInit
27 6. Call SEnqSRngBuf and SDeqSRngBuf from producer and consumer respectively
28  
29 */
30 #include "envopt.h"        /* environment options     */
31 #include "envdep.h"        /* environment dependent   */
32 #include "envind.h"        /* environment independent */
33 #include "gen.h"           /* general                 */
34 #include "ssi.h"           /* system services         */
35 #include "cm_err.h"       
36 #include <stdlib.h>
37 #include "gen.x"           /* general layer */
38 #include "ssi.x"           /* system services */
39 #include "ss_rbuf.h"
40 #include "ss_rbuf.x"
41
42 uint32_t ssRngBufStatus = 0;
43
44 /* Global Ring Loop Up Table */
45 SsRngBufTbl SsRngInfoTbl[SS_RNG_BUF_MAX];
46
47
48 Void SsRngBufEnable(Void)
49 {
50   ssRngBufStatus = TRUE;
51 }
52
53
54 Void SsRngBufDisable(Void)
55 {
56   ssRngBufStatus = FALSE;
57
58 }
59 /*
60 Func: SCreateSRngBuf
61 Desc: Creates Ring Buffer for the given Id.
62       Ring Structure is allocated from given 
63       Region and Pool
64 */
65 S16 SCreateSRngBuf
66 (
67 uint32_t id,  
68 Region region,
69 Pool pool,
70 uint32_t elmSize,
71 uint32_t rngSize
72 )
73 {
74    SsRngBuf* ring;
75
76    /* Validate Id */
77    if(id >= SS_RNG_BUF_MAX)
78    {
79 #if (ERRCLASS & ERRCLS_DEBUG)
80       SSLOGERROR(ERRCLS_DEBUG, ESSXXX, id, "Invalid RBUF ID");
81 #endif
82       return RFAILED;
83    }
84    if(SsRngInfoTbl[id].r_addr != 0)
85    {
86 #if (ERRCLASS & ERRCLS_DEBUG)
87       SSLOGERROR(ERRCLS_DEBUG, ESSXXX, id, 
88             "Failed to Create Ring Buffer Id Ring already exist");
89 #endif
90       return RFAILED;
91    }
92    /* Get Element Size */
93    
94    /* Get Ring Size    */
95    /* Allocate memory for Ring structure */
96    ring = (SsRngBuf* )malloc(sizeof(SsRngBuf));
97    if(ring == NULLP)
98    {
99 #if (ERRCLASS & ERRCLS_DEBUG)
100       SSLOGERROR(ERRCLS_INT_PAR, ESSXXX, ERRZERO, "Allocating Ring  Failed!!!")
101 #endif
102       return RFAILED;
103    }
104 #if (ERRCLASS & ERRCLS_DEBUG)
105       SSLOGERROR(ERRCLS_DEBUG, ESSXXX, ring, 
106             "Failed to Create Ring Buffer Id Ring already exist");
107 #endif
108
109    ring->size  = rngSize; /* No empty elem */
110    ring->read  = 0;
111    ring->write = 0;
112    ring->type  = elmSize;
113
114    /* Allocate elements memory */
115    ring->elem  = calloc(ring->size, ring->type);
116    if(ring->elem == NULLP)
117     {
118 #if (ERRCLASS & ERRCLS_DEBUG)
119       SSLOGERROR(ERRCLS_INT_PAR, ESSXXX, ERRZERO, "Allocating Ring  Failed!!!")
120 #endif
121       free(ring);
122       return RFAILED;
123     }
124     /* Update Buffer Id Table */
125     SsRngInfoTbl[id].r_addr   = ring;
126     SsRngInfoTbl[id].rngState = SS_RNG_CREATED;
127     SsRngInfoTbl[id].n_write  = 0;
128     SsRngInfoTbl[id].n_read   = 0;
129
130 #ifndef ALIGN_64BIT
131     printf("Ring Buffer Created with id =%ld rSize:%ld eSize:%ld %lx\n",id,ring->size,ring->type,(PTR)ring);
132 #else
133     printf("Ring Buffer Created with id =%d rSize:%d eSize:%d %lx\n",id,ring->size,ring->type,(PTR)ring);
134 #endif
135     return ROK;
136 }
137
138 /*
139 Func: SAttachSRngBuf
140 Desc: Attach the calling Entity to a ring buffer 
141       as consumer(Rx) or producer (Tx)
142 */
143 S16 SAttachSRngBuf
144 (
145 uint32_t id,  
146 uint32_t ent,
147 uint32_t txRx
148 )
149 {
150     /* Retrive Buffer from Global Info Table */
151     if( id >= SS_RNG_BUF_MAX)
152     {
153 #if (ERRCLASS & ERRCLS_DEBUG)
154       SSLOGERROR(ERRCLS_DEBUG, ESSXXX, id, "Invalid RBUF ID");
155 #endif
156        return RFAILED;
157     }
158     if(SsRngInfoTbl[id].rngState < SS_RNG_CREATED)
159     {
160 #if (ERRCLASS & ERRCLS_DEBUG)
161       SSLOGERROR(ERRCLS_DEBUG, ESSXXX, id, 
162             "Attach Request in Invalid Ring ID");
163 #endif
164 #ifndef ALIGN_64BIT
165        printf("Attach Request in Invalid Ring State %ld id%ld \n",
166          SsRngInfoTbl[id].rngState,id);
167 #else
168        printf("Attach Request in Invalid Ring State %d id%d \n",
169          SsRngInfoTbl[id].rngState,id);
170 #endif
171        return RFAILED;
172     }
173     if(txRx == SS_RNG_TX)
174     {
175         SsRngInfoTbl[id].txEnt = ent;
176         SsRngInfoTbl[id].rngState = SS_RNG_TX_ATTACHED;
177     }
178     else if(txRx == SS_RNG_RX)
179     {
180         SsRngInfoTbl[id].rxEnt = ent;
181         SsRngInfoTbl[id].rngState = SS_RNG_RX_ATTACHED;
182     }
183     return ROK;
184 }
185 /* 
186 Func: SConnectSRngBuf
187 Desc: Establish a pipe between producer and consumer
188
189 */
190 S16 SConnectSRngBuf
191 (
192 uint32_t id,  
193 uint32_t rxEnt
194 )
195 {
196    /* Send to Reciever ENT*/ 
197    return ROK; 
198 }
199
200 /*
201 Func: IsFull
202 Desc: Checks if Ring is full
203 */
204 inline static S16 IsFull(SsRngBuf* rBuf)
205 {
206 #if 1
207    if((rBuf->write+1) == rBuf->read)
208    {
209      return 1;
210    }
211    if((rBuf->write+1) == (rBuf->read + rBuf->size))
212    {
213      return 1;
214    }
215    if((rBuf->write + 1) > rBuf->size )
216    {
217      return 1;
218    }
219    return 0;
220 #endif
221
222 /*
223 Func: IsEmpty
224 Desc: Checks if ring is empty
225 */
226 inline static S16 IsEmpty(SsRngBuf* rBuf)
227 {
228    /* write == read implies Buffer is empty*/
229    return (rBuf->write == rBuf->read); 
230 }
231
232 S16 isRngEmpty(uint32_t id)
233 {
234    return (IsEmpty(SsRngInfoTbl[id].r_addr));
235 }
236 /*
237 Func: SEnqSRngBuf
238 Desc: Perform Queue operation on Ring bufer
239 */
240 S16 SEnqSRngBuf 
241 (
242 uint32_t id, 
243 Void* elem
244 )
245 {
246    uint8_t* w_ptr;
247    uint8_t i=0;
248    uint8_t *element = (uint8_t *)elem;
249    uint32_t wrIndex;
250    /* TBD To replace id with ring addr when SAttachSRngBuf is used*/
251    /* Retrive Buffer from Id */
252    SsRngBuf* ring = SsRngInfoTbl[id].r_addr;
253    if (IsFull(ring))
254    {
255         SsRngInfoTbl[id].nWriteFail++;
256         return RFAILED;
257    }
258    /* TBD Avoid multiplication for optimisation */
259    w_ptr = (uint8_t*)ring->elem + (ring->write * ring->type);
260    /* TBD Avoid for loop - use memcpy */
261    for( i=0; i < ring->type; i++)
262    {
263       *(uint8_t*)w_ptr = *(uint8_t*)element;
264       w_ptr++;
265       (uint8_t*)element++;
266    }
267    /* Increment write index */
268     wrIndex = ring->write + 1 ;
269     ring->write = (wrIndex == ring->size)?0: wrIndex;
270    /* Update Statistics */
271    SsRngInfoTbl[id].n_write++;
272    return ROK;
273 }
274
275 S16 SGetNumElemInRng(uint32_t id)
276 {
277
278    S16 freeDist = (SsRngInfoTbl[id].n_write- SsRngInfoTbl[id].n_read);
279
280         return (freeDist);
281 }
282 /*
283 Func: SDeqSRngBuf
284 Desc: Perform DeQueue operation on Ring bufer
285 */
286 S16 SDeqSRngBuf(uint32_t id,Void *elem)
287 {
288    uint8_t* r_ptr;
289    uint8_t i=0;
290    uint8_t *element = (uint8_t *)elem;
291    uint32_t rdIndex;
292    /* Retrive Buffer from Id*/
293    SsRngBuf* ring  = SsRngInfoTbl[id].r_addr;
294    if(IsEmpty(ring))
295    {  
296        SsRngInfoTbl[id].nReadFail++;
297        return RFAILED;
298    }
299    r_ptr = (uint8_t*)ring->elem + (ring->read * ring->type);
300    for(i=0; i<ring->type; i++)
301    {
302       *(uint8_t*)element = *r_ptr;
303       (uint8_t*)element++;
304       r_ptr++;
305    }
306    // Avoiding % operation for wrap around
307    rdIndex= ring->read + 1;
308    ring->read = (rdIndex == ring->size)?0:rdIndex;
309    SsRngInfoTbl[id].n_read++;
310    return ROK;
311 }
312
313 S16 SDestroySRngBuf 
314 (
315 uint32_t id,
316 Region region,
317 Pool pool
318 )
319 {
320    /* Retrive Buffer from Id */
321    SsRngBuf* ring = SsRngInfoTbl[id].r_addr;
322    if(ring)
323    {   
324       //SPutSBuf(region, pool, (Data *)ring->elem, (ring->size * ring->type));
325       //SPutSBuf(region, pool, (Data *)ring, sizeof(SsRngBuf));
326       
327       free(ring->elem); /* OK if null */ 
328       free(ring); /* OK if null */ 
329
330       /* Update Global Info  table */
331       SsRngInfoTbl[id].rngState = SS_RNG_DESTROYED;
332       SsRngInfoTbl[id].r_addr = 0;
333    }
334    return ROK;
335 }
336
337 S16 SPrintSRngStats(Void)
338 {
339 uint32_t i; 
340
341    Txt   prntBuf[100];
342
343 #ifdef RGL_SPECIFIC_CHANGES
344    return ROK;
345 #endif
346    for(i=0; i< SS_RNG_BUF_MAX;i++)
347    {
348       if(SsRngInfoTbl[i].r_addr != 0 )
349       {
350 #ifndef ALIGN_64BIT
351          sprintf(prntBuf,"\n=======Ring %ld Stats========\n",i);
352          SDisplay(0, prntBuf);
353          sprintf(prntBuf,"r_addr      = %lx\n", (PTR)SsRngInfoTbl[i].r_addr);
354          SDisplay(0, prntBuf);
355          sprintf(prntBuf,"txEnt       = %lx\n", (PTR)SsRngInfoTbl[i].txEnt);
356          SDisplay(0, prntBuf);
357          sprintf(prntBuf,"rxEnt       = %lx\n", (PTR)SsRngInfoTbl[i].rxEnt);
358          SDisplay(0, prntBuf);
359          sprintf(prntBuf,"n_write     = %lu\n", SsRngInfoTbl[i].n_write);
360          SDisplay(0, prntBuf);
361          sprintf(prntBuf,"n_read      = %lu\n", SsRngInfoTbl[i].n_read);
362          SDisplay(0, prntBuf);
363          sprintf(prntBuf,"nWriteFail  = %lu\n", SsRngInfoTbl[i].nWriteFail);
364          SDisplay(0, prntBuf);
365          sprintf(prntBuf,"nReadFail   = %lu\n", SsRngInfoTbl[i].nReadFail);
366          SDisplay(0, prntBuf);
367          sprintf(prntBuf,"pktDrop     = %lu\n", SsRngInfoTbl[i].pktDrop);
368          SDisplay(0, prntBuf);
369          sprintf(prntBuf,"State       = %lu\n\n", SsRngInfoTbl[i].rngState);
370          SDisplay(0, prntBuf);
371          sprintf(prntBuf,"nPktProc    = %lu\n\n", SsRngInfoTbl[i].nPktProc);
372          SDisplay(0, prntBuf);
373 #else
374          sprintf(prntBuf,"\n=======Ring %d Stats========\n",i);
375          SDisplay(0, prntBuf);
376          sprintf(prntBuf,"r_addr      = %lx\n", (PTR)SsRngInfoTbl[i].r_addr);
377          SDisplay(0, prntBuf);
378          sprintf(prntBuf,"txEnt       = %lx\n", (PTR)SsRngInfoTbl[i].txEnt);
379          SDisplay(0, prntBuf);
380          sprintf(prntBuf,"rxEnt       = %lx\n", (PTR)SsRngInfoTbl[i].rxEnt);
381          SDisplay(0, prntBuf);
382          sprintf(prntBuf,"n_write     = %u\n", SsRngInfoTbl[i].n_write);
383          SDisplay(0, prntBuf);
384          sprintf(prntBuf,"n_read      = %u\n", SsRngInfoTbl[i].n_read);
385          SDisplay(0, prntBuf);
386          sprintf(prntBuf,"nWriteFail  = %u\n", SsRngInfoTbl[i].nWriteFail);
387          SDisplay(0, prntBuf);
388          sprintf(prntBuf,"nReadFail   = %u\n", SsRngInfoTbl[i].nReadFail);
389          SDisplay(0, prntBuf);
390          sprintf(prntBuf,"pktDrop     = %u\n", SsRngInfoTbl[i].pktDrop);
391          SDisplay(0, prntBuf);
392          sprintf(prntBuf,"State       = %u\n\n", SsRngInfoTbl[i].rngState);
393          SDisplay(0, prntBuf);
394          sprintf(prntBuf,"nPktProc    = %u\n\n", SsRngInfoTbl[i].nPktProc);
395          SDisplay(0, prntBuf);
396
397 #endif
398       }
399    }
400    return ROK; 
401 }
402
403 Void* SRngGetWIndx(uint32_t rngId)
404 {
405    /* Retrive Buffer from Id*/
406    SsRngBuf* ring  = SsRngInfoTbl[rngId].r_addr;
407    if (IsFull(ring))
408    {
409       SsRngInfoTbl[rngId].nWriteFail++;
410       return (NULLP);
411    }
412    else
413    {
414       return (((uint8_t *)ring->elem) + (ring->type * ring->write));
415    }
416 }
417
418 Void* SRngGetRIndx(uint32_t rngId)
419 {
420    /* Retrive Buffer from Id*/
421    SsRngBuf* ring  = SsRngInfoTbl[rngId].r_addr;
422    if(IsEmpty(ring))
423    {
424       SsRngInfoTbl[rngId].nReadFail++;
425       return (NULLP);
426    }
427    else
428    {
429       return (((uint8_t *)ring->elem) + (ring->type * ring->read));
430    }
431 }
432
433 Void SRngIncrWIndx(uint32_t rngId)
434 {
435    uint32_t wrIndex;
436    /* Retrive Buffer from Id*/
437    SsRngBuf* ring  = SsRngInfoTbl[rngId].r_addr;
438    wrIndex = ring->write + 1;
439    ring->write = (wrIndex == ring->size)?0:wrIndex;
440    /* Update Statistics */
441    SsRngInfoTbl[rngId].n_write++;
442 }
443
444 Void SRngIncrRIndx(uint32_t rngId)
445 {
446    uint32_t rdIndex;
447    /* Retrive Buffer from Id*/
448    SsRngBuf* ring  = SsRngInfoTbl[rngId].r_addr;
449    rdIndex = ring->read + 1;
450    ring->read = (rdIndex == ring->size)?0:rdIndex;
451    /* Update Statistics */
452    SsRngInfoTbl[rngId].n_read++;
453 }
454 #ifdef XEON_SPECIFIC_CHANGES
455 #if (defined (MAC_FREE_RING_BUF) || defined (RLC_FREE_RING_BUF))
456 S16 mtAddBufToRing(SsRngBufId ringId,void *bufPtr,uint8_t freeType)
457 {
458    S16 ret1 = ROK;
459    
460    Void *elem = NULLP;
461
462    RgKwFreeInfo *bufFreeInfo = NULLP;
463    elem = SRngGetWIndx(ringId);
464
465    if (NULLP != elem)
466    {
467       bufFreeInfo = (RgKwFreeInfo *) elem;
468
469       bufFreeInfo->bufToFree = bufPtr;
470       bufFreeInfo->freeType  = freeType;
471
472       SRngIncrWIndx(ringId);
473
474       SsRngInfoTbl[ringId].pktRate++;
475    }   
476    else
477    {
478       printf("Free Ring FULL id %d!!! \n",ringId);
479       SsRngInfoTbl[ringId].pktDrop++;
480       ret1 = RFAILED;
481    }
482    return (ret1);
483 }
484 #endif
485 #endif
486
487
488
489 /**********************************************************************
490          End of file
491 **********************************************************************/