]>
Commit | Line | Data |
---|---|---|
c5c77ba1 | 1 | #include "wilc_wlan_if.h" |
491880eb | 2 | #include "wilc_wlan.h" |
60bd1003 | 3 | #include "wilc_wfi_netdevice.h" |
17e8f165 | 4 | #include "wilc_wlan_cfg.h" |
c5c77ba1 | 5 | |
c5c77ba1 JK |
6 | typedef struct { |
7 | int quit; | |
4bd7baf0 | 8 | int io_type; |
48d0aa97 | 9 | struct wilc_hif_func hif_func; |
c5c77ba1 | 10 | int cfg_frame_in_use; |
14cdc0a1 | 11 | struct wilc_cfg_frame cfg_frame; |
fbc2fe16 | 12 | u32 cfg_frame_offset; |
c5c77ba1 | 13 | int cfg_seq_no; |
c5c77ba1 | 14 | |
c5c77ba1 | 15 | #ifdef MEMORY_STATIC |
51e825f7 | 16 | u8 *rx_buffer; |
fbc2fe16 | 17 | u32 rx_buffer_offset; |
c5c77ba1 | 18 | #endif |
51e825f7 | 19 | u8 *tx_buffer; |
fbc2fe16 | 20 | u32 tx_buffer_offset; |
c5c77ba1 | 21 | |
c5c77ba1 JK |
22 | unsigned long txq_spinlock_flags; |
23 | ||
24 | struct txq_entry_t *txq_head; | |
25 | struct txq_entry_t *txq_tail; | |
26 | int txq_entries; | |
c5c77ba1 JK |
27 | int txq_exit; |
28 | ||
c5c77ba1 JK |
29 | struct rxq_entry_t *rxq_head; |
30 | struct rxq_entry_t *rxq_tail; | |
31 | int rxq_entries; | |
c5c77ba1 | 32 | int rxq_exit; |
c5c77ba1 JK |
33 | } wilc_wlan_dev_t; |
34 | ||
35 | static wilc_wlan_dev_t g_wlan; | |
36 | ||
1608c403 | 37 | #ifdef WILC_OPTIMIZE_SLEEP_INT |
00215dde | 38 | static inline void chip_allow_sleep(struct wilc *wilc); |
1608c403 | 39 | #endif |
00215dde | 40 | static inline void chip_wakeup(struct wilc *wilc); |
fbc2fe16 | 41 | static u32 dbgflag = N_INIT | N_ERR | N_INTR | N_TXQ | N_RXQ; |
c5c77ba1 | 42 | |
562ed3f1 | 43 | /* FIXME: replace with dev_debug() */ |
fbc2fe16 | 44 | static void wilc_debug(u32 flag, char *fmt, ...) |
c5c77ba1 JK |
45 | { |
46 | char buf[256]; | |
47 | va_list args; | |
c5c77ba1 JK |
48 | |
49 | if (flag & dbgflag) { | |
50 | va_start(args, fmt); | |
81053222 | 51 | vsprintf(buf, fmt, args); |
c5c77ba1 JK |
52 | va_end(args); |
53 | ||
562ed3f1 | 54 | wilc_dbg(wilc_dev, buf); |
c5c77ba1 | 55 | } |
c5c77ba1 JK |
56 | } |
57 | ||
b7d1e18c | 58 | static CHIP_PS_STATE_T chip_ps_state = CHIP_WAKEDUP; |
c5c77ba1 | 59 | |
562ed3f1 | 60 | static inline void acquire_bus(struct wilc *wilc, BUS_ACQUIRE_T acquire) |
c5c77ba1 | 61 | { |
562ed3f1 | 62 | mutex_lock(&wilc->hif_cs); |
c5c77ba1 | 63 | #ifndef WILC_OPTIMIZE_SLEEP_INT |
b7d1e18c | 64 | if (chip_ps_state != CHIP_WAKEDUP) |
c5c77ba1 JK |
65 | #endif |
66 | { | |
67 | if (acquire == ACQUIRE_AND_WAKEUP) | |
00215dde | 68 | chip_wakeup(wilc); |
c5c77ba1 | 69 | } |
c5c77ba1 | 70 | } |
2d6973e6 | 71 | |
562ed3f1 | 72 | static inline void release_bus(struct wilc *wilc, BUS_RELEASE_T release) |
c5c77ba1 JK |
73 | { |
74 | #ifdef WILC_OPTIMIZE_SLEEP_INT | |
75 | if (release == RELEASE_ALLOW_SLEEP) | |
00215dde | 76 | chip_allow_sleep(wilc); |
c5c77ba1 | 77 | #endif |
562ed3f1 | 78 | mutex_unlock(&wilc->hif_cs); |
c5c77ba1 | 79 | } |
c5c77ba1 | 80 | |
1608c403 | 81 | #ifdef TCP_ACK_FILTER |
c5c77ba1 JK |
82 | static void wilc_wlan_txq_remove(struct txq_entry_t *tqe) |
83 | { | |
7ee8291a | 84 | wilc_wlan_dev_t *p = &g_wlan; |
8739eeba | 85 | |
c5c77ba1 | 86 | if (tqe == p->txq_head) { |
c5c77ba1 JK |
87 | p->txq_head = tqe->next; |
88 | if (p->txq_head) | |
89 | p->txq_head->prev = NULL; | |
c5c77ba1 JK |
90 | } else if (tqe == p->txq_tail) { |
91 | p->txq_tail = (tqe->prev); | |
92 | if (p->txq_tail) | |
93 | p->txq_tail->next = NULL; | |
94 | } else { | |
95 | tqe->prev->next = tqe->next; | |
96 | tqe->next->prev = tqe->prev; | |
97 | } | |
98 | p->txq_entries -= 1; | |
c5c77ba1 | 99 | } |
1608c403 | 100 | #endif |
c5c77ba1 | 101 | |
718fc2c9 GL |
102 | static struct txq_entry_t * |
103 | wilc_wlan_txq_remove_from_head(struct net_device *dev) | |
c5c77ba1 JK |
104 | { |
105 | struct txq_entry_t *tqe; | |
7ee8291a | 106 | wilc_wlan_dev_t *p = &g_wlan; |
c5c77ba1 | 107 | unsigned long flags; |
718fc2c9 GL |
108 | perInterface_wlan_t *nic; |
109 | struct wilc *wilc; | |
8dfaafd6 | 110 | |
718fc2c9 GL |
111 | nic = netdev_priv(dev); |
112 | wilc = nic->wilc; | |
113 | ||
114 | spin_lock_irqsave(&wilc->txq_spinlock, flags); | |
c5c77ba1 | 115 | if (p->txq_head) { |
c5c77ba1 JK |
116 | tqe = p->txq_head; |
117 | p->txq_head = tqe->next; | |
39823a50 | 118 | if (p->txq_head) |
c5c77ba1 | 119 | p->txq_head->prev = NULL; |
39823a50 | 120 | |
c5c77ba1 | 121 | p->txq_entries -= 1; |
c5c77ba1 JK |
122 | } else { |
123 | tqe = NULL; | |
124 | } | |
718fc2c9 | 125 | spin_unlock_irqrestore(&wilc->txq_spinlock, flags); |
c5c77ba1 JK |
126 | return tqe; |
127 | } | |
128 | ||
32f03328 GL |
129 | static void wilc_wlan_txq_add_to_tail(struct net_device *dev, |
130 | struct txq_entry_t *tqe) | |
c5c77ba1 | 131 | { |
7ee8291a | 132 | wilc_wlan_dev_t *p = &g_wlan; |
c5c77ba1 | 133 | unsigned long flags; |
32f03328 GL |
134 | perInterface_wlan_t *nic; |
135 | struct wilc *wilc; | |
136 | ||
137 | nic = netdev_priv(dev); | |
138 | wilc = nic->wilc; | |
139 | ||
140 | spin_lock_irqsave(&wilc->txq_spinlock, flags); | |
c5c77ba1 | 141 | |
a4b17197 | 142 | if (!p->txq_head) { |
c5c77ba1 JK |
143 | tqe->next = NULL; |
144 | tqe->prev = NULL; | |
145 | p->txq_head = tqe; | |
146 | p->txq_tail = tqe; | |
c5c77ba1 JK |
147 | } else { |
148 | tqe->next = NULL; | |
149 | tqe->prev = p->txq_tail; | |
150 | p->txq_tail->next = tqe; | |
151 | p->txq_tail = tqe; | |
152 | } | |
153 | p->txq_entries += 1; | |
154 | PRINT_D(TX_DBG, "Number of entries in TxQ = %d\n", p->txq_entries); | |
c5c77ba1 | 155 | |
32f03328 | 156 | spin_unlock_irqrestore(&wilc->txq_spinlock, flags); |
c5c77ba1 | 157 | |
c5c77ba1 JK |
158 | PRINT_D(TX_DBG, "Wake the txq_handling\n"); |
159 | ||
32f03328 | 160 | up(&wilc->txq_event); |
c5c77ba1 JK |
161 | } |
162 | ||
562ed3f1 | 163 | static int wilc_wlan_txq_add_to_head(struct wilc *wilc, struct txq_entry_t *tqe) |
c5c77ba1 | 164 | { |
7ee8291a | 165 | wilc_wlan_dev_t *p = &g_wlan; |
c5c77ba1 | 166 | unsigned long flags; |
562ed3f1 | 167 | if (wilc_lock_timeout(wilc, &wilc->txq_add_to_head_cs, |
b002e20d | 168 | CFG_PKTS_TIMEOUT)) |
c5c77ba1 JK |
169 | return -1; |
170 | ||
562ed3f1 | 171 | spin_lock_irqsave(&wilc->txq_spinlock, flags); |
c5c77ba1 | 172 | |
a4b17197 | 173 | if (!p->txq_head) { |
c5c77ba1 JK |
174 | tqe->next = NULL; |
175 | tqe->prev = NULL; | |
176 | p->txq_head = tqe; | |
177 | p->txq_tail = tqe; | |
178 | } else { | |
179 | tqe->next = p->txq_head; | |
180 | tqe->prev = NULL; | |
181 | p->txq_head->prev = tqe; | |
182 | p->txq_head = tqe; | |
183 | } | |
184 | p->txq_entries += 1; | |
185 | PRINT_D(TX_DBG, "Number of entries in TxQ = %d\n", p->txq_entries); | |
c5c77ba1 | 186 | |
562ed3f1 AB |
187 | spin_unlock_irqrestore(&wilc->txq_spinlock, flags); |
188 | up(&wilc->txq_add_to_head_cs); | |
189 | up(&wilc->txq_event); | |
c5c77ba1 | 190 | PRINT_D(TX_DBG, "Wake up the txq_handler\n"); |
c5c77ba1 | 191 | |
c5c77ba1 | 192 | return 0; |
c5c77ba1 JK |
193 | } |
194 | ||
c5c77ba1 | 195 | #ifdef TCP_ACK_FILTER |
130a41f0 LK |
196 | struct ack_session_info; |
197 | struct ack_session_info { | |
d06b6cb2 | 198 | u32 seq_num; |
9d54d3d5 | 199 | u32 bigger_ack_num; |
ec53adfe CL |
200 | u16 src_port; |
201 | u16 dst_port; | |
202 | u16 status; | |
eeb1c062 | 203 | }; |
c5c77ba1 | 204 | |
08b90b10 | 205 | struct pending_acks_info { |
fbc2fe16 | 206 | u32 ack_num; |
84136978 | 207 | u32 session_index; |
c5c77ba1 | 208 | struct txq_entry_t *txqe; |
08b90b10 | 209 | }; |
c5c77ba1 | 210 | |
1608c403 | 211 | |
c5c77ba1 JK |
212 | #define NOT_TCP_ACK (-1) |
213 | ||
214 | #define MAX_TCP_SESSION 25 | |
215 | #define MAX_PENDING_ACKS 256 | |
1608c403 AB |
216 | static struct ack_session_info ack_session_info[2 * MAX_TCP_SESSION]; |
217 | static struct pending_acks_info pending_acks_info[MAX_PENDING_ACKS]; | |
c5c77ba1 | 218 | |
1608c403 AB |
219 | static u32 pending_base; |
220 | static u32 tcp_session; | |
221 | static u32 pending_acks; | |
c5c77ba1 | 222 | |
ef06b5f7 | 223 | static inline int init_tcp_tracking(void) |
c5c77ba1 | 224 | { |
c5c77ba1 | 225 | return 0; |
c5c77ba1 | 226 | } |
2d6973e6 | 227 | |
67620788 | 228 | static inline int add_tcp_session(u32 src_prt, u32 dst_prt, u32 seq) |
c5c77ba1 | 229 | { |
3056ec39 LK |
230 | ack_session_info[tcp_session].seq_num = seq; |
231 | ack_session_info[tcp_session].bigger_ack_num = 0; | |
232 | ack_session_info[tcp_session].src_port = src_prt; | |
233 | ack_session_info[tcp_session].dst_port = dst_prt; | |
234 | tcp_session++; | |
c5c77ba1 | 235 | |
3056ec39 | 236 | PRINT_D(TCP_ENH, "TCP Session %d to Ack %d\n", tcp_session, seq); |
c5c77ba1 JK |
237 | return 0; |
238 | } | |
239 | ||
b801a96c | 240 | static inline int update_tcp_session(u32 index, u32 ack) |
c5c77ba1 | 241 | { |
b801a96c LK |
242 | if (ack > ack_session_info[index].bigger_ack_num) |
243 | ack_session_info[index].bigger_ack_num = ack; | |
c5c77ba1 | 244 | return 0; |
c5c77ba1 | 245 | } |
2d6973e6 | 246 | |
ea03f57b | 247 | static inline int add_tcp_pending_ack(u32 ack, u32 session_index, |
66a43a91 | 248 | struct txq_entry_t *txqe) |
c5c77ba1 | 249 | { |
d12ac7e2 | 250 | if (pending_acks < MAX_PENDING_ACKS) { |
b801a96c | 251 | pending_acks_info[pending_base + pending_acks].ack_num = ack; |
d12ac7e2 | 252 | pending_acks_info[pending_base + pending_acks].txqe = txqe; |
ea03f57b | 253 | pending_acks_info[pending_base + pending_acks].session_index = session_index; |
8e55639d | 254 | txqe->index = pending_base + pending_acks; |
d12ac7e2 | 255 | pending_acks++; |
c5c77ba1 JK |
256 | } |
257 | return 0; | |
258 | } | |
562ed3f1 | 259 | static inline int remove_TCP_related(struct wilc *wilc) |
c5c77ba1 | 260 | { |
7ee8291a | 261 | wilc_wlan_dev_t *p = &g_wlan; |
c5c77ba1 | 262 | unsigned long flags; |
8dfaafd6 | 263 | |
562ed3f1 | 264 | spin_lock_irqsave(&wilc->txq_spinlock, flags); |
c5c77ba1 | 265 | |
562ed3f1 | 266 | spin_unlock_irqrestore(&wilc->txq_spinlock, flags); |
c5c77ba1 JK |
267 | return 0; |
268 | } | |
269 | ||
82bb18e1 | 270 | static inline int tcp_process(struct net_device *dev, struct txq_entry_t *tqe) |
c5c77ba1 JK |
271 | { |
272 | int ret; | |
51e825f7 CL |
273 | u8 *eth_hdr_ptr; |
274 | u8 *buffer = tqe->buffer; | |
c5c77ba1 JK |
275 | unsigned short h_proto; |
276 | int i; | |
7ee8291a | 277 | wilc_wlan_dev_t *p = &g_wlan; |
c5c77ba1 | 278 | unsigned long flags; |
82bb18e1 GL |
279 | perInterface_wlan_t *nic; |
280 | struct wilc *wilc; | |
8dfaafd6 | 281 | |
82bb18e1 GL |
282 | nic = netdev_priv(dev); |
283 | wilc = nic->wilc; | |
284 | ||
c5c77ba1 JK |
285 | |
286 | eth_hdr_ptr = &buffer[0]; | |
287 | h_proto = ntohs(*((unsigned short *)ð_hdr_ptr[12])); | |
ac087c82 | 288 | if (h_proto == 0x0800) { |
51e825f7 CL |
289 | u8 *ip_hdr_ptr; |
290 | u8 protocol; | |
c5c77ba1 JK |
291 | |
292 | ip_hdr_ptr = &buffer[ETHERNET_HDR_LEN]; | |
293 | protocol = ip_hdr_ptr[9]; | |
294 | ||
c5c77ba1 | 295 | if (protocol == 0x06) { |
51e825f7 | 296 | u8 *tcp_hdr_ptr; |
51bffa96 | 297 | u32 IHL, total_length, data_offset; |
8dfaafd6 | 298 | |
c5c77ba1 JK |
299 | tcp_hdr_ptr = &ip_hdr_ptr[IP_HDR_LEN]; |
300 | IHL = (ip_hdr_ptr[0] & 0xf) << 2; | |
24e2dac2 LK |
301 | total_length = ((u32)ip_hdr_ptr[2] << 8) + |
302 | (u32)ip_hdr_ptr[3]; | |
51bffa96 LK |
303 | data_offset = ((u32)tcp_hdr_ptr[12] & 0xf0) >> 2; |
304 | if (total_length == (IHL + data_offset)) { | |
f91c5d77 | 305 | u32 seq_no, ack_no; |
8dfaafd6 | 306 | |
4478c62a LK |
307 | seq_no = ((u32)tcp_hdr_ptr[4] << 24) + |
308 | ((u32)tcp_hdr_ptr[5] << 16) + | |
309 | ((u32)tcp_hdr_ptr[6] << 8) + | |
310 | (u32)tcp_hdr_ptr[7]; | |
c5c77ba1 | 311 | |
f91c5d77 LK |
312 | ack_no = ((u32)tcp_hdr_ptr[8] << 24) + |
313 | ((u32)tcp_hdr_ptr[9] << 16) + | |
314 | ((u32)tcp_hdr_ptr[10] << 8) + | |
315 | (u32)tcp_hdr_ptr[11]; | |
c5c77ba1 | 316 | |
3056ec39 | 317 | for (i = 0; i < tcp_session; i++) { |
32065054 | 318 | if (ack_session_info[i].seq_num == seq_no) { |
f91c5d77 | 319 | update_tcp_session(i, ack_no); |
c5c77ba1 JK |
320 | break; |
321 | } | |
322 | } | |
3056ec39 | 323 | if (i == tcp_session) |
67620788 | 324 | add_tcp_session(0, 0, seq_no); |
39823a50 | 325 | |
f91c5d77 | 326 | add_tcp_pending_ack(ack_no, i, tqe); |
c5c77ba1 JK |
327 | } |
328 | ||
329 | } else { | |
330 | ret = 0; | |
331 | } | |
332 | } else { | |
333 | ret = 0; | |
334 | } | |
82bb18e1 | 335 | spin_unlock_irqrestore(&wilc->txq_spinlock, flags); |
c5c77ba1 JK |
336 | return ret; |
337 | } | |
338 | ||
c029e99c | 339 | static int wilc_wlan_txq_filter_dup_tcp_ack(struct net_device *dev) |
c5c77ba1 | 340 | { |
c029e99c GL |
341 | perInterface_wlan_t *nic; |
342 | struct wilc *wilc; | |
fbc2fe16 | 343 | u32 i = 0; |
442eda4e | 344 | u32 dropped = 0; |
7ee8291a | 345 | wilc_wlan_dev_t *p = &g_wlan; |
c5c77ba1 | 346 | |
c029e99c GL |
347 | nic = netdev_priv(dev); |
348 | wilc = nic->wilc; | |
349 | ||
350 | spin_lock_irqsave(&wilc->txq_spinlock, p->txq_spinlock_flags); | |
d12ac7e2 | 351 | for (i = pending_base; i < (pending_base + pending_acks); i++) { |
2bb17087 | 352 | if (pending_acks_info[i].ack_num < ack_session_info[pending_acks_info[i].session_index].bigger_ack_num) { |
c5c77ba1 | 353 | struct txq_entry_t *tqe; |
8dfaafd6 | 354 | |
2bb17087 LK |
355 | PRINT_D(TCP_ENH, "DROP ACK: %u\n", |
356 | pending_acks_info[i].ack_num); | |
357 | tqe = pending_acks_info[i].txqe; | |
c5c77ba1 JK |
358 | if (tqe) { |
359 | wilc_wlan_txq_remove(tqe); | |
ac087c82 | 360 | tqe->status = 1; |
c5c77ba1 | 361 | if (tqe->tx_complete_func) |
ab12d8c7 LK |
362 | tqe->tx_complete_func(tqe->priv, |
363 | tqe->status); | |
a18dd630 | 364 | kfree(tqe); |
442eda4e | 365 | dropped++; |
c5c77ba1 JK |
366 | } |
367 | } | |
368 | } | |
d12ac7e2 | 369 | pending_acks = 0; |
3056ec39 | 370 | tcp_session = 0; |
c5c77ba1 | 371 | |
2ae91edb LK |
372 | if (pending_base == 0) |
373 | pending_base = MAX_TCP_SESSION; | |
78174ada | 374 | else |
2ae91edb | 375 | pending_base = 0; |
c5c77ba1 | 376 | |
c029e99c | 377 | spin_unlock_irqrestore(&wilc->txq_spinlock, p->txq_spinlock_flags); |
c5c77ba1 | 378 | |
442eda4e | 379 | while (dropped > 0) { |
562ed3f1 | 380 | wilc_lock_timeout(wilc, &wilc->txq_event, 1); |
442eda4e | 381 | dropped--; |
c5c77ba1 JK |
382 | } |
383 | ||
384 | return 1; | |
385 | } | |
386 | #endif | |
387 | ||
1608c403 | 388 | static bool enabled = false; |
c5c77ba1 | 389 | |
0e1af73d | 390 | void wilc_enable_tcp_ack_filter(bool value) |
c5c77ba1 | 391 | { |
7c4bafe9 | 392 | enabled = value; |
c5c77ba1 JK |
393 | } |
394 | ||
1608c403 AB |
395 | #ifdef TCP_ACK_FILTER |
396 | static bool is_tcp_ack_filter_enabled(void) | |
c5c77ba1 | 397 | { |
7c4bafe9 | 398 | return enabled; |
c5c77ba1 | 399 | } |
1608c403 | 400 | #endif |
c5c77ba1 | 401 | |
562ed3f1 | 402 | static int wilc_wlan_txq_add_cfg_pkt(struct wilc *wilc, u8 *buffer, u32 buffer_size) |
c5c77ba1 | 403 | { |
7ee8291a | 404 | wilc_wlan_dev_t *p = &g_wlan; |
c5c77ba1 JK |
405 | struct txq_entry_t *tqe; |
406 | ||
407 | PRINT_D(TX_DBG, "Adding config packet ...\n"); | |
408 | if (p->quit) { | |
409 | PRINT_D(TX_DBG, "Return due to clear function\n"); | |
562ed3f1 | 410 | up(&wilc->cfg_event); |
c5c77ba1 JK |
411 | return 0; |
412 | } | |
413 | ||
1d401a4d | 414 | tqe = kmalloc(sizeof(*tqe), GFP_ATOMIC); |
a4b17197 | 415 | if (!tqe) { |
c5c77ba1 JK |
416 | PRINT_ER("Failed to allocate memory\n"); |
417 | return 0; | |
418 | } | |
419 | ||
420 | tqe->type = WILC_CFG_PKT; | |
421 | tqe->buffer = buffer; | |
422 | tqe->buffer_size = buffer_size; | |
423 | tqe->tx_complete_func = NULL; | |
424 | tqe->priv = NULL; | |
425 | #ifdef TCP_ACK_FILTER | |
8e55639d | 426 | tqe->index = NOT_TCP_ACK; |
c5c77ba1 | 427 | #endif |
c5c77ba1 JK |
428 | PRINT_D(TX_DBG, "Adding the config packet at the Queue tail\n"); |
429 | ||
562ed3f1 | 430 | if (wilc_wlan_txq_add_to_head(wilc, tqe)) |
c5c77ba1 | 431 | return 0; |
c5c77ba1 JK |
432 | return 1; |
433 | } | |
434 | ||
691bbd42 GL |
435 | int wilc_wlan_txq_add_net_pkt(struct net_device *dev, void *priv, u8 *buffer, |
436 | u32 buffer_size, wilc_tx_complete_func_t func) | |
c5c77ba1 | 437 | { |
7ee8291a | 438 | wilc_wlan_dev_t *p = &g_wlan; |
c5c77ba1 JK |
439 | struct txq_entry_t *tqe; |
440 | ||
441 | if (p->quit) | |
442 | return 0; | |
443 | ||
1d401a4d | 444 | tqe = kmalloc(sizeof(*tqe), GFP_ATOMIC); |
c5c77ba1 | 445 | |
a4b17197 | 446 | if (!tqe) |
c5c77ba1 JK |
447 | return 0; |
448 | tqe->type = WILC_NET_PKT; | |
449 | tqe->buffer = buffer; | |
450 | tqe->buffer_size = buffer_size; | |
451 | tqe->tx_complete_func = func; | |
452 | tqe->priv = priv; | |
453 | ||
454 | PRINT_D(TX_DBG, "Adding mgmt packet at the Queue tail\n"); | |
455 | #ifdef TCP_ACK_FILTER | |
8e55639d | 456 | tqe->index = NOT_TCP_ACK; |
44c4417d | 457 | if (is_tcp_ack_filter_enabled()) |
82bb18e1 | 458 | tcp_process(dev, tqe); |
c5c77ba1 | 459 | #endif |
32f03328 | 460 | wilc_wlan_txq_add_to_tail(dev, tqe); |
c5c77ba1 JK |
461 | return p->txq_entries; |
462 | } | |
fcc6ef92 | 463 | |
829c477f GL |
464 | int wilc_wlan_txq_add_mgmt_pkt(struct net_device *dev, void *priv, u8 *buffer, |
465 | u32 buffer_size, wilc_tx_complete_func_t func) | |
c5c77ba1 | 466 | { |
7ee8291a | 467 | wilc_wlan_dev_t *p = &g_wlan; |
c5c77ba1 JK |
468 | struct txq_entry_t *tqe; |
469 | ||
470 | if (p->quit) | |
471 | return 0; | |
472 | ||
1d401a4d | 473 | tqe = kmalloc(sizeof(*tqe), GFP_KERNEL); |
c5c77ba1 | 474 | |
a4b17197 | 475 | if (!tqe) |
c5c77ba1 JK |
476 | return 0; |
477 | tqe->type = WILC_MGMT_PKT; | |
478 | tqe->buffer = buffer; | |
479 | tqe->buffer_size = buffer_size; | |
480 | tqe->tx_complete_func = func; | |
481 | tqe->priv = priv; | |
482 | #ifdef TCP_ACK_FILTER | |
8e55639d | 483 | tqe->index = NOT_TCP_ACK; |
c5c77ba1 JK |
484 | #endif |
485 | PRINT_D(TX_DBG, "Adding Network packet at the Queue tail\n"); | |
32f03328 | 486 | wilc_wlan_txq_add_to_tail(dev, tqe); |
c5c77ba1 JK |
487 | return 1; |
488 | } | |
fcc6ef92 | 489 | |
7af0522c | 490 | static struct txq_entry_t *wilc_wlan_txq_get_first(struct wilc *wilc) |
c5c77ba1 | 491 | { |
7ee8291a | 492 | wilc_wlan_dev_t *p = &g_wlan; |
c5c77ba1 JK |
493 | struct txq_entry_t *tqe; |
494 | unsigned long flags; | |
495 | ||
7af0522c | 496 | spin_lock_irqsave(&wilc->txq_spinlock, flags); |
c5c77ba1 | 497 | |
c5c77ba1 JK |
498 | tqe = p->txq_head; |
499 | ||
7af0522c | 500 | spin_unlock_irqrestore(&wilc->txq_spinlock, flags); |
c5c77ba1 | 501 | |
c5c77ba1 JK |
502 | return tqe; |
503 | } | |
504 | ||
50a0b3b7 GL |
505 | static struct txq_entry_t *wilc_wlan_txq_get_next(struct wilc *wilc, |
506 | struct txq_entry_t *tqe) | |
c5c77ba1 | 507 | { |
c5c77ba1 | 508 | unsigned long flags; |
8739eeba | 509 | |
50a0b3b7 | 510 | spin_lock_irqsave(&wilc->txq_spinlock, flags); |
c5c77ba1 | 511 | |
c5c77ba1 | 512 | tqe = tqe->next; |
50a0b3b7 | 513 | spin_unlock_irqrestore(&wilc->txq_spinlock, flags); |
c5c77ba1 | 514 | |
c5c77ba1 JK |
515 | return tqe; |
516 | } | |
517 | ||
d06f362c | 518 | static int wilc_wlan_rxq_add(struct wilc *wilc, struct rxq_entry_t *rqe) |
c5c77ba1 | 519 | { |
7ee8291a | 520 | wilc_wlan_dev_t *p = &g_wlan; |
c5c77ba1 JK |
521 | |
522 | if (p->quit) | |
523 | return 0; | |
524 | ||
d06f362c | 525 | mutex_lock(&wilc->rxq_cs); |
a4b17197 | 526 | if (!p->rxq_head) { |
c5c77ba1 JK |
527 | PRINT_D(RX_DBG, "Add to Queue head\n"); |
528 | rqe->next = NULL; | |
529 | p->rxq_head = rqe; | |
530 | p->rxq_tail = rqe; | |
531 | } else { | |
532 | PRINT_D(RX_DBG, "Add to Queue tail\n"); | |
533 | p->rxq_tail->next = rqe; | |
534 | rqe->next = NULL; | |
535 | p->rxq_tail = rqe; | |
536 | } | |
537 | p->rxq_entries += 1; | |
538 | PRINT_D(RX_DBG, "Number of queue entries: %d\n", p->rxq_entries); | |
d06f362c | 539 | mutex_unlock(&wilc->rxq_cs); |
c5c77ba1 JK |
540 | return p->rxq_entries; |
541 | } | |
542 | ||
db387635 | 543 | static struct rxq_entry_t *wilc_wlan_rxq_remove(struct wilc *wilc) |
c5c77ba1 | 544 | { |
7ee8291a | 545 | wilc_wlan_dev_t *p = &g_wlan; |
c5c77ba1 JK |
546 | |
547 | PRINT_D(RX_DBG, "Getting rxQ element\n"); | |
548 | if (p->rxq_head) { | |
549 | struct rxq_entry_t *rqe; | |
550 | ||
db387635 | 551 | mutex_lock(&wilc->rxq_cs); |
c5c77ba1 JK |
552 | rqe = p->rxq_head; |
553 | p->rxq_head = p->rxq_head->next; | |
554 | p->rxq_entries -= 1; | |
555 | PRINT_D(RX_DBG, "RXQ entries decreased\n"); | |
db387635 | 556 | mutex_unlock(&wilc->rxq_cs); |
c5c77ba1 JK |
557 | return rqe; |
558 | } | |
559 | PRINT_D(RX_DBG, "Nothing to get from Q\n"); | |
560 | return NULL; | |
561 | } | |
562 | ||
c5c77ba1 JK |
563 | #ifdef WILC_OPTIMIZE_SLEEP_INT |
564 | ||
00215dde | 565 | static inline void chip_allow_sleep(struct wilc *wilc) |
c5c77ba1 | 566 | { |
fbc2fe16 | 567 | u32 reg = 0; |
c5c77ba1 | 568 | |
49dcd0dd | 569 | g_wlan.hif_func.hif_read_reg(wilc, 0xf0, ®); |
c5c77ba1 | 570 | |
49dcd0dd | 571 | g_wlan.hif_func.hif_write_reg(wilc, 0xf0, reg & ~BIT(0)); |
c5c77ba1 JK |
572 | } |
573 | ||
00215dde | 574 | static inline void chip_wakeup(struct wilc *wilc) |
c5c77ba1 | 575 | { |
fbc2fe16 CL |
576 | u32 reg, clk_status_reg, trials = 0; |
577 | u32 sleep_time; | |
c5c77ba1 | 578 | |
4bd7baf0 | 579 | if ((g_wlan.io_type & 0x1) == HIF_SPI) { |
c5c77ba1 | 580 | do { |
49dcd0dd GL |
581 | g_wlan.hif_func.hif_read_reg(wilc, 1, ®); |
582 | g_wlan.hif_func.hif_write_reg(wilc, 1, reg | BIT(1)); | |
583 | g_wlan.hif_func.hif_write_reg(wilc, 1, reg & ~BIT(1)); | |
c5c77ba1 JK |
584 | |
585 | do { | |
80e29c7a | 586 | usleep_range(2 * 1000, 2 * 1000); |
00215dde | 587 | if ((wilc_get_chipid(wilc, true) == 0)) |
c5c77ba1 | 588 | wilc_debug(N_ERR, "Couldn't read chip id. Wake up failed\n"); |
39823a50 | 589 | |
00215dde | 590 | } while ((wilc_get_chipid(wilc, true) == 0) && ((++trials % 3) == 0)); |
c5c77ba1 | 591 | |
00215dde | 592 | } while (wilc_get_chipid(wilc, true) == 0); |
4bd7baf0 | 593 | } else if ((g_wlan.io_type & 0x1) == HIF_SDIO) { |
49dcd0dd | 594 | g_wlan.hif_func.hif_read_reg(wilc, 0xf0, ®); |
c5c77ba1 | 595 | do { |
49dcd0dd GL |
596 | g_wlan.hif_func.hif_write_reg(wilc, 0xf0, |
597 | reg | BIT(0)); | |
598 | g_wlan.hif_func.hif_read_reg(wilc, 0xf1, | |
599 | &clk_status_reg); | |
c5c77ba1 | 600 | |
c5c77ba1 | 601 | while (((clk_status_reg & 0x1) == 0) && (((++trials) % 3) == 0)) { |
80e29c7a | 602 | usleep_range(2 * 1000, 2 * 1000); |
c5c77ba1 | 603 | |
49dcd0dd GL |
604 | g_wlan.hif_func.hif_read_reg(wilc, 0xf1, |
605 | &clk_status_reg); | |
c5c77ba1 | 606 | |
39823a50 | 607 | if ((clk_status_reg & 0x1) == 0) |
c5c77ba1 | 608 | wilc_debug(N_ERR, "clocks still OFF. Wake up failed\n"); |
c5c77ba1 | 609 | } |
c5c77ba1 | 610 | if ((clk_status_reg & 0x1) == 0) { |
49dcd0dd GL |
611 | g_wlan.hif_func.hif_write_reg(wilc, 0xf0, |
612 | reg & (~BIT(0))); | |
c5c77ba1 JK |
613 | } |
614 | } while ((clk_status_reg & 0x1) == 0); | |
615 | } | |
616 | ||
b7d1e18c | 617 | if (chip_ps_state == CHIP_SLEEPING_MANUAL) { |
49dcd0dd | 618 | g_wlan.hif_func.hif_read_reg(wilc, 0x1C0C, ®); |
ffda203c | 619 | reg &= ~BIT(0); |
49dcd0dd | 620 | g_wlan.hif_func.hif_write_reg(wilc, 0x1C0C, reg); |
c5c77ba1 | 621 | |
00215dde | 622 | if (wilc_get_chipid(wilc, false) >= 0x1002b0) { |
fbc2fe16 | 623 | u32 val32; |
8dfaafd6 | 624 | |
49dcd0dd | 625 | g_wlan.hif_func.hif_read_reg(wilc, 0x1e1c, &val32); |
ffda203c | 626 | val32 |= BIT(6); |
49dcd0dd | 627 | g_wlan.hif_func.hif_write_reg(wilc, 0x1e1c, val32); |
c5c77ba1 | 628 | |
49dcd0dd | 629 | g_wlan.hif_func.hif_read_reg(wilc, 0x1e9c, &val32); |
ffda203c | 630 | val32 |= BIT(6); |
49dcd0dd | 631 | g_wlan.hif_func.hif_write_reg(wilc, 0x1e9c, val32); |
c5c77ba1 JK |
632 | } |
633 | } | |
b7d1e18c | 634 | chip_ps_state = CHIP_WAKEDUP; |
c5c77ba1 JK |
635 | } |
636 | #else | |
00215dde | 637 | static inline void chip_wakeup(struct wilc *wilc) |
c5c77ba1 | 638 | { |
fbc2fe16 | 639 | u32 reg, trials = 0; |
8dfaafd6 | 640 | |
c5c77ba1 | 641 | do { |
4bd7baf0 | 642 | if ((g_wlan.io_type & 0x1) == HIF_SPI) { |
49dcd0dd GL |
643 | g_wlan.hif_func.hif_read_reg(wilc, 1, ®); |
644 | g_wlan.hif_func.hif_write_reg(wilc, 1, reg & ~BIT(1)); | |
645 | g_wlan.hif_func.hif_write_reg(wilc, 1, reg | BIT(1)); | |
646 | g_wlan.hif_func.hif_write_reg(wilc, 1, reg & ~BIT(1)); | |
4bd7baf0 | 647 | } else if ((g_wlan.io_type & 0x1) == HIF_SDIO) { |
49dcd0dd GL |
648 | g_wlan.hif_func.hif_read_reg(wilc, 0xf0, ®); |
649 | g_wlan.hif_func.hif_write_reg(wilc, 0xf0, | |
650 | reg & ~BIT(0)); | |
651 | g_wlan.hif_func.hif_write_reg(wilc, 0xf0, | |
652 | reg | BIT(0)); | |
653 | g_wlan.hif_func.hif_write_reg(wilc, 0xf0, | |
654 | reg & ~BIT(0)); | |
c5c77ba1 JK |
655 | } |
656 | ||
657 | do { | |
c5c77ba1 JK |
658 | mdelay(3); |
659 | ||
00215dde | 660 | if ((wilc_get_chipid(wilc, true) == 0)) |
c5c77ba1 | 661 | wilc_debug(N_ERR, "Couldn't read chip id. Wake up failed\n"); |
39823a50 | 662 | |
00215dde | 663 | } while ((wilc_get_chipid(wilc, true) == 0) && ((++trials % 3) == 0)); |
c5c77ba1 | 664 | |
00215dde | 665 | } while (wilc_get_chipid(wilc, true) == 0); |
c5c77ba1 | 666 | |
b7d1e18c | 667 | if (chip_ps_state == CHIP_SLEEPING_MANUAL) { |
49dcd0dd | 668 | g_wlan.hif_func.hif_read_reg(wilc, 0x1C0C, ®); |
ffda203c | 669 | reg &= ~BIT(0); |
49dcd0dd | 670 | g_wlan.hif_func.hif_write_reg(wilc, 0x1C0C, reg); |
c5c77ba1 | 671 | |
00215dde | 672 | if (wilc_get_chipid(wilc, false) >= 0x1002b0) { |
fbc2fe16 | 673 | u32 val32; |
8dfaafd6 | 674 | |
49dcd0dd | 675 | g_wlan.hif_func.hif_read_reg(wilc, 0x1e1c, &val32); |
ffda203c | 676 | val32 |= BIT(6); |
49dcd0dd | 677 | g_wlan.hif_func.hif_write_reg(wilc, 0x1e1c, val32); |
c5c77ba1 | 678 | |
49dcd0dd | 679 | g_wlan.hif_func.hif_read_reg(wilc, 0x1e9c, &val32); |
ffda203c | 680 | val32 |= BIT(6); |
49dcd0dd | 681 | g_wlan.hif_func.hif_write_reg(wilc, 0x1e9c, val32); |
c5c77ba1 JK |
682 | } |
683 | } | |
b7d1e18c | 684 | chip_ps_state = CHIP_WAKEDUP; |
c5c77ba1 JK |
685 | } |
686 | #endif | |
00215dde | 687 | void wilc_chip_sleep_manually(struct wilc *wilc) |
c5c77ba1 | 688 | { |
b7d1e18c | 689 | if (chip_ps_state != CHIP_WAKEDUP) |
c5c77ba1 | 690 | return; |
00215dde | 691 | acquire_bus(wilc, ACQUIRE_ONLY); |
c5c77ba1 JK |
692 | |
693 | #ifdef WILC_OPTIMIZE_SLEEP_INT | |
00215dde | 694 | chip_allow_sleep(wilc); |
c5c77ba1 | 695 | #endif |
49dcd0dd | 696 | g_wlan.hif_func.hif_write_reg(wilc, 0x10a8, 1); |
c5c77ba1 | 697 | |
b7d1e18c | 698 | chip_ps_state = CHIP_SLEEPING_MANUAL; |
00215dde | 699 | release_bus(wilc, RELEASE_ONLY); |
c5c77ba1 JK |
700 | } |
701 | ||
b1d19298 | 702 | int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count) |
c5c77ba1 JK |
703 | { |
704 | wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan; | |
705 | int i, entries = 0; | |
fbc2fe16 CL |
706 | u32 sum; |
707 | u32 reg; | |
51e825f7 | 708 | u8 *txb = p->tx_buffer; |
fbc2fe16 | 709 | u32 offset = 0; |
c5c77ba1 JK |
710 | int vmm_sz = 0; |
711 | struct txq_entry_t *tqe; | |
712 | int ret = 0; | |
713 | int counter; | |
714 | int timeout; | |
fbc2fe16 | 715 | u32 vmm_table[WILC_VMM_TBL_SIZE]; |
a1332cad GL |
716 | perInterface_wlan_t *nic; |
717 | struct wilc *wilc; | |
718 | ||
719 | nic = netdev_priv(dev); | |
720 | wilc = nic->wilc; | |
8dfaafd6 | 721 | |
c5c77ba1 JK |
722 | p->txq_exit = 0; |
723 | do { | |
724 | if (p->quit) | |
725 | break; | |
726 | ||
562ed3f1 | 727 | wilc_lock_timeout(wilc, &wilc->txq_add_to_head_cs, |
b002e20d | 728 | CFG_PKTS_TIMEOUT); |
c5c77ba1 | 729 | #ifdef TCP_ACK_FILTER |
c029e99c | 730 | wilc_wlan_txq_filter_dup_tcp_ack(dev); |
c5c77ba1 | 731 | #endif |
c5c77ba1 | 732 | PRINT_D(TX_DBG, "Getting the head of the TxQ\n"); |
7af0522c | 733 | tqe = wilc_wlan_txq_get_first(wilc); |
c5c77ba1 JK |
734 | i = 0; |
735 | sum = 0; | |
736 | do { | |
a4b17197 | 737 | if (tqe && (i < (WILC_VMM_TBL_SIZE - 1))) { |
39823a50 | 738 | if (tqe->type == WILC_CFG_PKT) |
c5c77ba1 | 739 | vmm_sz = ETH_CONFIG_PKT_HDR_OFFSET; |
39823a50 AS |
740 | |
741 | else if (tqe->type == WILC_NET_PKT) | |
c5c77ba1 | 742 | vmm_sz = ETH_ETHERNET_HDR_OFFSET; |
39823a50 AS |
743 | |
744 | else | |
c5c77ba1 | 745 | vmm_sz = HOST_HDR_OFFSET; |
39823a50 | 746 | |
c5c77ba1 JK |
747 | vmm_sz += tqe->buffer_size; |
748 | PRINT_D(TX_DBG, "VMM Size before alignment = %d\n", vmm_sz); | |
ac087c82 | 749 | if (vmm_sz & 0x3) |
c5c77ba1 | 750 | vmm_sz = (vmm_sz + 4) & ~0x3; |
ac087c82 | 751 | |
39823a50 | 752 | if ((sum + vmm_sz) > LINUX_TX_SIZE) |
c5c77ba1 | 753 | break; |
39823a50 | 754 | |
c5c77ba1 | 755 | PRINT_D(TX_DBG, "VMM Size AFTER alignment = %d\n", vmm_sz); |
ac087c82 | 756 | vmm_table[i] = vmm_sz / 4; |
ab12d8c7 LK |
757 | PRINT_D(TX_DBG, "VMMTable entry size = %d\n", |
758 | vmm_table[i]); | |
c5c77ba1 JK |
759 | |
760 | if (tqe->type == WILC_CFG_PKT) { | |
ffda203c | 761 | vmm_table[i] |= BIT(10); |
c5c77ba1 JK |
762 | PRINT_D(TX_DBG, "VMMTable entry changed for CFG packet = %d\n", vmm_table[i]); |
763 | } | |
764 | #ifdef BIG_ENDIAN | |
765 | vmm_table[i] = BYTE_SWAP(vmm_table[i]); | |
766 | #endif | |
c5c77ba1 | 767 | |
c5c77ba1 JK |
768 | i++; |
769 | sum += vmm_sz; | |
770 | PRINT_D(TX_DBG, "sum = %d\n", sum); | |
50a0b3b7 | 771 | tqe = wilc_wlan_txq_get_next(wilc, tqe); |
c5c77ba1 JK |
772 | } else { |
773 | break; | |
774 | } | |
775 | } while (1); | |
776 | ||
ac087c82 | 777 | if (i == 0) { |
c5c77ba1 JK |
778 | PRINT_D(TX_DBG, "Nothing in TX-Q\n"); |
779 | break; | |
780 | } else { | |
781 | PRINT_D(TX_DBG, "Mark the last entry in VMM table - number of previous entries = %d\n", i); | |
ac087c82 | 782 | vmm_table[i] = 0x0; |
c5c77ba1 | 783 | } |
562ed3f1 | 784 | acquire_bus(wilc, ACQUIRE_AND_WAKEUP); |
c5c77ba1 JK |
785 | counter = 0; |
786 | do { | |
49dcd0dd GL |
787 | ret = p->hif_func.hif_read_reg(wilc, WILC_HOST_TX_CTRL, |
788 | ®); | |
c5c77ba1 JK |
789 | if (!ret) { |
790 | wilc_debug(N_ERR, "[wilc txq]: fail can't read reg vmm_tbl_entry..\n"); | |
791 | break; | |
792 | } | |
793 | ||
794 | if ((reg & 0x1) == 0) { | |
c5c77ba1 JK |
795 | PRINT_D(TX_DBG, "Writing VMM table ... with Size = %d\n", ((i + 1) * 4)); |
796 | break; | |
797 | } else { | |
798 | counter++; | |
799 | if (counter > 200) { | |
800 | counter = 0; | |
801 | PRINT_D(TX_DBG, "Looping in tx ctrl , forcce quit\n"); | |
49dcd0dd | 802 | ret = p->hif_func.hif_write_reg(wilc, WILC_HOST_TX_CTRL, 0); |
c5c77ba1 JK |
803 | break; |
804 | } | |
17aacd43 | 805 | PRINT_WRN(GENERIC_DBG, "[wilc txq]: warn, vmm table not clear yet, wait...\n"); |
562ed3f1 | 806 | release_bus(wilc, RELEASE_ALLOW_SLEEP); |
2b922cbe | 807 | usleep_range(3000, 3000); |
562ed3f1 | 808 | acquire_bus(wilc, ACQUIRE_AND_WAKEUP); |
c5c77ba1 JK |
809 | } |
810 | } while (!p->quit); | |
811 | ||
39823a50 | 812 | if (!ret) |
c5c77ba1 | 813 | goto _end_; |
c5c77ba1 JK |
814 | |
815 | timeout = 200; | |
816 | do { | |
49dcd0dd | 817 | ret = p->hif_func.hif_block_tx(wilc, WILC_VMM_TBL_RX_SHADOW_BASE, (u8 *)vmm_table, ((i + 1) * 4)); |
c5c77ba1 JK |
818 | if (!ret) { |
819 | wilc_debug(N_ERR, "ERR block TX of VMM table.\n"); | |
820 | break; | |
821 | } | |
822 | ||
49dcd0dd GL |
823 | ret = p->hif_func.hif_write_reg(wilc, WILC_HOST_VMM_CTL, |
824 | 0x2); | |
c5c77ba1 JK |
825 | if (!ret) { |
826 | wilc_debug(N_ERR, "[wilc txq]: fail can't write reg host_vmm_ctl..\n"); | |
827 | break; | |
828 | } | |
829 | ||
c5c77ba1 | 830 | do { |
49dcd0dd | 831 | ret = p->hif_func.hif_read_reg(wilc, WILC_HOST_VMM_CTL, ®); |
c5c77ba1 JK |
832 | if (!ret) { |
833 | wilc_debug(N_ERR, "[wilc txq]: fail can't read reg host_vmm_ctl..\n"); | |
834 | break; | |
835 | } | |
836 | if ((reg >> 2) & 0x1) { | |
c5c77ba1 | 837 | entries = ((reg >> 3) & 0x3f); |
c5c77ba1 JK |
838 | break; |
839 | } else { | |
562ed3f1 | 840 | release_bus(wilc, RELEASE_ALLOW_SLEEP); |
2b922cbe | 841 | usleep_range(3000, 3000); |
562ed3f1 | 842 | acquire_bus(wilc, ACQUIRE_AND_WAKEUP); |
c5c77ba1 JK |
843 | PRINT_WRN(GENERIC_DBG, "Can't get VMM entery - reg = %2x\n", reg); |
844 | } | |
845 | } while (--timeout); | |
846 | if (timeout <= 0) { | |
49dcd0dd | 847 | ret = p->hif_func.hif_write_reg(wilc, WILC_HOST_VMM_CTL, 0x0); |
c5c77ba1 JK |
848 | break; |
849 | } | |
850 | ||
39823a50 | 851 | if (!ret) |
c5c77ba1 | 852 | break; |
c5c77ba1 JK |
853 | |
854 | if (entries == 0) { | |
17aacd43 | 855 | PRINT_WRN(GENERIC_DBG, "[wilc txq]: no more buffer in the chip (reg: %08x), retry later [[ %d, %x ]]\n", reg, i, vmm_table[i - 1]); |
c5c77ba1 | 856 | |
49dcd0dd | 857 | ret = p->hif_func.hif_read_reg(wilc, WILC_HOST_TX_CTRL, ®); |
c5c77ba1 JK |
858 | if (!ret) { |
859 | wilc_debug(N_ERR, "[wilc txq]: fail can't read reg WILC_HOST_TX_CTRL..\n"); | |
860 | break; | |
861 | } | |
ffda203c | 862 | reg &= ~BIT(0); |
49dcd0dd | 863 | ret = p->hif_func.hif_write_reg(wilc, WILC_HOST_TX_CTRL, reg); |
c5c77ba1 JK |
864 | if (!ret) { |
865 | wilc_debug(N_ERR, "[wilc txq]: fail can't write reg WILC_HOST_TX_CTRL..\n"); | |
866 | break; | |
867 | } | |
868 | break; | |
869 | } else { | |
870 | break; | |
871 | } | |
872 | } while (1); | |
873 | ||
39823a50 | 874 | if (!ret) |
c5c77ba1 | 875 | goto _end_; |
39823a50 | 876 | |
c5c77ba1 JK |
877 | if (entries == 0) { |
878 | ret = WILC_TX_ERR_NO_BUF; | |
879 | goto _end_; | |
880 | } | |
881 | ||
562ed3f1 | 882 | release_bus(wilc, RELEASE_ALLOW_SLEEP); |
c5c77ba1 | 883 | |
c5c77ba1 JK |
884 | offset = 0; |
885 | i = 0; | |
886 | do { | |
718fc2c9 | 887 | tqe = wilc_wlan_txq_remove_from_head(dev); |
a4b17197 | 888 | if (tqe && (vmm_table[i] != 0)) { |
fbc2fe16 | 889 | u32 header, buffer_offset; |
c5c77ba1 JK |
890 | |
891 | #ifdef BIG_ENDIAN | |
892 | vmm_table[i] = BYTE_SWAP(vmm_table[i]); | |
893 | #endif | |
ac087c82 | 894 | vmm_sz = (vmm_table[i] & 0x3ff); |
c5c77ba1 | 895 | vmm_sz *= 4; |
ab12d8c7 LK |
896 | header = (tqe->type << 31) | |
897 | (tqe->buffer_size << 15) | | |
898 | vmm_sz; | |
78174ada | 899 | if (tqe->type == WILC_MGMT_PKT) |
ffda203c | 900 | header |= BIT(30); |
78174ada | 901 | else |
ffda203c | 902 | header &= ~BIT(30); |
c5c77ba1 JK |
903 | |
904 | #ifdef BIG_ENDIAN | |
905 | header = BYTE_SWAP(header); | |
906 | #endif | |
907 | memcpy(&txb[offset], &header, 4); | |
908 | if (tqe->type == WILC_CFG_PKT) { | |
909 | buffer_offset = ETH_CONFIG_PKT_HDR_OFFSET; | |
590c0a39 | 910 | } else if (tqe->type == WILC_NET_PKT) { |
2f7c31fd | 911 | char *bssid = ((struct tx_complete_data *)(tqe->priv))->pBssid; |
8dfaafd6 | 912 | |
c5c77ba1 | 913 | buffer_offset = ETH_ETHERNET_HDR_OFFSET; |
2f7c31fd | 914 | memcpy(&txb[offset + 4], bssid, 6); |
590c0a39 | 915 | } else { |
c5c77ba1 JK |
916 | buffer_offset = HOST_HDR_OFFSET; |
917 | } | |
918 | ||
ab12d8c7 LK |
919 | memcpy(&txb[offset + buffer_offset], |
920 | tqe->buffer, tqe->buffer_size); | |
c5c77ba1 JK |
921 | offset += vmm_sz; |
922 | i++; | |
ac087c82 | 923 | tqe->status = 1; |
c5c77ba1 | 924 | if (tqe->tx_complete_func) |
ab12d8c7 LK |
925 | tqe->tx_complete_func(tqe->priv, |
926 | tqe->status); | |
c5c77ba1 | 927 | #ifdef TCP_ACK_FILTER |
8e55639d LK |
928 | if (tqe->index != NOT_TCP_ACK) |
929 | pending_acks_info[tqe->index].txqe = NULL; | |
c5c77ba1 | 930 | #endif |
a18dd630 | 931 | kfree(tqe); |
c5c77ba1 JK |
932 | } else { |
933 | break; | |
934 | } | |
935 | } while (--entries); | |
936 | ||
562ed3f1 | 937 | acquire_bus(wilc, ACQUIRE_AND_WAKEUP); |
c5c77ba1 | 938 | |
49dcd0dd | 939 | ret = p->hif_func.hif_clear_int_ext(wilc, ENABLE_TX_VMM); |
c5c77ba1 JK |
940 | if (!ret) { |
941 | wilc_debug(N_ERR, "[wilc txq]: fail can't start tx VMM ...\n"); | |
942 | goto _end_; | |
943 | } | |
944 | ||
49dcd0dd | 945 | ret = p->hif_func.hif_block_tx_ext(wilc, 0, txb, offset); |
c5c77ba1 JK |
946 | if (!ret) { |
947 | wilc_debug(N_ERR, "[wilc txq]: fail can't block tx ext...\n"); | |
948 | goto _end_; | |
949 | } | |
950 | ||
951 | _end_: | |
952 | ||
562ed3f1 | 953 | release_bus(wilc, RELEASE_ALLOW_SLEEP); |
c5c77ba1 JK |
954 | if (ret != 1) |
955 | break; | |
956 | } while (0); | |
a1332cad | 957 | up(&wilc->txq_add_to_head_cs); |
c5c77ba1 JK |
958 | |
959 | p->txq_exit = 1; | |
960 | PRINT_D(TX_DBG, "THREAD: Exiting txq\n"); | |
b1d19298 | 961 | *txq_count = p->txq_entries; |
c5c77ba1 JK |
962 | return ret; |
963 | } | |
964 | ||
39ce4d3d | 965 | static void wilc_wlan_handle_rxq(struct wilc *wilc) |
c5c77ba1 | 966 | { |
7ee8291a | 967 | wilc_wlan_dev_t *p = &g_wlan; |
c5c77ba1 | 968 | int offset = 0, size, has_packet = 0; |
51e825f7 | 969 | u8 *buffer; |
c5c77ba1 JK |
970 | struct rxq_entry_t *rqe; |
971 | ||
972 | p->rxq_exit = 0; | |
973 | ||
c5c77ba1 JK |
974 | do { |
975 | if (p->quit) { | |
17aacd43 | 976 | PRINT_D(RX_DBG, "exit 1st do-while due to Clean_UP function\n"); |
39ce4d3d | 977 | up(&wilc->cfg_event); |
c5c77ba1 JK |
978 | break; |
979 | } | |
db387635 | 980 | rqe = wilc_wlan_rxq_remove(wilc); |
a4b17197 | 981 | if (!rqe) { |
c5c77ba1 JK |
982 | PRINT_D(RX_DBG, "nothing in the queue - exit 1st do-while\n"); |
983 | break; | |
984 | } | |
985 | buffer = rqe->buffer; | |
986 | size = rqe->buffer_size; | |
ab12d8c7 LK |
987 | PRINT_D(RX_DBG, "rxQ entery Size = %d - Address = %p\n", |
988 | size, buffer); | |
c5c77ba1 JK |
989 | offset = 0; |
990 | ||
c5c77ba1 | 991 | do { |
fbc2fe16 CL |
992 | u32 header; |
993 | u32 pkt_len, pkt_offset, tp_len; | |
c5c77ba1 | 994 | int is_cfg_packet; |
8dfaafd6 | 995 | |
c5c77ba1 JK |
996 | PRINT_D(RX_DBG, "In the 2nd do-while\n"); |
997 | memcpy(&header, &buffer[offset], 4); | |
998 | #ifdef BIG_ENDIAN | |
999 | header = BYTE_SWAP(header); | |
1000 | #endif | |
ab12d8c7 LK |
1001 | PRINT_D(RX_DBG, "Header = %04x - Offset = %d\n", |
1002 | header, offset); | |
c5c77ba1 | 1003 | |
c5c77ba1 JK |
1004 | is_cfg_packet = (header >> 31) & 0x1; |
1005 | pkt_offset = (header >> 22) & 0x1ff; | |
1006 | tp_len = (header >> 11) & 0x7ff; | |
1007 | pkt_len = header & 0x7ff; | |
1008 | ||
1009 | if (pkt_len == 0 || tp_len == 0) { | |
1010 | wilc_debug(N_RXQ, "[wilc rxq]: data corrupt, packet len or tp_len is 0 [%d][%d]\n", pkt_len, tp_len); | |
1011 | break; | |
1012 | } | |
1013 | ||
c5c77ba1 JK |
1014 | #define IS_MANAGMEMENT 0x100 |
1015 | #define IS_MANAGMEMENT_CALLBACK 0x080 | |
1016 | #define IS_MGMT_STATUS_SUCCES 0x040 | |
1017 | ||
c5c77ba1 | 1018 | if (pkt_offset & IS_MANAGMEMENT) { |
ab12d8c7 LK |
1019 | pkt_offset &= ~(IS_MANAGMEMENT | |
1020 | IS_MANAGMEMENT_CALLBACK | | |
1021 | IS_MGMT_STATUS_SUCCES); | |
c5c77ba1 | 1022 | |
11f4b2ee | 1023 | WILC_WFI_mgmt_rx(wilc, &buffer[offset + HOST_HDR_OFFSET], pkt_len); |
590c0a39 | 1024 | } else { |
c5c77ba1 | 1025 | if (!is_cfg_packet) { |
63611670 | 1026 | if (pkt_len > 0) { |
562ed3f1 | 1027 | wilc_frmw_to_linux(wilc, |
cb1991ac | 1028 | &buffer[offset], |
63611670 GL |
1029 | pkt_len, |
1030 | pkt_offset); | |
1031 | has_packet = 1; | |
c5c77ba1 JK |
1032 | } |
1033 | } else { | |
bcddd48b | 1034 | struct wilc_cfg_rsp rsp; |
c5c77ba1 | 1035 | |
30f535a6 | 1036 | wilc_wlan_cfg_indicate_rx(&buffer[pkt_offset + offset], pkt_len, &rsp); |
c5c77ba1 | 1037 | if (rsp.type == WILC_CFG_RSP) { |
c5c77ba1 | 1038 | PRINT_D(RX_DBG, "p->cfg_seq_no = %d - rsp.seq_no = %d\n", p->cfg_seq_no, rsp.seq_no); |
39823a50 | 1039 | if (p->cfg_seq_no == rsp.seq_no) |
39ce4d3d | 1040 | up(&wilc->cfg_event); |
c5c77ba1 | 1041 | } else if (rsp.type == WILC_CFG_RSP_STATUS) { |
562ed3f1 | 1042 | wilc_mac_indicate(wilc, WILC_MAC_INDICATE_STATUS); |
c5c77ba1 JK |
1043 | |
1044 | } else if (rsp.type == WILC_CFG_RSP_SCAN) { | |
562ed3f1 | 1045 | wilc_mac_indicate(wilc, WILC_MAC_INDICATE_SCAN); |
c5c77ba1 JK |
1046 | } |
1047 | } | |
1048 | } | |
1049 | offset += tp_len; | |
1050 | if (offset >= size) | |
1051 | break; | |
1052 | } while (1); | |
c5c77ba1 | 1053 | #ifndef MEMORY_STATIC |
a18dd630 | 1054 | kfree(buffer); |
c5c77ba1 | 1055 | #endif |
a18dd630 | 1056 | kfree(rqe); |
c5c77ba1 | 1057 | |
39823a50 | 1058 | if (has_packet) |
562ed3f1 | 1059 | wilc_rx_complete(wilc); |
39823a50 | 1060 | |
c5c77ba1 JK |
1061 | } while (1); |
1062 | ||
1063 | p->rxq_exit = 1; | |
17aacd43 | 1064 | PRINT_D(RX_DBG, "THREAD: Exiting RX thread\n"); |
c5c77ba1 JK |
1065 | } |
1066 | ||
00215dde | 1067 | static void wilc_unknown_isr_ext(struct wilc *wilc) |
c5c77ba1 | 1068 | { |
49dcd0dd | 1069 | g_wlan.hif_func.hif_clear_int_ext(wilc, 0); |
c5c77ba1 | 1070 | } |
2d6973e6 | 1071 | |
00215dde | 1072 | static void wilc_pllupdate_isr_ext(struct wilc *wilc, u32 int_stats) |
c5c77ba1 | 1073 | { |
c5c77ba1 JK |
1074 | int trials = 10; |
1075 | ||
49dcd0dd | 1076 | g_wlan.hif_func.hif_clear_int_ext(wilc, PLL_INT_CLR); |
c5c77ba1 | 1077 | |
e28e84d2 AB |
1078 | if (g_wlan.io_type == HIF_SDIO) |
1079 | mdelay(WILC_PLL_TO_SDIO); | |
1080 | else | |
1081 | mdelay(WILC_PLL_TO_SPI); | |
c5c77ba1 | 1082 | |
00215dde | 1083 | while (!(ISWILC1000(wilc_get_chipid(wilc, true)) && --trials)) { |
c5c77ba1 | 1084 | PRINT_D(TX_DBG, "PLL update retrying\n"); |
c2e4c0f1 | 1085 | mdelay(1); |
c5c77ba1 JK |
1086 | } |
1087 | } | |
1088 | ||
00215dde | 1089 | static void wilc_sleeptimer_isr_ext(struct wilc *wilc, u32 int_stats1) |
c5c77ba1 | 1090 | { |
49dcd0dd | 1091 | g_wlan.hif_func.hif_clear_int_ext(wilc, SLEEP_INT_CLR); |
c5c77ba1 | 1092 | #ifndef WILC_OPTIMIZE_SLEEP_INT |
b7d1e18c | 1093 | chip_ps_state = CHIP_SLEEPING_AUTO; |
c5c77ba1 JK |
1094 | #endif |
1095 | } | |
1096 | ||
3bcd45b6 | 1097 | static void wilc_wlan_handle_isr_ext(struct wilc *wilc, u32 int_status) |
c5c77ba1 | 1098 | { |
7ee8291a | 1099 | wilc_wlan_dev_t *p = &g_wlan; |
c5c77ba1 | 1100 | #ifdef MEMORY_STATIC |
fbc2fe16 | 1101 | u32 offset = p->rx_buffer_offset; |
c5c77ba1 | 1102 | #endif |
51e825f7 | 1103 | u8 *buffer = NULL; |
fbc2fe16 CL |
1104 | u32 size; |
1105 | u32 retries = 0; | |
c5c77ba1 JK |
1106 | int ret = 0; |
1107 | struct rxq_entry_t *rqe; | |
1108 | ||
c5c77ba1 JK |
1109 | size = ((int_status & 0x7fff) << 2); |
1110 | ||
1111 | while (!size && retries < 10) { | |
fbc2fe16 | 1112 | u32 time = 0; |
ac087c82 | 1113 | |
c5c77ba1 | 1114 | wilc_debug(N_ERR, "RX Size equal zero ... Trying to read it again for %d time\n", time++); |
49dcd0dd | 1115 | p->hif_func.hif_read_size(wilc, &size); |
c5c77ba1 JK |
1116 | size = ((size & 0x7fff) << 2); |
1117 | retries++; | |
c5c77ba1 JK |
1118 | } |
1119 | ||
1120 | if (size > 0) { | |
1121 | #ifdef MEMORY_STATIC | |
03eb7266 | 1122 | if (LINUX_RX_SIZE - offset < size) |
c5c77ba1 JK |
1123 | offset = 0; |
1124 | ||
7eb17b8d | 1125 | if (p->rx_buffer) { |
c5c77ba1 | 1126 | buffer = &p->rx_buffer[offset]; |
7eb17b8d | 1127 | } else { |
c5c77ba1 JK |
1128 | wilc_debug(N_ERR, "[wilc isr]: fail Rx Buffer is NULL...drop the packets (%d)\n", size); |
1129 | goto _end_; | |
1130 | } | |
1131 | ||
1132 | #else | |
f019b9d9 | 1133 | buffer = kmalloc(size, GFP_KERNEL); |
a4b17197 | 1134 | if (!buffer) { |
80e29c7a | 1135 | usleep_range(100 * 1000, 100 * 1000); |
c5c77ba1 JK |
1136 | goto _end_; |
1137 | } | |
1138 | #endif | |
49dcd0dd GL |
1139 | p->hif_func.hif_clear_int_ext(wilc, |
1140 | DATA_INT_CLR | ENABLE_RX_VMM); | |
1141 | ret = p->hif_func.hif_block_rx_ext(wilc, 0, buffer, size); | |
c5c77ba1 JK |
1142 | |
1143 | if (!ret) { | |
1144 | wilc_debug(N_ERR, "[wilc isr]: fail block rx...\n"); | |
1145 | goto _end_; | |
1146 | } | |
1147 | _end_: | |
c5c77ba1 JK |
1148 | if (ret) { |
1149 | #ifdef MEMORY_STATIC | |
1150 | offset += size; | |
1151 | p->rx_buffer_offset = offset; | |
1152 | #endif | |
13b01e40 | 1153 | rqe = kmalloc(sizeof(*rqe), GFP_KERNEL); |
a4b17197 | 1154 | if (rqe) { |
c5c77ba1 JK |
1155 | rqe->buffer = buffer; |
1156 | rqe->buffer_size = size; | |
1157 | PRINT_D(RX_DBG, "rxq entery Size= %d - Address = %p\n", rqe->buffer_size, rqe->buffer); | |
d06f362c | 1158 | wilc_wlan_rxq_add(wilc, rqe); |
c5c77ba1 JK |
1159 | } |
1160 | } else { | |
1161 | #ifndef MEMORY_STATIC | |
a18dd630 | 1162 | kfree(buffer); |
c5c77ba1 JK |
1163 | #endif |
1164 | } | |
1165 | } | |
39ce4d3d | 1166 | wilc_wlan_handle_rxq(wilc); |
c5c77ba1 JK |
1167 | } |
1168 | ||
562ed3f1 | 1169 | void wilc_handle_isr(struct wilc *wilc) |
c5c77ba1 | 1170 | { |
fbc2fe16 | 1171 | u32 int_status; |
c5c77ba1 | 1172 | |
562ed3f1 | 1173 | acquire_bus(wilc, ACQUIRE_AND_WAKEUP); |
49dcd0dd | 1174 | g_wlan.hif_func.hif_read_int(wilc, &int_status); |
c5c77ba1 | 1175 | |
39823a50 | 1176 | if (int_status & PLL_INT_EXT) |
00215dde | 1177 | wilc_pllupdate_isr_ext(wilc, int_status); |
39823a50 | 1178 | |
c5c77ba1 | 1179 | if (int_status & DATA_INT_EXT) { |
3bcd45b6 | 1180 | wilc_wlan_handle_isr_ext(wilc, int_status); |
c5c77ba1 | 1181 | #ifndef WILC_OPTIMIZE_SLEEP_INT |
b7d1e18c | 1182 | chip_ps_state = CHIP_WAKEDUP; |
c5c77ba1 JK |
1183 | #endif |
1184 | } | |
39823a50 | 1185 | if (int_status & SLEEP_INT_EXT) |
00215dde | 1186 | wilc_sleeptimer_isr_ext(wilc, int_status); |
c5c77ba1 JK |
1187 | |
1188 | if (!(int_status & (ALL_INT_EXT))) { | |
00215dde | 1189 | wilc_unknown_isr_ext(wilc); |
c5c77ba1 | 1190 | } |
562ed3f1 | 1191 | release_bus(wilc, RELEASE_ALLOW_SLEEP); |
c5c77ba1 | 1192 | } |
750ffe9b | 1193 | EXPORT_SYMBOL_GPL(wilc_handle_isr); |
c5c77ba1 | 1194 | |
562ed3f1 | 1195 | int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer, u32 buffer_size) |
c5c77ba1 | 1196 | { |
7ee8291a | 1197 | wilc_wlan_dev_t *p = &g_wlan; |
fbc2fe16 CL |
1198 | u32 offset; |
1199 | u32 addr, size, size2, blksz; | |
51e825f7 | 1200 | u8 *dma_buffer; |
c5c77ba1 JK |
1201 | int ret = 0; |
1202 | ||
ffda203c | 1203 | blksz = BIT(12); |
c5c77ba1 | 1204 | |
f019b9d9 | 1205 | dma_buffer = kmalloc(blksz, GFP_KERNEL); |
a4b17197 | 1206 | if (!dma_buffer) { |
92e7d188 | 1207 | ret = -EIO; |
c5c77ba1 JK |
1208 | PRINT_ER("Can't allocate buffer for firmware download IO error\n "); |
1209 | goto _fail_1; | |
1210 | } | |
1211 | ||
1212 | PRINT_D(INIT_DBG, "Downloading firmware size = %d ...\n", buffer_size); | |
ac087c82 | 1213 | |
c5c77ba1 JK |
1214 | offset = 0; |
1215 | do { | |
1216 | memcpy(&addr, &buffer[offset], 4); | |
1217 | memcpy(&size, &buffer[offset + 4], 4); | |
1218 | #ifdef BIG_ENDIAN | |
1219 | addr = BYTE_SWAP(addr); | |
1220 | size = BYTE_SWAP(size); | |
1221 | #endif | |
562ed3f1 | 1222 | acquire_bus(wilc, ACQUIRE_ONLY); |
c5c77ba1 JK |
1223 | offset += 8; |
1224 | while (((int)size) && (offset < buffer_size)) { | |
78174ada | 1225 | if (size <= blksz) |
c5c77ba1 | 1226 | size2 = size; |
78174ada | 1227 | else |
c5c77ba1 | 1228 | size2 = blksz; |
ac087c82 | 1229 | |
c5c77ba1 | 1230 | memcpy(dma_buffer, &buffer[offset], size2); |
49dcd0dd GL |
1231 | ret = p->hif_func.hif_block_tx(wilc, addr, dma_buffer, |
1232 | size2); | |
c5c77ba1 JK |
1233 | if (!ret) |
1234 | break; | |
1235 | ||
1236 | addr += size2; | |
1237 | offset += size2; | |
1238 | size -= size2; | |
1239 | } | |
562ed3f1 | 1240 | release_bus(wilc, RELEASE_ONLY); |
c5c77ba1 JK |
1241 | |
1242 | if (!ret) { | |
92e7d188 | 1243 | ret = -EIO; |
c5c77ba1 JK |
1244 | PRINT_ER("Can't download firmware IO error\n "); |
1245 | goto _fail_; | |
1246 | } | |
1247 | PRINT_D(INIT_DBG, "Offset = %d\n", offset); | |
1248 | } while (offset < buffer_size); | |
1249 | ||
1250 | _fail_: | |
1251 | ||
a18dd630 | 1252 | kfree(dma_buffer); |
c5c77ba1 JK |
1253 | |
1254 | _fail_1: | |
1255 | ||
1256 | return (ret < 0) ? ret : 0; | |
1257 | } | |
1258 | ||
562ed3f1 | 1259 | int wilc_wlan_start(struct wilc *wilc) |
c5c77ba1 | 1260 | { |
7ee8291a | 1261 | wilc_wlan_dev_t *p = &g_wlan; |
fbc2fe16 | 1262 | u32 reg = 0; |
c5c77ba1 | 1263 | int ret; |
fbc2fe16 | 1264 | u32 chipid; |
c5c77ba1 | 1265 | |
4bd7baf0 | 1266 | if (p->io_type == HIF_SDIO) { |
c5c77ba1 | 1267 | reg = 0; |
ac087c82 | 1268 | reg |= BIT(3); |
4bd7baf0 | 1269 | } else if (p->io_type == HIF_SPI) { |
c5c77ba1 JK |
1270 | reg = 1; |
1271 | } | |
562ed3f1 | 1272 | acquire_bus(wilc, ACQUIRE_ONLY); |
49dcd0dd | 1273 | ret = p->hif_func.hif_write_reg(wilc, WILC_VMM_CORE_CFG, reg); |
c5c77ba1 JK |
1274 | if (!ret) { |
1275 | wilc_debug(N_ERR, "[wilc start]: fail write reg vmm_core_cfg...\n"); | |
562ed3f1 | 1276 | release_bus(wilc, RELEASE_ONLY); |
92e7d188 | 1277 | ret = -EIO; |
c5c77ba1 JK |
1278 | return ret; |
1279 | } | |
1280 | reg = 0; | |
562ed3f1 | 1281 | if (p->io_type == HIF_SDIO && wilc->dev_irq_num) |
c4d139cb | 1282 | reg |= WILC_HAVE_SDIO_IRQ_GPIO; |
c5c77ba1 JK |
1283 | |
1284 | #ifdef WILC_DISABLE_PMU | |
1285 | #else | |
1286 | reg |= WILC_HAVE_USE_PMU; | |
1287 | #endif | |
1288 | ||
1289 | #ifdef WILC_SLEEP_CLK_SRC_XO | |
1290 | reg |= WILC_HAVE_SLEEP_CLK_SRC_XO; | |
1291 | #elif defined WILC_SLEEP_CLK_SRC_RTC | |
1292 | reg |= WILC_HAVE_SLEEP_CLK_SRC_RTC; | |
1293 | #endif | |
1294 | ||
1295 | #ifdef WILC_EXT_PA_INV_TX_RX | |
1296 | reg |= WILC_HAVE_EXT_PA_INV_TX_RX; | |
1297 | #endif | |
1298 | ||
1299 | reg |= WILC_HAVE_LEGACY_RF_SETTINGS; | |
c5c77ba1 JK |
1300 | #ifdef XTAL_24 |
1301 | reg |= WILC_HAVE_XTAL_24; | |
1302 | #endif | |
c5c77ba1 JK |
1303 | #ifdef DISABLE_WILC_UART |
1304 | reg |= WILC_HAVE_DISABLE_WILC_UART; | |
1305 | #endif | |
1306 | ||
49dcd0dd | 1307 | ret = p->hif_func.hif_write_reg(wilc, WILC_GP_REG_1, reg); |
c5c77ba1 JK |
1308 | if (!ret) { |
1309 | wilc_debug(N_ERR, "[wilc start]: fail write WILC_GP_REG_1 ...\n"); | |
562ed3f1 | 1310 | release_bus(wilc, RELEASE_ONLY); |
92e7d188 | 1311 | ret = -EIO; |
c5c77ba1 JK |
1312 | return ret; |
1313 | } | |
c5c77ba1 | 1314 | |
49dcd0dd | 1315 | p->hif_func.hif_sync_ext(wilc, NUM_INT_EXT); |
c5c77ba1 | 1316 | |
49dcd0dd | 1317 | ret = p->hif_func.hif_read_reg(wilc, 0x1000, &chipid); |
c5c77ba1 JK |
1318 | if (!ret) { |
1319 | wilc_debug(N_ERR, "[wilc start]: fail read reg 0x1000 ...\n"); | |
562ed3f1 | 1320 | release_bus(wilc, RELEASE_ONLY); |
92e7d188 | 1321 | ret = -EIO; |
c5c77ba1 JK |
1322 | return ret; |
1323 | } | |
1324 | ||
49dcd0dd | 1325 | p->hif_func.hif_read_reg(wilc, WILC_GLB_RESET_0, ®); |
ffda203c AB |
1326 | if ((reg & BIT(10)) == BIT(10)) { |
1327 | reg &= ~BIT(10); | |
49dcd0dd GL |
1328 | p->hif_func.hif_write_reg(wilc, WILC_GLB_RESET_0, reg); |
1329 | p->hif_func.hif_read_reg(wilc, WILC_GLB_RESET_0, ®); | |
c5c77ba1 JK |
1330 | } |
1331 | ||
ffda203c | 1332 | reg |= BIT(10); |
49dcd0dd GL |
1333 | ret = p->hif_func.hif_write_reg(wilc, WILC_GLB_RESET_0, reg); |
1334 | p->hif_func.hif_read_reg(wilc, WILC_GLB_RESET_0, ®); | |
562ed3f1 | 1335 | release_bus(wilc, RELEASE_ONLY); |
c5c77ba1 JK |
1336 | |
1337 | return (ret < 0) ? ret : 0; | |
1338 | } | |
1339 | ||
562ed3f1 | 1340 | void wilc_wlan_global_reset(struct wilc *wilc) |
c5c77ba1 JK |
1341 | { |
1342 | ||
7ee8291a | 1343 | wilc_wlan_dev_t *p = &g_wlan; |
8dfaafd6 | 1344 | |
562ed3f1 | 1345 | acquire_bus(wilc, ACQUIRE_AND_WAKEUP); |
49dcd0dd | 1346 | p->hif_func.hif_write_reg(wilc, WILC_GLB_RESET_0, 0x0); |
562ed3f1 | 1347 | release_bus(wilc, RELEASE_ONLY); |
c5c77ba1 | 1348 | } |
562ed3f1 | 1349 | int wilc_wlan_stop(struct wilc *wilc) |
c5c77ba1 | 1350 | { |
7ee8291a | 1351 | wilc_wlan_dev_t *p = &g_wlan; |
fbc2fe16 | 1352 | u32 reg = 0; |
c5c77ba1 | 1353 | int ret; |
51e825f7 | 1354 | u8 timeout = 10; |
562ed3f1 | 1355 | acquire_bus(wilc, ACQUIRE_AND_WAKEUP); |
c5c77ba1 | 1356 | |
49dcd0dd | 1357 | ret = p->hif_func.hif_read_reg(wilc, WILC_GLB_RESET_0, ®); |
c5c77ba1 JK |
1358 | if (!ret) { |
1359 | PRINT_ER("Error while reading reg\n"); | |
562ed3f1 | 1360 | release_bus(wilc, RELEASE_ALLOW_SLEEP); |
c5c77ba1 JK |
1361 | return ret; |
1362 | } | |
1363 | ||
ffda203c | 1364 | reg &= ~BIT(10); |
49dcd0dd | 1365 | ret = p->hif_func.hif_write_reg(wilc, WILC_GLB_RESET_0, reg); |
c5c77ba1 JK |
1366 | if (!ret) { |
1367 | PRINT_ER("Error while writing reg\n"); | |
562ed3f1 | 1368 | release_bus(wilc, RELEASE_ALLOW_SLEEP); |
c5c77ba1 JK |
1369 | return ret; |
1370 | } | |
1371 | ||
c5c77ba1 | 1372 | do { |
49dcd0dd | 1373 | ret = p->hif_func.hif_read_reg(wilc, WILC_GLB_RESET_0, ®); |
c5c77ba1 JK |
1374 | if (!ret) { |
1375 | PRINT_ER("Error while reading reg\n"); | |
562ed3f1 | 1376 | release_bus(wilc, RELEASE_ALLOW_SLEEP); |
c5c77ba1 JK |
1377 | return ret; |
1378 | } | |
ab12d8c7 LK |
1379 | PRINT_D(GENERIC_DBG, "Read RESET Reg %x : Retry%d\n", |
1380 | reg, timeout); | |
ac087c82 | 1381 | |
ffda203c | 1382 | if ((reg & BIT(10))) { |
ab12d8c7 LK |
1383 | PRINT_D(GENERIC_DBG, "Bit 10 not reset : Retry %d\n", |
1384 | timeout); | |
ffda203c | 1385 | reg &= ~BIT(10); |
49dcd0dd GL |
1386 | ret = p->hif_func.hif_write_reg(wilc, WILC_GLB_RESET_0, |
1387 | reg); | |
c5c77ba1 JK |
1388 | timeout--; |
1389 | } else { | |
ab12d8c7 LK |
1390 | PRINT_D(GENERIC_DBG, "Bit 10 reset after : Retry %d\n", |
1391 | timeout); | |
49dcd0dd GL |
1392 | ret = p->hif_func.hif_read_reg(wilc, WILC_GLB_RESET_0, |
1393 | ®); | |
c5c77ba1 JK |
1394 | if (!ret) { |
1395 | PRINT_ER("Error while reading reg\n"); | |
562ed3f1 | 1396 | release_bus(wilc, RELEASE_ALLOW_SLEEP); |
c5c77ba1 JK |
1397 | return ret; |
1398 | } | |
ab12d8c7 LK |
1399 | PRINT_D(GENERIC_DBG, "Read RESET Reg %x : Retry%d\n", |
1400 | reg, timeout); | |
c5c77ba1 JK |
1401 | break; |
1402 | } | |
1403 | ||
1404 | } while (timeout); | |
ffda203c AB |
1405 | reg = (BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(8) | BIT(9) | BIT(26) | |
1406 | BIT(29) | BIT(30) | BIT(31)); | |
65ead4ec | 1407 | |
49dcd0dd | 1408 | p->hif_func.hif_write_reg(wilc, WILC_GLB_RESET_0, reg); |
ffda203c | 1409 | reg = (u32)~BIT(10); |
65ead4ec | 1410 | |
49dcd0dd | 1411 | ret = p->hif_func.hif_write_reg(wilc, WILC_GLB_RESET_0, reg); |
c5c77ba1 | 1412 | |
562ed3f1 | 1413 | release_bus(wilc, RELEASE_ALLOW_SLEEP); |
c5c77ba1 JK |
1414 | |
1415 | return ret; | |
1416 | } | |
1417 | ||
2de7cbec | 1418 | void wilc_wlan_cleanup(struct net_device *dev) |
c5c77ba1 | 1419 | { |
7ee8291a | 1420 | wilc_wlan_dev_t *p = &g_wlan; |
c5c77ba1 JK |
1421 | struct txq_entry_t *tqe; |
1422 | struct rxq_entry_t *rqe; | |
fbc2fe16 | 1423 | u32 reg = 0; |
c5c77ba1 | 1424 | int ret; |
db387635 GL |
1425 | perInterface_wlan_t *nic; |
1426 | struct wilc *wilc; | |
1427 | ||
1428 | nic = netdev_priv(dev); | |
1429 | wilc = nic->wilc; | |
c5c77ba1 JK |
1430 | |
1431 | p->quit = 1; | |
c5c77ba1 | 1432 | do { |
718fc2c9 | 1433 | tqe = wilc_wlan_txq_remove_from_head(dev); |
a4b17197 | 1434 | if (!tqe) |
c5c77ba1 JK |
1435 | break; |
1436 | if (tqe->tx_complete_func) | |
1437 | tqe->tx_complete_func(tqe->priv, 0); | |
a18dd630 | 1438 | kfree(tqe); |
c5c77ba1 JK |
1439 | } while (1); |
1440 | ||
1441 | do { | |
db387635 | 1442 | rqe = wilc_wlan_rxq_remove(wilc); |
a4b17197 | 1443 | if (!rqe) |
c5c77ba1 | 1444 | break; |
6a27224f JMC |
1445 | #ifndef MEMORY_STATIC |
1446 | kfree(rqe->buffer); | |
c5c77ba1 | 1447 | #endif |
a18dd630 | 1448 | kfree(rqe); |
c5c77ba1 JK |
1449 | } while (1); |
1450 | ||
c5c77ba1 | 1451 | #ifdef MEMORY_STATIC |
a18dd630 GKH |
1452 | kfree(p->rx_buffer); |
1453 | p->rx_buffer = NULL; | |
c5c77ba1 | 1454 | #endif |
a18dd630 | 1455 | kfree(p->tx_buffer); |
c5c77ba1 | 1456 | |
562ed3f1 | 1457 | acquire_bus(wilc, ACQUIRE_AND_WAKEUP); |
c5c77ba1 | 1458 | |
49dcd0dd | 1459 | ret = p->hif_func.hif_read_reg(wilc, WILC_GP_REG_0, ®); |
c5c77ba1 JK |
1460 | if (!ret) { |
1461 | PRINT_ER("Error while reading reg\n"); | |
562ed3f1 | 1462 | release_bus(wilc, RELEASE_ALLOW_SLEEP); |
c5c77ba1 JK |
1463 | } |
1464 | PRINT_ER("Writing ABORT reg\n"); | |
49dcd0dd GL |
1465 | ret = p->hif_func.hif_write_reg(wilc, WILC_GP_REG_0, |
1466 | (reg | ABORT_INT)); | |
c5c77ba1 JK |
1467 | if (!ret) { |
1468 | PRINT_ER("Error while writing reg\n"); | |
562ed3f1 | 1469 | release_bus(wilc, RELEASE_ALLOW_SLEEP); |
c5c77ba1 | 1470 | } |
562ed3f1 | 1471 | release_bus(wilc, RELEASE_ALLOW_SLEEP); |
c5c77ba1 | 1472 | p->hif_func.hif_deinit(NULL); |
c5c77ba1 JK |
1473 | } |
1474 | ||
562ed3f1 | 1475 | static int wilc_wlan_cfg_commit(struct wilc *wilc, int type, u32 drv_handler) |
c5c77ba1 | 1476 | { |
7ee8291a | 1477 | wilc_wlan_dev_t *p = &g_wlan; |
14cdc0a1 | 1478 | struct wilc_cfg_frame *cfg = &p->cfg_frame; |
c5c77ba1 JK |
1479 | int total_len = p->cfg_frame_offset + 4 + DRIVER_HANDLER_SIZE; |
1480 | int seq_no = p->cfg_seq_no % 256; | |
48641679 | 1481 | int driver_handler = (u32)drv_handler; |
c5c77ba1 | 1482 | |
076ef657 | 1483 | if (type == WILC_CFG_SET) |
c5c77ba1 | 1484 | cfg->wid_header[0] = 'W'; |
076ef657 | 1485 | else |
c5c77ba1 | 1486 | cfg->wid_header[0] = 'Q'; |
ac087c82 | 1487 | cfg->wid_header[1] = seq_no; |
51e825f7 CL |
1488 | cfg->wid_header[2] = (u8)total_len; |
1489 | cfg->wid_header[3] = (u8)(total_len >> 8); | |
1490 | cfg->wid_header[4] = (u8)driver_handler; | |
1491 | cfg->wid_header[5] = (u8)(driver_handler >> 8); | |
1492 | cfg->wid_header[6] = (u8)(driver_handler >> 16); | |
1493 | cfg->wid_header[7] = (u8)(driver_handler >> 24); | |
c5c77ba1 JK |
1494 | p->cfg_seq_no = seq_no; |
1495 | ||
562ed3f1 | 1496 | if (!wilc_wlan_txq_add_cfg_pkt(wilc, &cfg->wid_header[0], total_len)) |
c5c77ba1 JK |
1497 | return -1; |
1498 | ||
1499 | return 0; | |
1500 | } | |
1501 | ||
89758e13 GL |
1502 | int wilc_wlan_cfg_set(struct wilc *wilc, int start, u32 wid, u8 *buffer, |
1503 | u32 buffer_size, int commit, u32 drv_handler) | |
c5c77ba1 | 1504 | { |
7ee8291a | 1505 | wilc_wlan_dev_t *p = &g_wlan; |
fbc2fe16 | 1506 | u32 offset; |
c5c77ba1 JK |
1507 | int ret_size; |
1508 | ||
c5c77ba1 JK |
1509 | if (p->cfg_frame_in_use) |
1510 | return 0; | |
1511 | ||
1512 | if (start) | |
1513 | p->cfg_frame_offset = 0; | |
1514 | ||
1515 | offset = p->cfg_frame_offset; | |
17e8f165 GL |
1516 | ret_size = wilc_wlan_cfg_set_wid(p->cfg_frame.frame, offset, (u16)wid, |
1517 | buffer, buffer_size); | |
c5c77ba1 JK |
1518 | offset += ret_size; |
1519 | p->cfg_frame_offset = offset; | |
1520 | ||
1521 | if (commit) { | |
ab12d8c7 LK |
1522 | PRINT_D(TX_DBG, "[WILC]PACKET Commit with sequence number %d\n", |
1523 | p->cfg_seq_no); | |
c5c77ba1 JK |
1524 | PRINT_D(RX_DBG, "Processing cfg_set()\n"); |
1525 | p->cfg_frame_in_use = 1; | |
1526 | ||
562ed3f1 | 1527 | if (wilc_wlan_cfg_commit(wilc, WILC_CFG_SET, drv_handler)) |
5af6b85b | 1528 | ret_size = 0; |
c5c77ba1 | 1529 | |
562ed3f1 | 1530 | if (wilc_lock_timeout(wilc, &wilc->cfg_event, |
b002e20d | 1531 | CFG_PKTS_TIMEOUT)) { |
c5c77ba1 JK |
1532 | PRINT_D(TX_DBG, "Set Timed Out\n"); |
1533 | ret_size = 0; | |
1534 | } | |
1535 | p->cfg_frame_in_use = 0; | |
1536 | p->cfg_frame_offset = 0; | |
1537 | p->cfg_seq_no += 1; | |
c5c77ba1 JK |
1538 | } |
1539 | ||
1540 | return ret_size; | |
1541 | } | |
2d6973e6 | 1542 | |
4878bd6c | 1543 | int wilc_wlan_cfg_get(int start, u32 wid, int commit, u32 drv_handler) |
c5c77ba1 | 1544 | { |
7ee8291a | 1545 | wilc_wlan_dev_t *p = &g_wlan; |
562ed3f1 | 1546 | struct wilc *wilc = wilc_dev; |
fbc2fe16 | 1547 | u32 offset; |
c5c77ba1 JK |
1548 | int ret_size; |
1549 | ||
c5c77ba1 JK |
1550 | if (p->cfg_frame_in_use) |
1551 | return 0; | |
1552 | ||
1553 | if (start) | |
1554 | p->cfg_frame_offset = 0; | |
1555 | ||
1556 | offset = p->cfg_frame_offset; | |
ec1b86bf | 1557 | ret_size = wilc_wlan_cfg_get_wid(p->cfg_frame.frame, offset, (u16)wid); |
c5c77ba1 JK |
1558 | offset += ret_size; |
1559 | p->cfg_frame_offset = offset; | |
1560 | ||
1561 | if (commit) { | |
1562 | p->cfg_frame_in_use = 1; | |
1563 | ||
562ed3f1 | 1564 | if (wilc_wlan_cfg_commit(wilc, WILC_CFG_QUERY, drv_handler)) |
5af6b85b | 1565 | ret_size = 0; |
c5c77ba1 | 1566 | |
562ed3f1 | 1567 | if (wilc_lock_timeout(wilc, &wilc->cfg_event, |
b002e20d | 1568 | CFG_PKTS_TIMEOUT)) { |
c5c77ba1 JK |
1569 | PRINT_D(TX_DBG, "Get Timed Out\n"); |
1570 | ret_size = 0; | |
1571 | } | |
1572 | PRINT_D(GENERIC_DBG, "[WILC]Get Response received\n"); | |
1573 | p->cfg_frame_in_use = 0; | |
1574 | p->cfg_frame_offset = 0; | |
1575 | p->cfg_seq_no += 1; | |
1576 | } | |
1577 | ||
1578 | return ret_size; | |
1579 | } | |
1580 | ||
894de36b | 1581 | int wilc_wlan_cfg_get_val(u32 wid, u8 *buffer, u32 buffer_size) |
c5c77ba1 | 1582 | { |
c5c77ba1 JK |
1583 | int ret; |
1584 | ||
355cca2a | 1585 | ret = wilc_wlan_cfg_get_wid_value((u16)wid, buffer, buffer_size); |
c5c77ba1 JK |
1586 | |
1587 | return ret; | |
1588 | } | |
1589 | ||
1608c403 | 1590 | static u32 init_chip(struct net_device *dev) |
c5c77ba1 | 1591 | { |
fbc2fe16 CL |
1592 | u32 chipid; |
1593 | u32 reg, ret = 0; | |
562ed3f1 AB |
1594 | perInterface_wlan_t *nic; |
1595 | struct wilc *wilc; | |
1596 | ||
1597 | nic = netdev_priv(dev); | |
1598 | wilc = nic->wilc; | |
c5c77ba1 | 1599 | |
562ed3f1 | 1600 | acquire_bus(wilc, ACQUIRE_ONLY); |
c5c77ba1 | 1601 | |
00215dde | 1602 | chipid = wilc_get_chipid(wilc, true); |
c5c77ba1 | 1603 | |
c5c77ba1 | 1604 | if ((chipid & 0xfff) != 0xa0) { |
49dcd0dd | 1605 | ret = g_wlan.hif_func.hif_read_reg(wilc, 0x1118, ®); |
c5c77ba1 JK |
1606 | if (!ret) { |
1607 | wilc_debug(N_ERR, "[wilc start]: fail read reg 0x1118 ...\n"); | |
1608 | return ret; | |
1609 | } | |
ffda203c | 1610 | reg |= BIT(0); |
49dcd0dd | 1611 | ret = g_wlan.hif_func.hif_write_reg(wilc, 0x1118, reg); |
c5c77ba1 JK |
1612 | if (!ret) { |
1613 | wilc_debug(N_ERR, "[wilc start]: fail write reg 0x1118 ...\n"); | |
1614 | return ret; | |
1615 | } | |
49dcd0dd | 1616 | ret = g_wlan.hif_func.hif_write_reg(wilc, 0xc0000, 0x71); |
c5c77ba1 JK |
1617 | if (!ret) { |
1618 | wilc_debug(N_ERR, "[wilc start]: fail write reg 0xc0000 ...\n"); | |
1619 | return ret; | |
1620 | } | |
1621 | } | |
1622 | ||
562ed3f1 | 1623 | release_bus(wilc, RELEASE_ONLY); |
c5c77ba1 JK |
1624 | |
1625 | return ret; | |
c5c77ba1 JK |
1626 | } |
1627 | ||
00215dde | 1628 | u32 wilc_get_chipid(struct wilc *wilc, u8 update) |
c5c77ba1 | 1629 | { |
fbc2fe16 | 1630 | static u32 chipid; |
fbc2fe16 CL |
1631 | u32 tempchipid = 0; |
1632 | u32 rfrevid; | |
c5c77ba1 JK |
1633 | |
1634 | if (chipid == 0 || update != 0) { | |
49dcd0dd GL |
1635 | g_wlan.hif_func.hif_read_reg(wilc, 0x1000, &tempchipid); |
1636 | g_wlan.hif_func.hif_read_reg(wilc, 0x13f4, &rfrevid); | |
c5c77ba1 JK |
1637 | if (!ISWILC1000(tempchipid)) { |
1638 | chipid = 0; | |
1639 | goto _fail_; | |
1640 | } | |
1641 | if (tempchipid == 0x1002a0) { | |
ac087c82 LK |
1642 | if (rfrevid == 0x1) { |
1643 | } else { | |
c5c77ba1 JK |
1644 | tempchipid = 0x1002a1; |
1645 | } | |
1646 | } else if (tempchipid == 0x1002b0) { | |
ac087c82 LK |
1647 | if (rfrevid == 3) { |
1648 | } else if (rfrevid == 4) { | |
c5c77ba1 | 1649 | tempchipid = 0x1002b1; |
ac087c82 | 1650 | } else { |
c5c77ba1 JK |
1651 | tempchipid = 0x1002b2; |
1652 | } | |
c5c77ba1 JK |
1653 | } |
1654 | ||
1655 | chipid = tempchipid; | |
1656 | } | |
1657 | _fail_: | |
1658 | return chipid; | |
1659 | } | |
1660 | ||
4bd7baf0 | 1661 | int wilc_wlan_init(struct net_device *dev) |
c5c77ba1 | 1662 | { |
c5c77ba1 | 1663 | int ret = 0; |
9c800322 GL |
1664 | perInterface_wlan_t *nic = netdev_priv(dev); |
1665 | struct wilc *wilc; | |
1666 | ||
1667 | wilc = nic->wilc; | |
c5c77ba1 JK |
1668 | |
1669 | PRINT_D(INIT_DBG, "Initializing WILC_Wlan ...\n"); | |
1670 | ||
1671 | memset((void *)&g_wlan, 0, sizeof(wilc_wlan_dev_t)); | |
4bd7baf0 | 1672 | g_wlan.io_type = wilc->io_type; |
7d37a4a1 AB |
1673 | g_wlan.hif_func = *wilc->ops; |
1674 | if (!g_wlan.hif_func.hif_init(wilc, wilc_debug)) { | |
cdb99231 GL |
1675 | ret = -EIO; |
1676 | goto _fail_; | |
1677 | } | |
c5c77ba1 | 1678 | |
814bc368 | 1679 | if (!wilc_wlan_cfg_init(wilc_debug)) { |
92e7d188 | 1680 | ret = -ENOBUFS; |
c5c77ba1 JK |
1681 | goto _fail_; |
1682 | } | |
c5c77ba1 | 1683 | |
a4b17197 | 1684 | if (!g_wlan.tx_buffer) |
7015b5db | 1685 | g_wlan.tx_buffer = kmalloc(LINUX_TX_SIZE, GFP_KERNEL); |
7a8fd841 | 1686 | PRINT_D(TX_DBG, "g_wlan.tx_buffer = %p\n", g_wlan.tx_buffer); |
c5c77ba1 | 1687 | |
a4b17197 | 1688 | if (!g_wlan.tx_buffer) { |
92e7d188 | 1689 | ret = -ENOBUFS; |
c5c77ba1 JK |
1690 | PRINT_ER("Can't allocate Tx Buffer"); |
1691 | goto _fail_; | |
1692 | } | |
1693 | ||
706671db | 1694 | #if defined(MEMORY_STATIC) |
a4b17197 | 1695 | if (!g_wlan.rx_buffer) |
03eb7266 | 1696 | g_wlan.rx_buffer = kmalloc(LINUX_RX_SIZE, GFP_KERNEL); |
7a8fd841 | 1697 | PRINT_D(TX_DBG, "g_wlan.rx_buffer =%p\n", g_wlan.rx_buffer); |
a4b17197 | 1698 | if (!g_wlan.rx_buffer) { |
92e7d188 | 1699 | ret = -ENOBUFS; |
c5c77ba1 JK |
1700 | PRINT_ER("Can't allocate Rx Buffer"); |
1701 | goto _fail_; | |
1702 | } | |
1703 | #endif | |
1704 | ||
ae6f772d | 1705 | if (!init_chip(dev)) { |
92e7d188 | 1706 | ret = -EIO; |
c5c77ba1 JK |
1707 | goto _fail_; |
1708 | } | |
1709 | #ifdef TCP_ACK_FILTER | |
ef06b5f7 | 1710 | init_tcp_tracking(); |
c5c77ba1 JK |
1711 | #endif |
1712 | ||
c5c77ba1 JK |
1713 | return 1; |
1714 | ||
1715 | _fail_: | |
1716 | ||
c5c77ba1 | 1717 | #ifdef MEMORY_STATIC |
a18dd630 GKH |
1718 | kfree(g_wlan.rx_buffer); |
1719 | g_wlan.rx_buffer = NULL; | |
c5c77ba1 | 1720 | #endif |
a18dd630 GKH |
1721 | kfree(g_wlan.tx_buffer); |
1722 | g_wlan.tx_buffer = NULL; | |
c5c77ba1 | 1723 | |
c5c77ba1 | 1724 | return ret; |
c5c77ba1 JK |
1725 | } |
1726 | ||
0e1af73d | 1727 | u16 wilc_set_machw_change_vir_if(struct net_device *dev, bool value) |
c5c77ba1 | 1728 | { |
d85f5326 | 1729 | u16 ret; |
4e4467fd | 1730 | u32 reg; |
178c383f GL |
1731 | perInterface_wlan_t *nic; |
1732 | struct wilc *wilc; | |
1733 | ||
1734 | nic = netdev_priv(dev); | |
1735 | wilc = nic->wilc; | |
c5c77ba1 | 1736 | |
178c383f | 1737 | mutex_lock(&wilc->hif_cs); |
49dcd0dd GL |
1738 | ret = (&g_wlan)->hif_func.hif_read_reg(wilc, WILC_CHANGING_VIR_IF, |
1739 | ®); | |
39823a50 | 1740 | if (!ret) |
c5c77ba1 | 1741 | PRINT_ER("Error while Reading reg WILC_CHANGING_VIR_IF\n"); |
c5c77ba1 | 1742 | |
aa313be3 | 1743 | if (value) |
50b51dac | 1744 | reg |= BIT(31); |
78174ada | 1745 | else |
50b51dac | 1746 | reg &= ~BIT(31); |
c5c77ba1 | 1747 | |
49dcd0dd GL |
1748 | ret = (&g_wlan)->hif_func.hif_write_reg(wilc, WILC_CHANGING_VIR_IF, |
1749 | reg); | |
c5c77ba1 | 1750 | |
39823a50 | 1751 | if (!ret) |
c5c77ba1 | 1752 | PRINT_ER("Error while writing reg WILC_CHANGING_VIR_IF\n"); |
39823a50 | 1753 | |
178c383f | 1754 | mutex_unlock(&wilc->hif_cs); |
c5c77ba1 JK |
1755 | |
1756 | return ret; | |
1757 | } |