5dc19db54e616ac499096d2ae662e252a7fc5a0a
[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                      nwalGlobalDeviceConfigParams_t   *p_nwalDeviceCfg,
128                      NETCP_CFG_GLOB_DEVICE_PARAMS_T   *p_netapiDeviceCfg)
131     int i;
132     int err;
133     int exception_id = 7;
134     void* pBase = NULL;
136     hplib_shmInfo_T* pshmBase = NULL;
137     NETAPI_HANDLE_T * p = (NETAPI_HANDLE_T *) calloc(1,sizeof(NETAPI_HANDLE_T));
138     NETAPI_HANDLE_T * p_master;
139     if (!p) return NULL;
140     p->master = master;
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         }
152         else
153              printf("netapi_init: hplib_shmCreate sucess\n");
155         if (hplib_shmAddEntry(pBase, sizeof(NETAPI_SHM_T), NETAPI_ENTRY) !=
156             hplib_OK)
157         {
158             netapi_Log("netapi_init: hplib_shmAddEntry failed for NETAPI_ENTRY\n");
159             return NULL;
160         }
161         hplib_utilOsalCreate();
162     }
163     /*ALL others:  we are not the system master; assume SYS_MASTER has
164       created SHM area for us already, so just open it */
165     else 
166     {
167         pBase = hplib_shmOpen(HPLIB_SHM_SIZE);
168         //error check;  
169         if (!pBase)
170         {
171             netapi_Log("netapi_init: hplib_shmOpen error\n");
172         }
173     }
175     /*ALL:  create space for our local pktios */
176     for(i=0;i<TUNE_NETAPI_MAX_PKTIO; i++)
177     {
178         p->pktios[i] = calloc(1,sizeof(PKTIO_HANDLE_T));
179         if (!p->pktios[i])
180         {
181             return NULL;
182         }
183     }
185 #ifdef NETAPI_INCLUDE_SCHED
186     /* ALL: create space for scheduler */
187     p->p_sched = calloc(1,sizeof(NETAPI_SCHED_HANDLE_T));
188     if (!p->p_sched)
189     {
190         goto ERR_netapi_init;
191     }
192 #endif
194     /* SYS_MASTER:  The following segment should be done 1 Time per system boot by global master process */
195     if (master == NETAPI_SYS_MASTER)
196     {
197         pnetapiShm = (NETAPI_SHM_T*)hplib_shmGetEntry(pBase, NETAPI_ENTRY);
198         pnetapiShm->netapi_pktio_lock= hplib_spinLock_UNLOCKED_INITIALIZER;
199         pnetapiShm->netapi_netcp_cfg_lock = hplib_spinLock_UNLOCKED_INITIALIZER;
200         pnetapiShm->netapi_netcp_cfg_l3_classi_lock = hplib_spinLock_UNLOCKED_INITIALIZER;
201         pnetapiShm->netapi_util_lock = hplib_spinLock_UNLOCKED_INITIALIZER;
202         if (p_cfg)
203         {
204             memcpy(&pnetapiShm->netapi_global.cfg,p_cfg, sizeof(NETAPI_CFG_T));
205         }
206         else
207         {
208             memcpy(&pnetapiShm->netapi_global.cfg,&netapi_default_cfg, sizeof(NETAPI_CFG_T));
209         }
210         for(i=0;i<TUNE_NETAPI_MAX_PKTIO;i++) 
211         {
212             pnetapiShm->netapi_global.pktios[i].qn.qNum=-1;
213             pnetapiShm->netapi_global.pktios[i].name[0]='\0';
214         }
215     }
216     else
217     {
218         /* other 'masters' will just get a pointer to the netapi SHM area*/
219         pnetapiShm = (NETAPI_SHM_T*)hplib_shmGetEntry(pBase, NETAPI_ENTRY);
220     }
222     //all:  for convenience set a back pointer to the SOC global area (in SHM)  
223     //      and process global in netapi_proc_global
224     p->global = (void *) &pnetapiShm->netapi_global;
225     p->proc_global = (void *)&netapi_proc_global;
226     /* Update spinLock to point to either MP spinlock or fast spinlocks, this is 
227        for all callers of netapi_init*/
228     if(p_cfg)
229     {
230         if(p_cfg->def_multi_process)
231             p->spinLock = spinlock_mp;
232         else
233             p->spinLock= spinlock_lol;
234     }
235     else
236         p->spinLock = spinlock_lol;
238     /* SYS_MASTER, PROC_MASTER: save a pointer to its netapi structure
239        globably for other threads/core of process to use */
240     if ((master == NETAPI_SYS_MASTER)||(master == NETAPI_PROC_MASTER))
241     {
242         p_master=netapi_proc_master = p;
243     }
244     else
245     {
246         /* CORE_MASTER/NO_MASTER: get system master/proc master's handle */
247         p_master=(NETAPI_HANDLE_T *) netapi_proc_master;
248     }
251     /* SYS_MASTER: The following segment should be done 1 Time per system boot by global master process */
252     /* system init */
253     if(master == NETAPI_SYS_MASTER)
254     {
255         err = netapip_systemInit(p,
256                                  p_hplibDeviceCfg,
257                                  p_netapiDeviceCfg,
258                                  p_nwalDeviceCfg,
259                                  TRUE);
260         if (err<0) 
261         {
262             goto ERR_netapi_init;
263         }
264         netapi_netcpCfgExceptions(p, NETCP_CFG_ALL_EXCEPTIONS, NETCP_CFG_ACTION_TO_SW, (NETCP_CFG_ROUTE_HANDLE_T) NULL);
265     }
266     /* PROC_MASTER case */
267     else if (master==NETAPI_PROC_MASTER)
268     {
269         /* More limited initialization */
270         err = netapip_systemInit(p,
271                                  p_hplibDeviceCfg,
272                                  p_netapiDeviceCfg,
273                                  p_nwalDeviceCfg,
274                                  FALSE);
275         if (err<0)
276         {
277             goto ERR_netapi_init;
278         }
279     }
280     /* NO_MASTER:  case */
281     else if (master == NETAPI_NO_MASTER)
282     {
283         /*Just copy master's pktio list for now */
284         p->n_pktios = p_master->n_pktios;
285         memcpy(&p->pktios[0],&p_master->pktios[0],TUNE_NETAPI_MAX_PKTIO*sizeof(PKTIO_HANDLE_T));
286         p->nwal_local=p_master->nwal_local;
287     }
288     /* this is the NETAPI_CORE_MASTER case */
289     else if (master == NETAPI_CORE_MASTER)
290     {
291         /* Start the QMSS. */
292         if (netapip_startQm() != 1)
293         {
294             goto ERR_netapi_init;
295         }
296         netapip_startNwal(p_master->netcp_heap, 
297                           p_master->netcp_control_rx_heap,
298                           p_master->netcp_control_tx_heap, 
299                                        &p->nwal_local,
300                           &pnetapiShm->netapi_global.cfg,
301                           &pnetapiShm->netapi_global.nwal_context);
302     }
303     else
304     {
305         netapi_Log("netapi_init: no master specified\n");
306         goto ERR_netapi_init;
307     }
309     return (NETAPI_T) p;
311 /* error handling */
312 ERR_netapi_init:
313     for(i=0;i<TUNE_NETAPI_MAX_PKTIO; i++)
314     {
315         if (p->pktios[i])
316         {
317             free(p->pktios[i]);
318         }
319     }
320 #ifdef NETAPI_INCLUDE_SCHED
321     if (p->p_sched)
322     {
323         free(p->p_sched);
324     }
325 #endif
326     return NULL;
329 /********************************************************************
330 * FUNCTION PURPOSE:  API de-allocates all global resources allocated as part 
331 *                                   of ref netapi_init
332  ********************************************************************
333  * DESCRIPTION:   API de-allocates all global resources allocated as part 
334 *                                   of ref netapi_init
335  ********************************************************************/
336 void netapi_shutdown(NETAPI_T h)
338     int i;
339     hplib_shmInfo_T* pshmBase;
340     NETAPI_HANDLE_T * p = (NETAPI_HANDLE_T *) h;
341     if (!p) return;
342     void * map_base;
343     hplib_VirtMemPoolheader_T *poolHdr;
345     netapi_Log("netapi: WARNING shutdown may not be fully implemented\n");
346     if (p->master ==NETAPI_SYS_MASTER)
347     {
348         /* Un-configure rules for execption packet handling */
349         netapi_netcpCfgExceptions(p,
350                               NETCP_CFG_ALL_EXCEPTIONS,
351                               NETCP_CFG_ACTION_DISCARD,
352                               (NETCP_CFG_ROUTE_HANDLE_T) NULL);
354         /* close nwal master (per soc) context */
355         nwal_delete(pnetapiShm->netapi_global.nwal_context.nwalInstHandle);
357         /* close heaps */
358         netapi_closeHeap(h, p->netcp_heap);
359         netapi_closeHeap(h, p->netcp_control_rx_heap);
360         netapi_closeHeap(h, p->netcp_control_tx_heap);
361         netapi_closeHeap(h, netapi_get_global()->nwal_context.pa2sa_heap); 
362         netapi_closeHeap(h, netapi_get_global()->nwal_context.sa2pa_heap); 
364         //loop over registered heaps
365         for(i=0;i<TUNE_NETAPI_MAX_HEAPS;i++)
366         {
367             if (p->createdHeaps[i])  {netapi_closeHeap(h,p->createdHeaps[i]);p->createdHeaps[i]=NULL;}
368         }
369         netapip_cleanupAtStart();  //clear 1st 50 not-specified queues
370         //reset DDR malloc area
371         hplib_resetMallocArea(0);
372         hplib_vmTeardown();
373         printf("netapi_shutdown: calling hplib_shmDelete\n");
374         hplib_shmDelete();
375     }
376     else if (p->master==NETAPI_PROC_MASTER)
377     {
378         //we can zap these because they are local to our process
379         netapi_closeHeap(h, p->netcp_control_rx_heap);
380         netapi_closeHeap(h, p->netcp_control_tx_heap);
381         //loop over registered heaps (again local to our process)
382         for(i=0;i<TUNE_NETAPI_MAX_HEAPS;i++)
383         {
384             if (p->createdHeaps[i])  {netapi_closeHeap(h,p->createdHeaps[i]);p->createdHeaps[i]=NULL;}
385         }
386         hplib_vmTeardown();
387     }
388     //TODO other master types
389     /* error handling */
390     
391     for(i=0;i<TUNE_NETAPI_MAX_PKTIO; i++)
392     {
393         if (p->pktios[i])
394         {
395             free(p->pktios[i]);
396             p->pktios[i] = NULL;
397         }
398     }
399 #ifdef NETAPI_INCLUDE_SCHED
400     if (p->p_sched)
401     {
402         free(p->p_sched);
403         p->p_sched = NULL;
404     }
405 #endif
407     free(p);
408     return;
411 /***********************************************************************
412 * FUNCTION PURPOSE:  API is used to poll for NETCP configuration response messages.
413 ************************************************************************
414 * DESCRIPTION:  This API is used to poll the netapi internal heaps and any 
415  *              application-created heaps that have been registered with 
416  *              the netapi instance. The poll function checks the garbage collection 
417  *              queue associated with the heap and returns descriptors and buffers 
418  *              when appropriate to the main free queue.
419 ***********************************************************************/
420 void netapi_pollHeapGarbage(NETAPI_T h)
422     int i;
423     NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h;
424     Pktlib_garbageCollection(n->netcp_heap);
425     //no need to do garbage collection on other internal heaps
426     for(i=0;i<TUNE_NETAPI_MAX_HEAPS;i++)
427     {
428         if (n->createdHeaps[i])
429         {
430             Pktlib_garbageCollection(n->createdHeaps[i]);
431         }
432     }
435 /****************************************************************************
436 * FUNCTION PURPOSE:  API is used to poll for NETCP configuration response messages.
437 ****************************************************************************
438 * DESCRIPTION:  This API is used to poll the netapi internal heaps and any 
439  *              application-created heaps    that have been registered with the 
440  *              netapi instance. The poll function checks the garbage collection 
441  *              queue associated with the heap and returns descriptors and buffers
442  *              when appropriate to the main free queue.
443 ***************************************************************************/
444 void netapi_netcpPoll(NETAPI_T  p)
446     NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) p;
447     nwal_pollCtl( ((NETAPI_GLOBAL_T *) (n->global))->nwal_context.nwalInstHandle,NULL,NULL);