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 | */ | |
2cc08b4f | 14 | int wilc_mq_create(struct message_queue *mq) |
c5c77ba1 | 15 | { |
2cc08b4f CL |
16 | spin_lock_init(&mq->lock); |
17 | sema_init(&mq->sem, 0); | |
18 | mq->msg_list = NULL; | |
19 | mq->recv_count = 0; | |
20 | mq->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 | */ | |
d742f67e | 30 | int wilc_mq_destroy(struct message_queue *mq) |
c5c77ba1 | 31 | { |
d742f67e | 32 | mq->exiting = true; |
c5c77ba1 JK |
33 | |
34 | /* Release any waiting receiver thread. */ | |
d742f67e CL |
35 | while (mq->recv_count > 0) { |
36 | up(&mq->sem); | |
37 | mq->recv_count--; | |
c5c77ba1 JK |
38 | } |
39 | ||
d742f67e | 40 | while (mq->msg_list) { |
fca978b7 | 41 | struct message *msg = mq->msg_list->next; |
8dfaafd6 | 42 | |
d742f67e | 43 | kfree(mq->msg_list); |
fca978b7 | 44 | mq->msg_list = msg; |
c5c77ba1 JK |
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 | */ | |
5eb35975 | 56 | int wilc_mq_send(struct message_queue *mq, |
81e886e0 | 57 | const void *send_buf, u32 send_buf_size) |
c5c77ba1 | 58 | { |
c5c77ba1 | 59 | unsigned long flags; |
669fd507 | 60 | struct message *new_msg = NULL; |
c5c77ba1 | 61 | |
81e886e0 | 62 | if ((!mq) || (send_buf_size == 0) || (!send_buf)) { |
832f4fa5 | 63 | PRINT_ER("mq or send_buf is null\n"); |
dee1bf76 | 64 | return -EINVAL; |
c5c77ba1 JK |
65 | } |
66 | ||
5eb35975 CL |
67 | if (mq->exiting) { |
68 | PRINT_ER("mq fail\n"); | |
dbef61e7 | 69 | return -EFAULT; |
c5c77ba1 JK |
70 | } |
71 | ||
c5c77ba1 | 72 | /* construct a new message */ |
669fd507 CL |
73 | new_msg = kmalloc(sizeof(struct message), GFP_ATOMIC); |
74 | if (!new_msg) | |
7ae43363 | 75 | return -ENOMEM; |
dbef61e7 | 76 | |
669fd507 CL |
77 | new_msg->len = send_buf_size; |
78 | new_msg->next = NULL; | |
79 | new_msg->buf = kmemdup(send_buf, send_buf_size, GFP_ATOMIC); | |
80 | if (!new_msg->buf) { | |
81 | kfree(new_msg); | |
dbef61e7 | 82 | return -ENOMEM; |
7ae43363 | 83 | } |
c5c77ba1 | 84 | |
5eb35975 | 85 | spin_lock_irqsave(&mq->lock, flags); |
dbef61e7 | 86 | |
c5c77ba1 | 87 | /* add it to the message queue */ |
5eb35975 | 88 | if (!mq->msg_list) { |
669fd507 | 89 | mq->msg_list = new_msg; |
c5c77ba1 | 90 | } else { |
bd07b007 | 91 | struct message *tail_msg = mq->msg_list; |
8dfaafd6 | 92 | |
bd07b007 CL |
93 | while (tail_msg->next) |
94 | tail_msg = tail_msg->next; | |
6fffc621 | 95 | |
bd07b007 | 96 | tail_msg->next = new_msg; |
c5c77ba1 JK |
97 | } |
98 | ||
5eb35975 | 99 | spin_unlock_irqrestore(&mq->lock, flags); |
c5c77ba1 | 100 | |
5eb35975 | 101 | up(&mq->sem); |
c5c77ba1 | 102 | |
dbef61e7 | 103 | return 0; |
c5c77ba1 JK |
104 | } |
105 | ||
c5c77ba1 JK |
106 | /*! |
107 | * @author syounan | |
108 | * @date 1 Sep 2010 | |
109 | * @note copied from FLO glue implementatuion | |
110 | * @version 1.0 | |
111 | */ | |
24752783 | 112 | int wilc_mq_recv(struct message_queue *mq, |
62082cbe | 113 | void *recv_buf, u32 recv_buf_size, u32 *recv_len) |
c5c77ba1 | 114 | { |
d16791bf | 115 | struct message *pstrMessage; |
c5c77ba1 | 116 | unsigned long flags; |
8dfaafd6 | 117 | |
e8f2d1f1 | 118 | if ((!mq) || (recv_buf_size == 0) |
62082cbe | 119 | || (!recv_buf) || (!recv_len)) { |
f034b01e | 120 | PRINT_ER("mq or recv_buf is null\n"); |
24db713f | 121 | return -EINVAL; |
c5c77ba1 JK |
122 | } |
123 | ||
24752783 CL |
124 | if (mq->exiting) { |
125 | PRINT_ER("mq fail\n"); | |
24db713f | 126 | return -EFAULT; |
c5c77ba1 JK |
127 | } |
128 | ||
24752783 CL |
129 | spin_lock_irqsave(&mq->lock, flags); |
130 | mq->recv_count++; | |
131 | spin_unlock_irqrestore(&mq->lock, flags); | |
c5c77ba1 | 132 | |
24752783 CL |
133 | down(&mq->sem); |
134 | spin_lock_irqsave(&mq->lock, flags); | |
c5c77ba1 | 135 | |
24752783 | 136 | pstrMessage = mq->msg_list; |
24db713f | 137 | if (!pstrMessage) { |
24752783 | 138 | spin_unlock_irqrestore(&mq->lock, flags); |
24db713f LK |
139 | PRINT_ER("pstrMessage is null\n"); |
140 | return -EFAULT; | |
c5c77ba1 | 141 | } |
24db713f | 142 | /* check buffer size */ |
e8f2d1f1 | 143 | if (recv_buf_size < pstrMessage->len) { |
24752783 CL |
144 | spin_unlock_irqrestore(&mq->lock, flags); |
145 | up(&mq->sem); | |
e8f2d1f1 | 146 | PRINT_ER("recv_buf_size overflow\n"); |
24db713f | 147 | return -EOVERFLOW; |
c5c77ba1 JK |
148 | } |
149 | ||
24db713f | 150 | /* consume the message */ |
24752783 | 151 | mq->recv_count--; |
f034b01e | 152 | memcpy(recv_buf, pstrMessage->buf, pstrMessage->len); |
62082cbe | 153 | *recv_len = pstrMessage->len; |
24db713f | 154 | |
24752783 | 155 | mq->msg_list = pstrMessage->next; |
24db713f | 156 | |
78d50f94 | 157 | kfree(pstrMessage->buf); |
24db713f LK |
158 | kfree(pstrMessage); |
159 | ||
24752783 | 160 | spin_unlock_irqrestore(&mq->lock, flags); |
24db713f | 161 | |
ff5d40a4 | 162 | return 0; |
c5c77ba1 | 163 | } |