| |
| #include "wilc_msgqueue.h" |
| #include <linux/spinlock.h> |
| |
| /*! |
| * @author syounan |
| * @date 1 Sep 2010 |
| * @note copied from FLO glue implementatuion |
| * @version 1.0 |
| */ |
| WILC_ErrNo WILC_MsgQueueCreate(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 |
| */ |
| WILC_ErrNo WILC_MsgQueueDestroy(WILC_MsgQueueHandle *pHandle) |
| { |
| |
| pHandle->bExiting = true; |
| |
| /* Release any waiting receiver thread. */ |
| while (pHandle->u32ReceiversCount > 0) { |
| up(&(pHandle->hSem)); |
| pHandle->u32ReceiversCount--; |
| } |
| |
| while (pHandle->pstrMessageList != NULL) { |
| 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 |
| */ |
| WILC_ErrNo WILC_MsgQueueSend(WILC_MsgQueueHandle *pHandle, |
| const void *pvSendBuffer, u32 u32SendBufferSize) |
| { |
| WILC_ErrNo s32RetStatus = WILC_SUCCESS; |
| unsigned long flags; |
| Message *pstrMessage = NULL; |
| |
| if ((pHandle == NULL) || (u32SendBufferSize == 0) || (pvSendBuffer == NULL)) { |
| WILC_ERRORREPORT(s32RetStatus, WILC_INVALID_ARGUMENT); |
| } |
| |
| if (pHandle->bExiting == true) { |
| 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 = WILC_MALLOC(u32SendBufferSize); |
| WILC_NULLCHECK(s32RetStatus, pstrMessage->pvBuffer); |
| memcpy(pstrMessage->pvBuffer, pvSendBuffer, u32SendBufferSize); |
| |
| |
| /* add it to the message queue */ |
| if (pHandle->pstrMessageList == NULL) { |
| pHandle->pstrMessageList = pstrMessage; |
| } else { |
| Message *pstrTailMsg = pHandle->pstrMessageList; |
| while (pstrTailMsg->pstrNext != NULL) { |
| 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 != NULL) { |
| if (pstrMessage->pvBuffer != NULL) { |
| kfree(pstrMessage->pvBuffer); |
| } |
| kfree(pstrMessage); |
| } |
| } |
| |
| return s32RetStatus; |
| } |
| |
| |
| |
| /*! |
| * @author syounan |
| * @date 1 Sep 2010 |
| * @note copied from FLO glue implementatuion |
| * @version 1.0 |
| */ |
| WILC_ErrNo WILC_MsgQueueRecv(WILC_MsgQueueHandle *pHandle, |
| void *pvRecvBuffer, u32 u32RecvBufferSize, |
| u32 *pu32ReceivedLength) |
| { |
| |
| Message *pstrMessage; |
| WILC_ErrNo s32RetStatus = WILC_SUCCESS; |
| unsigned long flags; |
| if ((pHandle == NULL) || (u32RecvBufferSize == 0) |
| || (pvRecvBuffer == NULL) || (pu32ReceivedLength == NULL)) { |
| WILC_ERRORREPORT(s32RetStatus, WILC_INVALID_ARGUMENT); |
| } |
| |
| if (pHandle->bExiting == true) { |
| 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 == NULL) { |
| 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; |
| } |