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