Merging the changes for tailroom configuration and update for heap allocation to...
[keystone-rtos/netapi.git] / ti / runtime / netapi / src / netapi.c
1 /*******************************
2  * FILE: netapi.c
3  * Purpose:  implementation of netapi startup/shutdown
4  **************************************************************
5  * FILE: netapi.c
6  * 
7  * DESCRIPTION:  netapi main source file for user space transport
8  *               library
9  * 
10  * REVISION HISTORY:  rev 0.0.1 
11  *
12  *  Copyright (c) Texas Instruments Incorporated 2010-2011
13  * 
14  *  Redistribution and use in source and binary forms, with or without 
15  *  modification, are permitted provided that the following conditions 
16  *  are met:
17  *
18  *    Redistributions of source code must retain the above copyright 
19  *    notice, this list of conditions and the following disclaimer.
20  *
21  *    Redistributions in binary form must reproduce the above copyright
22  *    notice, this list of conditions and the following disclaimer in the 
23  *    documentation and/or other materials provided with the   
24  *    distribution.
25  *
26  *    Neither the name of Texas Instruments Incorporated nor the names of
27  *    its contributors may be used to endorse or promote products derived
28  *    from this software without specific prior written permission.
29  *
30  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
31  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
32  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
33  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
34  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
35  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
36  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
37  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
38  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
39  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
40  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42  * *****************************/
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <unistd.h>
46 #include <string.h>
47 #include "netapi.h"
49 typedef struct PRESET_Tag
50 {
51 #define KMAXQ 10
52         int kqinuse[KMAXQ];
53         //more..
54 } PRESET_T;
56 /*------------internal prototypes---------------*/
57 static uint8_t* netapiSharedMemoryMalloc(uint32_t size);
58 static void netapiSharedMemoryFree(uint8_t* ptr);
59 static int system_init(NETAPI_HANDLE_T *);
60 static void get_presets(PRESET_T * p_preset);
61 static void netapi_cleanup_at_start(void);
64 /*------------globals-----------------*/
65 #define NUM_HOST_DESC  (TUNE_NETAPI_NUM_LOCAL_DESC)
66 #define SIZE_LOCAL_DESC  (TUNE_NETAPI_DESC_SIZE) 
67 #define SIZE_SHARED_DESC (TUNE_NETAPI_DESC_SIZE)
69 #define CONFIG_BUFSIZE_PA_INST      256
70 #define CONFIG_BUFSIZE_L2_TABLE     1000
71 #define CONFIG_BUFSIZE_L3_TABLE     4000
73 static NETAPI_CFG_T netapi_default_cfg=
74 {
75 TUNE_NETAPI_PERM_MEM_SZ,
76 0,  //start of packet offset for hw to place data on rx for default flow
77 TUNE_NETAPI_QM_CONFIG_MAX_DESC_NUM, //max number of descriptors in system
78 TUNE_NETAPI_NUM_GLOBAL_DESC,        //total we will use
79 TUNE_NETAPI_DEFAULT_NUM_BUFFERS,   //#descriptors+buffers in default heap
80 TUNE_NETAPI_DEFAULT_NUM_SOLO_DESCRIPTORS, //#descriptors w/o buffers in default heap
81 TUNE_NETAPI_DEFAULT_BUFFER_SIZE,   //size of buffers in default heap
82 0,0
84 };
86 static Pktlib_HeapIfTable  netapi_pktlib_ifTable;
87 static NETAPI_GLOBAL_T netapi_global;
88 NETAPI_GLOBAL_T * netapi_get_global(){ return &netapi_global;}
90 /* utility API for NETAPI user to get pktlib if table to use if he creates his own heap */
91 Pktlib_HeapIfTable *netapi_getPktlibIfTable(void) {return &netapi_pktlib_ifTable;}
93 //zap a queue
94 void netapi_zapQ(int queueNum);
95 /*-------------------------------------
96  *  initialize NETAPI instance 
97  *-------------------------------------*/
98 NETAPI_T netapi_init(int master, NETAPI_CFG_T * p_cfg)
99 {
100  int i;
101  int err;
102  NETAPI_HANDLE_T * p = (NETAPI_HANDLE_T *) calloc(1,sizeof(NETAPI_HANDLE_T));
103  if (!p) return NULL;
104  p->master = master;
106  /* create space for our local pktios */
107  for(i=0;i<NETAPI_MAX_PKTIO; i++)
108  {
109    p->pktios[i] = calloc(1,sizeof(PKTIO_HANDLE_T));
110   if (!p->pktios[i]) return NULL;
111  }
113 #ifdef NETAPI_INCLUDE_SCHED
114  /* create space for scheduler */
115  p->p_sched = calloc(1,sizeof(NETAPI_SCHED_HANDLE_T));
116 #endif 
119  /* global stuff (if master) */
120  if (master==NETAPI_SYS_MASTER)
121  {
122    if (p_cfg) memcpy(&netapi_global.cfg,p_cfg, sizeof(NETAPI_CFG_T));
123    else      memcpy(&netapi_global.cfg,&netapi_default_cfg, sizeof(NETAPI_CFG_T));
124    for(i=0;i<NETAPI_MAX_PKTIO;i++) 
125    { 
126         netapi_global.pktios[i].qn.qNum=-1;
127         netapi_global.pktios[i].name[0]='\0';
128    }
129  }   
130  //this goes to shared memory eventually
131  p->global = (void *) &netapi_global;
134    /* system init */
135    if(master==NETAPI_SYS_MASTER)
136    {
137       err = system_init(p);
138       if (err<0) 
139       {
140         //todo: cleanup
141         return NULL;
142       }
143       /* create pktio channels for tx,rx */
144    }
145    else
146    {
147        /*todo init for non-system cores/threads */
148        /* qm_start, */
149        /* attach to heaps */
150        /* nwal_start */
151    }
152   
153    return (NETAPI_T) p;
156 /*-------------------------------
157  * Shut down netapi instance
158  *-------------------------------*/
159 void netapi_shutdown(NETAPI_T h)
161         int i;
162         NETAPI_HANDLE_T * p = (NETAPI_HANDLE_T *) h;
163         if (!p) return;
165         printf(">netapi: WARNING shutdown may not be fully implemented\n");
166         if (p->master)
167         {
168            /* close nwal */
169            nwal_delete(netapi_global.nwal_context.nwalInstHandle);
171            /* close heaps */
172            netapi_closeHeap(h, p->netcp_heap);
173            netapi_closeHeap(h, p->netcp_control_heap);
174            netapi_closeHeap(h, netapi_get_global()->nwal_context.pa2sa_heap); 
175            netapi_closeHeap(h, netapi_get_global()->nwal_context.sa2pa_heap); 
176  
177            //loop over registered heaps
178            for(i=0;i<TUNE_NETAPI_MAX_HEAPS;i++)
179            {
180                 if (p->createdHeaps[i])  {netapi_closeHeap(h,p->createdHeaps[i]);p->createdHeaps[i]=NULL;}
181            }
182            netapi_cleanup_at_start();  //clear 1st 50 not-specified queues..
183            netapi_VM_memory_teardown();
184         } 
185         free(p);
186         return;
189 //exception crash
190 void netapi_err_teardown() { netapi_cleanup_at_start(); exit(-99); }
192 /*-------------------utilities-------------------*/
193 static uint8_t* netapiSharedMemoryMalloc(uint32_t size)
195 return  (uint8_t *)netapi_VM_memAlloc(size +netapi_global.cfg.def_heap_extra_size , 128); 
198 static void netapiSharedMemoryFree(uint8_t* ptr)
200     /* Do Nothing. */
201     printf(">netapi Unexpected.  need to provide a free () for some reason!! \n");
202     return;
205 // initialization
206 static int system_init(NETAPI_HANDLE_T * handle) 
208     int32_t             result;
209     Pktlib_HeapHandle   sharedHeapHandle;
210     Pktlib_HeapHandle   controlHeapHandle;    
211     Pktlib_HeapCfg      heapCfg;
212     int32_t             errCode;
214     /* initialize all the memory we are going to use
215        - chunk for buffers, descriptors
216        - memory mapped peripherals we use, such as QMSS, PA, etc */
217     result= netapi_VM_memory_setup();
218     if (result) printf(">netapi: system init - memory set  up OK\n");
219     else {printf(">netap: system init - memory set up failed\n"); return -1;}
221     //get timer running
222     netapi_init_timer();
224     /* Initialize Queue Manager Sub System */
225     result = netapi_init_qm (netapi_global.cfg.def_max_descriptors); 
226     if (result != 1)
227     {
228         return -1;
229     }
231     /* Start the QMSS. */
232     if (netapi_start_qm() != 1)
233     {
234         return -1;
235     }
237     //clean our old junk in 1st bunch of queues that will be allocated to us
238     netapi_cleanup_at_start();
240     /* Initialize the global descriptor memory region. */
241     result= netapi_qm_setup_mem_region( 
242                       netapi_global.cfg.def_tot_descriptors_for_us,
243                       SIZE_SHARED_DESC,
244                       (unsigned int *) netapi_VM_QMemGlobalDescRam,
245                       NETAPI_GLOBAL_REGION);
246     if(result <0) {printf(">netapi; can't setup QM shared region\n"); return -1;}
248 #if 0 //todo setup 2nd region
249 /* Initialize the local memory region configuration. */
250     result= netapi_qm_setup_mem_region( 
251                       NUM_HOST_DESC,
252                       SIZE_LOCAL_DESC,
253                       netapi_VM_QMemLocalDescRam,
254                       NETAPI_LOCAL_REGION);
255     if(result <0) {printf("can't setup local region\n"); return -1;}
256 #endif
257     /* Initialize CPPI CPDMA */
259     result = netapi_init_cppi ();
260     if (result != 1)
261     {
262         printf (">netapi: Error initializing CPPI SubSystem error code : %d\n",result);
263         return -1;
264     }
266     /* CPPI and Queue Manager are initialized. */
267     printf (">netapi: Queue Manager and CPPI are initialized.\n");
269     /* create main pkt heap */
270     /* Initialize the Shared Heaps. */
271     Pktlib_sharedHeapInit();
273     /* Populate the heap interface table. */
274     netapi_pktlib_ifTable.data_malloc             = netapiSharedMemoryMalloc;
275     netapi_pktlib_ifTable.data_free               = netapiSharedMemoryFree;
277     /* Initialize the heap configuration. */
278     memset ((void *)&heapCfg, 0, sizeof(Pktlib_HeapCfg));
279     /* Populate the heap configuration */
280     heapCfg.name                = "netapi";
281     heapCfg.memRegion           = NETAPI_GLOBAL_REGION;
282     heapCfg.sharedHeap          = 1;
283     heapCfg.useStarvationQueue  = 0;
284     heapCfg.dataBufferSize      = netapi_global.cfg.def_heap_buf_size;
285     heapCfg.numPkts             = netapi_global.cfg.def_heap_n_descriptors;
286     heapCfg.numZeroBufferPackets= netapi_global.cfg.def_heap_n_zdescriptors;
287     heapCfg.heapInterfaceTable.data_malloc  = netapi_pktlib_ifTable.data_malloc;
288     heapCfg.heapInterfaceTable.data_free    = netapi_pktlib_ifTable.data_free;
289     heapCfg.dataBufferPktThreshold   = 0;
290     heapCfg.zeroBufferPktThreshold   = 0;
292     /* Create Shared Heap with specified configuration. */
293     sharedHeapHandle = Pktlib_createHeap(&heapCfg, &errCode);
294     //todo -> cleanup on failure
295     if (!sharedHeapHandle) { printf(">'netapi' heap create failed, Error Code: %d\n",errCode); return -1;}
296     handle->netcp_heap= sharedHeapHandle;
299     /* Update for Control */
300     heapCfg.name                = "netapi_control";
301     heapCfg.sharedHeap          = 1;
302     heapCfg.dataBufferSize      = TUNE_NETAPI_CONFIG_MAX_CTL_RXTX_BUF_SIZE;
303     heapCfg.numPkts             = TUNE_NETAPI_CONFIG_NUM_CTL_BUF;
304     heapCfg.numZeroBufferPackets= 0;
306     controlHeapHandle = Pktlib_createHeap(&heapCfg, &errCode);;
307    //todo -> cleanup on failure
308    if (!controlHeapHandle) { printf(">netapi -'netapicontrol' heap create failed, Error Code: %d\n",errCode); return -1;}
309    handle->netcp_control_heap= controlHeapHandle;
312     /* now NWAL */
313     result = netapi_init_nwal(
314                               NETAPI_GLOBAL_REGION,
315                               &netapi_pktlib_ifTable, 
316                               &netapi_global.nwal_context,
317                               &netapi_global.cfg);
318     if (result<0) {printf(">netapi  init_nwal() failed\n"); return -1; }
320     /* start NWAL */
321     result = netapi_start_nwal(sharedHeapHandle, 
322                                controlHeapHandle,
323                                &handle->nwal_local,
324                                &netapi_global.cfg,
325                                &netapi_global.nwal_context);
326     if (result<0) {printf(">netapi start_nwal() failed\n"); return -1; }
327     //** success **
330     return 0;
335 /*---------------
336  * get presets()
337  *---------------*/
338 static void get_presets(PRESET_T * p_preset)
340  /* read from kernel or overall config area */
341  /* for now hard code what kernel did */
345 /*************************************************************
346  ******************MISC INTERNAL******************************
347 **************************************************************/
348 /* poll the garbage queues of all registered heaps */
349 void netapi_pollHeapGarbage(NETAPI_T h)
351 int i;
352         NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h;
353         Pktlib_garbageCollection(n->netcp_heap);
354         //no need to do garbage collection on other internal heaps
355         for(i=0;i<TUNE_NETAPI_MAX_HEAPS;i++)
356         {
357                 if (n->createdHeaps[i]) Pktlib_garbageCollection(n->createdHeaps[i]);
358         }
361 /* poll NETCP control queue for responses */
362 void netapi_netcpPoll(NETAPI_T  p)
364         NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) p;
365         nwal_pollCtl( ((NETAPI_GLOBAL_T *) (n->global))->nwal_context.nwalInstHandle,NULL,NULL);
368 /****************************************************************
369  *****************Cleanup Functions******************************
370 *****************************************************************/
372 //clean up function for linux user space
373 void netapi_zapQ(int queueNum)
375 char * descPtr;
376 int i;
377 if (!queueNum) return;
378 for (i=0;;i+=1 )
379         {
380                 /* Pop descriptor from source queue */
381                 if ((descPtr = (char *)Qmss_queuePop (queueNum)) == NULL)
382                 {
383                         break;
384                 }
385                 else {/*printf("netapi qzap in play\n");*/}
386         }
387         if(i) printf(">netapi: @recovery -  %d descriptors cleaned from qn %d\n",i, queueNum);
390 //defensive: clean out stuff hanging around
391 //
392 //  open a bunch of free queues and zap them
393 #define NQUEUES2CLEAR 15
394 static Qmss_QueueHnd tempQH[NQUEUES2CLEAR];
395 static void netapi_cleanup_at_start(void)
397 int i;
398 uint8_t         isAllocated;
400 for(i=0;i<NQUEUES2CLEAR;i++) 
402         tempQH[i] = Qmss_queueOpen(Qmss_QueueType_GENERAL_PURPOSE_QUEUE,
403                                                   QMSS_PARAM_NOT_SPECIFIED, &isAllocated);
404         netapi_zapQ(tempQH[i]);
407 for(i=0;i<NQUEUES2CLEAR;i++)
409         Qmss_queueClose(tempQH[i]);
414 /********************************
415  *  clean up a  pktlib heap
416  ***********************************/
417 int netapi_closeHeap(NETAPI_T h, Pktlib_HeapHandle p)
419 Qmss_QueueHnd q;
420 Pktlib_garbageCollection(p);  
421 q = Pktlib_getZeroHeapQueue(p);
422 netapi_zapQ(q);
423 q= Pktlib_getInternalHeapQueue(p);
424 netapi_zapQ(q);