blob: 41244ce942ba26021b223cc66c77d1a09bd3fa5e [file] [log] [blame]
#include "wilc_msgqueue.h"
#include <linux/spinlock.h>
/*!
* @author syounan
* @date 1 Sep 2010
* @note copied from FLO glue implementatuion
* @version 1.0
*/
int wilc_mq_create(WILC_MsgQueueHandle *pHandle)
{
spin_lock_init(&pHandle->strCriticalSection);
sema_init(&pHandle->hSem, 0);
pHandle->pstrMessageList = NULL;
pHandle->u32ReceiversCount = 0;
pHandle->bExiting = false;
return WILC_SUCCESS;
}
/*!
* @author syounan
* @date 1 Sep 2010
* @note copied from FLO glue implementatuion
* @version 1.0
*/
int wilc_mq_destroy(WILC_MsgQueueHandle *pHandle)
{
pHandle->bExiting = true;
/* Release any waiting receiver thread. */
while (pHandle->u32ReceiversCount > 0) {
up(&pHandle->hSem);
pHandle->u32ReceiversCount--;
}
while (pHandle->pstrMessageList) {
Message *pstrMessge = pHandle->pstrMessageList->pstrNext;
kfree(pHandle->pstrMessageList);
pHandle->pstrMessageList = pstrMessge;
}
return WILC_SUCCESS;
}
/*!
* @author syounan
* @date 1 Sep 2010
* @note copied from FLO glue implementatuion
* @version 1.0
*/
int wilc_mq_send(WILC_MsgQueueHandle *pHandle,
const void *pvSendBuffer, u32 u32SendBufferSize)
{
int s32RetStatus = WILC_SUCCESS;
unsigned long flags;
Message *pstrMessage = NULL;
if ((!pHandle) || (u32SendBufferSize == 0) || (!pvSendBuffer)) {
WILC_ERRORREPORT(s32RetStatus, WILC_INVALID_ARGUMENT);
}
if (pHandle->bExiting) {
WILC_ERRORREPORT(s32RetStatus, WILC_FAIL);
}
spin_lock_irqsave(&pHandle->strCriticalSection, flags);
/* construct a new message */
pstrMessage = kmalloc(sizeof(Message), GFP_ATOMIC);
WILC_NULLCHECK(s32RetStatus, pstrMessage);
pstrMessage->u32Length = u32SendBufferSize;
pstrMessage->pstrNext = NULL;
pstrMessage->pvBuffer = kmalloc(u32SendBufferSize, GFP_ATOMIC);
WILC_NULLCHECK(s32RetStatus, pstrMessage->pvBuffer);
memcpy(pstrMessage->pvBuffer, pvSendBuffer, u32SendBufferSize);
/* add it to the message queue */
if (!pHandle->pstrMessageList) {
pHandle->pstrMessageList = pstrMessage;
} else {
Message *pstrTailMsg = pHandle->pstrMessageList;
while (pstrTailMsg->pstrNext)
pstrTailMsg = pstrTailMsg->pstrNext;
pstrTailMsg->pstrNext = pstrMessage;
}
spin_unlock_irqrestore(&pHandle->strCriticalSection, flags);
up(&pHandle->hSem);
WILC_CATCH(s32RetStatus)
{
/* error occured, free any allocations */
if (pstrMessage) {
kfree(pstrMessage->pvBuffer);
kfree(pstrMessage);
}
}
return s32RetStatus;
}
/*!
* @author syounan
* @date 1 Sep 2010
* @note copied from FLO glue implementatuion
* @version 1.0
*/
int wilc_mq_recv(WILC_MsgQueueHandle *pHandle,
void *pvRecvBuffer, u32 u32RecvBufferSize,
u32 *pu32ReceivedLength)
{
Message *pstrMessage;
int s32RetStatus = WILC_SUCCESS;
unsigned long flags;
if ((!pHandle) || (u32RecvBufferSize == 0)
|| (!pvRecvBuffer) || (!pu32ReceivedLength)) {
WILC_ERRORREPORT(s32RetStatus, WILC_INVALID_ARGUMENT);
}
if (pHandle->bExiting) {
WILC_ERRORREPORT(s32RetStatus, WILC_FAIL);
}
spin_lock_irqsave(&pHandle->strCriticalSection, flags);
pHandle->u32ReceiversCount++;
spin_unlock_irqrestore(&pHandle->strCriticalSection, flags);
down(&pHandle->hSem);
if (s32RetStatus == WILC_TIMEOUT) {
/* timed out, just exit without consumeing the message */
spin_lock_irqsave(&pHandle->strCriticalSection, flags);
pHandle->u32ReceiversCount--;
spin_unlock_irqrestore(&pHandle->strCriticalSection, flags);
} else {
/* other non-timeout scenarios */
WILC_ERRORCHECK(s32RetStatus);
if (pHandle->bExiting) {
WILC_ERRORREPORT(s32RetStatus, WILC_FAIL);
}
spin_lock_irqsave(&pHandle->strCriticalSection, flags);
pstrMessage = pHandle->pstrMessageList;
if (!pstrMessage) {
spin_unlock_irqrestore(&pHandle->strCriticalSection, flags);
WILC_ERRORREPORT(s32RetStatus, WILC_FAIL);
}
/* check buffer size */
if (u32RecvBufferSize < pstrMessage->u32Length) {
spin_unlock_irqrestore(&pHandle->strCriticalSection, flags);
up(&pHandle->hSem);
WILC_ERRORREPORT(s32RetStatus, WILC_BUFFER_OVERFLOW);
}
/* consume the message */
pHandle->u32ReceiversCount--;
memcpy(pvRecvBuffer, pstrMessage->pvBuffer, pstrMessage->u32Length);
*pu32ReceivedLength = pstrMessage->u32Length;
pHandle->pstrMessageList = pstrMessage->pstrNext;
kfree(pstrMessage->pvBuffer);
kfree(pstrMessage);
spin_unlock_irqrestore(&pHandle->strCriticalSection, flags);
}
WILC_CATCH(s32RetStatus)
{
}
return s32RetStatus;
}