1
2 #include "wilc_msgqueue.h"
3 #include <linux/spinlock.h>
4 #include "linux_wlan_common.h"
5 #include <linux/errno.h>
6 #include <linux/slab.h>
7
8 /*!
9 * @author syounan
10 * @date 1 Sep 2010
11 * @note copied from FLO glue implementatuion
12 * @version 1.0
13 */
wilc_mq_create(WILC_MsgQueueHandle * pHandle)14 int wilc_mq_create(WILC_MsgQueueHandle *pHandle)
15 {
16 spin_lock_init(&pHandle->strCriticalSection);
17 sema_init(&pHandle->hSem, 0);
18 pHandle->pstrMessageList = NULL;
19 pHandle->u32ReceiversCount = 0;
20 pHandle->bExiting = false;
21 return 0;
22 }
23
24 /*!
25 * @author syounan
26 * @date 1 Sep 2010
27 * @note copied from FLO glue implementatuion
28 * @version 1.0
29 */
wilc_mq_destroy(WILC_MsgQueueHandle * pHandle)30 int wilc_mq_destroy(WILC_MsgQueueHandle *pHandle)
31 {
32 pHandle->bExiting = true;
33
34 /* Release any waiting receiver thread. */
35 while (pHandle->u32ReceiversCount > 0) {
36 up(&pHandle->hSem);
37 pHandle->u32ReceiversCount--;
38 }
39
40 while (pHandle->pstrMessageList) {
41 Message *pstrMessge = pHandle->pstrMessageList->pstrNext;
42
43 kfree(pHandle->pstrMessageList);
44 pHandle->pstrMessageList = pstrMessge;
45 }
46
47 return 0;
48 }
49
50 /*!
51 * @author syounan
52 * @date 1 Sep 2010
53 * @note copied from FLO glue implementatuion
54 * @version 1.0
55 */
wilc_mq_send(WILC_MsgQueueHandle * pHandle,const void * pvSendBuffer,u32 u32SendBufferSize)56 int wilc_mq_send(WILC_MsgQueueHandle *pHandle,
57 const void *pvSendBuffer, u32 u32SendBufferSize)
58 {
59 unsigned long flags;
60 Message *pstrMessage = NULL;
61
62 if ((!pHandle) || (u32SendBufferSize == 0) || (!pvSendBuffer)) {
63 PRINT_ER("pHandle or pvSendBuffer is null\n");
64 return -EFAULT;
65 }
66
67 if (pHandle->bExiting) {
68 PRINT_ER("pHandle fail\n");
69 return -EFAULT;
70 }
71
72 /* construct a new message */
73 pstrMessage = kmalloc(sizeof(Message), GFP_ATOMIC);
74 if (!pstrMessage)
75 return -ENOMEM;
76
77 pstrMessage->u32Length = u32SendBufferSize;
78 pstrMessage->pstrNext = NULL;
79 pstrMessage->pvBuffer = kmemdup(pvSendBuffer, u32SendBufferSize,
80 GFP_ATOMIC);
81 if (!pstrMessage->pvBuffer) {
82 kfree(pstrMessage);
83 return -ENOMEM;
84 }
85
86 spin_lock_irqsave(&pHandle->strCriticalSection, flags);
87
88 /* add it to the message queue */
89 if (!pHandle->pstrMessageList) {
90 pHandle->pstrMessageList = pstrMessage;
91 } else {
92 Message *pstrTailMsg = pHandle->pstrMessageList;
93
94 while (pstrTailMsg->pstrNext)
95 pstrTailMsg = pstrTailMsg->pstrNext;
96
97 pstrTailMsg->pstrNext = pstrMessage;
98 }
99
100 spin_unlock_irqrestore(&pHandle->strCriticalSection, flags);
101
102 up(&pHandle->hSem);
103
104 return 0;
105 }
106
107 /*!
108 * @author syounan
109 * @date 1 Sep 2010
110 * @note copied from FLO glue implementatuion
111 * @version 1.0
112 */
wilc_mq_recv(WILC_MsgQueueHandle * pHandle,void * pvRecvBuffer,u32 u32RecvBufferSize,u32 * pu32ReceivedLength)113 int wilc_mq_recv(WILC_MsgQueueHandle *pHandle,
114 void *pvRecvBuffer, u32 u32RecvBufferSize,
115 u32 *pu32ReceivedLength)
116 {
117 Message *pstrMessage;
118 int result = 0;
119 unsigned long flags;
120
121 if ((!pHandle) || (u32RecvBufferSize == 0)
122 || (!pvRecvBuffer) || (!pu32ReceivedLength)) {
123 PRINT_ER("pHandle or pvRecvBuffer is null\n");
124 return -EINVAL;
125 }
126
127 if (pHandle->bExiting) {
128 PRINT_ER("pHandle fail\n");
129 return -EFAULT;
130 }
131
132 spin_lock_irqsave(&pHandle->strCriticalSection, flags);
133 pHandle->u32ReceiversCount++;
134 spin_unlock_irqrestore(&pHandle->strCriticalSection, flags);
135
136 down(&pHandle->hSem);
137
138 /* other non-timeout scenarios */
139 if (result) {
140 PRINT_ER("Non-timeout\n");
141 return result;
142 }
143
144 if (pHandle->bExiting) {
145 PRINT_ER("pHandle fail\n");
146 return -EFAULT;
147 }
148
149 spin_lock_irqsave(&pHandle->strCriticalSection, flags);
150
151 pstrMessage = pHandle->pstrMessageList;
152 if (!pstrMessage) {
153 spin_unlock_irqrestore(&pHandle->strCriticalSection, flags);
154 PRINT_ER("pstrMessage is null\n");
155 return -EFAULT;
156 }
157 /* check buffer size */
158 if (u32RecvBufferSize < pstrMessage->u32Length) {
159 spin_unlock_irqrestore(&pHandle->strCriticalSection, flags);
160 up(&pHandle->hSem);
161 PRINT_ER("u32RecvBufferSize overflow\n");
162 return -EOVERFLOW;
163 }
164
165 /* consume the message */
166 pHandle->u32ReceiversCount--;
167 memcpy(pvRecvBuffer, pstrMessage->pvBuffer, pstrMessage->u32Length);
168 *pu32ReceivedLength = pstrMessage->u32Length;
169
170 pHandle->pstrMessageList = pstrMessage->pstrNext;
171
172 kfree(pstrMessage->pvBuffer);
173 kfree(pstrMessage);
174
175 spin_unlock_irqrestore(&pHandle->strCriticalSection, flags);
176
177 return result;
178 }
179