123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178 |
- #include "wilc_msgqueue.h"
- #include <linux/spinlock.h>
- #include "linux_wlan_common.h"
- #include <linux/errno.h>
- #include <linux/slab.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 0;
- }
- /*!
- * @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 0;
- }
- /*!
- * @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)
- {
- unsigned long flags;
- Message *pstrMessage = NULL;
- if ((!pHandle) || (u32SendBufferSize == 0) || (!pvSendBuffer)) {
- PRINT_ER("pHandle or pvSendBuffer is null\n");
- return -EFAULT;
- }
- if (pHandle->bExiting) {
- PRINT_ER("pHandle fail\n");
- return -EFAULT;
- }
- /* construct a new message */
- pstrMessage = kmalloc(sizeof(Message), GFP_ATOMIC);
- if (!pstrMessage)
- return -ENOMEM;
- pstrMessage->u32Length = u32SendBufferSize;
- pstrMessage->pstrNext = NULL;
- pstrMessage->pvBuffer = kmemdup(pvSendBuffer, u32SendBufferSize,
- GFP_ATOMIC);
- if (!pstrMessage->pvBuffer) {
- kfree(pstrMessage);
- return -ENOMEM;
- }
- spin_lock_irqsave(&pHandle->strCriticalSection, flags);
- /* 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);
- return 0;
- }
- /*!
- * @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 result = 0;
- unsigned long flags;
- if ((!pHandle) || (u32RecvBufferSize == 0)
- || (!pvRecvBuffer) || (!pu32ReceivedLength)) {
- PRINT_ER("pHandle or pvRecvBuffer is null\n");
- return -EINVAL;
- }
- if (pHandle->bExiting) {
- PRINT_ER("pHandle fail\n");
- return -EFAULT;
- }
- spin_lock_irqsave(&pHandle->strCriticalSection, flags);
- pHandle->u32ReceiversCount++;
- spin_unlock_irqrestore(&pHandle->strCriticalSection, flags);
- down(&pHandle->hSem);
- /* other non-timeout scenarios */
- if (result) {
- PRINT_ER("Non-timeout\n");
- return result;
- }
- if (pHandle->bExiting) {
- PRINT_ER("pHandle fail\n");
- return -EFAULT;
- }
- spin_lock_irqsave(&pHandle->strCriticalSection, flags);
- pstrMessage = pHandle->pstrMessageList;
- if (!pstrMessage) {
- spin_unlock_irqrestore(&pHandle->strCriticalSection, flags);
- PRINT_ER("pstrMessage is null\n");
- return -EFAULT;
- }
- /* check buffer size */
- if (u32RecvBufferSize < pstrMessage->u32Length) {
- spin_unlock_irqrestore(&pHandle->strCriticalSection, flags);
- up(&pHandle->hSem);
- PRINT_ER("u32RecvBufferSize overflow\n");
- return -EOVERFLOW;
- }
- /* 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);
- return result;
- }
|