Integration changes with latest NWAL
[keystone-rtos/netapi.git] / ti / runtime / netapi / src / netapi.c
1 /***********************************************************************
2  * FILE: netapi.c
3  * Purpose:  Main initialization and shutdown routines of NETAPI 
4  *           user space transport library.
5  ***********************************************************************
6  * FILE: netapi.c
7  * 
8  * DESCRIPTION:  netapi main source file for user space transport
9  *               library
10  * 
11  * REVISION HISTORY:
12  *
13  *  Copyright (c) Texas Instruments Incorporated 2013
14  * 
15  *  Redistribution and use in source and binary forms, with or without 
16  *  modification, are permitted provided that the following conditions 
17  *  are met:
18  *
19  *    Redistributions of source code must retain the above copyright 
20  *    notice, this list of conditions and the following disclaimer.
21  *
22  *    Redistributions in binary form must reproduce the above copyright
23  *    notice, this list of conditions and the following disclaimer in the 
24  *    documentation and/or other materials provided with the   
25  *    distribution.
26  *
27  *    Neither the name of Texas Instruments Incorporated nor the names of
28  *    its contributors may be used to endorse or promote products derived
29  *    from this software without specific prior written permission.
30  *
31  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
32  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
33  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
34  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
35  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
36  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
37  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
38  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
39  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
40  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
41  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43  * *****************************/
45 #include <unistd.h>
46 #include "ti/runtime/netapi/netapi.h"
47 #include "netapi_loc.h"
49 void* pBase;
50 NETAPI_SHM_T* pnetapiShm;
52 static NETAPI_CFG_T netapi_default_cfg=
53 {
54     TUNE_NETAPI_PERM_MEM_SZ,
55     0,  //start of packet offset for hw to place data on rx for default flow
56     TUNE_NETAPI_QM_CONFIG_MAX_DESC_NUM, //max number of descriptors in system
57     TUNE_NETAPI_NUM_GLOBAL_DESC,        //total we will use
58     TUNE_NETAPI_DEFAULT_NUM_BUFFERS,   //#descriptors+buffers in default heap
59     TUNE_NETAPI_DEFAULT_NUM_SOLO_DESCRIPTORS, //#descriptors w/o buffers in default heap
60     TUNE_NETAPI_DEFAULT_BUFFER_SIZE,   //size of buffers in default heap
61     0,
62     0,
63     0
64 };
66 HPLIB_SPINLOCK_IF_T spinlock_lol =
67 {
68     hplib_mSpinLockInit,
69     hplib_mSpinLockTryLock,
70     hplib_mSpinLockIsLocked,
71     hplib_mSpinLockLock,
72     hplib_mSpinLockUnlock,
73     hplib_mRWLockInit,
74     hplib_mRWLockWriteLock,
75     hplib_mRWLockWriteUnlock,
76     hplib_mRWLockReadLock,
77     hplib_mRWLockReadUnlock
78 };
81 HPLIB_SPINLOCK_IF_T spinlock_mp =
82 {
83     hplib_mSpinLockInit,
84     hplib_mSpinLockTryLock,
85     hplib_mSpinLockIsLocked,
86     hplib_mSpinLockLockMP,
87     hplib_mSpinLockUnlockMP,
88     hplib_mRWLockInit,
89     hplib_mRWLockWriteLockMP,
90     hplib_mRWLockWriteUnlockMP,
91     hplib_mRWLockReadLockMP,
92     hplib_mRWLockReadUnlockMP
93 };
95 /* Global variablesto hold virtual address of various subsystems */
96 hplib_virtualAddrInfo_T netapi_VM_VirtAddr[HPLIB_MAX_MEM_POOLS];
98 /* Global variables which needs to be populated with memory pool attributes
99    which is passed to HPLIB for memory pool initialization*/
100 hplib_memPoolAttr_T netapi_VM_MempoolAttr[HPLIB_MAX_MEM_POOLS];
101 unsigned char *netapi_VM_QMemLocalDescRam;
102 unsigned char *netapi_VM_QMemGlobalDescRam;
103 unsigned char *netapi_VM_SaContextVaddr;
105 //global for this process that points to the 
106 // master thread for this process (either the SYS_MASTER, or PROC_MASTER)
107 //...
108 NETAPI_HANDLE_T * netapi_proc_master = NULL;
109 Pktlib_HeapIfTable  netapi_pktlib_ifTable;
110 NETAPI_PROC_GLOBAL_T netapi_proc_global;
111 //NETAPI_GLOBAL_T * netapi_get_global(){ return &netapi_global;}
112 NETAPI_GLOBAL_T * netapi_get_global(){ return &pnetapiShm->netapi_global;}
113 NETAPI_PROC_GLOBAL_T * netapi_get_proc_global(){ return &netapi_proc_global;}
115 /* utility API for NETAPI user to get pktlib if table to use if he creates his own heap */
116 Pktlib_HeapIfTable *netapi_getPktlibIfTable(void) {return &netapi_pktlib_ifTable;}
119 /********************************************************************
120 * FUNCTION PURPOSE:  API instantiates the NETAPI and allocated global resources.
121  ********************************************************************
122  * DESCRIPTION:  API instantiates the NETAPI and allocated global resources.
123  ********************************************************************/
124 NETAPI_T netapi_init(int                master,
125                      NETAPI_CFG_T *     p_cfg,
126                      hplib_globalDeviceConfigParams_t *p_hplibDeviceCfg,
127                      NETCP_CFG_GLOB_DEVICE_PARAMS_T   *p_netapiDeviceCfg)
130     int i;
131     int err;
132     int exception_id = 7;
133     void* pBase = NULL;
135     hplib_shmInfo_T* pshmBase = NULL;
136     NETAPI_HANDLE_T * p = (NETAPI_HANDLE_T *) calloc(1,sizeof(NETAPI_HANDLE_T));
137     NETAPI_HANDLE_T * p_master;
138     if (!p) return NULL;
139     p->master = master;
140     p->fNssGen2 = p_netapiDeviceCfg->fNssGen2;
141     
142     /*  SYS_MASTER: The following segment should be done 1 Time per system boot by global master process's main core/thread */
143     if (master == NETAPI_SYS_MASTER)
144     {
145         pBase = hplib_shmCreate(HPLIB_SHM_SIZE);
147         if (pBase == NULL)
148         {
149             printf("netapi_init: hplib_shmCreate failure\n");
150             return NULL;
151         }
153         if (hplib_shmAddEntry(pBase, sizeof(NETAPI_SHM_T), NETAPI_ENTRY) !=
154             hplib_OK)
155         {
156             netapi_Log("netapi_init: hplib_shmAddEntry failed for NETAPI_ENTRY\n");
157             return NULL;
158         }
159         hplib_utilOsalCreate();
160     }
161     /*ALL others:  we are not the system master; assume SYS_MASTER has
162       created SHM area for us already, so just open it */
163     else 
164     {
165         pBase = hplib_shmOpen(HPLIB_SHM_SIZE);
166         //error check;  
167         if (!pBase)
168         {
169             netapi_Log("netapi_init: hplib_shmOpen error\n");
170         }
171     }
173     /*ALL:  create space for our local pktios */
174     for(i=0;i<TUNE_NETAPI_MAX_PKTIO; i++)
175     {
176         p->pktios[i] = calloc(1,sizeof(PKTIO_HANDLE_T));
177         if (!p->pktios[i])
178         {
179             return NULL;
180         }
181     }
183 #ifdef NETAPI_INCLUDE_SCHED
184     /* ALL: create space for scheduler */
185     p->p_sched = calloc(1,sizeof(NETAPI_SCHED_HANDLE_T));
186     if (!p->p_sched)
187     {
188         goto ERR_netapi_init;
189     }
190 #endif
192     /* SYS_MASTER:  The following segment should be done 1 Time per system boot by global master process */
193     if (master == NETAPI_SYS_MASTER)
194     {
195         pnetapiShm = (NETAPI_SHM_T*)hplib_shmGetEntry(pBase, NETAPI_ENTRY);
196         pnetapiShm->netapi_pktio_lock= hplib_spinLock_UNLOCKED_INITIALIZER;
197         pnetapiShm->netapi_netcp_cfg_lock = hplib_spinLock_UNLOCKED_INITIALIZER;
198         pnetapiShm->netapi_netcp_cfg_l3_classi_lock = hplib_spinLock_UNLOCKED_INITIALIZER;
199         pnetapiShm->netapi_util_lock = hplib_spinLock_UNLOCKED_INITIALIZER;
200         if (p_cfg)
201         {
202             memcpy(&pnetapiShm->netapi_global.cfg,p_cfg, sizeof(NETAPI_CFG_T));
203         }
204         else
205         {
206             memcpy(&pnetapiShm->netapi_global.cfg,&netapi_default_cfg, sizeof(NETAPI_CFG_T));
207         }
208         for(i=0;i<TUNE_NETAPI_MAX_PKTIO;i++) 
209         {
210             pnetapiShm->netapi_global.pktios[i].qn.qNum=-1;
211             pnetapiShm->netapi_global.pktios[i].name[0]='\0';
212         }
213     }
214     else
215     {
216         /* other 'masters' will just get a pointer to the netapi SHM area*/
217         pnetapiShm = (NETAPI_SHM_T*)hplib_shmGetEntry(pBase, NETAPI_ENTRY);
218     }
220     //all:  for convenience set a back pointer to the SOC global area (in SHM)  
221     //      and process global in netapi_proc_global
222     p->global = (void *) &pnetapiShm->netapi_global;
223     p->proc_global = (void *)&netapi_proc_global;
224     /* Update spinLock to point to either MP spinlock or fast spinlocks, this is 
225        for all callers of netapi_init*/
226     if(p_cfg)
227     {
228         if(p_cfg->def_multi_process)
229             p->spinLock = spinlock_mp;
230         else
231             p->spinLock= spinlock_lol;
232     }
233     else
234         p->spinLock = spinlock_lol;
236     /* SYS_MASTER, PROC_MASTER: save a pointer to its netapi structure
237        globably for other threads/core of process to use */
238     if ((master == NETAPI_SYS_MASTER)||(master == NETAPI_PROC_MASTER))
239     {
240         p_master=netapi_proc_master = p;
241     }
242     else
243     {
244         /* CORE_MASTER/NO_MASTER: get system master/proc master's handle */
245         p_master=(NETAPI_HANDLE_T *) netapi_proc_master;
246     }
249     /* SYS_MASTER: The following segment should be done 1 Time per system boot by global master process */
250     /* system init */
251     if(master == NETAPI_SYS_MASTER)
252     {
253         err = netapip_systemInit(p,
254                                  p_hplibDeviceCfg,
255                                  p_netapiDeviceCfg,
256                                  TRUE);
257         if (err<0) 
258         {
259             goto ERR_netapi_init;
260         }
261         netapi_netcpCfgExceptions(p, NETCP_CFG_ALL_EXCEPTIONS, NETCP_CFG_ACTION_TO_SW, (NETCP_CFG_ROUTE_HANDLE_T) NULL);
262     }
263     /* PROC_MASTER case */
264     else if (master==NETAPI_PROC_MASTER)
265     {
266         /* More limited initialization */
267         err = netapip_systemInit(p,
268                                  p_hplibDeviceCfg,
269                                  p_netapiDeviceCfg,
270                                  FALSE);
271         if (err<0)
272         {
273             goto ERR_netapi_init;
274         }
275     }
276     /* NO_MASTER:  case */
277     else if (master == NETAPI_NO_MASTER)
278     {
279         /*Just copy master's pktio list for now */
280         p->n_pktios = p_master->n_pktios;
281         memcpy(&p->pktios[0],&p_master->pktios[0],TUNE_NETAPI_MAX_PKTIO*sizeof(PKTIO_HANDLE_T));
282         p->nwal_local=p_master->nwal_local;
283     }
284     /* this is the NETAPI_CORE_MASTER case */
285     else if (master == NETAPI_CORE_MASTER)
286     {
287         /* Start the QMSS. */
288         if (netapip_startQm() != 1)
289         {
290             goto ERR_netapi_init;
291         }
292         netapip_startNwal(p_master->netcp_heap, 
293                           p_master->netcp_control_rx_heap,
294                           p_master->netcp_control_tx_heap, 
295                                        &p->nwal_local,
296                           &pnetapiShm->netapi_global.cfg,
297                           &pnetapiShm->netapi_global.nwal_context);
298     }
299     else
300     {
301         netapi_Log("netapi_init: no master specified\n");
302         goto ERR_netapi_init;
303     }
305     return (NETAPI_T) p;
307 /* error handling */
308 ERR_netapi_init:
309     for(i=0;i<TUNE_NETAPI_MAX_PKTIO; i++)
310     {
311         if (p->pktios[i])
312         {
313             free(p->pktios[i]);
314         }
315     }
316 #ifdef NETAPI_INCLUDE_SCHED
317     if (p->p_sched)
318     {
319         free(p->p_sched);
320     }
321 #endif
322     return NULL;
325 /********************************************************************
326 * FUNCTION PURPOSE:  API de-allocates all global resources allocated as part 
327 *                                   of ref netapi_init
328  ********************************************************************
329  * DESCRIPTION:   API de-allocates all global resources allocated as part 
330 *                                   of ref netapi_init
331  ********************************************************************/
332 void netapi_shutdown(NETAPI_T h)
334     int i;
335     hplib_shmInfo_T* pshmBase;
336     NETAPI_HANDLE_T * p = (NETAPI_HANDLE_T *) h;
337     if (!p) return;
338     void * map_base;
339     hplib_VirtMemPoolheader_T *poolHdr;
341     netapi_Log("netapi: WARNING shutdown may not be fully implemented\n");
342     if (p->master == NETAPI_SYS_MASTER)
343     {
344         /* Un-configure rules for execption packet handling */
345         netapi_netcpCfgExceptions(p,
346                               NETCP_CFG_ALL_EXCEPTIONS,
347                               NETCP_CFG_ACTION_DISCARD,
348                               (NETCP_CFG_ROUTE_HANDLE_T) NULL);
350         /* close nwal master (per soc) context */
351         nwal_delete(pnetapiShm->netapi_global.nwal_context.nwalInstHandle);
353         /* close heaps */
354         netapi_closeHeap(h, p->netcp_heap);
355         netapi_closeHeap(h, p->netcp_control_rx_heap);
356         netapi_closeHeap(h, p->netcp_control_tx_heap);
357         netapi_closeHeap(h, netapi_get_global()->nwal_context.pa2sa_heap); 
358         netapi_closeHeap(h, netapi_get_global()->nwal_context.sa2pa_heap); 
360         //loop over registered heaps
361         for(i=0;i<TUNE_NETAPI_MAX_HEAPS;i++)
362         {
363             if (p->createdHeaps[i])  {netapi_closeHeap(h,p->createdHeaps[i]);p->createdHeaps[i]=NULL;}
364         }
365         netapip_cleanupAtStart();  //clear 1st 50 not-specified queues
366         //reset DDR malloc area
367         hplib_resetMallocArea(0);
368         hplib_vmTeardown();
369         printf("netapi_shutdown: calling hplib_shmDelete\n");
370         hplib_shmDelete();
371     }
372     else if (p->master == NETAPI_PROC_MASTER)
373     {
374         //we can zap these because they are local to our process
375         netapi_closeHeap(h, p->netcp_control_rx_heap);
376         netapi_closeHeap(h, p->netcp_control_tx_heap);
377         //loop over registered heaps (again local to our process)
378         for(i=0;i<TUNE_NETAPI_MAX_HEAPS;i++)
379         {
380             if (p->createdHeaps[i])  {netapi_closeHeap(h,p->createdHeaps[i]);p->createdHeaps[i]=NULL;}
381         }
382         hplib_vmTeardown();
383     }
384     //TODO other master types
385     /* error handling */
386     
387     for(i=0;i<TUNE_NETAPI_MAX_PKTIO; i++)
388     {
389         if (p->pktios[i])
390         {
391             free(p->pktios[i]);
392             p->pktios[i] = NULL;
393         }
394     }
395 #ifdef NETAPI_INCLUDE_SCHED
396     if (p->p_sched)
397     {
398         free(p->p_sched);
399         p->p_sched = NULL;
400     }
401 #endif
403     free(p);
404     printf("netapi_shutdown: complete\n");
405     return;
408 /***********************************************************************
409 * FUNCTION PURPOSE:  API is used to poll for NETCP configuration response messages.
410 ************************************************************************
411 * DESCRIPTION:  This API is used to poll the netapi internal heaps and any 
412  *              application-created heaps that have been registered with 
413  *              the netapi instance. The poll function checks the garbage collection 
414  *              queue associated with the heap and returns descriptors and buffers 
415  *              when appropriate to the main free queue.
416 ***********************************************************************/
417 void netapi_pollHeapGarbage(NETAPI_T h)
419     int i;
420     NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h;
421     Pktlib_garbageCollection(n->netcp_heap);
422     //no need to do garbage collection on other internal heaps
423     for(i=0;i<TUNE_NETAPI_MAX_HEAPS;i++)
424     {
425         if (n->createdHeaps[i])
426         {
427             Pktlib_garbageCollection(n->createdHeaps[i]);
428         }
429     }
432 /****************************************************************************
433 * FUNCTION PURPOSE:  API is used to poll for NETCP configuration response messages.
434 ****************************************************************************
435 * DESCRIPTION:  This API is used to poll the netapi internal heaps and any 
436  *              application-created heaps    that have been registered with the 
437  *              netapi instance. The poll function checks the garbage collection 
438  *              queue associated with the heap and returns descriptors and buffers
439  *              when appropriate to the main free queue.
440 ***************************************************************************/
441 void netapi_netcpPoll(NETAPI_T  p)
443     NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) p;
444     nwal_pollCtl( ((NETAPI_GLOBAL_T *) (n->global))->nwal_context.nwalInstHandle,NULL,NULL);