/* * dspbridge/src/api/linux/DSPProcessor.c * * DSP-BIOS Bridge driver support functions for TI OMAP processors. * * Copyright (C) 2007 Texas Instruments, Inc. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation version 2.1 of the License. * * This program is distributed .as is. WITHOUT ANY WARRANTY of any kind, * whether express or implied; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ /* * ======== DSPProcessor.c ======== * Description: * This is the source for the DSP/BIOS Bridge API processor module. The * parameters are validated at the API level, but the bulk of the * work is done at the driver level through the PM PROC module. * * Public Functions: * DSPProcessor_Attach * DSPProcessor_Detach * DSPProcessor_EnumNodes * DSPProcessor_FlushMemory * DSPProcessor_GetResourceInfo * DSPProcessor_GetState * DSPProcessor_Map * DSPProcessor_RegisterNotify * DSPProcessor_ReserveMemory * DSPProcessor_UnMap * DSPProcessor_UnReserveMemory * DSPProcessor_InvalidateMemory *! Revision History *! ================ *! 04-Apr-2007 sh Added DSPProcessor_InvalidateMemory *! 19-Apr-2004 sb Aligned DMM definitions with Symbian *! 08-Mar-2004 sb Added the Dynamic Memory Mapping APIs *! 27-Jun-2001 rr: DSPProcessor_RegisterNotify allows EventMask =0 *! for De Registration. *! 16-Feb-2001 jeh Fixed message in DSPProcessor_Detach. *! 12-Dec-2000 rr: DSP_ProcessorEnumNodes returns DSP_ESIZE if *! uNodeTabSize is zero and valid aNodeTab. *! 29-Nov-2000 rr: Incorporated code review changes. *! 09-Nov-2000 rr: Code cleaned up. Use of IsValidEvent/Mask Macros. *! 28-Sep-2000 rr: Updated to version 0.9. *! 07-Sep-2000 jeh Changed type HANDLE in DSPProcessor_RegisterNotify to *! DSP_HNOTIFICATION. *! 07-Aug-2000 rr: Enum fxns do not return ESIZE if the size of the data *! structure is less than the actual size for backward *! compatibility. *! 04-Aug-2000 rr: DSPProcessor_Attach does not check for pAttrin for NULL. *! file name changed to DSPProcessor.c *! 27-Jul-2000 rr: Updated to 0.8 ver API. GetTrace Implemented. *! 10-Jul-2000 rr: Calls into DSP Trap for the bulk of the functionality. *! 12-May-2000 gp: Removed PROC_UNKNOWN state. Mapped to return DSP_EFAIL. *! Return DSP_EHANDLE in DSPProcessor_Ctrl()/Detach(). *! Return DSP_EWRONGSTATE from DSPProcessor_Start(). *! 03-May-2000 rr: Uses SERVICES CSL fxns *! 19-Apr-2000 ww: Updated based on code review. *! 12-Apr-2000 ww: Created based on DirectDSP API specification, Version 0.6. * */ /* ----------------------------------- Host OS */ #include <host_os.h> /* ----------------------------------- DSP/BIOS Bridge */ #include <dbdefs.h> #include <errbase.h> /* ----------------------------------- Others */ #include <dsptrap.h> #ifdef DEBUG_BRIDGE_PERF #include <perfutils.h> #endif /* ----------------------------------- This */ #include "_dbdebug.h" #include "_dbpriv.h" #include <DSPProcessor.h> /* * ======== DSPProcessor_Attach ======== * Purpose: * Prepare for communication with a particular DSP processor, and * return a handle to the processor object. */ DBAPI DSPProcessor_Attach(UINT uProcessor, OPTIONAL CONST struct DSP_PROCESSORATTRIN *pAttrIn, OUT DSP_HPROCESSOR *phProcessor) { DSP_STATUS status = DSP_SOK; Trapped_Args tempStruct; DEBUGMSG(DSPAPI_ZONE_FUNCTION, (TEXT("PROC: DSPProcessor_Attach\r\n"))); if (!DSP_ValidWritePtr(phProcessor, sizeof(DSP_HPROCESSOR))) { if (uProcessor <= DSP_MAX_PROCESSOR) { tempStruct.ARGS_PROC_ATTACH.uProcessor = uProcessor; tempStruct.ARGS_PROC_ATTACH.pAttrIn = (struct DSP_PROCESSORATTRIN *)pAttrIn; tempStruct.ARGS_PROC_ATTACH.phProcessor = phProcessor; status = DSPTRAP_Trap(&tempStruct, CMD_PROC_ATTACH_OFFSET); } else { status = DSP_EINVALIDARG; DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT("PROC: invalid processor number\r\n"))); } } else { /* Invalid pointer */ status = DSP_EPOINTER; DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT("PROC: Invalid Pointer \r\n"))); } return status; } /* * ======== DSPProcessor_Detach ======== * Purpose: * Close a DSP processor and de-allocate all (GPP) resources. */ DBAPI DSPProcessor_Detach(DSP_HPROCESSOR hProcessor) { DSP_STATUS status = DSP_SOK; Trapped_Args tempStruct; DEBUGMSG(DSPAPI_ZONE_FUNCTION, (TEXT("PROC: DSPProcessor_Detach\r\n"))); /* Check the handle */ if (hProcessor) { tempStruct.ARGS_PROC_DETACH.hProcessor = hProcessor; status = DSPTRAP_Trap(&tempStruct, CMD_PROC_DETACH_OFFSET); } else { /* Invalid handle */ status = DSP_EHANDLE; DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT("PROC: Invalid Handle \r\n"))); } return status; } /* * ======== DSPProcessor_EnumNodes ======== * Purpose: * Enumerate and get configuration information about nodes allocated * on a DSP processor. */ DBAPI DSPProcessor_EnumNodes(DSP_HPROCESSOR hProcessor, IN DSP_HNODE *aNodeTab, IN UINT uNodeTabSize, OUT UINT *puNumNodes, OUT UINT *puAllocated) { DSP_STATUS status = DSP_SOK; Trapped_Args tempStruct; DEBUGMSG(DSPAPI_ZONE_FUNCTION, (TEXT("PROC:DSPProcessor_EnumNodes\r\n"))); /* Check the handle */ if (hProcessor) { if (!DSP_ValidWritePtr(puNumNodes, sizeof(UINT)) && !DSP_ValidWritePtr(puAllocated, sizeof(UINT)) && (uNodeTabSize && !DSP_ValidWritePtr(aNodeTab, (sizeof(DSP_HNODE)*uNodeTabSize)))) { tempStruct.ARGS_PROC_ENUMNODE_INFO.hProcessor = hProcessor; tempStruct.ARGS_PROC_ENUMNODE_INFO.aNodeTab = aNodeTab; tempStruct.ARGS_PROC_ENUMNODE_INFO.uNodeTabSize = uNodeTabSize; tempStruct.ARGS_PROC_ENUMNODE_INFO.puNumNodes = puNumNodes; tempStruct.ARGS_PROC_ENUMNODE_INFO.puAllocated = puAllocated; status = DSPTRAP_Trap(&tempStruct, CMD_PROC_ENUMNODE_OFFSET); } else { if (uNodeTabSize <= 0 && !DSP_ValidWritePtr(puNumNodes, sizeof(UINT)) && !DSP_ValidWritePtr(puAllocated, sizeof(UINT)) && !DSP_ValidWritePtr(aNodeTab, sizeof(DSP_HNODE)*1)) { status = DSP_ESIZE; } else status = DSP_EPOINTER; DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT("PROC: " "pNodeInfo is invalid \r\n"))); } } else { /* Invalid handle */ status = DSP_EHANDLE; DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT("PROC: Invalid Handle \r\n"))); } return status; } /* * ======== DSPProcessor_FlushMemory ======== * Purpose: * Flushes a buffer from the MPU data cache. */ DBAPI DSPProcessor_FlushMemory(DSP_HPROCESSOR hProcessor, PVOID pMpuAddr, ULONG ulSize, ULONG ulFlags) { DSP_STATUS status = DSP_SOK; Trapped_Args tempStruct; #ifdef DEBUG_BRIDGE_PERF struct timeval tv_beg; struct timeval tv_end; struct timezone tz; int timeRetVal = 0; timeRetVal = getTimeStamp(&tv_beg); #endif DEBUGMSG(DSPAPI_ZONE_FUNCTION, (TEXT("PROC: DSPProcessor_FlushMemory\r\n"))); /* Check the handle */ if (hProcessor) { tempStruct.ARGS_PROC_FLUSHMEMORY.hProcessor = hProcessor; tempStruct.ARGS_PROC_FLUSHMEMORY.pMpuAddr = pMpuAddr; tempStruct.ARGS_PROC_FLUSHMEMORY.ulSize = ulSize; tempStruct.ARGS_PROC_FLUSHMEMORY.ulFlags = ulFlags; status = DSPTRAP_Trap(&tempStruct, CMD_PROC_FLUSHMEMORY_OFFSET); } else { /* Invalid handle */ status = DSP_EHANDLE; DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT("PROC: Invalid Handle\r\n"))); } #ifdef DEBUG_BRIDGE_PERF timeRetVal = getTimeStamp(&tv_end); PrintStatistics(&tv_beg, &tv_end, "DSPProcessor_FlushMemory", ulSize); #endif return status; } /* * ======== DSPProcessor_InvalidateMemory ======== * Purpose: * Invalidates a buffer from MPU data cache. */ DBAPI DSPProcessor_InvalidateMemory(DSP_HPROCESSOR hProcessor, PVOID pMpuAddr, ULONG ulSize) { DSP_STATUS status = DSP_SOK; Trapped_Args tempStruct; #ifdef DEBUG_BRIDGE_PERF struct timeval tv_beg; struct timeval tv_end; struct timezone tz; int timeRetVal = 0; timeRetVal = getTimeStamp(&tv_beg); #endif DEBUGMSG(DSPAPI_ZONE_FUNCTION, (TEXT("PROC: DSPProcessor_InvalidateMemory\r\n"))); /* Check the handle */ if (hProcessor) { tempStruct.ARGS_PROC_INVALIDATEMEMORY.hProcessor = hProcessor; tempStruct.ARGS_PROC_INVALIDATEMEMORY.pMpuAddr = pMpuAddr; tempStruct.ARGS_PROC_INVALIDATEMEMORY.ulSize = ulSize; status = DSPTRAP_Trap(&tempStruct, CMD_PROC_INVALIDATEMEMORY_OFFSET); } else { /* Invalid handle */ status = DSP_EHANDLE; DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT("PROC: Invalid Handle\r\n"))); } #ifdef DEBUG_BRIDGE_PERF timeRetVal = getTimeStamp(&tv_end); PrintStatistics(&tv_beg, &tv_end, "DSPProcessor_InvalidateMemory", ulSize); #endif return status; } /* * ======== DSPProcessor_GetResourceInfo ======== * Purpose: * Enumerate the resources currently available on a processor. */ DBAPI DSPProcessor_GetResourceInfo(DSP_HPROCESSOR hProcessor, UINT uResourceType, OUT struct DSP_RESOURCEINFO *pResourceInfo, UINT uResourceInfoSize) { DSP_STATUS status = DSP_SOK; Trapped_Args tempStruct; DEBUGMSG(DSPAPI_ZONE_FUNCTION, (TEXT("PROC: DSPProcessor_Ctrl\r\n"))); if (hProcessor) { if (!DSP_ValidWritePtr(pResourceInfo, sizeof(struct DSP_RESOURCEINFO))) { if (uResourceInfoSize >= sizeof(struct DSP_RESOURCEINFO)) { tempStruct.ARGS_PROC_ENUMRESOURCES.hProcessor = hProcessor; tempStruct.ARGS_PROC_ENUMRESOURCES\ .uResourceType = uResourceType; tempStruct.ARGS_PROC_ENUMRESOURCES\ .pResourceInfo = pResourceInfo; tempStruct.ARGS_PROC_ENUMRESOURCES\ .uResourceInfoSize = uResourceInfoSize; status = DSPTRAP_Trap(&tempStruct, CMD_PROC_ENUMRESOURCES_OFFSET); } else { status = DSP_ESIZE; DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT("PROC: uResourceInfoSize " "is small \r\n"))); } } else { /* Invalid pointer */ status = DSP_EPOINTER; DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT("PROC: pResourceInfo is invalid \r\n"))); } } else { /* Invalid handle */ status = DSP_EHANDLE; DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT("PROC: Invalid Handle \r\n"))); } return status; } /* * ======== DSPProcessor_GetState ======== * Purpose: * Report the state of the specified DSP processor. */ DBAPI DSPProcessor_GetState(DSP_HPROCESSOR hProcessor, OUT struct DSP_PROCESSORSTATE *pProcStatus, UINT uStateInfoSize) { DSP_STATUS status = DSP_SOK; Trapped_Args tempStruct; DEBUGMSG(DSPAPI_ZONE_FUNCTION, (TEXT("PROC: DSPProcessor_Ctrl\r\n"))); /* Check the handle */ if (hProcessor) { if (!DSP_ValidWritePtr(pProcStatus, sizeof(struct DSP_PROCESSORSTATE))) { if (uStateInfoSize >= sizeof(struct DSP_PROCESSORSTATE)) { tempStruct.ARGS_PROC_GETSTATE.hProcessor = hProcessor; tempStruct.ARGS_PROC_GETSTATE.pProcStatus = pProcStatus; tempStruct.ARGS_PROC_GETSTATE.uStateInfoSize = uStateInfoSize; status = DSPTRAP_Trap(&tempStruct, CMD_PROC_GETSTATE_OFFSET); } else { status = DSP_ESIZE; DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT("PROC: uStateInfoSize is small \r\n"))); } } else { status = DSP_EPOINTER; DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT("PROC: pProcStatus is invalid \r\n"))); } } else { /* Invalid handle */ status = DSP_EHANDLE; DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT("PROC: Invalid Handle \r\n"))); } return status; } /* * ======== DSPProcessor_Map ======== * Purpose: * Map an MPU buffer to a reserved virtual address */ DBAPI DSPProcessor_Map(DSP_HPROCESSOR hProcessor, PVOID pMpuAddr, ULONG ulSize, PVOID pReqAddr, PVOID *ppMapAddr, ULONG ulMapAttr) { DSP_STATUS status = DSP_SOK; Trapped_Args tempStruct; #ifdef DEBUG_BRIDGE_PERF struct timeval tv_beg; struct timeval tv_end; struct timezone tz; int timeRetVal = 0; timeRetVal = getTimeStamp(&tv_beg); #endif DEBUGMSG(DSPAPI_ZONE_FUNCTION, (TEXT("PROC: DSPProcessor_Map\r\n"))); /* Check the handle */ if (hProcessor) { if (!DSP_ValidWritePtr(ppMapAddr, sizeof(PVOID *)) && !DSP_ValidReadPtr(pMpuAddr, sizeof(PVOID)) && (pReqAddr != NULL)) { if (ulSize > 0) { #if 0 INT i; ULONG ulLastByte; /* Physical memory pages are reserved by the * driver (get_user_pages), so no need to * reserve here. Ensure that physical memory * pages are reserved */ size_t page_size = getpagesize(); for (i = 0; i < (INT)ulSize; i += page_size) { *(volatile BYTE *)(pMpuAddr + i) = *(BYTE *)(pMpuAddr + i); } /* Non page-aligned size: Write final byte */ ulLastByte = pMpuAddr + ulSize - 1; *(volatile BYTE *)(ulLastByte) = *(BYTE *)(ulLastByte); #endif tempStruct.ARGS_PROC_MAPMEM.hProcessor = hProcessor; tempStruct.ARGS_PROC_MAPMEM.pMpuAddr = pMpuAddr; tempStruct.ARGS_PROC_MAPMEM.ulSize = ulSize; tempStruct.ARGS_PROC_MAPMEM.pReqAddr = pReqAddr; tempStruct.ARGS_PROC_MAPMEM.ppMapAddr = ppMapAddr; tempStruct.ARGS_PROC_MAPMEM.ulMapAttr = ulMapAttr; status = DSPTRAP_Trap(&tempStruct, CMD_PROC_MAPMEM_OFFSET); } else { status = DSP_ESIZE; DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT("PROC:size is zero\r\n"))); } } else { status = DSP_EPOINTER; DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT ("PROC: Atleast one pointer argument " "is invalid\r\n"))); } } else { /* Invalid handle */ status = DSP_EHANDLE; DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT("PROC: Invalid Handle\r\n"))); } #ifdef DEBUG_BRIDGE_PERF timeRetVal = getTimeStamp(&tv_end); PrintStatistics(&tv_beg, &tv_end, "DSPProcessor_Map", ulSize); #endif return status; } /* * ======== DSPProcessor_RegisterNotify ======== * Purpose: * Register to be notified of specific processor events */ DBAPI DSPProcessor_RegisterNotify(DSP_HPROCESSOR hProcessor, UINT uEventMask, UINT uNotifyType, struct DSP_NOTIFICATION *hNotification) { DSP_STATUS status = DSP_SOK; Trapped_Args tempStruct; DEBUGMSG(DSPAPI_ZONE_FUNCTION, (TEXT("PROC: DSPProcessor_RegisterNotify\r\n"))); /* Check the handle */ if ((hProcessor) && (hNotification)) { if (IsValidProcEvent(uEventMask)) { if (IsValidNotifyMask(uNotifyType)) { tempStruct.ARGS_PROC_REGISTER_NOTIFY\ .hProcessor = hProcessor; tempStruct.ARGS_PROC_REGISTER_NOTIFY\ .uEventMask = uEventMask; tempStruct.ARGS_PROC_REGISTER_NOTIFY\ .uNotifyType = uNotifyType; tempStruct.ARGS_PROC_REGISTER_NOTIFY\ .hNotification = hNotification; status = DSPTRAP_Trap(&tempStruct, CMD_PROC_REGISTERNOTIFY_OFFSET); } else { status = DSP_ENOTIMPL; DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT("PROC: Invalid Notify Mask \r\n"))); } } else { status = DSP_EVALUE; DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT("PROC: Invalid Evnet Mask \r\n"))); } } else { /* Invalid handle */ status = DSP_EHANDLE; DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT("PROC: Invalid Handle \r\n"))); } return status; } /* * ======== DSPProcessor_ReserveMemory ======== * Purpose: * Reserve a chunk of memory from the DMM */ DBAPI DSPProcessor_ReserveMemory(DSP_HPROCESSOR hProcessor, ULONG ulSize, PVOID *ppRsvAddr) { DSP_STATUS status = DSP_SOK; Trapped_Args tempStruct; #ifdef DEBUG_BRIDGE_PERF struct timeval tv_beg; struct timeval tv_end; struct timezone tz; int timeRetVal = 0; timeRetVal = getTimeStamp(&tv_beg); #endif DEBUGMSG(DSPAPI_ZONE_FUNCTION, (TEXT("PROC: DSPProcessor_ReserveMemory\r\n"))); /* Check the handle */ if (hProcessor) { if (!DSP_ValidWritePtr(ppRsvAddr, sizeof(PVOID *))) { if (ulSize > 0) { if ((ulSize & (PG_SIZE_4K - 1)) == 0) { tempStruct.ARGS_PROC_RSVMEM.hProcessor = hProcessor; tempStruct.ARGS_PROC_RSVMEM.ulSize = ulSize; tempStruct.ARGS_PROC_RSVMEM.ppRsvAddr = ppRsvAddr; status = DSPTRAP_Trap(&tempStruct, CMD_PROC_RSVMEM_OFFSET); } else { status = DSP_EINVALIDARG; DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT ("PROC: size is not 4KB " "page-aligned\r\n"))); } } else { status = DSP_ESIZE; DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT("PROC:size is zero\r\n"))); } } else { status = DSP_EPOINTER; DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT("PROC:ppRsvAddr is invalid\r\n"))); } } else { /* Invalid handle */ status = DSP_EHANDLE; DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT("PROC: Invalid Handle\r\n"))); } #ifdef DEBUG_BRIDGE_PERF timeRetVal = getTimeStamp(&tv_end); PrintStatistics(&tv_beg, &tv_end, "DSPProcessor_ReserveMemory", ulSize); #endif return status; } /* ======== DSPProcessor_UnMap ======== * Purpose: * UnMap an MPU buffer from a reserved virtual address */ DBAPI DSPProcessor_UnMap(DSP_HPROCESSOR hProcessor, PVOID pMapAddr) { DSP_STATUS status = DSP_SOK; Trapped_Args tempStruct; #ifdef DEBUG_BRIDGE_PERF struct timeval tv_beg; struct timeval tv_end; struct timezone tz; int timeRetVal = 0; timeRetVal = getTimeStamp(&tv_beg); #endif DEBUGMSG(DSPAPI_ZONE_FUNCTION, (TEXT("PROC: DSPProcessor_UnMap\r\n"))); /* Check the handle */ if (hProcessor) { if ((pMapAddr != NULL)) { tempStruct.ARGS_PROC_UNMAPMEM.hProcessor = hProcessor; tempStruct.ARGS_PROC_UNMAPMEM.pMapAddr = pMapAddr; status = DSPTRAP_Trap(&tempStruct, CMD_PROC_UNMAPMEM_OFFSET); } else { status = DSP_EPOINTER; DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT("PROC: pMapAddr is invalid\r\n"))); } } else { /* Invalid handle */ status = DSP_EHANDLE; DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT("PROC: Invalid Handle\r\n"))); } #ifdef DEBUG_BRIDGE_PERF timeRetVal = getTimeStamp(&tv_end); PrintStatistics(&tv_beg, &tv_end, "DSPProcessor_UnMap", 0); #endif return status; } /* * ======== DSPProcessor_UnReserveMemory ======== * Purpose: * Free a chunk of memory from the DMM */ DBAPI DSPProcessor_UnReserveMemory(DSP_HPROCESSOR hProcessor, PVOID pRsvAddr) { DSP_STATUS status = DSP_SOK; Trapped_Args tempStruct; #ifdef DEBUG_BRIDGE_PERF struct timeval tv_beg; struct timeval tv_end; struct timezone tz; int timeRetVal = 0; timeRetVal = getTimeStamp(&tv_beg); #endif DEBUGMSG(DSPAPI_ZONE_FUNCTION, (TEXT("PROC: DSPProcessor_UnReserveMemory\r\n"))); /* Check the handle */ if (hProcessor) { if (pRsvAddr != NULL) { tempStruct.ARGS_PROC_UNRSVMEM.hProcessor = hProcessor; tempStruct.ARGS_PROC_UNRSVMEM.pRsvAddr = pRsvAddr; status = DSPTRAP_Trap(&tempStruct, CMD_PROC_UNRSVMEM_OFFSET); } else { status = DSP_EPOINTER; DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT( "PROC: pRsvAddr is invalid\r\n"))); } } else { /* Invalid handle */ status = DSP_EHANDLE; DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT("PROC: Invalid Handle\r\n"))); } #ifdef DEBUG_BRIDGE_PERF timeRetVal = getTimeStamp(&tv_end); PrintStatistics(&tv_beg, &tv_end, "DSPProcessor_UnReserveMemory", 0); #endif return status; }