1113092398d18590cf3af035076d8f6c9f6269e8
[linux-drm-fsl-dcu.git] / drivers / staging / wilc1000 / wilc_msgqueue.c
1
2 #include "wilc_oswrapper.h"
3 #include <linux/spinlock.h>
4
5 /*!
6  *  @author             syounan
7  *  @date               1 Sep 2010
8  *  @note               copied from FLO glue implementatuion
9  *  @version            1.0
10  */
11 WILC_ErrNo WILC_MsgQueueCreate(WILC_MsgQueueHandle *pHandle,
12                                tstrWILC_MsgQueueAttrs *pstrAttrs)
13 {
14         tstrWILC_SemaphoreAttrs strSemAttrs;
15         WILC_SemaphoreFillDefault(&strSemAttrs);
16         strSemAttrs.u32InitCount = 0;
17
18         spin_lock_init(&pHandle->strCriticalSection);
19         if ((WILC_SemaphoreCreate(&pHandle->hSem, &strSemAttrs) == WILC_SUCCESS)) {
20
21                 pHandle->pstrMessageList = NULL;
22                 pHandle->u32ReceiversCount = 0;
23                 pHandle->bExiting = WILC_FALSE;
24
25                 return WILC_SUCCESS;
26         } else {
27                 return WILC_FAIL;
28         }
29 }
30
31 /*!
32  *  @author             syounan
33  *  @date               1 Sep 2010
34  *  @note               copied from FLO glue implementatuion
35  *  @version            1.0
36  */
37 WILC_ErrNo WILC_MsgQueueDestroy(WILC_MsgQueueHandle *pHandle,
38                                 tstrWILC_MsgQueueAttrs *pstrAttrs)
39 {
40
41         pHandle->bExiting = WILC_TRUE;
42
43         /* Release any waiting receiver thread. */
44         while (pHandle->u32ReceiversCount > 0) {
45                 WILC_SemaphoreRelease(&(pHandle->hSem), WILC_NULL);
46                 pHandle->u32ReceiversCount--;
47         }
48
49         WILC_SemaphoreDestroy(&pHandle->hSem, WILC_NULL);
50
51         while (pHandle->pstrMessageList != NULL) {
52                 Message *pstrMessge = pHandle->pstrMessageList->pstrNext;
53                 WILC_FREE(pHandle->pstrMessageList);
54                 pHandle->pstrMessageList = pstrMessge;
55         }
56
57         return WILC_SUCCESS;
58 }
59
60 /*!
61  *  @author             syounan
62  *  @date               1 Sep 2010
63  *  @note               copied from FLO glue implementatuion
64  *  @version            1.0
65  */
66 WILC_ErrNo WILC_MsgQueueSend(WILC_MsgQueueHandle *pHandle,
67                              const void *pvSendBuffer, WILC_Uint32 u32SendBufferSize,
68                              tstrWILC_MsgQueueAttrs *pstrAttrs)
69 {
70         WILC_ErrNo s32RetStatus = WILC_SUCCESS;
71         unsigned long flags;
72         Message *pstrMessage = NULL;
73
74         if ((pHandle == NULL) || (u32SendBufferSize == 0) || (pvSendBuffer == NULL)) {
75                 WILC_ERRORREPORT(s32RetStatus, WILC_INVALID_ARGUMENT);
76         }
77
78         if (pHandle->bExiting == WILC_TRUE) {
79                 WILC_ERRORREPORT(s32RetStatus, WILC_FAIL);
80         }
81
82         spin_lock_irqsave(&pHandle->strCriticalSection, flags);
83
84         /* construct a new message */
85         pstrMessage = WILC_NEW(Message, 1);
86         WILC_NULLCHECK(s32RetStatus, pstrMessage);
87         pstrMessage->u32Length = u32SendBufferSize;
88         pstrMessage->pstrNext = NULL;
89         pstrMessage->pvBuffer = WILC_MALLOC(u32SendBufferSize);
90         WILC_NULLCHECK(s32RetStatus, pstrMessage->pvBuffer);
91         WILC_memcpy(pstrMessage->pvBuffer, pvSendBuffer, u32SendBufferSize);
92
93
94         /* add it to the message queue */
95         if (pHandle->pstrMessageList == NULL) {
96                 pHandle->pstrMessageList  = pstrMessage;
97         } else {
98                 Message *pstrTailMsg = pHandle->pstrMessageList;
99                 while (pstrTailMsg->pstrNext != NULL) {
100                         pstrTailMsg = pstrTailMsg->pstrNext;
101                 }
102                 pstrTailMsg->pstrNext = pstrMessage;
103         }
104
105         spin_unlock_irqrestore(&pHandle->strCriticalSection, flags);
106
107         WILC_SemaphoreRelease(&pHandle->hSem, WILC_NULL);
108
109         WILC_CATCH(s32RetStatus)
110         {
111                 /* error occured, free any allocations */
112                 if (pstrMessage != NULL) {
113                         if (pstrMessage->pvBuffer != NULL) {
114                                 WILC_FREE(pstrMessage->pvBuffer);
115                         }
116                         WILC_FREE(pstrMessage);
117                 }
118         }
119
120         return s32RetStatus;
121 }
122
123
124
125 /*!
126  *  @author             syounan
127  *  @date               1 Sep 2010
128  *  @note               copied from FLO glue implementatuion
129  *  @version            1.0
130  */
131 WILC_ErrNo WILC_MsgQueueRecv(WILC_MsgQueueHandle *pHandle,
132                              void *pvRecvBuffer, WILC_Uint32 u32RecvBufferSize,
133                              WILC_Uint32 *pu32ReceivedLength,
134                              tstrWILC_MsgQueueAttrs *pstrAttrs)
135 {
136
137         Message *pstrMessage;
138         WILC_ErrNo s32RetStatus = WILC_SUCCESS;
139         tstrWILC_SemaphoreAttrs strSemAttrs;
140         unsigned long flags;
141         if ((pHandle == NULL) || (u32RecvBufferSize == 0)
142             || (pvRecvBuffer == NULL) || (pu32ReceivedLength == NULL)) {
143                 WILC_ERRORREPORT(s32RetStatus, WILC_INVALID_ARGUMENT);
144         }
145
146         if (pHandle->bExiting == WILC_TRUE) {
147                 WILC_ERRORREPORT(s32RetStatus, WILC_FAIL);
148         }
149
150         spin_lock_irqsave(&pHandle->strCriticalSection, flags);
151         pHandle->u32ReceiversCount++;
152         spin_unlock_irqrestore(&pHandle->strCriticalSection, flags);
153
154         WILC_SemaphoreFillDefault(&strSemAttrs);
155         s32RetStatus = WILC_SemaphoreAcquire(&(pHandle->hSem), &strSemAttrs);
156         if (s32RetStatus == WILC_TIMEOUT) {
157                 /* timed out, just exit without consumeing the message */
158                 spin_lock_irqsave(&pHandle->strCriticalSection, flags);
159                 pHandle->u32ReceiversCount--;
160                 spin_unlock_irqrestore(&pHandle->strCriticalSection, flags);
161         } else {
162                 /* other non-timeout scenarios */
163                 WILC_ERRORCHECK(s32RetStatus);
164
165                 if (pHandle->bExiting) {
166                         WILC_ERRORREPORT(s32RetStatus, WILC_FAIL);
167                 }
168
169                 spin_lock_irqsave(&pHandle->strCriticalSection, flags);
170
171                 pstrMessage = pHandle->pstrMessageList;
172                 if (pstrMessage == NULL) {
173                         spin_unlock_irqrestore(&pHandle->strCriticalSection, flags);
174                         WILC_ERRORREPORT(s32RetStatus, WILC_FAIL);
175                 }
176                 /* check buffer size */
177                 if (u32RecvBufferSize < pstrMessage->u32Length) {
178                         spin_unlock_irqrestore(&pHandle->strCriticalSection, flags);
179                         WILC_SemaphoreRelease(&pHandle->hSem, WILC_NULL);
180                         WILC_ERRORREPORT(s32RetStatus, WILC_BUFFER_OVERFLOW);
181                 }
182
183                 /* consume the message */
184                 pHandle->u32ReceiversCount--;
185                 WILC_memcpy(pvRecvBuffer, pstrMessage->pvBuffer, pstrMessage->u32Length);
186                 *pu32ReceivedLength = pstrMessage->u32Length;
187
188                 pHandle->pstrMessageList = pstrMessage->pstrNext;
189
190                 WILC_FREE(pstrMessage->pvBuffer);
191                 WILC_FREE(pstrMessage);
192
193                 spin_unlock_irqrestore(&pHandle->strCriticalSection, flags);
194
195         }
196
197         WILC_CATCH(s32RetStatus)
198         {
199         }
200
201         return s32RetStatus;
202 }