/* * ======== WMD_DEH_Destroy ======== * Destroys DEH manager object. */ DSP_STATUS WMD_DEH_Destroy(struct DEH_MGR *hDehMgr) { DSP_STATUS status = DSP_SOK; struct DEH_MGR *pDehMgr = (struct DEH_MGR *)hDehMgr; if (MEM_IsValidHandle(pDehMgr, SIGNATURE)) { /* Release dummy VA buffer */ WMD_DEH_ReleaseDummyMem(); /* If notification object exists, delete it */ if (pDehMgr->hNtfy) (void)NTFY_Delete(pDehMgr->hNtfy); /* Disable DSP MMU fault */ free_irq(INT_DSP_MMU_IRQ, pDehMgr); /* Free DPC object */ tasklet_kill(&pDehMgr->dpc_tasklet); /* Deallocate the DEH manager object */ MEM_FreeObject(pDehMgr); /* The GPTimer is no longer needed */ if (timer) { omap_dm_timer_free(timer); timer = NULL; } } return status; }
/* * ======== WMD_CHNL_Close ======== * Purpose: * Ensures all pending I/O on this channel is cancelled, discards all * queued I/O completion notifications, then frees the resources allocated * for this channel, and makes the corresponding logical channel id * available for subsequent use. */ DSP_STATUS WMD_CHNL_Close(struct CHNL_OBJECT *hChnl) { DSP_STATUS status; struct CHNL_OBJECT *pChnl = (struct CHNL_OBJECT *)hChnl; /* Check args: */ if (!MEM_IsValidHandle(pChnl, CHNL_SIGNATURE)) { status = DSP_EHANDLE; goto func_cont; } { /* Cancel IO: this ensures no further IO requests or * notifications.*/ status = WMD_CHNL_CancelIO(hChnl); } func_cont: if (DSP_SUCCEEDED(status)) { /* Assert I/O on this channel is now cancelled: Protects * from IO_DPC. */ DBC_Assert((pChnl->dwState & CHNL_STATECANCEL)); /* Invalidate channel object: Protects from * CHNL_GetIOCompletion(). */ pChnl->dwSignature = 0x0000; /* Free the slot in the channel manager: */ pChnl->pChnlMgr->apChannel[pChnl->uId] = NULL; pChnl->pChnlMgr->cOpenChannels -= 1; if (pChnl->hNtfy) { NTFY_Delete(pChnl->hNtfy); pChnl->hNtfy = NULL; } /* Reset channel event: (NOTE: hUserEvent freed in user * context.). */ if (pChnl->hSyncEvent) { SYNC_ResetEvent(pChnl->hSyncEvent); SYNC_CloseEvent(pChnl->hSyncEvent); pChnl->hSyncEvent = NULL; } /* Free I/O request and I/O completion queues: */ if (pChnl->pIOCompletions) { FreeChirpList(pChnl->pIOCompletions); pChnl->pIOCompletions = NULL; pChnl->cIOCs = 0; } if (pChnl->pIORequests) { FreeChirpList(pChnl->pIORequests); pChnl->pIORequests = NULL; pChnl->cIOReqs = 0; } if (pChnl->pFreeList) { FreeChirpList(pChnl->pFreeList); pChnl->pFreeList = NULL; } /* Release channel object. */ MEM_FreeObject(pChnl); pChnl = NULL; } DBC_Ensure(DSP_FAILED(status) || !MEM_IsValidHandle(pChnl, CHNL_SIGNATURE)); return status; }
/* * ======== DeleteMsgQueue ======== */ static void DeleteMsgQueue(struct MSG_QUEUE *hMsgQueue, u32 uNumToDSP) { struct MSG_MGR *hMsgMgr; struct MSG_FRAME *pMsg; u32 i; if (!MEM_IsValidHandle(hMsgQueue, MSGQ_SIGNATURE) || !hMsgQueue->hMsgMgr || !hMsgQueue->hMsgMgr->msgFreeList) goto func_end; hMsgMgr = hMsgQueue->hMsgMgr; /* Pull off uNumToDSP message frames from Msg manager and free */ for (i = 0; i < uNumToDSP; i++) { if (!LST_IsEmpty(hMsgMgr->msgFreeList)) { pMsg = (struct MSG_FRAME *)LST_GetHead(hMsgMgr-> msgFreeList); MEM_Free(pMsg); } else { /* Cannot free all of the message frames */ break; } } if (hMsgQueue->msgFreeList) { FreeMsgList(hMsgQueue->msgFreeList); hMsgQueue->msgFreeList = NULL; } if (hMsgQueue->msgUsedList) { FreeMsgList(hMsgQueue->msgUsedList); hMsgQueue->msgUsedList = NULL; } if (hMsgQueue->hNtfy) NTFY_Delete(hMsgQueue->hNtfy); if (hMsgQueue->hSyncEvent) SYNC_CloseEvent(hMsgQueue->hSyncEvent); if (hMsgQueue->hSyncDone) SYNC_CloseEvent(hMsgQueue->hSyncDone); if (hMsgQueue->hSyncDoneAck) SYNC_CloseEvent(hMsgQueue->hSyncDoneAck); MEM_FreeObject(hMsgQueue); func_end: return; }
/* * ======== WMD_CHNL_Open ======== * Open a new half-duplex channel to the DSP board. */ DSP_STATUS WMD_CHNL_Open(OUT struct CHNL_OBJECT **phChnl, struct CHNL_MGR *hChnlMgr, short int uMode, u32 uChnlId, CONST IN struct CHNL_ATTRS *pAttrs) { DSP_STATUS status = DSP_SOK; struct CHNL_MGR *pChnlMgr = hChnlMgr; struct CHNL_OBJECT *pChnl = NULL; struct SYNC_ATTRS *pSyncAttrs = NULL; struct SYNC_OBJECT *hSyncEvent = NULL; /* Ensure DBC requirements: */ DBC_Require(phChnl != NULL); DBC_Require(pAttrs != NULL); DBC_Require(hChnlMgr != NULL); *phChnl = NULL; /* Validate Args: */ if (pAttrs->uIOReqs == 0) { status = DSP_EINVALIDARG; } else { if (!MEM_IsValidHandle(hChnlMgr, CHNL_MGRSIGNATURE)) { status = DSP_EHANDLE; } else { if (uChnlId != CHNL_PICKFREE) { if (uChnlId >= pChnlMgr->cChannels) status = CHNL_E_BADCHANID; else if (pChnlMgr->apChannel[uChnlId] != NULL) status = CHNL_E_CHANBUSY; } else { /* Check for free channel */ status = SearchFreeChannel(pChnlMgr, &uChnlId); } } } if (DSP_FAILED(status)) goto func_end; DBC_Assert(uChnlId < pChnlMgr->cChannels); /* Create channel object: */ MEM_AllocObject(pChnl, struct CHNL_OBJECT, 0x0000); if (!pChnl) { status = DSP_EMEMORY; goto func_end; } /* Protect queues from IO_DPC: */ pChnl->dwState = CHNL_STATECANCEL; /* Allocate initial IOR and IOC queues: */ pChnl->pFreeList = CreateChirpList(pAttrs->uIOReqs); pChnl->pIORequests = CreateChirpList(0); pChnl->pIOCompletions = CreateChirpList(0); pChnl->cChirps = pAttrs->uIOReqs; pChnl->cIOCs = 0; pChnl->cIOReqs = 0; status = SYNC_OpenEvent(&hSyncEvent, pSyncAttrs); if (DSP_SUCCEEDED(status)) status = NTFY_Create(&pChnl->hNtfy); if (DSP_SUCCEEDED(status)) { if (pChnl->pIOCompletions && pChnl->pIORequests && pChnl->pFreeList) { /* Initialize CHNL object fields: */ pChnl->pChnlMgr = pChnlMgr; pChnl->uId = uChnlId; pChnl->uMode = uMode; pChnl->hUserEvent = hSyncEvent; /* for Linux */ pChnl->hSyncEvent = hSyncEvent; /* Get the process handle */ pChnl->hProcess = current->tgid; pChnl->pCBArg = 0; pChnl->cBytesMoved = 0; /* Default to proc-copy */ pChnl->uChnlType = CHNL_PCPY; } else { status = DSP_EMEMORY; } } if (DSP_FAILED(status)) { /* Free memory */ if (pChnl->pIOCompletions) { FreeChirpList(pChnl->pIOCompletions); pChnl->pIOCompletions = NULL; pChnl->cIOCs = 0; } if (pChnl->pIORequests) { FreeChirpList(pChnl->pIORequests); pChnl->pIORequests = NULL; } if (pChnl->pFreeList) { FreeChirpList(pChnl->pFreeList); pChnl->pFreeList = NULL; } if (hSyncEvent) { SYNC_CloseEvent(hSyncEvent); hSyncEvent = NULL; } if (pChnl->hNtfy) { NTFY_Delete(pChnl->hNtfy); pChnl->hNtfy = NULL; } MEM_FreeObject(pChnl); } else { /* Insert channel object in channel manager: */ pChnlMgr->apChannel[pChnl->uId] = pChnl; SYNC_EnterCS(pChnlMgr->hCSObj); pChnlMgr->cOpenChannels++; SYNC_LeaveCS(pChnlMgr->hCSObj); /* Return result... */ pChnl->dwSignature = CHNL_SIGNATURE; pChnl->dwState = CHNL_STATEREADY; *phChnl = pChnl; } func_end: DBC_Ensure((DSP_SUCCEEDED(status) && MEM_IsValidHandle(pChnl, CHNL_SIGNATURE)) || (*phChnl == NULL)); return status; }