7c005e29cf75e17a3c19e8b83c8bb326675896a8
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;
51 void *pRmClientHandle = NULL;
53 static NETAPI_CFG_T netapi_default_cfg=
54 {
55 TUNE_NETAPI_PERM_MEM_SZ,
56 0, //start of packet offset for hw to place data on rx for default flow
57 TUNE_NETAPI_QM_CONFIG_MAX_DESC_NUM, //max number of descriptors in system
58 TUNE_NETAPI_NUM_GLOBAL_DESC, //total we will use
59 TUNE_NETAPI_DEFAULT_NUM_BUFFERS, //#descriptors+buffers in default heap
60 TUNE_NETAPI_DEFAULT_NUM_SOLO_DESCRIPTORS, //#descriptors w/o buffers in default heap
61 TUNE_NETAPI_DEFAULT_BUFFER_SIZE, //size of buffers in default heap
62 0,
63 0,
64 0,
65 NULL /* Resource manager handle to use RM server */
66 };
68 HPLIB_SPINLOCK_IF_T spinlock_lol =
69 {
70 hplib_mSpinLockInit,
71 hplib_mSpinLockTryLock,
72 hplib_mSpinLockIsLocked,
73 hplib_mSpinLockLock,
74 hplib_mSpinLockUnlock,
75 hplib_mRWLockInit,
76 hplib_mRWLockWriteLock,
77 hplib_mRWLockWriteUnlock,
78 hplib_mRWLockReadLock,
79 hplib_mRWLockReadUnlock
80 };
83 HPLIB_SPINLOCK_IF_T spinlock_mp =
84 {
85 hplib_mSpinLockInit,
86 hplib_mSpinLockTryLock,
87 hplib_mSpinLockIsLocked,
88 hplib_mSpinLockLockMP,
89 hplib_mSpinLockUnlockMP,
90 hplib_mRWLockInit,
91 hplib_mRWLockWriteLockMP,
92 hplib_mRWLockWriteUnlockMP,
93 hplib_mRWLockReadLockMP,
94 hplib_mRWLockReadUnlockMP
95 };
97 /* Global variablesto hold virtual address of various subsystems */
98 hplib_virtualAddrInfo_T netapi_VM_VirtAddr[HPLIB_MAX_MEM_POOLS];
100 /* Global variables which needs to be populated with memory pool attributes
101 which is passed to HPLIB for memory pool initialization*/
102 hplib_memPoolAttr_T netapi_VM_MempoolAttr[HPLIB_MAX_MEM_POOLS];
103 unsigned char *netapi_VM_QMemLocalDescRam;
104 unsigned char *netapi_VM_QMemGlobalDescRam;
105 unsigned char *netapi_VM_SaContextVaddr;
107 //global for this process that points to the
108 // master thread for this process (either the SYS_MASTER, or PROC_MASTER)
109 //...
110 NETAPI_HANDLE_T * netapi_proc_master = NULL;
111 Pktlib_HeapIfTable netapi_pktlib_ifTable;
112 NETAPI_PROC_GLOBAL_T netapi_proc_global;
113 //NETAPI_GLOBAL_T * netapi_get_global(){ return &netapi_global;}
114 NETAPI_GLOBAL_T * netapi_get_global(){ return &pnetapiShm->netapi_global;}
115 NETAPI_PROC_GLOBAL_T * netapi_get_proc_global(){ return &netapi_proc_global;}
117 /* utility API for NETAPI user to get pktlib if table to use if he creates his own heap */
118 Pktlib_HeapIfTable *netapi_getPktlibIfTable(void) {return &netapi_pktlib_ifTable;}
121 /********************************************************************
122 * FUNCTION PURPOSE: API instantiates the NETAPI and allocated global resources.
123 ********************************************************************
124 * DESCRIPTION: API instantiates the NETAPI and allocated global resources.
125 ********************************************************************/
126 NETAPI_T netapi_init(int master,
127 NETAPI_CFG_T * p_cfg)
128 {
129 int i;
130 int err;
131 int exception_id = 7;
132 void* pBase = NULL;
134 hplib_shmInfo_T* pshmBase = NULL;
135 NETAPI_HANDLE_T * p = (NETAPI_HANDLE_T *) calloc(1,sizeof(NETAPI_HANDLE_T));
136 NETAPI_HANDLE_T * p_master;
137 if (!p) return NULL;
138 p->master = master;
140 /* SYS_MASTER: The following segment should be done 1 Time per system boot by global master process's main core/thread */
141 if (master == NETAPI_SYS_MASTER)
142 {
143 pBase = hplib_shmCreate(HPLIB_SHM_SIZE);
145 if (pBase == NULL)
146 {
147 printf("netapi_init: hplib_shmCreate failure\n");
148 return NULL;
149 }
151 if (hplib_shmAddEntry(pBase, sizeof(NETAPI_SHM_T), NETAPI_ENTRY) !=
152 hplib_OK)
153 {
154 netapi_Log("netapi_init: hplib_shmAddEntry failed for NETAPI_ENTRY\n");
155 return NULL;
156 }
157 hplib_utilOsalCreate();
158 }
159 /*ALL others: we are not the system master; assume SYS_MASTER has
160 created SHM area for us already, so just open it */
161 else
162 {
163 pBase = hplib_shmOpen(HPLIB_SHM_SIZE);
164 if (!pBase)
165 {
166 netapi_Log("netapi_init: hplib_shmOpen error\n");
167 }
168 else
169 Osal_start(pBase);
170 }
172 /*ALL: create space for our local pktios */
173 for(i=0;i<TUNE_NETAPI_MAX_PKTIO; i++)
174 {
175 p->pktios[i] = calloc(1,sizeof(PKTIO_HANDLE_T));
176 if (!p->pktios[i])
177 {
178 return NULL;
179 }
180 else
181 {
182 PKTIO_ENTRY_T *pe = (PKTIO_ENTRY_T*)p->pktios[i];
183 pe->qn.qNum = -1;
184 }
185 }
187 #ifdef NETAPI_INCLUDE_SCHED
188 /* ALL: create space for scheduler */
189 p->p_sched = calloc(1,sizeof(NETAPI_SCHED_HANDLE_T));
190 if (!p->p_sched)
191 {
192 goto ERR_netapi_init;
193 }
194 #endif
196 /* SYS_MASTER: The following segment should be done 1 Time per system boot by global master process */
197 if (master == NETAPI_SYS_MASTER)
198 {
199 pnetapiShm = (NETAPI_SHM_T*)hplib_shmGetEntry(pBase, NETAPI_ENTRY);
200 pnetapiShm->netapi_pktio_lock= hplib_spinLock_UNLOCKED_INITIALIZER;
201 pnetapiShm->netapi_netcp_cfg_lock = hplib_spinLock_UNLOCKED_INITIALIZER;
202 pnetapiShm->netapi_netcp_cfg_l3_classi_lock = hplib_spinLock_UNLOCKED_INITIALIZER;
203 pnetapiShm->netapi_util_lock = hplib_spinLock_UNLOCKED_INITIALIZER;
205 if (p_cfg)
206 {
207 memcpy(&pnetapiShm->netapi_global.cfg,p_cfg, sizeof(NETAPI_CFG_T));
208 }
209 else
210 {
211 memcpy(&pnetapiShm->netapi_global.cfg,&netapi_default_cfg, sizeof(NETAPI_CFG_T));
212 }
213 for(i=0;i<TUNE_NETAPI_MAX_PKTIO;i++)
214 {
215 pnetapiShm->netapi_global.pktios[i].qn.qNum=-1;
216 pnetapiShm->netapi_global.pktios[i].name[0]='\0';
217 }
218 }
219 else
220 {
221 /* other 'masters' will just get a pointer to the netapi SHM area*/
222 pnetapiShm = (NETAPI_SHM_T*)hplib_shmGetEntry(pBase, NETAPI_ENTRY);
223 }
225 /* all for convenience set a back pointer to the SOC global area
226 (in SHM) and process global in netapi_proc_global */
227 p->global = (void *) &pnetapiShm->netapi_global;
228 p->proc_global = (void *)&netapi_proc_global;
229 /* Update spinLock to point to either MP spinlock or fast spinlocks, this is
230 for all callers of netapi_init*/
231 if(p_cfg)
232 {
233 if(p_cfg->def_multi_process)
234 p->spinLock = spinlock_mp;
235 else
236 p->spinLock= spinlock_lol;
237 }
238 else
239 p->spinLock = spinlock_lol;
241 /* SYS_MASTER, PROC_MASTER: save a pointer to its netapi structure
242 globably for other threads/core of process to use */
243 if ((master == NETAPI_SYS_MASTER)||(master == NETAPI_PROC_MASTER))
244 {
245 p_master=netapi_proc_master = p;
246 if (p_cfg->rmHandle)
247 pRmClientHandle = p_cfg->rmHandle;
248 }
249 else
250 {
251 /* CORE_MASTER/NO_MASTER: get system master/proc master's handle */
252 p_master=(NETAPI_HANDLE_T *) netapi_proc_master;
253 }
256 /* SYS_MASTER: The following segment should be done 1 Time per system boot by global master process */
257 /* system init */
258 if(master == NETAPI_SYS_MASTER)
259 {
260 err = netapip_systemInit(p, NETAPI_TRUE);
261 if (err < 0)
262 {
263 goto ERR_netapi_init;
264 }
265 netapi_netcpCfgExceptions(p, NETCP_CFG_ALL_EXCEPTIONS, NETCP_CFG_ACTION_TO_SW, (NETCP_CFG_ROUTE_HANDLE_T) NULL);
266 }
267 /* PROC_MASTER case */
268 else if (master==NETAPI_PROC_MASTER)
269 {
270 /* More limited initialization */
271 err = netapip_systemInit(p,
272 NETAPI_FALSE);
273 if (err<0)
274 {
275 goto ERR_netapi_init;
276 }
277 }
278 /* NO_MASTER: case */
279 else if (master == NETAPI_NO_MASTER)
280 {
281 /*Just copy master's pktio list for now */
282 p->n_pktios = p_master->n_pktios;
283 memcpy(&p->pktios[0],&p_master->pktios[0],TUNE_NETAPI_MAX_PKTIO*sizeof(PKTIO_HANDLE_T));
284 p->nwal_local=p_master->nwal_local;
285 }
286 /* this is the NETAPI_CORE_MASTER case */
287 else if (master == NETAPI_CORE_MASTER)
288 {
289 /* Start the QMSS. */
290 if (netapip_startQm(pRmClientHandle) != 1)
291 {
292 goto ERR_netapi_init;
293 }
294 netapip_startNwal(p_master->netcp_heap,
295 p_master->netcp_control_rx_heap,
296 p_master->netcp_control_tx_heap,
297 &p->nwal_local,
298 &pnetapiShm->netapi_global.cfg,
299 &pnetapiShm->netapi_global.nwal_context,
300 master);
301 }
302 else
303 {
304 netapi_Log("netapi_init: no master specified\n");
305 goto ERR_netapi_init;
306 }
308 return (NETAPI_T) p;
310 /* error handling */
311 ERR_netapi_init:
312 for(i=0;i<TUNE_NETAPI_MAX_PKTIO; i++)
313 {
314 if (p->pktios[i])
315 {
316 free(p->pktios[i]);
317 }
318 }
319 #ifdef NETAPI_INCLUDE_SCHED
320 if (p->p_sched)
321 {
322 free(p->p_sched);
323 }
324 #endif
325 return NULL;
326 }
328 /********************************************************************
329 * FUNCTION PURPOSE: API de-allocates all global resources allocated as part
330 * of ref netapi_init
331 ********************************************************************
332 * DESCRIPTION: API de-allocates all global resources allocated as part
333 * of ref netapi_init
334 ********************************************************************/
335 void netapi_shutdown(NETAPI_T h)
336 {
337 int i;
338 hplib_shmInfo_T* pshmBase;
339 NETAPI_HANDLE_T * p = (NETAPI_HANDLE_T *) h;
340 if (!p) return;
341 void * map_base;
342 hplib_VirtMemPoolheader_T *poolHdr;
344 netapi_Log("netapi: WARNING shutdown may not be fully implemented\n");
345 if (p->master == NETAPI_SYS_MASTER)
346 {
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])
368 {
369 printf("netapi_shutdown: heapPtr[%d]: 0x%x\n", i, p->createdHeaps);
370 netapi_closeHeap(h,p->createdHeaps[i]);
371 p->createdHeaps[i]=NULL;
372 }
373 }
374 netapip_cleanupAtStart(); //clear 1st 50 not-specified queues
375 //netapip_cleanupAtStart(); //clear 1st 50 not-specified queues
376 //reset DDR malloc area
377 hplib_resetMallocArea(0);
378 Qmss_removeMemoryRegion(p->memRegion,0);
379 hplib_vmTeardown();
380 printf("netapi_shutdown: calling hplib_shmDelete\n");
381 hplib_shmDelete();
382 }
383 else if (p->master == NETAPI_PROC_MASTER)
384 {
385 //we can zap these because they are local to our process
386 netapi_closeHeap(h, p->netcp_control_rx_heap);
387 netapi_closeHeap(h, p->netcp_control_tx_heap);
388 //loop over registered heaps (again local to our process)
389 for(i=0;i<TUNE_NETAPI_MAX_HEAPS;i++)
390 {
391 if (p->createdHeaps[i])
392 {
393 printf("netapi_shutdown: heapPtr[%d]: 0x%x\n", i, p->createdHeaps);
394 netapi_closeHeap(h,p->createdHeaps[i]);
395 p->createdHeaps[i]=NULL;
396 }
397 }
398 Qmss_removeMemoryRegion(p->memRegion,0);
399 hplib_vmTeardown();
400 }
401 //TODO other master types
402 /* error handling */
404 for(i=0;i<TUNE_NETAPI_MAX_PKTIO; i++)
405 {
406 if (p->pktios[i])
407 {
408 free(p->pktios[i]);
409 p->pktios[i] = NULL;
410 }
411 }
412 #ifdef NETAPI_INCLUDE_SCHED
413 if (p->p_sched)
414 {
415 free(p->p_sched);
416 p->p_sched = NULL;
417 }
418 #endif
420 free(p);
421 printf("netapi_shutdown: complete\n");
422 return;
423 }
425 /***********************************************************************
426 * FUNCTION PURPOSE: API is used to poll for NETCP configuration response messages.
427 ************************************************************************
428 * DESCRIPTION: This API is used to poll the netapi internal heaps and any
429 * application-created heaps that have been registered with
430 * the netapi instance. The poll function checks the garbage collection
431 * queue associated with the heap and returns descriptors and buffers
432 * when appropriate to the main free queue.
433 ***********************************************************************/
434 void netapi_pollHeapGarbage(NETAPI_T h)
435 {
436 int i;
437 NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h;
438 Pktlib_garbageCollection(n->netcp_heap);
439 //no need to do garbage collection on other internal heaps
440 for(i=0;i<TUNE_NETAPI_MAX_HEAPS;i++)
441 {
442 if (n->createdHeaps[i])
443 {
444 Pktlib_garbageCollection(n->createdHeaps[i]);
445 }
446 }
447 }
449 /****************************************************************************
450 * FUNCTION PURPOSE: API is used to poll for NETCP configuration response messages.
451 ****************************************************************************
452 * DESCRIPTION: This API is used to poll the netapi internal heaps and any
453 * application-created heaps that have been registered with the
454 * netapi instance. The poll function checks the garbage collection
455 * queue associated with the heap and returns descriptors and buffers
456 * when appropriate to the main free queue.
457 ***************************************************************************/
458 void netapi_netcpPoll(NETAPI_T p)
459 {
460 NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) p;
461 nwal_pollCtl( ((NETAPI_GLOBAL_T *) (n->global))->nwal_context.nwalInstHandle,NULL,NULL);
462 }