コード例 #1
0
static void MEM_Check(void)
{
	struct memInfo *pMem;
	struct LST_ELEM *last = &mMan.lst.head;
	struct LST_ELEM *curr = mMan.lst.head.next;

	if (!LST_IsEmpty(&mMan.lst)) {
		GT_0trace(MEM_debugMask, GT_7CLASS, "*** MEMORY LEAK ***\n");
		GT_0trace(MEM_debugMask, GT_7CLASS,
			  "Addr      Size      Caller\n");
		while (curr != last) {
			pMem = (struct memInfo *)curr;
			curr = curr->next;
			if ((u32)pMem > PAGE_OFFSET &&
			    MEM_IsValidHandle(pMem, memInfoSign)) {
				GT_3trace(MEM_debugMask, GT_7CLASS,
					"%lx  %d\t [<%p>]\n",
					(u32) pMem + sizeof(struct memInfo),
					pMem->size, pMem->caller);
				MLST_RemoveElem(&mMan.lst,
						(struct LST_ELEM *) pMem);
				kfree(pMem);
			} else {
				GT_1trace(MEM_debugMask, GT_7CLASS,
					  "Invalid allocation or "
					  "Buffer underflow at %x\n",
					  (u32)pMem +	sizeof(struct memInfo));
				break;
			}
		}
	}
	DBC_Ensure(LST_IsEmpty(&mMan.lst));
}
コード例 #2
0
/*
 *  ======== WMD_CHNL_CancelIO ========
 *      Return all I/O requests to the client which have not yet been
 *      transferred.  The channel's I/O completion object is
 *      signalled, and all the I/O requests are queued as IOC's, with the
 *      status field set to CHNL_IOCSTATCANCEL.
 *      This call is typically used in abort situations, and is a prelude to
 *      CHNL_Close();
 */
DSP_STATUS WMD_CHNL_CancelIO(struct CHNL_OBJECT *hChnl)
{
	DSP_STATUS status = DSP_SOK;
	struct CHNL_OBJECT *pChnl = (struct CHNL_OBJECT *)hChnl;
	u32 iChnl = -1;
	short int uMode;
	struct CHNL_IRP *pChirp;
	struct CHNL_MGR *pChnlMgr = NULL;

	/* Check args: */
	if (MEM_IsValidHandle(pChnl, CHNL_SIGNATURE) && pChnl->pChnlMgr) {
		iChnl = pChnl->uId;
		uMode = pChnl->uMode;
		pChnlMgr = pChnl->pChnlMgr;
	} else {
		status = DSP_EHANDLE;
	}
	if (DSP_FAILED(status))
		goto func_end;

	 /*  Mark this channel as cancelled, to prevent further IORequests or
	 *  IORequests or dispatching.  */
	SYNC_EnterCS(pChnlMgr->hCSObj);
	pChnl->dwState |= CHNL_STATECANCEL;
	if (LST_IsEmpty(pChnl->pIORequests))
		goto func_cont;

	if (pChnl->uChnlType == CHNL_PCPY) {
		/* Indicate we have no more buffers available for transfer: */
		if (CHNL_IsInput(pChnl->uMode)) {
			IO_CancelChnl(pChnlMgr->hIOMgr, iChnl);
		} else {
			/* Record that we no longer have output buffers
			 * available: */
			pChnlMgr->dwOutputMask &= ~(1 << iChnl);
		}
	}
	/* Move all IOR's to IOC queue:  */
	while (!LST_IsEmpty(pChnl->pIORequests)) {
		pChirp = (struct CHNL_IRP *)LST_GetHead(pChnl->pIORequests);
		if (pChirp) {
			pChirp->cBytes = 0;
			pChirp->status |= CHNL_IOCSTATCANCEL;
			LST_PutTail(pChnl->pIOCompletions,
				   (struct list_head *)pChirp);
			pChnl->cIOCs++;
			pChnl->cIOReqs--;
			DBC_Assert(pChnl->cIOReqs >= 0);
		}
	}
func_cont:
		SYNC_LeaveCS(pChnlMgr->hCSObj);
func_end:
	return status;
}
コード例 #3
0
ファイル: msg_sm.c プロジェクト: Racing1/zeppelin_kernel
/*
 *  ======== WMD_MSG_DeleteQueue ========
 *      Delete a MSG queue allocated in WMD_MSG_CreateQueue.
 */
void WMD_MSG_DeleteQueue(struct MSG_QUEUE *hMsgQueue)
{
	struct MSG_MGR *hMsgMgr = hMsgQueue->hMsgMgr;
	u32 refCount;

	DBC_Require(MEM_IsValidHandle(hMsgQueue, MSGQ_SIGNATURE));
	hMsgQueue->fDone = true;
	 /*  Unblock all threads blocked in MSG_Get() or MSG_Put().  */
	refCount = hMsgQueue->refCount;
	while (refCount) {
		/* Unblock thread */
		SYNC_SetEvent(hMsgQueue->hSyncDone);
		/* Wait for acknowledgement */
		SYNC_WaitOnEvent(hMsgQueue->hSyncDoneAck, SYNC_INFINITE);
		refCount = hMsgQueue->refCount;
	}
	/* Remove message queue from hMsgMgr->queueList */
	(void)SYNC_EnterCS(hMsgMgr->hSyncCS);
	LST_RemoveElem(hMsgMgr->queueList, (struct LST_ELEM *)hMsgQueue);
	/* Free the message queue object */
	DeleteMsgQueue(hMsgQueue, hMsgQueue->uMaxMsgs);
       if (!hMsgMgr->msgFreeList)
               goto func_cont;
	if (LST_IsEmpty(hMsgMgr->msgFreeList))
		SYNC_ResetEvent(hMsgMgr->hSyncEvent);
func_cont:
	(void)SYNC_LeaveCS(hMsgMgr->hSyncCS);
}
コード例 #4
0
ファイル: ntfy.c プロジェクト: ka6sox/nook_kernel
/*
 *  ======== NTFY_Delete ========
 *  Purpose:
 *      Free resources allocated in NTFY_Create.
 */
void NTFY_Delete(struct NTFY_OBJECT *hNtfy)
{
	struct NOTIFICATION *pNotify;

	DBC_Require(MEM_IsValidHandle(hNtfy, NTFY_SIGNATURE));

	/* Remove any elements remaining in list */
	if (hNtfy->notifyList) {

		(void) SYNC_EnterCS(hNtfy->hSync);
	
		while ((pNotify = (struct NOTIFICATION *)LST_GetHead(hNtfy->
								notifyList))) {
			DeleteNotify(pNotify);
		}
		DBC_Assert(LST_IsEmpty(hNtfy->notifyList));
		kfree(hNtfy->notifyList);

		(void) SYNC_LeaveCS(hNtfy->hSync);
	}

	
	if (hNtfy->hSync)
		(void)SYNC_DeleteCS(hNtfy->hSync);

	MEM_FreeObject(hNtfy);
}
コード例 #5
0
ファイル: msg_sm.c プロジェクト: Racing1/zeppelin_kernel
/*
 *  ======== DeleteMsgMgr ========
 */
static void DeleteMsgMgr(struct MSG_MGR *hMsgMgr)
{
	DBC_Require(MEM_IsValidHandle(hMsgMgr, MSGMGR_SIGNATURE));

	if (hMsgMgr->queueList) {
               if (LST_IsEmpty(hMsgMgr->queueList)) {
                       LST_Delete(hMsgMgr->queueList);
                       hMsgMgr->queueList = NULL;
               }
	}

       if (hMsgMgr->msgFreeList) {
		FreeMsgList(hMsgMgr->msgFreeList);
               hMsgMgr->msgFreeList = NULL;
       }

       if (hMsgMgr->msgUsedList) {
		FreeMsgList(hMsgMgr->msgUsedList);
               hMsgMgr->msgUsedList = NULL;
       }

	if (hMsgMgr->hSyncEvent)
		SYNC_CloseEvent(hMsgMgr->hSyncEvent);

	if (hMsgMgr->hSyncCS)
		SYNC_DeleteCS(hMsgMgr->hSyncCS);

	MEM_FreeObject(hMsgMgr);
}
コード例 #6
0
/*
 *  ======== WMD_CHNL_FlushIO ========
 *  purpose:
 *      Flushes all the outstanding data requests on a channel.
 */
DSP_STATUS WMD_CHNL_FlushIO(struct CHNL_OBJECT *hChnl, u32 dwTimeOut)
{
	DSP_STATUS status = DSP_SOK;
	struct CHNL_OBJECT *pChnl = (struct CHNL_OBJECT *)hChnl;
	short int uMode = -1;
	struct CHNL_MGR *pChnlMgr;
	struct CHNL_IOC chnlIOC;
	/* Check args:  */
	if (MEM_IsValidHandle(pChnl, CHNL_SIGNATURE)) {
		if ((dwTimeOut == CHNL_IOCNOWAIT)
		    && CHNL_IsOutput(pChnl->uMode)) {
			status = DSP_EINVALIDARG;
		} else {
			uMode = pChnl->uMode;
			pChnlMgr = pChnl->pChnlMgr;
		}
	} else {
		status = DSP_EHANDLE;
	}
	if (DSP_SUCCEEDED(status)) {
		/* Note: Currently, if another thread continues to add IO
		 * requests to this channel, this function will continue to
		 * flush all such queued IO requests.  */
		if (CHNL_IsOutput(uMode) && (pChnl->uChnlType == CHNL_PCPY)) {
			/* Wait for IO completions, up to the specified
			 * timeout: */
			while (!LST_IsEmpty(pChnl->pIORequests) &&
			      DSP_SUCCEEDED(status)) {
				status = WMD_CHNL_GetIOC(hChnl, dwTimeOut,
							 &chnlIOC);
				if (DSP_FAILED(status))
					continue;

				if (chnlIOC.status & CHNL_IOCSTATTIMEOUT)
					status = CHNL_E_WAITTIMEOUT;

			}
		} else {
			status = WMD_CHNL_CancelIO(hChnl);
			/* Now, leave the channel in the ready state: */
			pChnl->dwState &= ~CHNL_STATECANCEL;
		}
	}
	DBC_Ensure(DSP_FAILED(status) || LST_IsEmpty(pChnl->pIORequests));
	return status;
}
コード例 #7
0
/*
 *  ======== FreeChirpList ========
 *  Purpose:
 *      Free the queue of Chirps.
 */
static void FreeChirpList(struct LST_LIST *pChirpList)
{
	DBC_Require(pChirpList != NULL);

	while (!LST_IsEmpty(pChirpList))
		kfree(LST_GetHead(pChirpList));

	kfree(pChirpList);
}
コード例 #8
0
/*
 *  ======== LST_First ========
 *  Purpose:
 *      Returns a pointer to the first element of the list, or NULL if the
 *      list is empty.
 */
struct LST_ELEM *LST_First(struct LST_LIST *pList)
{
	struct LST_ELEM *pElem = NULL;

	GT_1trace(LST_debugMask, GT_ENTER, "LST_First: pList 0x%x\n", pList);

	if (pList && !LST_IsEmpty(pList))
		pElem = pList->head.next;

	return pElem;
}
コード例 #9
0
ファイル: msg_sm.c プロジェクト: Racing1/zeppelin_kernel
/*
 *  ======== 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;

}
コード例 #10
0
/*
 *  ======== LST_PutTail ========
 *  Purpose:
 *      Adds the specified element to the tail of the list
 */
void LST_PutTail(struct LST_LIST *pList, struct LST_ELEM *pElem)
{

	GT_2trace(LST_debugMask, GT_ENTER,
		  "LST_PutTail: pList 0x%x, pElem 0x%x\n",
		  pList, pElem);

	if (!pList || !pElem)
		return;
	pElem->prev = pList->head.prev;
	pElem->next = &pList->head;
	pList->head.prev = pElem;
	pElem->prev->next = pElem;

	DBC_Ensure(!LST_IsEmpty(pList));
}
コード例 #11
0
ファイル: msg_sm.c プロジェクト: Racing1/zeppelin_kernel
/*
 *  ======== FreeMsgList ========
 */
static void FreeMsgList(struct LST_LIST *msgList)
{
	struct MSG_FRAME *pMsg;

       if (!msgList)
               goto func_end;

	while ((pMsg = (struct MSG_FRAME *)LST_GetHead(msgList)) != NULL)
		MEM_Free(pMsg);

	DBC_Assert(LST_IsEmpty(msgList));

	LST_Delete(msgList);
func_end:
       return;
}
コード例 #12
0
/*
 *  ======== LST_Next ========
 *  Purpose:
 *      Returns a pointer to the next element of the list, or NULL if the
 *      next element is the head of the list or the list is empty.
 */
struct LST_ELEM *LST_Next(struct LST_LIST *pList, struct LST_ELEM *pCurElem)
{
	struct LST_ELEM *pNextElem = NULL;

	GT_2trace(LST_debugMask, GT_ENTER,
		  "LST_Next: pList 0x%x, pCurElem 0x%x\n",
		  pList, pCurElem);

	if (!pList || !pCurElem)
		return NULL;
	if (!LST_IsEmpty(pList)) {
		if (pCurElem->next != &pList->head)
			pNextElem = pCurElem->next;
	}

	return pNextElem;
}
コード例 #13
0
/*
 *  ======== LST_GetHead ========
 *  Purpose:
 *      "Pops" the head off the list and returns a pointer to it.
 */
struct LST_ELEM *LST_GetHead(struct LST_LIST *pList)
{
	struct LST_ELEM *pElem;

	GT_1trace(LST_debugMask, GT_ENTER, "LST_GetHead: pList 0x%x\n", pList);

	if (!pList || LST_IsEmpty(pList))
		return NULL;

	/* pElem is always valid because the list cannot be empty
	 * at this point */
	pElem = pList->head.next;
	pList->head.next = pElem->next;
	pElem->next->prev = &pList->head;

	return pElem->self;
}
コード例 #14
0
/*
 *  ======== LST_RemoveElem ========
 *  Purpose:
 *      Removes (unlinks) the given element from the list, if the list is not
 *      empty.  Does not free the list element.
 */
void LST_RemoveElem(struct LST_LIST *pList, struct LST_ELEM *pCurElem)
{

	GT_2trace(LST_debugMask, GT_ENTER,
		  "LST_RemoveElem: pList 0x%x, pCurElem "
		  "0x%x\n", pList, pCurElem);

	if (!pList || !pCurElem)
		return;
	if (!LST_IsEmpty(pList)) {
		pCurElem->prev->next = pCurElem->next;
		pCurElem->next->prev = pCurElem->prev;

		/* set elem fields to NULL to prevent illegal references */
		pCurElem->next = NULL;
		pCurElem->prev = NULL;
	}
}
コード例 #15
0
ファイル: rmm.c プロジェクト: MuMu360121/jordan-kernel
/*
 *  ======== RMM_delete ========
 */
void RMM_delete(struct RMM_TargetObj *target)
{
	struct RMM_OvlySect *pSect;
	struct RMM_Header *hptr;
	struct RMM_Header *next;
	u32 i;

	DBC_Require(MEM_IsValidHandle(target, RMM_TARGSIGNATURE));

	GT_1trace(RMM_debugMask, GT_ENTER, "RMM_delete(0x%lx)\n", target);

	if (target->segTab != NULL)
		MEM_Free(target->segTab);

	if (target->ovlyList) {
		while ((pSect = (struct RMM_OvlySect *)LST_GetHead
		      (target->ovlyList))) {
			MEM_Free(pSect);
		}
		DBC_Assert(LST_IsEmpty(target->ovlyList));
		LST_Delete(target->ovlyList);
	}

	if (target->freeList != NULL) {
		/* Free elements on freelist */
		for (i = 0; i < target->numSegs; i++) {
			hptr = next = target->freeList[i];
			while (next) {
				hptr = next;
				next = hptr->next;
				MEM_Free(hptr);
			}
		}
		MEM_Free(target->freeList);
	}

	MEM_FreeObject(target);
}
コード例 #16
0
ファイル: msg_sm.c プロジェクト: Racing1/zeppelin_kernel
/*
 *  ======== WMD_MSG_Get ========
 *      Get a message from a MSG queue.
 */
DSP_STATUS WMD_MSG_Get(struct MSG_QUEUE *hMsgQueue,
		      struct DSP_MSG *pMsg, u32 uTimeout)
{
	struct MSG_FRAME *pMsgFrame;
	struct MSG_MGR *hMsgMgr;
	bool fGotMsg = false;
	struct SYNC_OBJECT *hSyncs[2];
	u32 uIndex;
	DSP_STATUS status = DSP_SOK;

	DBC_Require(MEM_IsValidHandle(hMsgQueue, MSGQ_SIGNATURE));
	DBC_Require(pMsg != NULL);

	hMsgMgr = hMsgQueue->hMsgMgr;
       if (!hMsgQueue->msgUsedList) {
               status = DSP_EHANDLE;
               goto func_end;
       }

	/* Enter critical section */
	(void)SYNC_EnterCS(hMsgMgr->hSyncCS);
	/* If a message is already there, get it */
	if (!LST_IsEmpty(hMsgQueue->msgUsedList)) {
		pMsgFrame = (struct MSG_FRAME *)LST_GetHead(hMsgQueue->
			    msgUsedList);
		if (pMsgFrame != NULL) {
			*pMsg = pMsgFrame->msgData.msg;
			LST_PutTail(hMsgQueue->msgFreeList,
				   (struct LST_ELEM *)pMsgFrame);
			if (LST_IsEmpty(hMsgQueue->msgUsedList))
				SYNC_ResetEvent(hMsgQueue->hSyncEvent);
			else {
				NTFY_Notify(hMsgQueue->hNtfy,
				    DSP_NODEMESSAGEREADY);
				SYNC_SetEvent(hMsgQueue->hSyncEvent);
			}

			fGotMsg = true;
		}
	} else {
		if (hMsgQueue->fDone)
			status = DSP_EFAIL;
		else
			hMsgQueue->refCount++;

	}
	/* Exit critical section */
	(void)SYNC_LeaveCS(hMsgMgr->hSyncCS);
	if (DSP_SUCCEEDED(status) && !fGotMsg) {
		/*  Wait til message is available, timeout, or done. We don't
		 *  have to schedule the DPC, since the DSP will send messages
		 *  when they are available.  */
		hSyncs[0] = hMsgQueue->hSyncEvent;
		hSyncs[1] = hMsgQueue->hSyncDone;
		status = SYNC_WaitOnMultipleEvents(hSyncs, 2, uTimeout,
			 &uIndex);
		/* Enter critical section */
		(void)SYNC_EnterCS(hMsgMgr->hSyncCS);
		if (hMsgQueue->fDone) {
			hMsgQueue->refCount--;
			/* Exit critical section */
			(void)SYNC_LeaveCS(hMsgMgr->hSyncCS);
			 /*  Signal that we're not going to access hMsgQueue
			  *  anymore, so it can be deleted.  */
			(void)SYNC_SetEvent(hMsgQueue->hSyncDoneAck);
			status = DSP_EFAIL;
		} else {
			if (DSP_SUCCEEDED(status)) {
				DBC_Assert(!LST_IsEmpty(hMsgQueue->
					  msgUsedList));
				/* Get msg from used list */
				pMsgFrame = (struct MSG_FRAME *)
					   LST_GetHead(hMsgQueue->msgUsedList);
				/* Copy message into pMsg and put frame on the
				 * free list */
				if (pMsgFrame != NULL) {
					*pMsg = pMsgFrame->msgData.msg;
					LST_PutTail(hMsgQueue->msgFreeList,
					(struct LST_ELEM *)pMsgFrame);
				}
			}
			hMsgQueue->refCount--;
			/* Reset the event if there are still queued messages */
			if (!LST_IsEmpty(hMsgQueue->msgUsedList)) {
				NTFY_Notify(hMsgQueue->hNtfy,
					DSP_NODEMESSAGEREADY);
				SYNC_SetEvent(hMsgQueue->hSyncEvent);
			}

			/* Exit critical section */
			(void)SYNC_LeaveCS(hMsgMgr->hSyncCS);
		}
	}
func_end:
	return status;
}
コード例 #17
0
/*
 *  ======== WMD_CHNL_GetIOC ========
 *      Optionally wait for I/O completion on a channel.  Dequeue an I/O
 *      completion record, which contains information about the completed
 *      I/O request.
 *      Note: Ensures Channel Invariant (see notes above).
 */
DSP_STATUS WMD_CHNL_GetIOC(struct CHNL_OBJECT *hChnl, u32 dwTimeOut,
			  OUT struct CHNL_IOC *pIOC)
{
	DSP_STATUS status = DSP_SOK;
	struct CHNL_OBJECT *pChnl = (struct CHNL_OBJECT *)hChnl;
	struct CHNL_IRP *pChirp;
	DSP_STATUS statSync;
	bool fDequeueIOC = true;
	struct CHNL_IOC ioc = { NULL, 0, 0, 0, 0 };
	u8 *pHostSysBuf = NULL;
	struct WMD_DEV_CONTEXT *dev_ctxt;
	struct DEV_OBJECT *dev_obj;

	/* Check args: */
	if (pIOC == NULL) {
		status = DSP_EPOINTER;
	} else if (!MEM_IsValidHandle(pChnl, CHNL_SIGNATURE)) {
		status = DSP_EHANDLE;
	} else if (dwTimeOut == CHNL_IOCNOWAIT) {
		if (LST_IsEmpty(pChnl->pIOCompletions))
			status = CHNL_E_NOIOC;

	}

	dev_obj = DEV_GetFirst();
	DEV_GetWMDContext(dev_obj, &dev_ctxt);
	if (!dev_ctxt)
		status = DSP_EHANDLE;

	if (DSP_FAILED(status))
		goto func_end;

	ioc.status = CHNL_IOCSTATCOMPLETE;
	if (dwTimeOut != CHNL_IOCNOWAIT && LST_IsEmpty(pChnl->pIOCompletions)) {
		if (dwTimeOut == CHNL_IOCINFINITE)
			dwTimeOut = SYNC_INFINITE;

		statSync = SYNC_WaitOnEvent(pChnl->hSyncEvent, dwTimeOut);
		if (statSync == DSP_ETIMEOUT) {
			/* No response from DSP */
			ioc.status |= CHNL_IOCSTATTIMEOUT;
			fDequeueIOC = false;
		} else if (statSync == DSP_EFAIL) {
			/* This can occur when the user mode thread is
			 * aborted (^C), or when _VWIN32_WaitSingleObject()
			 * fails due to unkown causes.  */
			/* Even though Wait failed, there may be something in
			 * the Q: */
			if (LST_IsEmpty(pChnl->pIOCompletions)) {
				ioc.status |= CHNL_IOCSTATCANCEL;
				fDequeueIOC = false;
			}
		}
	}
	/* See comment in AddIOReq */
	SYNC_EnterCS(pChnl->pChnlMgr->hCSObj);
	omap_mbox_disable_irq(dev_ctxt->mbox, IRQ_RX);
	if (fDequeueIOC) {
		/* Dequeue IOC and set pIOC; */
		DBC_Assert(!LST_IsEmpty(pChnl->pIOCompletions));
		pChirp = (struct CHNL_IRP *)LST_GetHead(pChnl->pIOCompletions);
		/* Update pIOC from channel state and chirp: */
		if (pChirp) {
			pChnl->cIOCs--;
			/*  If this is a zero-copy channel, then set IOC's pBuf
			 *  to the DSP's address. This DSP address will get
			 *  translated to user's virtual addr later.  */
			{
				pHostSysBuf = pChirp->pHostSysBuf;
				ioc.pBuf = pChirp->pHostUserBuf;
			}
			ioc.cBytes = pChirp->cBytes;
			ioc.cBufSize = pChirp->cBufSize;
			ioc.dwArg = pChirp->dwArg;
			ioc.status |= pChirp->status;
			/* Place the used chirp on the free list: */
			LST_PutTail(pChnl->pFreeList,
					(struct list_head *)pChirp);
		} else {
			ioc.pBuf = NULL;
			ioc.cBytes = 0;
		}
	} else {
		ioc.pBuf = NULL;
		ioc.cBytes = 0;
		ioc.dwArg = 0;
		ioc.cBufSize = 0;
	}
	/* Ensure invariant: If any IOC's are queued for this channel... */
	if (!LST_IsEmpty(pChnl->pIOCompletions)) {
		/*  Since DSPStream_Reclaim() does not take a timeout
		 *  parameter, we pass the stream's timeout value to
		 *  WMD_CHNL_GetIOC. We cannot determine whether or not
		 *  we have waited in User mode. Since the stream's timeout
		 *  value may be non-zero, we still have to set the event.
		 *  Therefore, this optimization is taken out.
		 *
		 *  if (dwTimeOut == CHNL_IOCNOWAIT) {
		 *    ... ensure event is set..
		 *      SYNC_SetEvent(pChnl->hSyncEvent);
		 *  } */
		SYNC_SetEvent(pChnl->hSyncEvent);
	} else {
		/* else, if list is empty, ensure event is reset. */
		SYNC_ResetEvent(pChnl->hSyncEvent);
	}
	omap_mbox_enable_irq(dev_ctxt->mbox, IRQ_RX);
	SYNC_LeaveCS(pChnl->pChnlMgr->hCSObj);
	if (fDequeueIOC && (pChnl->uChnlType == CHNL_PCPY && pChnl->uId > 1)) {
		if (!(ioc.pBuf < (void *) USERMODE_ADDR))
			goto func_cont;

		/* If the addr is in user mode, then copy it */
		if (!pHostSysBuf || !ioc.pBuf) {
			status = DSP_EPOINTER;
			goto func_cont;
		}
		if (!CHNL_IsInput(pChnl->uMode))
			goto func_cont1;

		/*pHostUserBuf */
		status = copy_to_user(ioc.pBuf, pHostSysBuf, ioc.cBytes);
		if (status) {
			if (current->flags & PF_EXITING)
				status = 0;
		}
		if (status)
			status = DSP_EPOINTER;
func_cont1:
		kfree(pHostSysBuf);
	}
func_cont:
	/* Update User's IOC block: */
	*pIOC = ioc;
func_end:
	return status;
}
コード例 #18
0
ファイル: msg_sm.c プロジェクト: Racing1/zeppelin_kernel
/*
 *  ======== WMD_MSG_CreateQueue ========
 *      Create a MSG_QUEUE for sending/receiving messages to/from a node
 *      on the DSP.
 */
DSP_STATUS WMD_MSG_CreateQueue(struct MSG_MGR *hMsgMgr,
			      OUT struct MSG_QUEUE **phMsgQueue,
			      u32 dwId, u32 uMaxMsgs, HANDLE hArg)
{
	u32 i;
	u32 uNumAllocated = 0;
	struct MSG_QUEUE *pMsgQ;
	DSP_STATUS status = DSP_SOK;

	DBC_Require(MEM_IsValidHandle(hMsgMgr, MSGMGR_SIGNATURE));
	DBC_Require(phMsgQueue != NULL);

	*phMsgQueue = NULL;
	/* Allocate MSG_QUEUE object */
	MEM_AllocObject(pMsgQ, struct MSG_QUEUE, MSGQ_SIGNATURE);
	if (!pMsgQ) {
		status = DSP_EMEMORY;
		goto func_end;
	}
	LST_InitElem((struct LST_ELEM *) pMsgQ);
	pMsgQ->uMaxMsgs = uMaxMsgs;
	pMsgQ->hMsgMgr = hMsgMgr;
	pMsgQ->hArg = hArg;	/* Node handle */
	pMsgQ->dwId = dwId;	/* Node env (not valid yet) */
	/* Queues of Message frames for messages from the DSP */
	pMsgQ->msgFreeList = LST_Create();
	pMsgQ->msgUsedList = LST_Create();
	if (pMsgQ->msgFreeList == NULL || pMsgQ->msgUsedList == NULL)
		status = DSP_EMEMORY;

	 /*  Create event that will be signalled when a message from
	 *  the DSP is available.  */
	if (DSP_SUCCEEDED(status))
		status = SYNC_OpenEvent(&pMsgQ->hSyncEvent, NULL);

	/* Create a notification list for message ready notification. */
	if (DSP_SUCCEEDED(status))
		status = NTFY_Create(&pMsgQ->hNtfy);

	 /*  Create events that will be used to synchronize cleanup
	 *  when the object is deleted. hSyncDone will be set to
	 *  unblock threads in MSG_Put() or MSG_Get(). hSyncDoneAck
	 *  will be set by the unblocked thread to signal that it
	 *  is unblocked and will no longer reference the object.  */
	if (DSP_SUCCEEDED(status))
		status = SYNC_OpenEvent(&pMsgQ->hSyncDone, NULL);

	if (DSP_SUCCEEDED(status))
		status = SYNC_OpenEvent(&pMsgQ->hSyncDoneAck, NULL);

	if (DSP_SUCCEEDED(status)) {
               if (!hMsgMgr->msgFreeList) {
                       status = DSP_EHANDLE;
                       goto func_end;
               }
		/* Enter critical section */
		(void)SYNC_EnterCS(hMsgMgr->hSyncCS);
		/* Initialize message frames and put in appropriate queues */
		for (i = 0; i < uMaxMsgs && DSP_SUCCEEDED(status); i++) {
			status = AddNewMsg(hMsgMgr->msgFreeList);
			if (DSP_SUCCEEDED(status)) {
				uNumAllocated++;
				status = AddNewMsg(pMsgQ->msgFreeList);
			}
		}
		if (DSP_FAILED(status)) {
			/*  Stay inside CS to prevent others from taking any
			 *  of the newly allocated message frames.  */
			DeleteMsgQueue(pMsgQ, uNumAllocated);
		} else {
			LST_PutTail(hMsgMgr->queueList,
				   (struct LST_ELEM *)pMsgQ);
			*phMsgQueue = pMsgQ;
			/* Signal that free frames are now available */
			if (!LST_IsEmpty(hMsgMgr->msgFreeList))
				SYNC_SetEvent(hMsgMgr->hSyncEvent);

		}
		/* Exit critical section */
		(void)SYNC_LeaveCS(hMsgMgr->hSyncCS);
	} else {
		DeleteMsgQueue(pMsgQ, 0);
	}
func_end:
	return status;
}
コード例 #19
0
/*
 *  ======== WMD_CHNL_GetIOC ========
 *      Optionally wait for I/O completion on a channel.  Dequeue an I/O
 *      completion record, which contains information about the completed
 *      I/O request.
 *      Note: Ensures Channel Invariant (see notes above).
 */
DSP_STATUS WMD_CHNL_GetIOC(struct CHNL_OBJECT *hChnl, u32 dwTimeOut,
			  OUT struct CHNL_IOC *pIOC)
{
	DSP_STATUS status = DSP_SOK;
	struct CHNL_OBJECT *pChnl = (struct CHNL_OBJECT *)hChnl;
	struct CHNL_IRP *pChirp;
	DSP_STATUS statSync;
	bool fDequeueIOC = true;
	struct CHNL_IOC ioc = { NULL, 0, 0, 0, 0 };
	u8 *pHostSysBuf = NULL;

	DBG_Trace(DBG_ENTER, "> WMD_CHNL_GetIOC pChnl %p CHNL_IsOutput %x "
		 "uChnlType %x\n", pChnl, CHNL_IsOutput(pChnl->uMode),
		 pChnl->uChnlType);
	/* Check args: */
	if (pIOC == NULL) {
		status = DSP_EPOINTER;
	} else if (!MEM_IsValidHandle(pChnl, CHNL_SIGNATURE)) {
		status = DSP_EHANDLE;
	} else if (dwTimeOut == CHNL_IOCNOWAIT) {
		if (LST_IsEmpty(pChnl->pIOCompletions))
			status = CHNL_E_NOIOC;

	}
	if (DSP_FAILED(status))
		goto func_end;

	ioc.status = CHNL_IOCSTATCOMPLETE;
	if (dwTimeOut != CHNL_IOCNOWAIT && LST_IsEmpty(pChnl->pIOCompletions)) {
		if (dwTimeOut == CHNL_IOCINFINITE)
			dwTimeOut = SYNC_INFINITE;

		statSync = SYNC_WaitOnEvent(pChnl->hSyncEvent, dwTimeOut);
		if (statSync == DSP_ETIMEOUT) {
			/* No response from DSP */
			ioc.status |= CHNL_IOCSTATTIMEOUT;
			fDequeueIOC = false;
		} else if (statSync == DSP_EFAIL) {
			/* This can occur when the user mode thread is
			 * aborted (^C), or when _VWIN32_WaitSingleObject()
			 * fails due to unkown causes.  */
			/* Even though Wait failed, there may be something in
			 * the Q: */
			if (LST_IsEmpty(pChnl->pIOCompletions)) {
				ioc.status |= CHNL_IOCSTATCANCEL;
				fDequeueIOC = false;
			}
		}
	}
	/* See comment in AddIOReq */
	SYNC_EnterCS(pChnl->pChnlMgr->hCSObj);
	disable_irq(MAILBOX_IRQ);
	if (fDequeueIOC) {
		/* Dequeue IOC and set pIOC; */
		DBC_Assert(!LST_IsEmpty(pChnl->pIOCompletions));
		pChirp = (struct CHNL_IRP *)LST_GetHead(pChnl->pIOCompletions);
		/* Update pIOC from channel state and chirp: */
		if (pChirp) {
			pChnl->cIOCs--;
			/*  If this is a zero-copy channel, then set IOC's pBuf
			 *  to the DSP's address. This DSP address will get
			 *  translated to user's virtual addr later.  */
			{
				pHostSysBuf = pChirp->pHostSysBuf;
				ioc.pBuf = pChirp->pHostUserBuf;
			}
			ioc.cBytes = pChirp->cBytes;
			ioc.cBufSize = pChirp->cBufSize;
			ioc.dwArg = pChirp->dwArg;
			ioc.status |= pChirp->status;
			/* Place the used chirp on the free list: */
			LST_PutTail(pChnl->pFreeList, (struct LST_ELEM *)
				   pChirp);
		} else {
			ioc.pBuf = NULL;
			ioc.cBytes = 0;
		}
	} else {
		ioc.pBuf = NULL;
		ioc.cBytes = 0;
		ioc.dwArg = 0;
		ioc.cBufSize = 0;
	}
	/* Ensure invariant: If any IOC's are queued for this channel... */
	if (!LST_IsEmpty(pChnl->pIOCompletions)) {
		/*  Since DSPStream_Reclaim() does not take a timeout
		 *  parameter, we pass the stream's timeout value to
		 *  WMD_CHNL_GetIOC. We cannot determine whether or not
		 *  we have waited in User mode. Since the stream's timeout
		 *  value may be non-zero, we still have to set the event.
		 *  Therefore, this optimization is taken out.
		 *
		 *  if (dwTimeOut == CHNL_IOCNOWAIT) {
		 *    ... ensure event is set..
		 *      SYNC_SetEvent(pChnl->hSyncEvent);
		 *  } */
		SYNC_SetEvent(pChnl->hSyncEvent);
	} else {
		/* else, if list is empty, ensure event is reset. */
		SYNC_ResetEvent(pChnl->hSyncEvent);
	}
	enable_irq(MAILBOX_IRQ);
	SYNC_LeaveCS(pChnl->pChnlMgr->hCSObj);
	if (fDequeueIOC && (pChnl->uChnlType == CHNL_PCPY && pChnl->uId > 1)) {
		if (!(ioc.pBuf < (void *) USERMODE_ADDR))
			goto func_cont;

		/* If the addr is in user mode, then copy it */
		if (!pHostSysBuf || !ioc.pBuf) {
			status = DSP_EPOINTER;
			DBG_Trace(DBG_LEVEL7,
				 "System buffer NULL in IO completion.\n");
			goto func_cont;
		}
		if (!CHNL_IsInput(pChnl->uMode))
			goto func_cont1;

		/*pHostUserBuf */
		status = copy_to_user(ioc.pBuf, pHostSysBuf, ioc.cBytes);
#ifndef RES_CLEANUP_DISABLE
		if (status) {
			if (current->flags & PF_EXITING) {
				DBG_Trace(DBG_LEVEL7,
					 "\n2current->flags ==  PF_EXITING, "
					 " current->flags;0x%x\n",
					 current->flags);
				status = 0;
			} else {
				DBG_Trace(DBG_LEVEL7,
					 "\n2current->flags != PF_EXITING, "
					 " current->flags;0x%x\n",
					 current->flags);
			}
		}
#endif
		if (status) {
			DBG_Trace(DBG_LEVEL7,
				 "Error copying kernel buffer to user, %d"
				 " bytes remaining.  in_interupt %d\n",
				 status, in_interrupt());
			status = DSP_EPOINTER;
		}
func_cont1:
		MEM_Free(pHostSysBuf);
	}
func_cont:
	/* Update User's IOC block: */
	*pIOC = ioc;
func_end:
	DBG_Trace(DBG_ENTER, "< WMD_CHNL_GetIOC pChnl %p\n", pChnl);
	return status;
}
コード例 #20
0
ファイル: msg_sm.c プロジェクト: Racing1/zeppelin_kernel
/*
 *  ======== WMD_MSG_Put ========
 *      Put a message onto a MSG queue.
 */
DSP_STATUS WMD_MSG_Put(struct MSG_QUEUE *hMsgQueue,
		      IN CONST struct DSP_MSG *pMsg, u32 uTimeout)
{
	struct MSG_FRAME *pMsgFrame;
	struct MSG_MGR *hMsgMgr;
	bool fPutMsg = false;
	struct SYNC_OBJECT *hSyncs[2];
	u32 uIndex;
	DSP_STATUS status = DSP_SOK;

	DBC_Require(MEM_IsValidHandle(hMsgQueue, MSGQ_SIGNATURE));
	DBC_Require(pMsg != NULL);

	hMsgMgr = hMsgQueue->hMsgMgr;

       if (!hMsgMgr->msgFreeList) {
               status = DSP_EHANDLE;
               goto func_end;
       }


	(void) SYNC_EnterCS(hMsgMgr->hSyncCS);

	/* If a message frame is available, use it */
	if (!LST_IsEmpty(hMsgMgr->msgFreeList)) {
		pMsgFrame = (struct MSG_FRAME *)LST_GetHead(hMsgMgr->
			    msgFreeList);
		if (pMsgFrame != NULL) {
			pMsgFrame->msgData.msg = *pMsg;
			pMsgFrame->msgData.dwId = hMsgQueue->dwId;
			LST_PutTail(hMsgMgr->msgUsedList, (struct LST_ELEM *)
				   pMsgFrame);
			hMsgMgr->uMsgsPending++;
			fPutMsg = true;
		}
		if (LST_IsEmpty(hMsgMgr->msgFreeList))
			SYNC_ResetEvent(hMsgMgr->hSyncEvent);

		/* Release critical section before scheduling DPC */
		(void)SYNC_LeaveCS(hMsgMgr->hSyncCS);
		/* Schedule a DPC, to do the actual data transfer: */
		IO_Schedule(hMsgMgr->hIOMgr);
	} else {
		if (hMsgQueue->fDone)
			status = DSP_EFAIL;
		else
			hMsgQueue->refCount++;

		(void)SYNC_LeaveCS(hMsgMgr->hSyncCS);
	}
	if (DSP_SUCCEEDED(status) && !fPutMsg) {
		/* Wait til a free message frame is available, timeout,
		 * or done */
		hSyncs[0] = hMsgMgr->hSyncEvent;
		hSyncs[1] = hMsgQueue->hSyncDone;
		status = SYNC_WaitOnMultipleEvents(hSyncs, 2, uTimeout,
			 &uIndex);
		/* Enter critical section */
		(void)SYNC_EnterCS(hMsgMgr->hSyncCS);
		if (hMsgQueue->fDone) {
			hMsgQueue->refCount--;
			/* Exit critical section */
			(void)SYNC_LeaveCS(hMsgMgr->hSyncCS);
			 /*  Signal that we're not going to access hMsgQueue
			  *  anymore, so it can be deleted.  */
			(void)SYNC_SetEvent(hMsgQueue->hSyncDoneAck);
			status = DSP_EFAIL;
		} else {
			if (DSP_SUCCEEDED(status)) {
                               if (LST_IsEmpty(hMsgMgr->msgFreeList)) {
                                       status = DSP_EPOINTER;
                                       goto func_cont;
                               }
				/* Get msg from free list */
				pMsgFrame = (struct MSG_FRAME *)
					    LST_GetHead(hMsgMgr->msgFreeList);
				/* Copy message into pMsg and put frame on the
				 * used list */
				if (pMsgFrame != NULL) {
					pMsgFrame->msgData.msg = *pMsg;
					pMsgFrame->msgData.dwId =
						hMsgQueue->dwId;
					LST_PutTail(hMsgMgr->msgUsedList,
						   (struct LST_ELEM *)
						   pMsgFrame);
					hMsgMgr->uMsgsPending++;
					/* Schedule a DPC, to do the actual
					 * data transfer: */
					IO_Schedule(hMsgMgr->hIOMgr);
				}
			}
			hMsgQueue->refCount--;
			/* Reset event if there are still frames available */
			if (!LST_IsEmpty(hMsgMgr->msgFreeList))
				SYNC_SetEvent(hMsgMgr->hSyncEvent);
func_cont:
			/* Exit critical section */
			(void) SYNC_LeaveCS(hMsgMgr->hSyncCS);
		}
	}
func_end:
	return status;
}