Johnny Kim | c5c77ba | 2015-05-11 14:30:56 +0900 | [diff] [blame] | 1 | |
Dean Lee | c3ea8a7 | 2015-06-16 15:28:21 +0900 | [diff] [blame] | 2 | #include "wilc_msgqueue.h" |
Johnny Kim | c5c77ba | 2015-05-11 14:30:56 +0900 | [diff] [blame] | 3 | #include <linux/spinlock.h> |
Johnny Kim | c5c77ba | 2015-05-11 14:30:56 +0900 | [diff] [blame] | 4 | |
| 5 | /*! |
| 6 | * @author syounan |
| 7 | * @date 1 Sep 2010 |
| 8 | * @note copied from FLO glue implementatuion |
| 9 | * @version 1.0 |
| 10 | */ |
Greg Kroah-Hartman | c4f83a5 | 2015-08-17 11:32:38 -0700 | [diff] [blame] | 11 | WILC_ErrNo WILC_MsgQueueCreate(WILC_MsgQueueHandle *pHandle) |
Johnny Kim | c5c77ba | 2015-05-11 14:30:56 +0900 | [diff] [blame] | 12 | { |
Johnny Kim | c5c77ba | 2015-05-11 14:30:56 +0900 | [diff] [blame] | 13 | spin_lock_init(&pHandle->strCriticalSection); |
Arnd Bergmann | 83383ea | 2015-06-01 21:06:43 +0200 | [diff] [blame] | 14 | sema_init(&pHandle->hSem, 0); |
| 15 | pHandle->pstrMessageList = NULL; |
| 16 | pHandle->u32ReceiversCount = 0; |
Dean Lee | 72ed4dc | 2015-06-12 14:11:44 +0900 | [diff] [blame] | 17 | pHandle->bExiting = false; |
Arnd Bergmann | 83383ea | 2015-06-01 21:06:43 +0200 | [diff] [blame] | 18 | return WILC_SUCCESS; |
Johnny Kim | c5c77ba | 2015-05-11 14:30:56 +0900 | [diff] [blame] | 19 | } |
| 20 | |
| 21 | /*! |
| 22 | * @author syounan |
| 23 | * @date 1 Sep 2010 |
| 24 | * @note copied from FLO glue implementatuion |
| 25 | * @version 1.0 |
| 26 | */ |
Greg Kroah-Hartman | c4f83a5 | 2015-08-17 11:32:38 -0700 | [diff] [blame] | 27 | WILC_ErrNo WILC_MsgQueueDestroy(WILC_MsgQueueHandle *pHandle) |
Johnny Kim | c5c77ba | 2015-05-11 14:30:56 +0900 | [diff] [blame] | 28 | { |
| 29 | |
Dean Lee | 72ed4dc | 2015-06-12 14:11:44 +0900 | [diff] [blame] | 30 | pHandle->bExiting = true; |
Johnny Kim | c5c77ba | 2015-05-11 14:30:56 +0900 | [diff] [blame] | 31 | |
| 32 | /* Release any waiting receiver thread. */ |
| 33 | while (pHandle->u32ReceiversCount > 0) { |
Arnd Bergmann | 83383ea | 2015-06-01 21:06:43 +0200 | [diff] [blame] | 34 | up(&(pHandle->hSem)); |
Johnny Kim | c5c77ba | 2015-05-11 14:30:56 +0900 | [diff] [blame] | 35 | pHandle->u32ReceiversCount--; |
| 36 | } |
| 37 | |
Johnny Kim | c5c77ba | 2015-05-11 14:30:56 +0900 | [diff] [blame] | 38 | while (pHandle->pstrMessageList != NULL) { |
| 39 | Message *pstrMessge = pHandle->pstrMessageList->pstrNext; |
Chaehyun Lim | 49188af | 2015-08-11 10:32:41 +0900 | [diff] [blame] | 40 | kfree(pHandle->pstrMessageList); |
Johnny Kim | c5c77ba | 2015-05-11 14:30:56 +0900 | [diff] [blame] | 41 | pHandle->pstrMessageList = pstrMessge; |
| 42 | } |
| 43 | |
| 44 | return WILC_SUCCESS; |
| 45 | } |
| 46 | |
| 47 | /*! |
| 48 | * @author syounan |
| 49 | * @date 1 Sep 2010 |
| 50 | * @note copied from FLO glue implementatuion |
| 51 | * @version 1.0 |
| 52 | */ |
| 53 | WILC_ErrNo WILC_MsgQueueSend(WILC_MsgQueueHandle *pHandle, |
Greg Kroah-Hartman | c4f83a5 | 2015-08-17 11:32:38 -0700 | [diff] [blame] | 54 | const void *pvSendBuffer, u32 u32SendBufferSize) |
Johnny Kim | c5c77ba | 2015-05-11 14:30:56 +0900 | [diff] [blame] | 55 | { |
| 56 | WILC_ErrNo s32RetStatus = WILC_SUCCESS; |
| 57 | unsigned long flags; |
| 58 | Message *pstrMessage = NULL; |
| 59 | |
| 60 | if ((pHandle == NULL) || (u32SendBufferSize == 0) || (pvSendBuffer == NULL)) { |
| 61 | WILC_ERRORREPORT(s32RetStatus, WILC_INVALID_ARGUMENT); |
| 62 | } |
| 63 | |
Dean Lee | 72ed4dc | 2015-06-12 14:11:44 +0900 | [diff] [blame] | 64 | if (pHandle->bExiting == true) { |
Johnny Kim | c5c77ba | 2015-05-11 14:30:56 +0900 | [diff] [blame] | 65 | WILC_ERRORREPORT(s32RetStatus, WILC_FAIL); |
| 66 | } |
| 67 | |
| 68 | spin_lock_irqsave(&pHandle->strCriticalSection, flags); |
| 69 | |
| 70 | /* construct a new message */ |
Chaehyun Lim | 5c07828 | 2015-08-17 11:05:10 +0900 | [diff] [blame] | 71 | pstrMessage = kmalloc(sizeof(Message), GFP_ATOMIC); |
Johnny Kim | c5c77ba | 2015-05-11 14:30:56 +0900 | [diff] [blame] | 72 | WILC_NULLCHECK(s32RetStatus, pstrMessage); |
| 73 | pstrMessage->u32Length = u32SendBufferSize; |
| 74 | pstrMessage->pstrNext = NULL; |
| 75 | pstrMessage->pvBuffer = WILC_MALLOC(u32SendBufferSize); |
| 76 | WILC_NULLCHECK(s32RetStatus, pstrMessage->pvBuffer); |
Chaehyun Lim | d00d2ba | 2015-08-10 11:33:19 +0900 | [diff] [blame] | 77 | memcpy(pstrMessage->pvBuffer, pvSendBuffer, u32SendBufferSize); |
Johnny Kim | c5c77ba | 2015-05-11 14:30:56 +0900 | [diff] [blame] | 78 | |
| 79 | |
| 80 | /* add it to the message queue */ |
| 81 | if (pHandle->pstrMessageList == NULL) { |
| 82 | pHandle->pstrMessageList = pstrMessage; |
| 83 | } else { |
| 84 | Message *pstrTailMsg = pHandle->pstrMessageList; |
| 85 | while (pstrTailMsg->pstrNext != NULL) { |
| 86 | pstrTailMsg = pstrTailMsg->pstrNext; |
| 87 | } |
| 88 | pstrTailMsg->pstrNext = pstrMessage; |
| 89 | } |
| 90 | |
| 91 | spin_unlock_irqrestore(&pHandle->strCriticalSection, flags); |
| 92 | |
Arnd Bergmann | 83383ea | 2015-06-01 21:06:43 +0200 | [diff] [blame] | 93 | up(&pHandle->hSem); |
Johnny Kim | c5c77ba | 2015-05-11 14:30:56 +0900 | [diff] [blame] | 94 | |
| 95 | WILC_CATCH(s32RetStatus) |
| 96 | { |
| 97 | /* error occured, free any allocations */ |
| 98 | if (pstrMessage != NULL) { |
| 99 | if (pstrMessage->pvBuffer != NULL) { |
Chaehyun Lim | 49188af | 2015-08-11 10:32:41 +0900 | [diff] [blame] | 100 | kfree(pstrMessage->pvBuffer); |
Johnny Kim | c5c77ba | 2015-05-11 14:30:56 +0900 | [diff] [blame] | 101 | } |
Chaehyun Lim | 49188af | 2015-08-11 10:32:41 +0900 | [diff] [blame] | 102 | kfree(pstrMessage); |
Johnny Kim | c5c77ba | 2015-05-11 14:30:56 +0900 | [diff] [blame] | 103 | } |
| 104 | } |
| 105 | |
| 106 | return s32RetStatus; |
| 107 | } |
| 108 | |
| 109 | |
| 110 | |
| 111 | /*! |
| 112 | * @author syounan |
| 113 | * @date 1 Sep 2010 |
| 114 | * @note copied from FLO glue implementatuion |
| 115 | * @version 1.0 |
| 116 | */ |
| 117 | WILC_ErrNo WILC_MsgQueueRecv(WILC_MsgQueueHandle *pHandle, |
Chaehyun Lim | 4e4467f | 2015-06-11 14:35:55 +0900 | [diff] [blame] | 118 | void *pvRecvBuffer, u32 u32RecvBufferSize, |
Greg Kroah-Hartman | c4f83a5 | 2015-08-17 11:32:38 -0700 | [diff] [blame] | 119 | u32 *pu32ReceivedLength) |
Johnny Kim | c5c77ba | 2015-05-11 14:30:56 +0900 | [diff] [blame] | 120 | { |
| 121 | |
| 122 | Message *pstrMessage; |
| 123 | WILC_ErrNo s32RetStatus = WILC_SUCCESS; |
Johnny Kim | c5c77ba | 2015-05-11 14:30:56 +0900 | [diff] [blame] | 124 | unsigned long flags; |
| 125 | if ((pHandle == NULL) || (u32RecvBufferSize == 0) |
| 126 | || (pvRecvBuffer == NULL) || (pu32ReceivedLength == NULL)) { |
| 127 | WILC_ERRORREPORT(s32RetStatus, WILC_INVALID_ARGUMENT); |
| 128 | } |
| 129 | |
Dean Lee | 72ed4dc | 2015-06-12 14:11:44 +0900 | [diff] [blame] | 130 | if (pHandle->bExiting == true) { |
Johnny Kim | c5c77ba | 2015-05-11 14:30:56 +0900 | [diff] [blame] | 131 | WILC_ERRORREPORT(s32RetStatus, WILC_FAIL); |
| 132 | } |
| 133 | |
| 134 | spin_lock_irqsave(&pHandle->strCriticalSection, flags); |
| 135 | pHandle->u32ReceiversCount++; |
| 136 | spin_unlock_irqrestore(&pHandle->strCriticalSection, flags); |
| 137 | |
Arnd Bergmann | 83383ea | 2015-06-01 21:06:43 +0200 | [diff] [blame] | 138 | down(&(pHandle->hSem)); |
| 139 | |
Johnny Kim | c5c77ba | 2015-05-11 14:30:56 +0900 | [diff] [blame] | 140 | if (s32RetStatus == WILC_TIMEOUT) { |
| 141 | /* timed out, just exit without consumeing the message */ |
| 142 | spin_lock_irqsave(&pHandle->strCriticalSection, flags); |
| 143 | pHandle->u32ReceiversCount--; |
| 144 | spin_unlock_irqrestore(&pHandle->strCriticalSection, flags); |
| 145 | } else { |
| 146 | /* other non-timeout scenarios */ |
| 147 | WILC_ERRORCHECK(s32RetStatus); |
| 148 | |
| 149 | if (pHandle->bExiting) { |
| 150 | WILC_ERRORREPORT(s32RetStatus, WILC_FAIL); |
| 151 | } |
| 152 | |
| 153 | spin_lock_irqsave(&pHandle->strCriticalSection, flags); |
| 154 | |
| 155 | pstrMessage = pHandle->pstrMessageList; |
| 156 | if (pstrMessage == NULL) { |
| 157 | spin_unlock_irqrestore(&pHandle->strCriticalSection, flags); |
| 158 | WILC_ERRORREPORT(s32RetStatus, WILC_FAIL); |
| 159 | } |
| 160 | /* check buffer size */ |
| 161 | if (u32RecvBufferSize < pstrMessage->u32Length) { |
| 162 | spin_unlock_irqrestore(&pHandle->strCriticalSection, flags); |
Arnd Bergmann | 83383ea | 2015-06-01 21:06:43 +0200 | [diff] [blame] | 163 | up(&pHandle->hSem); |
Johnny Kim | c5c77ba | 2015-05-11 14:30:56 +0900 | [diff] [blame] | 164 | WILC_ERRORREPORT(s32RetStatus, WILC_BUFFER_OVERFLOW); |
| 165 | } |
| 166 | |
| 167 | /* consume the message */ |
| 168 | pHandle->u32ReceiversCount--; |
Chaehyun Lim | d00d2ba | 2015-08-10 11:33:19 +0900 | [diff] [blame] | 169 | memcpy(pvRecvBuffer, pstrMessage->pvBuffer, pstrMessage->u32Length); |
Johnny Kim | c5c77ba | 2015-05-11 14:30:56 +0900 | [diff] [blame] | 170 | *pu32ReceivedLength = pstrMessage->u32Length; |
| 171 | |
| 172 | pHandle->pstrMessageList = pstrMessage->pstrNext; |
| 173 | |
Chaehyun Lim | 49188af | 2015-08-11 10:32:41 +0900 | [diff] [blame] | 174 | kfree(pstrMessage->pvBuffer); |
| 175 | kfree(pstrMessage); |
Johnny Kim | c5c77ba | 2015-05-11 14:30:56 +0900 | [diff] [blame] | 176 | |
| 177 | spin_unlock_irqrestore(&pHandle->strCriticalSection, flags); |
| 178 | |
| 179 | } |
| 180 | |
| 181 | WILC_CATCH(s32RetStatus) |
| 182 | { |
| 183 | } |
| 184 | |
| 185 | return s32RetStatus; |
| 186 | } |