1 /** @file mlan_sdio.c
2 *
3 * @brief This file contains SDIO specific code
4 *
5 *
6 * Copyright 2008-2021 NXP
7 *
8 * This software file (the File) is distributed by NXP
9 * under the terms of the GNU General Public License Version 2, June 1991
10 * (the License). You may use, redistribute and/or modify the File in
11 * accordance with the terms and conditions of the License, a copy of which
12 * is available by writing to the Free Software Foundation, Inc.,
13 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
14 * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
15 *
16 * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
18 * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
19 * this warranty disclaimer.
20 *
21 */
22
23 /********************************************************
24 Change log:
25 10/27/2008: initial version
26 ********************************************************/
27
28 #include "mlan.h"
29 #ifdef STA_SUPPORT
30 #include "mlan_join.h"
31 #endif
32 #include "mlan_util.h"
33 #include "mlan_fw.h"
34 #include "mlan_main.h"
35 #include "mlan_init.h"
36 #include "mlan_wmm.h"
37 #include "mlan_11n.h"
38 #include "mlan_sdio.h"
39
40 /********************************************************
41 Local Variables
42 ********************************************************/
43 #ifdef SD8887
44 static const struct _mlan_sdio_card_reg mlan_reg_sd8887 = {
45 .start_rd_port = 0,
46 .start_wr_port = 0,
47 .base_0_reg = 0x6C,
48 .base_1_reg = 0x6D,
49 .poll_reg = 0x5C,
50 .host_int_enable = UP_LD_HOST_INT_MASK | DN_LD_HOST_INT_MASK |
51 CMD_PORT_UPLD_INT_MASK | CMD_PORT_DNLD_INT_MASK,
52 .host_int_status = DN_LD_HOST_INT_STATUS | UP_LD_HOST_INT_STATUS |
53 DN_LD_CMD_PORT_HOST_INT_STATUS |
54 UP_LD_CMD_PORT_HOST_INT_STATUS,
55 .status_reg_0 = 0x90,
56 .status_reg_1 = 0x91,
57 .sdio_int_mask = 0xff,
58 .data_port_mask = 0xffffffff,
59 .max_mp_regs = 196,
60 .rd_bitmap_l = 0x10,
61 .rd_bitmap_u = 0x11,
62 .rd_bitmap_1l = 0x12,
63 .rd_bitmap_1u = 0x13,
64 .wr_bitmap_l = 0x14,
65 .wr_bitmap_u = 0x15,
66 .wr_bitmap_1l = 0x16,
67 .wr_bitmap_1u = 0x17,
68 .rd_len_p0_l = 0x18,
69 .rd_len_p0_u = 0x19,
70 .card_config_2_1_reg = 0xD9,
71 .cmd_config_0 = 0xC4,
72 .cmd_config_1 = 0xC5,
73 .cmd_config_2 = 0xC6,
74 .cmd_config_3 = 0xC7,
75 .cmd_rd_len_0 = 0xC0,
76 .cmd_rd_len_1 = 0xC1,
77 .cmd_rd_len_2 = 0xC2,
78 .cmd_rd_len_3 = 0xC3,
79 .io_port_0_reg = 0xE4,
80 .io_port_1_reg = 0xE5,
81 .io_port_2_reg = 0xE6,
82 .host_int_rsr_reg = 0x04,
83 .host_int_mask_reg = 0x08,
84 .host_int_status_reg = 0x0C,
85 .host_restart_reg = 0x58,
86 .card_to_host_event_reg = 0x5C,
87 .host_interrupt_mask_reg = 0x60,
88 .card_interrupt_status_reg = 0x64,
89 .card_interrupt_rsr_reg = 0x68,
90 .card_revision_reg = 0xC8,
91 .card_ocr_0_reg = 0xD4,
92 .card_ocr_1_reg = 0xD5,
93 .card_ocr_3_reg = 0xD6,
94 .card_config_reg = 0xD7,
95 .card_misc_cfg_reg = 0xD8,
96 .debug_0_reg = 0xDC,
97 .debug_1_reg = 0xDD,
98 .debug_2_reg = 0xDE,
99 .debug_3_reg = 0xDF,
100 .fw_reset_reg = 0x0B6,
101 .fw_reset_val = 1,
102 .winner_check_reg = 0x90,
103 };
104
105 static const struct _mlan_card_info mlan_card_info_sd8887 = {
106 .max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_2K,
107 .v16_fw_api = 0,
108 .supp_ps_handshake = 0,
109 .default_11n_tx_bf_cap = DEFAULT_11N_TX_BF_CAP_1X1,
110 };
111 #endif
112
113 #ifdef SD8801
114 static const struct _mlan_sdio_card_reg mlan_reg_sd8801 = {
115 .start_rd_port = 1,
116 .start_wr_port = 1,
117 .base_0_reg = 0x40,
118 .base_1_reg = 0x41,
119 .poll_reg = 0x30,
120 .host_int_enable = UP_LD_HOST_INT_MASK | DN_LD_HOST_INT_MASK,
121 .host_int_status = DN_LD_HOST_INT_STATUS | UP_LD_HOST_INT_STATUS,
122 .status_reg_0 = 0x60,
123 .status_reg_1 = 0x61,
124 .sdio_int_mask = 0x3f,
125 .data_port_mask = 0x0000fffe,
126 .max_mp_regs = 64,
127 .rd_bitmap_l = 0x4,
128 .rd_bitmap_u = 0x5,
129 .wr_bitmap_l = 0x6,
130 .wr_bitmap_u = 0x7,
131 .rd_len_p0_l = 0x8,
132 .rd_len_p0_u = 0x9,
133 .io_port_0_reg = 0x78,
134 .io_port_1_reg = 0x79,
135 .io_port_2_reg = 0x7A,
136 .host_int_rsr_reg = 0x01,
137 .host_int_mask_reg = 0x02,
138 .host_int_status_reg = 0x03,
139 .card_misc_cfg_reg = 0x6c,
140 .fw_reset_reg = 0x64,
141 .fw_reset_val = 0,
142 };
143
144 static const struct _mlan_card_info mlan_card_info_sd8801 = {
145 .max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_2K,
146 .v14_fw_api = 1,
147 .v16_fw_api = 0,
148 .supp_ps_handshake = 0,
149 .default_11n_tx_bf_cap = DEFAULT_11N_TX_BF_CAP_1X1,
150 };
151 #endif
152
153 #ifdef SD8897
154 static const struct _mlan_sdio_card_reg mlan_reg_sd8897 = {
155 .start_rd_port = 0,
156 .start_wr_port = 0,
157 .base_0_reg = 0x60,
158 .base_1_reg = 0x61,
159 .poll_reg = 0x50,
160 .host_int_enable = UP_LD_HOST_INT_MASK | DN_LD_HOST_INT_MASK |
161 CMD_PORT_UPLD_INT_MASK | CMD_PORT_DNLD_INT_MASK,
162 .host_int_status = DN_LD_HOST_INT_STATUS | UP_LD_HOST_INT_STATUS |
163 DN_LD_CMD_PORT_HOST_INT_STATUS |
164 UP_LD_CMD_PORT_HOST_INT_STATUS,
165 .status_reg_0 = 0xC0,
166 .status_reg_1 = 0xC1,
167 .sdio_int_mask = 0xff,
168 .data_port_mask = 0xffffffff,
169 .max_mp_regs = 184,
170 .rd_bitmap_l = 0x04,
171 .rd_bitmap_u = 0x05,
172 .rd_bitmap_1l = 0x06,
173 .rd_bitmap_1u = 0x07,
174 .wr_bitmap_l = 0x08,
175 .wr_bitmap_u = 0x09,
176 .wr_bitmap_1l = 0x0A,
177 .wr_bitmap_1u = 0x0B,
178 .rd_len_p0_l = 0x0C,
179 .rd_len_p0_u = 0x0D,
180 .card_config_2_1_reg = 0xCD,
181 .cmd_config_0 = 0xB8,
182 .cmd_config_1 = 0xB9,
183 .cmd_config_2 = 0xBA,
184 .cmd_config_3 = 0xBB,
185 .cmd_rd_len_0 = 0xB4,
186 .cmd_rd_len_1 = 0xB5,
187 .cmd_rd_len_2 = 0xB6,
188 .cmd_rd_len_3 = 0xB7,
189 .io_port_0_reg = 0xD8,
190 .io_port_1_reg = 0xD9,
191 .io_port_2_reg = 0xDA,
192 .host_int_rsr_reg = 0x01,
193 .host_int_mask_reg = 0x02,
194 .host_int_status_reg = 0x03,
195 .host_restart_reg = 0x4C,
196 .card_to_host_event_reg = 0x50,
197 .host_interrupt_mask_reg = 0x54,
198 .card_interrupt_status_reg = 0x58,
199 .card_interrupt_rsr_reg = 0x5C,
200 .card_revision_reg = 0xBC,
201 .card_ocr_0_reg = 0xC8,
202 .card_ocr_1_reg = 0xC9,
203 .card_ocr_3_reg = 0xCA,
204 .card_config_reg = 0xCB,
205 .card_misc_cfg_reg = 0xCC,
206 .debug_0_reg = 0xD0,
207 .debug_1_reg = 0xD1,
208 .debug_2_reg = 0xD2,
209 .debug_3_reg = 0xD3,
210 .fw_reset_reg = 0x0E8,
211 .fw_reset_val = 1,
212 .winner_check_reg = 0xC0,
213 };
214
215 static const struct _mlan_card_info mlan_card_info_sd8897 = {
216 .max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_4K,
217 .v16_fw_api = 0,
218 .supp_ps_handshake = 0,
219 .default_11n_tx_bf_cap = DEFAULT_11N_TX_BF_CAP_2X2,
220 };
221 #endif
222
223 #if defined(SD8977) || defined(SD8997) || defined(SD8987) || \
224 defined(SD9098) || defined(SD9097) || defined(SDNW62X) || \
225 defined(SD8978) || defined(SD9177)
226 static const struct _mlan_sdio_card_reg mlan_reg_sd8977_sd8997 = {
227 .start_rd_port = 0,
228 .start_wr_port = 0,
229 .base_0_reg = 0xf8,
230 .base_1_reg = 0xf9,
231 .poll_reg = 0x5C,
232 .host_int_enable = UP_LD_HOST_INT_MASK | DN_LD_HOST_INT_MASK |
233 CMD_PORT_UPLD_INT_MASK | CMD_PORT_DNLD_INT_MASK,
234 .host_int_status = DN_LD_HOST_INT_STATUS | UP_LD_HOST_INT_STATUS |
235 DN_LD_CMD_PORT_HOST_INT_STATUS |
236 UP_LD_CMD_PORT_HOST_INT_STATUS,
237 .status_reg_0 = 0xe8,
238 .status_reg_1 = 0xe9,
239 .sdio_int_mask = 0xff,
240 .data_port_mask = 0xffffffff,
241 .max_mp_regs = 196,
242 .rd_bitmap_l = 0x10,
243 .rd_bitmap_u = 0x11,
244 .rd_bitmap_1l = 0x12,
245 .rd_bitmap_1u = 0x13,
246 .wr_bitmap_l = 0x14,
247 .wr_bitmap_u = 0x15,
248 .wr_bitmap_1l = 0x16,
249 .wr_bitmap_1u = 0x17,
250 .rd_len_p0_l = 0x18,
251 .rd_len_p0_u = 0x19,
252 .card_config_2_1_reg = 0xD9,
253 .cmd_config_0 = 0xC4,
254 .cmd_config_1 = 0xC5,
255 .cmd_config_2 = 0xC6,
256 .cmd_config_3 = 0xC7,
257 .cmd_rd_len_0 = 0xC0,
258 .cmd_rd_len_1 = 0xC1,
259 .cmd_rd_len_2 = 0xC2,
260 .cmd_rd_len_3 = 0xC3,
261 .io_port_0_reg = 0xE4,
262 .io_port_1_reg = 0xE5,
263 .io_port_2_reg = 0xE6,
264 .host_int_rsr_reg = 0x04,
265 .host_int_mask_reg = 0x08,
266 .host_int_status_reg = 0x0C,
267 .host_restart_reg = 0x58,
268 .card_to_host_event_reg = 0x5C,
269 .host_interrupt_mask_reg = 0x60,
270 .card_interrupt_status_reg = 0x64,
271 .card_interrupt_rsr_reg = 0x68,
272 .card_revision_reg = 0xC8,
273 .card_ocr_0_reg = 0xD4,
274 .card_ocr_1_reg = 0xD5,
275 .card_ocr_3_reg = 0xD6,
276 .card_config_reg = 0xD7,
277 .card_misc_cfg_reg = 0xD8,
278 .debug_0_reg = 0xDC,
279 .debug_1_reg = 0xDD,
280 .debug_2_reg = 0xDE,
281 .debug_3_reg = 0xDF,
282 .fw_reset_reg = 0x0EE,
283 .fw_reset_val = 0x99,
284 .fw_dnld_offset_0_reg = 0xEC,
285 .fw_dnld_offset_1_reg = 0xED,
286 .fw_dnld_offset_2_reg = 0xEE,
287 .fw_dnld_offset_3_reg = 0xEF,
288 .fw_dnld_status_0_reg = 0xE8,
289 .fw_dnld_status_1_reg = 0xE9,
290 .winner_check_reg = 0xFC,
291 };
292 #endif
293
294 #ifdef SD8997
295 static const struct _mlan_card_info mlan_card_info_sd8997 = {
296 .max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_4K,
297 .v16_fw_api = 1,
298 .supp_ps_handshake = 0,
299 .default_11n_tx_bf_cap = DEFAULT_11N_TX_BF_CAP_2X2,
300 };
301 #endif
302
303 #ifdef SD9097
304 static const struct _mlan_card_info mlan_card_info_sd9097 = {
305 .max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_4K,
306 .v16_fw_api = 1,
307 .v17_fw_api = 1,
308 .supp_ps_handshake = 0,
309 .default_11n_tx_bf_cap = DEFAULT_11N_TX_BF_CAP_2X2,
310 };
311 #endif
312
313 #ifdef SDNW62X
314 static const struct _mlan_card_info mlan_card_info_sdnw62x = {
315 .max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_4K,
316 .v16_fw_api = 1,
317 .v17_fw_api = 1,
318 .supp_ps_handshake = 0,
319 .default_11n_tx_bf_cap = DEFAULT_11N_TX_BF_CAP_2X2,
320 };
321 #endif
322
323 #ifdef SD9098
324 static const struct _mlan_card_info mlan_card_info_sd9098 = {
325 .max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_4K,
326 .v16_fw_api = 1,
327 .v17_fw_api = 1,
328 .supp_ps_handshake = 0,
329 .default_11n_tx_bf_cap = DEFAULT_11N_TX_BF_CAP_2X2,
330 };
331 #endif
332 #ifdef SD9177
333 static const struct _mlan_card_info mlan_card_info_sd9177 = {
334 .max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_4K,
335 .v16_fw_api = 1,
336 .v17_fw_api = 1,
337 .supp_ps_handshake = 0,
338 .default_11n_tx_bf_cap = DEFAULT_11N_TX_BF_CAP_1X1,
339 };
340 #endif
341
342 #if defined(SD8977) || defined(SD8978)
343 static const struct _mlan_card_info mlan_card_info_sd8977 = {
344 .max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_2K,
345 .v16_fw_api = 1,
346 .supp_ps_handshake = 0,
347 .default_11n_tx_bf_cap = DEFAULT_11N_TX_BF_CAP_1X1,
348 };
349 #endif
350
351 #ifdef SD8987
352 static const struct _mlan_card_info mlan_card_info_sd8987 = {
353 .max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_2K,
354 .v16_fw_api = 1,
355 .supp_ps_handshake = 0,
356 .default_11n_tx_bf_cap = DEFAULT_11N_TX_BF_CAP_1X1,
357 };
358 #endif
359
360 /********************************************************
361 Global Variables
362 ********************************************************/
363
364 /********************************************************
365 Local Functions
366 ********************************************************/
367
368 /**
369 * @brief This function initialize the SDIO port
370 *
371 * @param pmadapter A pointer to mlan_adapter structure
372 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
373 */
wlan_sdio_init_ioport(mlan_adapter * pmadapter)374 static mlan_status wlan_sdio_init_ioport(mlan_adapter *pmadapter)
375 {
376 t_u32 reg;
377 pmlan_callbacks pcb = &pmadapter->callbacks;
378 t_u8 host_int_rsr_reg = pmadapter->pcard_sd->reg->host_int_rsr_reg;
379 t_u8 host_int_rsr_mask = pmadapter->pcard_sd->reg->sdio_int_mask;
380 t_u8 card_misc_cfg_reg = pmadapter->pcard_sd->reg->card_misc_cfg_reg;
381 t_u8 card_config_2_1_reg =
382 pmadapter->pcard_sd->reg->card_config_2_1_reg;
383 t_u8 cmd_config_0 = pmadapter->pcard_sd->reg->cmd_config_0;
384 t_u8 cmd_config_1 = pmadapter->pcard_sd->reg->cmd_config_1;
385
386 ENTER();
387 if (pmadapter->pcard_sd->supports_sdio_new_mode) {
388 pmadapter->pcard_sd->ioport = MEM_PORT;
389 } else {
390 if (MLAN_STATUS_SUCCESS ==
391 pcb->moal_read_reg(pmadapter->pmoal_handle,
392 pmadapter->pcard_sd->reg->io_port_0_reg,
393 ®))
394 pmadapter->pcard_sd->ioport |= (reg & 0xff);
395 else {
396 LEAVE();
397 return MLAN_STATUS_FAILURE;
398 }
399 if (MLAN_STATUS_SUCCESS ==
400 pcb->moal_read_reg(pmadapter->pmoal_handle,
401 pmadapter->pcard_sd->reg->io_port_1_reg,
402 ®))
403 pmadapter->pcard_sd->ioport |= ((reg & 0xff) << 8);
404 else {
405 LEAVE();
406 return MLAN_STATUS_FAILURE;
407 }
408 if (MLAN_STATUS_SUCCESS ==
409 pcb->moal_read_reg(pmadapter->pmoal_handle,
410 pmadapter->pcard_sd->reg->io_port_2_reg,
411 ®))
412 pmadapter->pcard_sd->ioport |= ((reg & 0xff) << 16);
413 else {
414 LEAVE();
415 return MLAN_STATUS_FAILURE;
416 }
417 }
418 PRINTM(MINFO, "SDIO FUNC1 IO port: 0x%x\n",
419 pmadapter->pcard_sd->ioport);
420
421 if (pmadapter->pcard_sd->supports_sdio_new_mode) {
422 /* enable sdio cmd53 new mode */
423 if (MLAN_STATUS_SUCCESS ==
424 pcb->moal_read_reg(pmadapter->pmoal_handle,
425 card_config_2_1_reg, ®)) {
426 pcb->moal_write_reg(pmadapter->pmoal_handle,
427 card_config_2_1_reg,
428 reg | CMD53_NEW_MODE);
429 } else {
430 LEAVE();
431 return MLAN_STATUS_FAILURE;
432 }
433
434 /* configure cmd port */
435 /* enable reading rx length from the register */
436 if (MLAN_STATUS_SUCCESS ==
437 pcb->moal_read_reg(pmadapter->pmoal_handle, cmd_config_0,
438 ®)) {
439 pcb->moal_write_reg(pmadapter->pmoal_handle,
440 cmd_config_0,
441 reg | CMD_PORT_RD_LEN_EN);
442 } else {
443 LEAVE();
444 return MLAN_STATUS_FAILURE;
445 }
446 /* enable Dnld/Upld ready auto reset for cmd port
447 * after cmd53 is completed */
448 if (MLAN_STATUS_SUCCESS ==
449 pcb->moal_read_reg(pmadapter->pmoal_handle, cmd_config_1,
450 ®)) {
451 pcb->moal_write_reg(pmadapter->pmoal_handle,
452 cmd_config_1,
453 reg | CMD_PORT_AUTO_EN);
454 } else {
455 LEAVE();
456 return MLAN_STATUS_FAILURE;
457 }
458 }
459
460 #if defined(SD8977) || defined(SD8978)
461 if (IS_SD8977(pmadapter->card_type) ||
462 IS_SD8978(pmadapter->card_type)) {
463 if ((pmadapter->init_para.int_mode == INT_MODE_GPIO) &&
464 (pmadapter->init_para.gpio_pin == GPIO_INT_NEW_MODE)) {
465 PRINTM(MMSG, "Enable GPIO-1 int mode\n");
466 pcb->moal_write_reg(pmadapter->pmoal_handle,
467 SCRATCH_REG_32,
468 ENABLE_GPIO_1_INT_MODE);
469 }
470 }
471 #endif
472 /* Set Host interrupt reset to read to clear */
473 if (MLAN_STATUS_SUCCESS == pcb->moal_read_reg(pmadapter->pmoal_handle,
474 host_int_rsr_reg, ®)) {
475 pcb->moal_write_reg(pmadapter->pmoal_handle, host_int_rsr_reg,
476 reg | host_int_rsr_mask);
477 } else {
478 LEAVE();
479 return MLAN_STATUS_FAILURE;
480 }
481
482 /* Dnld/Upld ready set to auto reset */
483 if (MLAN_STATUS_SUCCESS == pcb->moal_read_reg(pmadapter->pmoal_handle,
484 card_misc_cfg_reg,
485 ®)) {
486 pcb->moal_write_reg(pmadapter->pmoal_handle, card_misc_cfg_reg,
487 reg | AUTO_RE_ENABLE_INT);
488 } else {
489 LEAVE();
490 return MLAN_STATUS_FAILURE;
491 }
492 LEAVE();
493 return MLAN_STATUS_SUCCESS;
494 }
495
496 /**
497 * @brief This function sends data to the card.
498 *
499 * @param pmadapter A pointer to mlan_adapter structure
500 * @param pmbuf A pointer to mlan_buffer (pmbuf->data_len should include
501 * SDIO header)
502 * @param port Port
503 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
504 */
wlan_write_data_sync(mlan_adapter * pmadapter,mlan_buffer * pmbuf,t_u32 port)505 static mlan_status wlan_write_data_sync(mlan_adapter *pmadapter,
506 mlan_buffer *pmbuf, t_u32 port)
507 {
508 t_u32 i = 0;
509 pmlan_callbacks pcb = &pmadapter->callbacks;
510 mlan_status ret = MLAN_STATUS_SUCCESS;
511
512 ENTER();
513
514 do {
515 ret = pcb->moal_write_data_sync(pmadapter->pmoal_handle, pmbuf,
516 port, 0);
517 if (ret != MLAN_STATUS_SUCCESS) {
518 i++;
519 PRINTM(MERROR,
520 "host_to_card, write iomem (%d) failed: %d\n", i,
521 ret);
522 if (MLAN_STATUS_SUCCESS !=
523 pcb->moal_write_reg(pmadapter->pmoal_handle,
524 HOST_TO_CARD_EVENT_REG,
525 HOST_TERM_CMD53)) {
526 PRINTM(MERROR, "write CFG reg failed\n");
527 }
528 ret = MLAN_STATUS_FAILURE;
529 if (i > MAX_WRITE_IOMEM_RETRY) {
530 pmbuf->status_code = MLAN_ERROR_DATA_TX_FAIL;
531 goto exit;
532 }
533 }
534 } while (ret == MLAN_STATUS_FAILURE);
535 exit:
536 LEAVE();
537 return ret;
538 }
539
540 /**
541 * @brief This function gets available SDIO port for reading cmd/data
542 *
543 * @param pmadapter A pointer to mlan_adapter structure
544 * @param pport A pointer to port number
545 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
546 */
wlan_get_rd_port(mlan_adapter * pmadapter,t_u8 * pport)547 static mlan_status wlan_get_rd_port(mlan_adapter *pmadapter, t_u8 *pport)
548 {
549 t_u32 rd_bitmap = pmadapter->pcard_sd->mp_rd_bitmap;
550 const mlan_sdio_card_reg *reg = pmadapter->pcard_sd->reg;
551 t_u8 max_ports = pmadapter->pcard_sd->max_ports;
552 t_bool new_mode = pmadapter->pcard_sd->supports_sdio_new_mode;
553
554 ENTER();
555
556 PRINTM(MIF_D, "wlan_get_rd_port: mp_rd_bitmap=0x%08x\n", rd_bitmap);
557 if (new_mode) {
558 if (!(rd_bitmap & reg->data_port_mask)) {
559 LEAVE();
560 return MLAN_STATUS_FAILURE;
561 }
562 } else {
563 if (!(rd_bitmap & (CTRL_PORT_MASK | reg->data_port_mask))) {
564 LEAVE();
565 return MLAN_STATUS_FAILURE;
566 }
567 }
568 if (!new_mode && (pmadapter->pcard_sd->mp_rd_bitmap & CTRL_PORT_MASK)) {
569 pmadapter->pcard_sd->mp_rd_bitmap &= (t_u32)(~CTRL_PORT_MASK);
570 *pport = CTRL_PORT;
571 PRINTM(MIF_D, "wlan_get_rd_port: port=%d mp_rd_bitmap=0x%08x\n",
572 *pport, pmadapter->pcard_sd->mp_rd_bitmap);
573 } else {
574 if (pmadapter->pcard_sd->mp_rd_bitmap &
575 (1 << pmadapter->pcard_sd->curr_rd_port)) {
576 pmadapter->pcard_sd->mp_rd_bitmap &= (t_u32)(
577 ~(1 << pmadapter->pcard_sd->curr_rd_port));
578 *pport = pmadapter->pcard_sd->curr_rd_port;
579
580 /* hw rx wraps round only after port (MAX_PORT-1) */
581 if (++pmadapter->pcard_sd->curr_rd_port == max_ports)
582 pmadapter->pcard_sd->curr_rd_port =
583 reg->start_rd_port;
584 } else {
585 LEAVE();
586 return MLAN_STATUS_FAILURE;
587 }
588
589 PRINTM(MIF_D, "port=%d mp_rd_bitmap=0x%08x -> 0x%08x\n", *pport,
590 rd_bitmap, pmadapter->pcard_sd->mp_rd_bitmap);
591 }
592
593 LEAVE();
594 return MLAN_STATUS_SUCCESS;
595 }
596
597 /**
598 * @brief This function gets available SDIO port for writing data
599 *
600 * @param pmadapter A pointer to mlan_adapter structure
601 * @param pport A pointer to port number
602 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
603 */
wlan_get_wr_port_data(mlan_adapter * pmadapter,t_u8 * pport)604 static mlan_status wlan_get_wr_port_data(mlan_adapter *pmadapter, t_u8 *pport)
605 {
606 t_u32 wr_bitmap = pmadapter->pcard_sd->mp_wr_bitmap;
607 const mlan_sdio_card_reg *reg = pmadapter->pcard_sd->reg;
608 t_bool new_mode = pmadapter->pcard_sd->supports_sdio_new_mode;
609
610 ENTER();
611
612 PRINTM(MIF_D, "wlan_get_wr_port_data: mp_wr_bitmap=0x%08x\n",
613 wr_bitmap);
614
615 if (!(wr_bitmap & pmadapter->pcard_sd->mp_data_port_mask)) {
616 pmadapter->data_sent = MTRUE;
617 LEAVE();
618 return MLAN_STATUS_RESOURCE;
619 }
620
621 if (pmadapter->pcard_sd->mp_wr_bitmap &
622 (1 << pmadapter->pcard_sd->curr_wr_port)) {
623 pmadapter->pcard_sd->mp_wr_bitmap &=
624 (t_u32)(~(1 << pmadapter->pcard_sd->curr_wr_port));
625 *pport = pmadapter->pcard_sd->curr_wr_port;
626 if (++pmadapter->pcard_sd->curr_wr_port ==
627 pmadapter->pcard_sd->mp_end_port)
628 pmadapter->pcard_sd->curr_wr_port = reg->start_wr_port;
629 } else {
630 pmadapter->data_sent = MTRUE;
631 LEAVE();
632 return MLAN_STATUS_RESOURCE;
633 }
634 if ((!new_mode) && (*pport == CTRL_PORT)) {
635 PRINTM(MERROR,
636 "Invalid data port=%d cur port=%d mp_wr_bitmap=0x%08x -> 0x%08x\n",
637 *pport, pmadapter->pcard_sd->curr_wr_port, wr_bitmap,
638 pmadapter->pcard_sd->mp_wr_bitmap);
639 LEAVE();
640 return MLAN_STATUS_FAILURE;
641 }
642 PRINTM(MIF_D, "port=%d mp_wr_bitmap=0x%08x -> 0x%08x\n", *pport,
643 wr_bitmap, pmadapter->pcard_sd->mp_wr_bitmap);
644 LEAVE();
645 return MLAN_STATUS_SUCCESS;
646 }
647
648 /**
649 * @brief This function polls the card status register.
650 *
651 * @param pmadapter A pointer to mlan_adapter structure
652 * @param bits the bit mask
653 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
654 */
wlan_sdio_poll_card_status(mlan_adapter * pmadapter,t_u8 bits)655 static mlan_status wlan_sdio_poll_card_status(mlan_adapter *pmadapter,
656 t_u8 bits)
657 {
658 pmlan_callbacks pcb = &pmadapter->callbacks;
659 t_u32 tries;
660 t_u32 cs = 0;
661
662 ENTER();
663
664 for (tries = 0; tries < 10000; tries++) {
665 if (pcb->moal_read_reg(pmadapter->pmoal_handle,
666 pmadapter->pcard_sd->reg->poll_reg,
667 &cs) != MLAN_STATUS_SUCCESS)
668 break;
669 else if ((cs & bits) == bits) {
670 LEAVE();
671 return MLAN_STATUS_SUCCESS;
672 }
673 wlan_udelay(pmadapter, 10);
674 }
675
676 PRINTM(MERROR,
677 "wlan_sdio_poll_card_status failed, tries = %d, cs = 0x%x\n",
678 tries, cs);
679 LEAVE();
680 return MLAN_STATUS_FAILURE;
681 }
682
683 /**
684 * @brief This function reads firmware status registers
685 *
686 * @param pmadapter A pointer to mlan_adapter structure
687 * @param dat A pointer to keep returned data
688 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
689 */
wlan_sdio_read_fw_status(mlan_adapter * pmadapter,t_u16 * dat)690 static mlan_status wlan_sdio_read_fw_status(mlan_adapter *pmadapter, t_u16 *dat)
691 {
692 pmlan_callbacks pcb = &pmadapter->callbacks;
693 t_u32 fws0 = 0, fws1 = 0;
694
695 ENTER();
696 if (MLAN_STATUS_SUCCESS !=
697 pcb->moal_read_reg(pmadapter->pmoal_handle,
698 pmadapter->pcard_sd->reg->status_reg_0, &fws0)) {
699 LEAVE();
700 return MLAN_STATUS_FAILURE;
701 }
702
703 if (MLAN_STATUS_SUCCESS !=
704 pcb->moal_read_reg(pmadapter->pmoal_handle,
705 pmadapter->pcard_sd->reg->status_reg_1, &fws1)) {
706 LEAVE();
707 return MLAN_STATUS_FAILURE;
708 }
709
710 *dat = (t_u16)((fws1 << 8) | fws0);
711 LEAVE();
712 return MLAN_STATUS_SUCCESS;
713 }
714
715 /**
716 * @brief This function reads firmware dnld offset registers
717 *
718 * @param pmadapter A pointer to mlan_adapter structure
719 * @param dat A pointer to keep returned data
720 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
721 */
wlan_sdio_read_fw_dnld_offset(mlan_adapter * pmadapter,t_u32 * dat)722 static mlan_status wlan_sdio_read_fw_dnld_offset(mlan_adapter *pmadapter,
723 t_u32 *dat)
724 {
725 pmlan_callbacks pcb = &pmadapter->callbacks;
726 const mlan_sdio_card_reg *reg = pmadapter->pcard_sd->reg;
727 mlan_status ret = MLAN_STATUS_SUCCESS;
728 t_u32 fw_dnld_offset_0 = 0;
729 t_u32 fw_dnld_offset_1 = 0;
730 t_u32 fw_dnld_offset_2 = 0;
731 t_u32 fw_dnld_offset_3 = 0;
732
733 ENTER();
734
735 ret = pcb->moal_read_reg(pmadapter->pmoal_handle,
736 reg->fw_dnld_offset_0_reg, &fw_dnld_offset_0);
737 if (ret != MLAN_STATUS_SUCCESS) {
738 PRINTM(MERROR,
739 "Dev fw_dnld_offset_0 reg read failed: reg(0x%04X)=0x%x. Terminating download\n",
740 reg->fw_dnld_offset_0_reg, fw_dnld_offset_0);
741 ret = MLAN_STATUS_FAILURE;
742 goto done;
743 }
744 ret = pcb->moal_read_reg(pmadapter->pmoal_handle,
745 reg->fw_dnld_offset_1_reg, &fw_dnld_offset_1);
746 if (ret != MLAN_STATUS_SUCCESS) {
747 PRINTM(MERROR,
748 "Dev fw_dnld_offset_1 reg read failed: reg(0x%04X)=0x%x. Terminating download\n",
749 reg->fw_dnld_offset_1_reg, fw_dnld_offset_1);
750 ret = MLAN_STATUS_FAILURE;
751 goto done;
752 }
753 ret = pcb->moal_read_reg(pmadapter->pmoal_handle,
754 reg->fw_dnld_offset_2_reg, &fw_dnld_offset_2);
755 if (ret != MLAN_STATUS_SUCCESS) {
756 PRINTM(MERROR,
757 "Dev fw_dnld_offset_2 reg read failed: reg(0x%04X)=0x%x. Terminating download\n",
758 reg->fw_dnld_offset_2_reg, fw_dnld_offset_2);
759 ret = MLAN_STATUS_FAILURE;
760 goto done;
761 }
762 ret = pcb->moal_read_reg(pmadapter->pmoal_handle,
763 reg->fw_dnld_offset_3_reg, &fw_dnld_offset_3);
764 if (ret != MLAN_STATUS_SUCCESS) {
765 PRINTM(MERROR,
766 "Dev fw_dnld_offset_3 reg read failed: reg(0x%04X)=0x%x. Terminating download\n",
767 reg->fw_dnld_offset_3_reg, fw_dnld_offset_3);
768 ret = MLAN_STATUS_FAILURE;
769 goto done;
770 }
771
772 *dat = (t_u32)(((fw_dnld_offset_3 & 0xff) << 24) |
773 ((fw_dnld_offset_2 & 0xff) << 16) |
774 ((fw_dnld_offset_1 & 0xff) << 8) |
775 (fw_dnld_offset_0 & 0xff));
776
777 done:
778 LEAVE();
779 return ret;
780 }
781
782 /**
783 * @brief This function reads firmware dnld status registers
784 *
785 * @param pmadapter A pointer to mlan_adapter structure
786 * @param dat A pointer to keep returned data
787 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
788 */
wlan_sdio_read_fw_dnld_status(mlan_adapter * pmadapter,t_u16 * dat)789 static mlan_status wlan_sdio_read_fw_dnld_status(mlan_adapter *pmadapter,
790 t_u16 *dat)
791 {
792 pmlan_callbacks pcb = &pmadapter->callbacks;
793 const mlan_sdio_card_reg *reg = pmadapter->pcard_sd->reg;
794 mlan_status ret = MLAN_STATUS_SUCCESS;
795 t_u32 fw_dnld_status_0 = 0;
796 t_u32 fw_dnld_status_1 = 0;
797
798 ENTER();
799
800 ret = pcb->moal_read_reg(pmadapter->pmoal_handle,
801 reg->fw_dnld_status_0_reg, &fw_dnld_status_0);
802 if (ret != MLAN_STATUS_SUCCESS) {
803 PRINTM(MERROR,
804 "Dev fw_dnld_status_0 reg read failed: reg(0x%04X)=0x%x. Terminating download\n",
805 reg->fw_dnld_status_0_reg, fw_dnld_status_0);
806 ret = MLAN_STATUS_FAILURE;
807 goto done;
808 }
809 ret = pcb->moal_read_reg(pmadapter->pmoal_handle,
810 reg->fw_dnld_status_1_reg, &fw_dnld_status_1);
811 if (ret != MLAN_STATUS_SUCCESS) {
812 PRINTM(MERROR,
813 "Dev fw_dnld_status_1 reg read failed: reg(0x%04X)=0x%x. Terminating download\n",
814 reg->fw_dnld_status_1_reg, fw_dnld_status_1);
815 ret = MLAN_STATUS_FAILURE;
816 goto done;
817 }
818
819 *dat = (t_u16)(((fw_dnld_status_1 & 0xff) << 8) |
820 (fw_dnld_status_0 & 0xff));
821
822 done:
823 LEAVE();
824 return ret;
825 }
826
827 /** @brief This function disables the host interrupts mask.
828 *
829 * @param pmadapter A pointer to mlan_adapter structure
830 * @param mask the interrupt mask
831 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
832 */
wlan_sdio_disable_host_int_mask(pmlan_adapter pmadapter,t_u8 mask)833 static mlan_status wlan_sdio_disable_host_int_mask(pmlan_adapter pmadapter,
834 t_u8 mask)
835 {
836 t_u32 host_int_mask = 0;
837 pmlan_callbacks pcb = &pmadapter->callbacks;
838
839 ENTER();
840
841 /* Read back the host_int_mask register */
842 if (MLAN_STATUS_SUCCESS !=
843 pcb->moal_read_reg(pmadapter->pmoal_handle,
844 pmadapter->pcard_sd->reg->host_int_mask_reg,
845 &host_int_mask)) {
846 LEAVE();
847 return MLAN_STATUS_FAILURE;
848 }
849
850 /* Update with the mask and write back to the register */
851 host_int_mask &= ~mask;
852
853 if (MLAN_STATUS_SUCCESS !=
854 pcb->moal_write_reg(pmadapter->pmoal_handle,
855 pmadapter->pcard_sd->reg->host_int_mask_reg,
856 host_int_mask)) {
857 PRINTM(MWARN, "Disable host interrupt failed\n");
858 LEAVE();
859 return MLAN_STATUS_FAILURE;
860 }
861
862 LEAVE();
863 return MLAN_STATUS_SUCCESS;
864 }
865
866 /**
867 * @brief This function enables the host interrupts mask
868 *
869 * @param pmadapter A pointer to mlan_adapter structure
870 * @param mask the interrupt mask
871 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
872 */
wlan_sdio_enable_host_int_mask(pmlan_adapter pmadapter,t_u8 mask)873 static mlan_status wlan_sdio_enable_host_int_mask(pmlan_adapter pmadapter,
874 t_u8 mask)
875 {
876 pmlan_callbacks pcb = &pmadapter->callbacks;
877
878 ENTER();
879
880 /* Simply write the mask to the register */
881 if (MLAN_STATUS_SUCCESS !=
882 pcb->moal_write_reg(pmadapter->pmoal_handle,
883 pmadapter->pcard_sd->reg->host_int_mask_reg,
884 mask)) {
885 PRINTM(MWARN, "Enable host interrupt failed\n");
886 LEAVE();
887 return MLAN_STATUS_FAILURE;
888 }
889
890 LEAVE();
891 return MLAN_STATUS_SUCCESS;
892 }
893
894 /**
895 * @brief This function reads data from the card.
896 *
897 * @param pmadapter A pointer to mlan_adapter structure
898 * @param type A pointer to keep type as data or command
899 * @param nb A pointer to keep the data/cmd length returned in buffer
900 * @param pmbuf A pointer to the SDIO data/cmd buffer
901 * @param npayload the length of data/cmd buffer
902 * @param ioport the SDIO ioport
903 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
904 */
wlan_sdio_card_to_host(mlan_adapter * pmadapter,t_u32 * type,t_u32 * nb,pmlan_buffer pmbuf,t_u32 npayload,t_u32 ioport)905 static mlan_status wlan_sdio_card_to_host(mlan_adapter *pmadapter, t_u32 *type,
906 t_u32 *nb, pmlan_buffer pmbuf,
907 t_u32 npayload, t_u32 ioport)
908 {
909 mlan_status ret = MLAN_STATUS_SUCCESS;
910 pmlan_callbacks pcb = &pmadapter->callbacks;
911 t_u32 i = 0;
912
913 ENTER();
914
915 if (!pmbuf) {
916 PRINTM(MWARN, "pmbuf is NULL!\n");
917 ret = MLAN_STATUS_FAILURE;
918 goto exit;
919 }
920 do {
921 ret = pcb->moal_read_data_sync(pmadapter->pmoal_handle, pmbuf,
922 ioport, 0);
923
924 if (ret != MLAN_STATUS_SUCCESS) {
925 PRINTM(MERROR,
926 "wlan: cmd53 read failed: %d ioport=0x%x retry=%d\n",
927 ret, ioport, i);
928 i++;
929 if (MLAN_STATUS_SUCCESS !=
930 pcb->moal_write_reg(pmadapter->pmoal_handle,
931 HOST_TO_CARD_EVENT_REG,
932 HOST_TERM_CMD53)) {
933 PRINTM(MERROR, "Set Term cmd53 failed\n");
934 }
935 if (i > MAX_WRITE_IOMEM_RETRY) {
936 pmbuf->status_code = MLAN_ERROR_DATA_RX_FAIL;
937 ret = MLAN_STATUS_FAILURE;
938 goto exit;
939 }
940 }
941 } while (ret == MLAN_STATUS_FAILURE);
942 *nb = wlan_le16_to_cpu(*(t_u16 *)(pmbuf->pbuf + pmbuf->data_offset));
943 if (*nb > npayload) {
944 PRINTM(MERROR, "invalid packet, *nb=%d, npayload=%d\n", *nb,
945 npayload);
946 pmbuf->status_code = MLAN_ERROR_PKT_SIZE_INVALID;
947 ret = MLAN_STATUS_FAILURE;
948 goto exit;
949 }
950
951 DBG_HEXDUMP(MIF_D, "SDIO Blk Rd", pmbuf->pbuf + pmbuf->data_offset,
952 MIN(*nb, MAX_DATA_DUMP_LEN));
953
954 *type = wlan_le16_to_cpu(
955 *(t_u16 *)(pmbuf->pbuf + pmbuf->data_offset + 2));
956
957 exit:
958 LEAVE();
959 return ret;
960 }
961
962 /**
963 * @brief This function downloads FW blocks to device
964 *
965 * @param pmadapter A pointer to mlan_adapter
966 * @param firmware A pointer to firmware image
967 * @param firmwarelen firmware len
968 *
969 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
970 */
wlan_sdio_prog_fw_w_helper(pmlan_adapter pmadapter,t_u8 * fw,t_u32 fw_len)971 static mlan_status wlan_sdio_prog_fw_w_helper(pmlan_adapter pmadapter, t_u8 *fw,
972 t_u32 fw_len)
973 {
974 mlan_status ret = MLAN_STATUS_SUCCESS;
975 pmlan_callbacks pcb = &pmadapter->callbacks;
976 t_u8 *firmware = fw;
977 t_u32 firmwarelen = fw_len;
978 t_u32 offset = 0;
979 t_u32 base0, base1;
980 t_void *tmpfwbuf = MNULL;
981 t_u32 tmpfwbufsz;
982 t_u8 *fwbuf;
983 mlan_buffer mbuf;
984 t_u16 len = 0;
985 t_u32 txlen = 0, tx_blocks = 0, tries = 0;
986 t_u32 i = 0;
987 const mlan_sdio_card_reg *reg = pmadapter->pcard_sd->reg;
988 t_u32 read_base_0_reg = reg->base_0_reg;
989 t_u32 read_base_1_reg = reg->base_1_reg;
990 #if defined(SD9098)
991 t_u32 rev_id_reg = 0;
992 t_u32 revision_id = 0;
993 #endif
994 t_u8 check_fw_status = MFALSE;
995 t_u16 fw_dnld_status = 0;
996 t_u32 fw_dnld_offset = 0;
997 t_u8 mic_retry = 0;
998
999 ENTER();
1000
1001 if (!firmware && !pcb->moal_get_fw_data) {
1002 PRINTM(MMSG, "No firmware image found! Terminating download\n");
1003 LEAVE();
1004 return MLAN_STATUS_FAILURE;
1005 }
1006
1007 PRINTM(MINFO, "WLAN: Downloading FW image (%d bytes)\n", firmwarelen);
1008
1009 tmpfwbufsz = ALIGN_SZ(WLAN_UPLD_SIZE, DMA_ALIGNMENT);
1010 ret = pcb->moal_malloc(pmadapter->pmoal_handle, tmpfwbufsz,
1011 MLAN_MEM_DEF | MLAN_MEM_DMA, (t_u8 **)&tmpfwbuf);
1012 if ((ret != MLAN_STATUS_SUCCESS) || !tmpfwbuf) {
1013 PRINTM(MERROR,
1014 "Unable to allocate buffer for firmware. Terminating download\n");
1015 ret = MLAN_STATUS_FAILURE;
1016 goto done;
1017 }
1018 memset(pmadapter, tmpfwbuf, 0, tmpfwbufsz);
1019 /* Ensure 8-byte aligned firmware buffer */
1020 fwbuf = (t_u8 *)ALIGN_ADDR(tmpfwbuf, DMA_ALIGNMENT);
1021 #if defined(SD9098)
1022 if (IS_SD9098(pmadapter->card_type)) {
1023 rev_id_reg = pmadapter->pcard_sd->reg->card_revision_reg;
1024 ret = pcb->moal_read_reg(pmadapter->pmoal_handle, rev_id_reg,
1025 &revision_id);
1026 if (ret != MLAN_STATUS_SUCCESS) {
1027 PRINTM(MERROR,
1028 "Card Revision register read failed:"
1029 "card_revision_reg=0x%x\n",
1030 rev_id_reg);
1031 goto done;
1032 }
1033 /* Skyhawk A0, need to check both CRC and MIC error */
1034 if (revision_id >= CHIP_9098_REV_A0)
1035 check_fw_status = MTRUE;
1036 }
1037 #endif
1038 #if defined(SD9097) || defined(SD9177) || defined(SDNW62X)
1039 if (IS_SD9097(pmadapter->card_type) ||
1040 IS_SDNW62X(pmadapter->card_type) || IS_SD9177(pmadapter->card_type))
1041 check_fw_status = MTRUE;
1042 #endif
1043
1044 /* Perform firmware data transfer */
1045 do {
1046 /* The host polls for the DN_LD_CARD_RDY and CARD_IO_READY bits
1047 */
1048 ret = wlan_sdio_poll_card_status(
1049 pmadapter, CARD_IO_READY | DN_LD_CARD_RDY);
1050 if (ret != MLAN_STATUS_SUCCESS) {
1051 PRINTM(MFATAL,
1052 "WLAN: FW download with helper poll status timeout @ %d\n",
1053 offset);
1054 goto done;
1055 }
1056
1057 /* More data */
1058 if (firmwarelen && offset >= firmwarelen)
1059 break;
1060
1061 for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
1062 ret = pcb->moal_read_reg(pmadapter->pmoal_handle,
1063 read_base_0_reg, &base0);
1064 if (ret != MLAN_STATUS_SUCCESS) {
1065 PRINTM(MERROR,
1066 "Dev BASE0 register read failed:"
1067 " base0=0x%04X(%d). Terminating download\n",
1068 base0, base0);
1069 goto done;
1070 }
1071 ret = pcb->moal_read_reg(pmadapter->pmoal_handle,
1072 read_base_1_reg, &base1);
1073 if (ret != MLAN_STATUS_SUCCESS) {
1074 PRINTM(MERROR,
1075 "Dev BASE1 register read failed:"
1076 " base1=0x%04X(%d). Terminating download\n",
1077 base1, base1);
1078 goto done;
1079 }
1080 len = (t_u16)(((base1 & 0xff) << 8) | (base0 & 0xff));
1081
1082 if (len)
1083 break;
1084 wlan_udelay(pmadapter, 10);
1085 }
1086
1087 if (!len)
1088 break;
1089 else if (len > WLAN_UPLD_SIZE) {
1090 PRINTM(MFATAL,
1091 "WLAN: FW download failure @ %d, invalid length %d\n",
1092 offset, len);
1093 ret = MLAN_STATUS_FAILURE;
1094 goto done;
1095 }
1096
1097 /* Ignore CRC check before download the 1st packet */
1098 if (offset == 0 && (len & MBIT(0)))
1099 len &= ~MBIT(0);
1100
1101 txlen = len;
1102
1103 if (len & MBIT(0)) {
1104 /* New fw download process, check CRC and MIC error */
1105 if (check_fw_status) {
1106 /* Get offset from fw dnld offset Register */
1107 ret = wlan_sdio_read_fw_dnld_offset(
1108 pmadapter, &fw_dnld_offset);
1109 if (ret != MLAN_STATUS_SUCCESS) {
1110 PRINTM(MFATAL,
1111 "WLAN: FW download with helper read fw dnld offset failed @ %d\n",
1112 offset);
1113 goto done;
1114 }
1115 /* Get CRC MIC error from fw dnld status
1116 * Register */
1117 ret = wlan_sdio_read_fw_dnld_status(
1118 pmadapter, &fw_dnld_status);
1119 if (ret != MLAN_STATUS_SUCCESS) {
1120 PRINTM(MFATAL,
1121 "WLAN: FW download with helper read fw dnld status failed @ %d\n",
1122 offset);
1123 goto done;
1124 }
1125 PRINTM(MERROR,
1126 "WLAN: FW download error: status=0x%x offset = 0x%x fw offset = 0x%x\n",
1127 fw_dnld_status, offset, fw_dnld_offset);
1128 }
1129 i++;
1130 if (i > MAX_WRITE_IOMEM_RETRY) {
1131 PRINTM(MFATAL,
1132 "WLAN: FW download failure @ %d, over max retry count\n",
1133 offset);
1134 ret = MLAN_STATUS_FAILURE;
1135 goto done;
1136 }
1137
1138 PRINTM(MERROR,
1139 "WLAN: FW CRC error indicated by the helper:"
1140 " len = 0x%04X, txlen = %d\n",
1141 len, txlen);
1142 len &= ~MBIT(0);
1143 if (fw_dnld_status & (MBIT(6) | MBIT(7))) {
1144 offset = 0;
1145 mic_retry++;
1146 if (mic_retry > MAX_FW_RETRY) {
1147 PRINTM(MFATAL,
1148 "WLAN: FW download failure @ %d, over max mic retry count\n",
1149 offset);
1150 ret = MLAN_STATUS_FAILURE;
1151 goto done;
1152 }
1153 }
1154 PRINTM(MERROR, "WLAN: retry: %d, offset %d\n", i,
1155 offset);
1156 DBG_HEXDUMP(MERROR, "WLAN: FW block:", fwbuf, len);
1157 /* Setting this to 0 to resend from same offset */
1158 txlen = 0;
1159 } else {
1160 i = 0;
1161
1162 /* Set blocksize to transfer - checking
1163 * for last block */
1164 if (firmwarelen && firmwarelen - offset < txlen)
1165 txlen = firmwarelen - offset;
1166 PRINTM(MINFO, ".");
1167
1168 tx_blocks = (txlen + MLAN_SDIO_BLOCK_SIZE_FW_DNLD - 1) /
1169 MLAN_SDIO_BLOCK_SIZE_FW_DNLD;
1170
1171 /* Copy payload to buffer */
1172 if (firmware)
1173 memmove(pmadapter, fwbuf, &firmware[offset],
1174 txlen);
1175 else
1176 pcb->moal_get_fw_data(pmadapter->pmoal_handle,
1177 offset, txlen, fwbuf);
1178 }
1179
1180 /* Send data */
1181 memset(pmadapter, &mbuf, 0, sizeof(mlan_buffer));
1182 mbuf.pbuf = (t_u8 *)fwbuf;
1183 mbuf.data_len = tx_blocks * MLAN_SDIO_BLOCK_SIZE_FW_DNLD;
1184
1185 ret = pcb->moal_write_data_sync(pmadapter->pmoal_handle, &mbuf,
1186 pmadapter->pcard_sd->ioport, 0);
1187 if (ret != MLAN_STATUS_SUCCESS) {
1188 PRINTM(MERROR,
1189 "WLAN: FW download, write iomem (%d) failed @ %d\n",
1190 i, offset);
1191 if (pcb->moal_write_reg(pmadapter->pmoal_handle,
1192 HOST_TO_CARD_EVENT_REG,
1193 HOST_TERM_CMD53) !=
1194 MLAN_STATUS_SUCCESS) {
1195 PRINTM(MERROR, "write CFG reg failed\n");
1196 }
1197 ret = MLAN_STATUS_FAILURE;
1198 goto done;
1199 }
1200
1201 offset += txlen;
1202 } while (MTRUE);
1203
1204 PRINTM(MMSG, "Wlan: FW download over, firmwarelen=%d downloaded %d\n",
1205 firmwarelen, offset);
1206
1207 ret = MLAN_STATUS_SUCCESS;
1208 done:
1209 if (tmpfwbuf)
1210 pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)tmpfwbuf);
1211
1212 LEAVE();
1213 return ret;
1214 }
1215
1216 /**
1217 * @brief This function disables the host interrupts.
1218 *
1219 * @param pmadapter A pointer to mlan_adapter structure
1220 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1221 */
wlan_disable_sdio_host_int(pmlan_adapter pmadapter)1222 static mlan_status wlan_disable_sdio_host_int(pmlan_adapter pmadapter)
1223 {
1224 mlan_status ret;
1225
1226 ENTER();
1227 ret = wlan_sdio_disable_host_int_mask(pmadapter, HIM_DISABLE);
1228 LEAVE();
1229 return ret;
1230 }
1231
1232 /**
1233 * @brief This function decodes the rx packet &
1234 * calls corresponding handlers according to the packet type
1235 *
1236 * @param pmadapter A pointer to mlan_adapter structure
1237 * @param pmbuf A pointer to the SDIO data/cmd buffer
1238 * @param upld_typ Type of rx packet
1239 * @param lock_flag flag for spin_lock.
1240 * @return MLAN_STATUS_SUCCESS
1241 */
wlan_decode_rx_packet(mlan_adapter * pmadapter,mlan_buffer * pmbuf,t_u32 upld_typ,t_u8 lock_flag)1242 static mlan_status wlan_decode_rx_packet(mlan_adapter *pmadapter,
1243 mlan_buffer *pmbuf, t_u32 upld_typ,
1244 t_u8 lock_flag)
1245 {
1246 t_u8 *cmd_buf;
1247 t_u32 event;
1248 t_u32 in_ts_sec, in_ts_usec;
1249 pmlan_callbacks pcb = &pmadapter->callbacks;
1250
1251 ENTER();
1252
1253 switch (upld_typ) {
1254 case MLAN_TYPE_SPA_DATA:
1255 PRINTM(MINFO, "--- Rx: SPA Data packet ---\n");
1256 pmbuf->data_len = pmadapter->upld_len;
1257 if (pmadapter->rx_work_flag) {
1258 pmbuf->buf_type = MLAN_BUF_TYPE_SPA_DATA;
1259 if (lock_flag)
1260 pmadapter->callbacks.moal_spin_lock(
1261 pmadapter->pmoal_handle,
1262 pmadapter->rx_data_queue.plock);
1263 util_enqueue_list_tail(pmadapter->pmoal_handle,
1264 &pmadapter->rx_data_queue,
1265 (pmlan_linked_list)pmbuf, MNULL,
1266 MNULL);
1267 pmadapter->rx_pkts_queued++;
1268 if (lock_flag)
1269 pmadapter->callbacks.moal_spin_unlock(
1270 pmadapter->pmoal_handle,
1271 pmadapter->rx_data_queue.plock);
1272 } else {
1273 wlan_decode_spa_buffer(pmadapter,
1274 pmbuf->pbuf + pmbuf->data_offset,
1275 pmbuf->data_len);
1276 wlan_free_mlan_buffer(pmadapter, pmbuf);
1277 }
1278 pmadapter->data_received = MTRUE;
1279 break;
1280 case MLAN_TYPE_DATA:
1281 PRINTM(MINFO, "--- Rx: Data packet ---\n");
1282 if (pmadapter->upld_len > pmbuf->data_len) {
1283 PRINTM(MERROR,
1284 "SDIO: Drop packet upld_len=%d data_len=%d \n",
1285 pmadapter->upld_len, pmbuf->data_len);
1286 wlan_free_mlan_buffer(pmadapter, pmbuf);
1287 break;
1288 }
1289 pmbuf->data_len = (pmadapter->upld_len - SDIO_INTF_HEADER_LEN);
1290 pmbuf->data_offset += SDIO_INTF_HEADER_LEN;
1291 if (pmadapter->rx_work_flag) {
1292 // rx_trace 5
1293 if (pmadapter->tp_state_on) {
1294 pmadapter->callbacks.moal_tp_accounting(
1295 pmadapter->pmoal_handle, pmbuf,
1296 5 /*RX_DROP_P1*/);
1297 pcb->moal_get_system_time(
1298 pmadapter->pmoal_handle, &in_ts_sec,
1299 &in_ts_usec);
1300 pmbuf->in_ts_sec = in_ts_sec;
1301 pmbuf->in_ts_usec = in_ts_usec;
1302 }
1303 if (pmadapter->tp_state_drop_point ==
1304 5 /*RX_DROP_P1*/) {
1305 pmadapter->ops.data_complete(
1306 pmadapter, pmbuf, MLAN_STATUS_SUCCESS);
1307 } else {
1308 if (lock_flag)
1309 pmadapter->callbacks.moal_spin_lock(
1310 pmadapter->pmoal_handle,
1311 pmadapter->rx_data_queue.plock);
1312 util_enqueue_list_tail(
1313 pmadapter->pmoal_handle,
1314 &pmadapter->rx_data_queue,
1315 (pmlan_linked_list)pmbuf, MNULL, MNULL);
1316 pmadapter->rx_pkts_queued++;
1317 if (pmadapter->tp_state_on)
1318 pmadapter->callbacks
1319 .moal_tp_accounting_rx_param(
1320 pmadapter->pmoal_handle,
1321 1,
1322 pmadapter
1323 ->rx_pkts_queued);
1324 if (lock_flag)
1325 pmadapter->callbacks.moal_spin_unlock(
1326 pmadapter->pmoal_handle,
1327 pmadapter->rx_data_queue.plock);
1328 }
1329 } else {
1330 wlan_handle_rx_packet(pmadapter, pmbuf);
1331 }
1332 pmadapter->data_received = MTRUE;
1333 break;
1334
1335 case MLAN_TYPE_CMD:
1336 PRINTM(MINFO, "--- Rx: Cmd Response ---\n");
1337 if (pmadapter->cmd_sent)
1338 pmadapter->cmd_sent = MFALSE;
1339 /* take care of curr_cmd = NULL case */
1340 if (!pmadapter->curr_cmd) {
1341 cmd_buf = pmadapter->upld_buf;
1342 if (pmadapter->ps_state == PS_STATE_SLEEP_CFM) {
1343 wlan_process_sleep_confirm_resp(
1344 pmadapter,
1345 pmbuf->pbuf + pmbuf->data_offset +
1346 SDIO_INTF_HEADER_LEN,
1347 pmadapter->upld_len -
1348 SDIO_INTF_HEADER_LEN);
1349 }
1350 pmadapter->upld_len -= SDIO_INTF_HEADER_LEN;
1351 memcpy_ext(pmadapter, cmd_buf,
1352 pmbuf->pbuf + pmbuf->data_offset +
1353 SDIO_INTF_HEADER_LEN,
1354 pmadapter->upld_len - SDIO_INTF_HEADER_LEN,
1355 MRVDRV_SIZE_OF_CMD_BUFFER);
1356 wlan_free_mlan_buffer(pmadapter, pmbuf);
1357 } else {
1358 pmadapter->cmd_resp_received = MTRUE;
1359 pmadapter->upld_len -= SDIO_INTF_HEADER_LEN;
1360 pmbuf->data_len = pmadapter->upld_len;
1361 pmbuf->data_offset += SDIO_INTF_HEADER_LEN;
1362 pmadapter->curr_cmd->respbuf = pmbuf;
1363 if (pmadapter->upld_len >= MRVDRV_SIZE_OF_CMD_BUFFER) {
1364 PRINTM(MMSG, "Invalid CmdResp len=%d\n",
1365 pmadapter->upld_len);
1366 DBG_HEXDUMP(MERROR, "Invalid CmdResp",
1367 pmbuf->pbuf + pmbuf->data_offset,
1368 MAX_DATA_DUMP_LEN);
1369 }
1370 }
1371 break;
1372
1373 case MLAN_TYPE_EVENT:
1374 PRINTM(MINFO, "--- Rx: Event ---\n");
1375 event = *(t_u32 *)&pmbuf->pbuf[pmbuf->data_offset +
1376 SDIO_INTF_HEADER_LEN];
1377 pmadapter->event_cause = wlan_le32_to_cpu(event);
1378 if ((pmadapter->upld_len > MLAN_EVENT_HEADER_LEN) &&
1379 ((pmadapter->upld_len - MLAN_EVENT_HEADER_LEN) <
1380 MAX_EVENT_SIZE)) {
1381 memcpy_ext(pmadapter, pmadapter->event_body,
1382 pmbuf->pbuf + pmbuf->data_offset +
1383 MLAN_EVENT_HEADER_LEN,
1384 pmadapter->upld_len - MLAN_EVENT_HEADER_LEN,
1385 MAX_EVENT_SIZE);
1386 }
1387
1388 /* event cause has been saved to adapter->event_cause */
1389 pmadapter->event_received = MTRUE;
1390 pmbuf->data_len = pmadapter->upld_len;
1391 pmadapter->pmlan_buffer_event = pmbuf;
1392
1393 /* remove SDIO header */
1394 pmbuf->data_offset += SDIO_INTF_HEADER_LEN;
1395 pmbuf->data_len -= SDIO_INTF_HEADER_LEN;
1396 break;
1397
1398 default:
1399 PRINTM(MERROR, "SDIO unknown upload type = 0x%x\n", upld_typ);
1400 wlan_free_mlan_buffer(pmadapter, pmbuf);
1401 break;
1402 }
1403
1404 LEAVE();
1405 return MLAN_STATUS_SUCCESS;
1406 }
1407
1408 /**
1409 * @brief This function receives single packet
1410 *
1411 * @param pmadapter A pointer to mlan_adapter structure
1412 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1413 */
wlan_receive_single_packet(mlan_adapter * pmadapter)1414 static mlan_status wlan_receive_single_packet(mlan_adapter *pmadapter)
1415 {
1416 mlan_buffer *pmbuf;
1417 t_u8 port;
1418 t_u16 rx_len;
1419 t_u32 pkt_type = 0;
1420 mlan_status ret = MLAN_STATUS_SUCCESS;
1421
1422 ENTER();
1423 pmbuf = pmadapter->pcard_sd->mpa_rx.mbuf_arr[0];
1424 port = pmadapter->pcard_sd->mpa_rx.start_port;
1425 rx_len = pmadapter->pcard_sd->mpa_rx.len_arr[0];
1426 if (MLAN_STATUS_SUCCESS !=
1427 wlan_sdio_card_to_host(pmadapter, &pkt_type,
1428 (t_u32 *)&pmadapter->upld_len, pmbuf, rx_len,
1429 pmadapter->pcard_sd->ioport + port)) {
1430 ret = MLAN_STATUS_FAILURE;
1431 goto done;
1432 }
1433 if (pkt_type != MLAN_TYPE_DATA && pkt_type != MLAN_TYPE_SPA_DATA) {
1434 PRINTM(MERROR,
1435 "receive a wrong pkt from DATA PORT: type=%d, len=%dd\n",
1436 pkt_type, pmbuf->data_len);
1437 pmbuf->status_code = MLAN_ERROR_DATA_RX_FAIL;
1438 ret = MLAN_STATUS_FAILURE;
1439 goto done;
1440 }
1441 pmadapter->pcard_sd->mpa_rx_count[0]++;
1442 wlan_decode_rx_packet(pmadapter, pmbuf, pkt_type, MTRUE);
1443 done:
1444 if (ret != MLAN_STATUS_SUCCESS)
1445 wlan_free_mlan_buffer(pmadapter, pmbuf);
1446 MP_RX_AGGR_BUF_RESET(pmadapter);
1447 LEAVE();
1448 return ret;
1449 }
1450
1451 /**
1452 * @brief This function receives data from the card in aggregate mode.
1453 *
1454 * @param pmadapter A pointer to mlan_adapter structure
1455 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1456 */
wlan_receive_mp_aggr_buf(mlan_adapter * pmadapter)1457 static mlan_status wlan_receive_mp_aggr_buf(mlan_adapter *pmadapter)
1458 {
1459 mlan_status ret = MLAN_STATUS_SUCCESS;
1460 pmlan_callbacks pcb = &pmadapter->callbacks;
1461 mlan_buffer mbuf_aggr;
1462 mlan_buffer *mbuf_deaggr;
1463 t_u32 pind = 0;
1464 t_u32 pkt_len, pkt_type = 0;
1465 t_u8 *curr_ptr;
1466 t_u32 cmd53_port = 0;
1467 t_u32 i = 0;
1468 t_u32 port_count = 0;
1469 t_bool new_mode = pmadapter->pcard_sd->supports_sdio_new_mode;
1470
1471 /* do aggr RX now */
1472 PRINTM(MINFO, "do_rx_aggr: num of packets: %d\n",
1473 pmadapter->pcard_sd->mpa_rx.pkt_cnt);
1474
1475 memset(pmadapter, &mbuf_aggr, 0, sizeof(mlan_buffer));
1476
1477 if (pmadapter->pcard_sd->mpa_rx.pkt_cnt == 1)
1478 return wlan_receive_single_packet(pmadapter);
1479 if (!pmadapter->pcard_sd->mpa_rx.buf) {
1480 mbuf_aggr.data_len = pmadapter->pcard_sd->mpa_rx.buf_len;
1481 mbuf_aggr.pnext = mbuf_aggr.pprev = &mbuf_aggr;
1482 mbuf_aggr.use_count = 0;
1483 for (pind = 0; pind < pmadapter->pcard_sd->mpa_rx.pkt_cnt;
1484 pind++) {
1485 pmadapter->pcard_sd->mpa_rx.mbuf_arr[pind]->data_len =
1486 pmadapter->pcard_sd->mpa_rx.len_arr[pind];
1487 wlan_link_buf_to_aggr(
1488 &mbuf_aggr,
1489 pmadapter->pcard_sd->mpa_rx.mbuf_arr[pind]);
1490 }
1491 } else {
1492 mbuf_aggr.pbuf = (t_u8 *)pmadapter->pcard_sd->mpa_rx.buf;
1493 mbuf_aggr.data_len = pmadapter->pcard_sd->mpa_rx.buf_len;
1494 }
1495
1496 if (new_mode) {
1497 port_count = bitcount(pmadapter->pcard_sd->mpa_rx.ports) - 1;
1498 /* port_count = pmadapter->mpa_rx.pkt_cnt - 1; */
1499 cmd53_port = (pmadapter->pcard_sd->ioport | SDIO_MPA_ADDR_BASE |
1500 (port_count << 8)) +
1501 pmadapter->pcard_sd->mpa_rx.start_port;
1502 } else {
1503 cmd53_port = (pmadapter->pcard_sd->ioport | SDIO_MPA_ADDR_BASE |
1504 (pmadapter->pcard_sd->mpa_rx.ports << 4)) +
1505 pmadapter->pcard_sd->mpa_rx.start_port;
1506 }
1507 do {
1508 ret = pcb->moal_read_data_sync(pmadapter->pmoal_handle,
1509 &mbuf_aggr, cmd53_port, 0);
1510 if (ret != MLAN_STATUS_SUCCESS) {
1511 PRINTM(MERROR,
1512 "wlan: sdio mp cmd53 read failed: %d ioport=0x%x retry=%d\n",
1513 ret, cmd53_port, i);
1514 i++;
1515 if (MLAN_STATUS_SUCCESS !=
1516 pcb->moal_write_reg(pmadapter->pmoal_handle,
1517 HOST_TO_CARD_EVENT_REG,
1518 HOST_TERM_CMD53)) {
1519 PRINTM(MERROR, "Set Term cmd53 failed\n");
1520 }
1521 if (i > MAX_WRITE_IOMEM_RETRY) {
1522 ret = MLAN_STATUS_FAILURE;
1523 goto done;
1524 }
1525 }
1526 } while (ret == MLAN_STATUS_FAILURE);
1527 if (pmadapter->rx_work_flag)
1528 pmadapter->callbacks.moal_spin_lock(
1529 pmadapter->pmoal_handle,
1530 pmadapter->rx_data_queue.plock);
1531 if (!pmadapter->pcard_sd->mpa_rx.buf &&
1532 pmadapter->pcard_sd->mpa_rx.pkt_cnt > 1) {
1533 for (pind = 0; pind < pmadapter->pcard_sd->mpa_rx.pkt_cnt;
1534 pind++) {
1535 mbuf_deaggr =
1536 pmadapter->pcard_sd->mpa_rx.mbuf_arr[pind];
1537 pkt_len = wlan_le16_to_cpu(
1538 *(t_u16 *)(mbuf_deaggr->pbuf +
1539 mbuf_deaggr->data_offset));
1540 pkt_type = wlan_le16_to_cpu(
1541 *(t_u16 *)(mbuf_deaggr->pbuf +
1542 mbuf_deaggr->data_offset + 2));
1543 pmadapter->upld_len = pkt_len;
1544 wlan_decode_rx_packet(pmadapter, mbuf_deaggr, pkt_type,
1545 MFALSE);
1546 }
1547 } else {
1548 DBG_HEXDUMP(MIF_D, "SDIO MP-A Blk Rd",
1549 pmadapter->pcard_sd->mpa_rx.buf,
1550 MIN(pmadapter->pcard_sd->mpa_rx.buf_len,
1551 MAX_DATA_DUMP_LEN));
1552
1553 curr_ptr = pmadapter->pcard_sd->mpa_rx.buf;
1554
1555 for (pind = 0; pind < pmadapter->pcard_sd->mpa_rx.pkt_cnt;
1556 pind++) {
1557 /* get curr PKT len & type */
1558 pkt_len = wlan_le16_to_cpu(*(t_u16 *)&curr_ptr[0]);
1559 pkt_type = wlan_le16_to_cpu(*(t_u16 *)&curr_ptr[2]);
1560
1561 PRINTM(MINFO, "RX: [%d] pktlen: %d pkt_type: 0x%x\n",
1562 pind, pkt_len, pkt_type);
1563
1564 /* copy pkt to deaggr buf */
1565 mbuf_deaggr =
1566 pmadapter->pcard_sd->mpa_rx.mbuf_arr[pind];
1567 if ((pkt_type == MLAN_TYPE_DATA ||
1568 pkt_type == MLAN_TYPE_SPA_DATA) &&
1569 (pkt_len <=
1570 pmadapter->pcard_sd->mpa_rx.len_arr[pind])) {
1571 memcpy_ext(pmadapter,
1572 mbuf_deaggr->pbuf +
1573 mbuf_deaggr->data_offset,
1574 curr_ptr, pkt_len, pkt_len);
1575 pmadapter->upld_len = pkt_len;
1576 /* Process de-aggr packet */
1577 wlan_decode_rx_packet(pmadapter, mbuf_deaggr,
1578 pkt_type, MFALSE);
1579 } else {
1580 PRINTM(MERROR,
1581 "Wrong aggr packet: type=%d, len=%d, max_len=%d\n",
1582 pkt_type, pkt_len,
1583 pmadapter->pcard_sd->mpa_rx
1584 .len_arr[pind]);
1585 wlan_free_mlan_buffer(pmadapter, mbuf_deaggr);
1586 }
1587 curr_ptr += pmadapter->pcard_sd->mpa_rx.len_arr[pind];
1588 }
1589 }
1590 if (pmadapter->rx_work_flag)
1591 pmadapter->callbacks.moal_spin_unlock(
1592 pmadapter->pmoal_handle,
1593 pmadapter->rx_data_queue.plock);
1594 pmadapter->pcard_sd
1595 ->mpa_rx_count[pmadapter->pcard_sd->mpa_rx.pkt_cnt - 1]++;
1596 MP_RX_AGGR_BUF_RESET(pmadapter);
1597 done:
1598 return ret;
1599 }
1600
1601 /**
1602 * @brief This function receives data from the card in aggregate mode.
1603 *
1604 * @param pmadapter A pointer to mlan_adapter structure
1605 * @param pmbuf A pointer to the SDIO data/cmd buffer
1606 * @param port Current port on which packet needs to be rxed
1607 * @param rx_len Length of received packet
1608 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1609 */
wlan_sdio_card_to_host_mp_aggr(mlan_adapter * pmadapter,mlan_buffer * pmbuf,t_u8 port,t_u16 rx_len)1610 static mlan_status wlan_sdio_card_to_host_mp_aggr(mlan_adapter *pmadapter,
1611 mlan_buffer *pmbuf, t_u8 port,
1612 t_u16 rx_len)
1613 {
1614 mlan_status ret = MLAN_STATUS_SUCCESS;
1615 t_s32 f_do_rx_aggr = 0;
1616 t_s32 f_do_rx_cur = 0;
1617 t_s32 f_aggr_cur = 0;
1618 t_s32 f_post_aggr_cur = 0;
1619 t_u32 pind = 0;
1620 t_u32 pkt_type = 0;
1621 const mlan_sdio_card_reg *reg = pmadapter->pcard_sd->reg;
1622 t_bool new_mode = pmadapter->pcard_sd->supports_sdio_new_mode;
1623
1624 ENTER();
1625 if (!new_mode && (port == CTRL_PORT)) {
1626 /* Read the command response or event without aggr */
1627 PRINTM(MINFO,
1628 "card_2_host_mp_aggr: No aggr for control port\n");
1629
1630 f_do_rx_cur = 1;
1631 goto rx_curr_single;
1632 }
1633
1634 if (!pmadapter->pcard_sd->mpa_rx.enabled) {
1635 PRINTM(MINFO,
1636 "card_2_host_mp_aggr: rx aggregation disabled !\n");
1637
1638 f_do_rx_cur = 1;
1639 goto rx_curr_single;
1640 }
1641 if ((new_mode &&
1642 (pmadapter->pcard_sd->mp_rd_bitmap & reg->data_port_mask)) ||
1643 (!new_mode && (pmadapter->pcard_sd->mp_rd_bitmap &
1644 (~((t_u32)CTRL_PORT_MASK))))) {
1645 /* Some more data RX pending */
1646 PRINTM(MINFO, "card_2_host_mp_aggr: Not last packet\n");
1647
1648 if (MP_RX_AGGR_IN_PROGRESS(pmadapter)) {
1649 if (MP_RX_AGGR_BUF_HAS_ROOM(pmadapter, rx_len)) {
1650 f_aggr_cur = 1;
1651 } else {
1652 /* No room in Aggr buf, do rx aggr now */
1653 f_do_rx_aggr = 1;
1654 f_post_aggr_cur = 1;
1655 }
1656 } else {
1657 /* Rx aggr not in progress */
1658 f_aggr_cur = 1;
1659 }
1660
1661 } else {
1662 /* No more data RX pending */
1663 PRINTM(MINFO, "card_2_host_mp_aggr: Last packet\n");
1664
1665 if (MP_RX_AGGR_IN_PROGRESS(pmadapter)) {
1666 f_do_rx_aggr = 1;
1667 if (MP_RX_AGGR_BUF_HAS_ROOM(pmadapter, rx_len)) {
1668 f_aggr_cur = 1;
1669 } else {
1670 /* No room in Aggr buf, do rx aggr now */
1671 f_do_rx_cur = 1;
1672 }
1673 } else {
1674 f_do_rx_cur = 1;
1675 }
1676 }
1677
1678 if (f_aggr_cur) {
1679 PRINTM(MINFO, "Current packet aggregation.\n");
1680 /* Curr pkt can be aggregated */
1681 if (new_mode)
1682 MP_RX_AGGR_SETUP(pmadapter, pmbuf, port, rx_len);
1683 else
1684 MP_RX_AGGR_SETUP_NONEWMODE(pmadapter, pmbuf, port,
1685 rx_len);
1686 if (MP_RX_AGGR_PKT_LIMIT_REACHED(pmadapter) ||
1687 ((new_mode && MP_RX_AGGR_PORT_LIMIT_REACHED(pmadapter)) ||
1688 (!new_mode &&
1689 MP_RX_AGGR_PORT_LIMIT_REACHED_NONEWMODE(pmadapter)))) {
1690 PRINTM(MINFO,
1691 "card_2_host_mp_aggr: Aggregation Packet limit reached\n");
1692 /* No more pkts allowed in Aggr buf, rx it */
1693 f_do_rx_aggr = 1;
1694 }
1695 }
1696
1697 if (f_do_rx_aggr) {
1698 /* do aggr RX now */
1699 if (MLAN_STATUS_SUCCESS !=
1700 wlan_receive_mp_aggr_buf(pmadapter)) {
1701 ret = MLAN_STATUS_FAILURE;
1702 goto done;
1703 }
1704 }
1705 rx_curr_single:
1706 if (f_do_rx_cur) {
1707 PRINTM(MINFO, "RX: f_do_rx_cur: port: %d rx_len: %d\n", port,
1708 rx_len);
1709
1710 if (MLAN_STATUS_SUCCESS !=
1711 wlan_sdio_card_to_host(
1712 pmadapter, &pkt_type, (t_u32 *)&pmadapter->upld_len,
1713 pmbuf, rx_len,
1714 pmadapter->pcard_sd->ioport + port)) {
1715 ret = MLAN_STATUS_FAILURE;
1716 goto done;
1717 }
1718 if (!new_mode &&
1719 ((port == CTRL_PORT) && ((pkt_type != MLAN_TYPE_EVENT) &&
1720 (pkt_type != MLAN_TYPE_CMD)))) {
1721 PRINTM(MERROR,
1722 "Wrong pkt from CTRL PORT: type=%d, len=%dd\n",
1723 pkt_type, pmbuf->data_len);
1724 pmbuf->status_code = MLAN_ERROR_DATA_RX_FAIL;
1725 ret = MLAN_STATUS_FAILURE;
1726 goto done;
1727 }
1728 if (new_mode || (port != CTRL_PORT)) {
1729 if (pkt_type != MLAN_TYPE_DATA &&
1730 pkt_type != MLAN_TYPE_SPA_DATA) {
1731 PRINTM(MERROR,
1732 "receive a wrong pkt from DATA PORT: type=%d, len=%dd\n",
1733 pkt_type, pmbuf->data_len);
1734 pmbuf->status_code = MLAN_ERROR_DATA_RX_FAIL;
1735 ret = MLAN_STATUS_FAILURE;
1736 goto done;
1737 }
1738 }
1739
1740 if (new_mode || (port != CTRL_PORT))
1741 pmadapter->pcard_sd->mpa_rx_count[0]++;
1742
1743 wlan_decode_rx_packet(pmadapter, pmbuf, pkt_type, MTRUE);
1744 }
1745 if (f_post_aggr_cur) {
1746 PRINTM(MINFO, "Current packet aggregation.\n");
1747 /* Curr pkt can be aggregated */
1748 if (new_mode)
1749 MP_RX_AGGR_SETUP(pmadapter, pmbuf, port, rx_len);
1750 else
1751 MP_RX_AGGR_SETUP_NONEWMODE(pmadapter, pmbuf, port,
1752 rx_len);
1753 }
1754 done:
1755 if (ret == MLAN_STATUS_FAILURE) {
1756 if (MP_RX_AGGR_IN_PROGRESS(pmadapter)) {
1757 /* MP-A transfer failed - cleanup */
1758 for (pind = 0;
1759 pind < pmadapter->pcard_sd->mpa_rx.pkt_cnt;
1760 pind++) {
1761 wlan_free_mlan_buffer(
1762 pmadapter, pmadapter->pcard_sd->mpa_rx
1763 .mbuf_arr[pind]);
1764 }
1765 MP_RX_AGGR_BUF_RESET(pmadapter);
1766 }
1767
1768 if (f_do_rx_cur) {
1769 /* Single Transfer pending */
1770 /* Free curr buff also */
1771 wlan_free_mlan_buffer(pmadapter, pmbuf);
1772 }
1773 }
1774
1775 LEAVE();
1776 return ret;
1777 }
1778
1779 /**
1780 * @brief This function sends aggr buf
1781 *
1782 * @param pmadapter A pointer to mlan_adapter structure
1783 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1784 */
wlan_send_mp_aggr_buf(mlan_adapter * pmadapter)1785 mlan_status wlan_send_mp_aggr_buf(mlan_adapter *pmadapter)
1786 {
1787 mlan_status ret = MLAN_STATUS_SUCCESS;
1788 t_u32 cmd53_port = 0;
1789 t_u32 port_count = 0;
1790 mlan_buffer mbuf_aggr;
1791 t_u8 i = 0;
1792 t_u8 mp_aggr_pkt_limit = pmadapter->pcard_sd->mp_aggr_pkt_limit;
1793 t_bool new_mode = pmadapter->pcard_sd->supports_sdio_new_mode;
1794
1795 ENTER();
1796
1797 if (!pmadapter->pcard_sd->mpa_tx.pkt_cnt) {
1798 LEAVE();
1799 return ret;
1800 }
1801 PRINTM(MINFO,
1802 "host_2_card_mp_aggr: Send aggregation buffer."
1803 "%d %d\n",
1804 pmadapter->pcard_sd->mpa_tx.start_port,
1805 pmadapter->pcard_sd->mpa_tx.ports);
1806
1807 memset(pmadapter, &mbuf_aggr, 0, sizeof(mlan_buffer));
1808
1809 if (!pmadapter->pcard_sd->mpa_tx.buf &&
1810 pmadapter->pcard_sd->mpa_tx.pkt_cnt > 1) {
1811 mbuf_aggr.data_len = pmadapter->pcard_sd->mpa_tx.buf_len;
1812 mbuf_aggr.pnext = mbuf_aggr.pprev = &mbuf_aggr;
1813 mbuf_aggr.use_count = 0;
1814 for (i = 0; i < pmadapter->pcard_sd->mpa_tx.pkt_cnt; i++)
1815 wlan_link_buf_to_aggr(
1816 &mbuf_aggr,
1817 pmadapter->pcard_sd->mpa_tx.mbuf_arr[i]);
1818 } else {
1819 mbuf_aggr.pbuf = (t_u8 *)pmadapter->pcard_sd->mpa_tx.buf;
1820 mbuf_aggr.data_len = pmadapter->pcard_sd->mpa_tx.buf_len;
1821 }
1822
1823 if (new_mode) {
1824 port_count = bitcount(pmadapter->pcard_sd->mpa_tx.ports) - 1;
1825 cmd53_port = (pmadapter->pcard_sd->ioport | SDIO_MPA_ADDR_BASE |
1826 (port_count << 8)) +
1827 pmadapter->pcard_sd->mpa_tx.start_port;
1828 } else {
1829 cmd53_port = (pmadapter->pcard_sd->ioport | SDIO_MPA_ADDR_BASE |
1830 (pmadapter->pcard_sd->mpa_tx.ports << 4)) +
1831 pmadapter->pcard_sd->mpa_tx.start_port;
1832 }
1833 if (pmadapter->pcard_sd->mpa_tx.pkt_cnt == 1)
1834 cmd53_port = pmadapter->pcard_sd->ioport +
1835 pmadapter->pcard_sd->mpa_tx.start_port;
1836 /** only one packet */
1837 if (!pmadapter->pcard_sd->mpa_tx.buf &&
1838 pmadapter->pcard_sd->mpa_tx.pkt_cnt == 1)
1839 ret = wlan_write_data_sync(
1840 pmadapter, pmadapter->pcard_sd->mpa_tx.mbuf_arr[0],
1841 cmd53_port);
1842 else
1843 ret = wlan_write_data_sync(pmadapter, &mbuf_aggr, cmd53_port);
1844 if (!pmadapter->pcard_sd->mpa_tx.buf) {
1845 /** free mlan buffer */
1846 for (i = 0; i < pmadapter->pcard_sd->mpa_tx.pkt_cnt; i++) {
1847 wlan_write_data_complete(
1848 pmadapter,
1849 pmadapter->pcard_sd->mpa_tx.mbuf_arr[i],
1850 MLAN_STATUS_SUCCESS);
1851 }
1852 }
1853 if (!(pmadapter->pcard_sd->mp_wr_bitmap &
1854 (1 << pmadapter->pcard_sd->curr_wr_port)) &&
1855 (pmadapter->pcard_sd->mpa_tx.pkt_cnt < mp_aggr_pkt_limit))
1856 pmadapter->pcard_sd->mpa_sent_no_ports++;
1857 pmadapter->pcard_sd
1858 ->mpa_tx_count[pmadapter->pcard_sd->mpa_tx.pkt_cnt - 1]++;
1859 pmadapter->pcard_sd
1860 ->last_mp_wr_bitmap[pmadapter->pcard_sd->last_mp_index] =
1861 pmadapter->pcard_sd->mp_wr_bitmap;
1862 pmadapter->pcard_sd
1863 ->last_mp_wr_ports[pmadapter->pcard_sd->last_mp_index] =
1864 cmd53_port;
1865 pmadapter->pcard_sd->last_mp_wr_len[pmadapter->pcard_sd->last_mp_index] =
1866 pmadapter->pcard_sd->mpa_tx.buf_len;
1867 pmadapter->pcard_sd
1868 ->last_curr_wr_port[pmadapter->pcard_sd->last_mp_index] =
1869 pmadapter->pcard_sd->curr_wr_port;
1870 memcpy_ext(
1871 pmadapter,
1872 (t_u8 *)&pmadapter->pcard_sd
1873 ->last_mp_wr_info[pmadapter->pcard_sd->last_mp_index *
1874 mp_aggr_pkt_limit],
1875 (t_u8 *)pmadapter->pcard_sd->mpa_tx.mp_wr_info,
1876 mp_aggr_pkt_limit * sizeof(t_u16),
1877 mp_aggr_pkt_limit * sizeof(t_u16));
1878 pmadapter->pcard_sd->last_mp_index++;
1879 if (pmadapter->pcard_sd->last_mp_index >= SDIO_MP_DBG_NUM)
1880 pmadapter->pcard_sd->last_mp_index = 0;
1881 MP_TX_AGGR_BUF_RESET(pmadapter);
1882 LEAVE();
1883 return ret;
1884 }
1885
1886 /**
1887 * @brief This function sends data to the card in SDIO aggregated mode.
1888 *
1889 * @param pmadapter A pointer to mlan_adapter structure
1890 * @param mbuf A pointer to the SDIO data/cmd buffer
1891 * @param port current port for aggregation
1892 * @param next_pkt_len Length of next packet used for multiport aggregation
1893 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1894 */
wlan_host_to_card_mp_aggr(mlan_adapter * pmadapter,mlan_buffer * mbuf,t_u8 port,t_u32 next_pkt_len)1895 static mlan_status wlan_host_to_card_mp_aggr(mlan_adapter *pmadapter,
1896 mlan_buffer *mbuf, t_u8 port,
1897 t_u32 next_pkt_len)
1898 {
1899 mlan_status ret = MLAN_STATUS_SUCCESS;
1900 t_s32 f_send_aggr_buf = 0;
1901 t_s32 f_send_cur_buf = 0;
1902 t_s32 f_precopy_cur_buf = 0;
1903 t_s32 f_postcopy_cur_buf = 0;
1904 t_u8 aggr_sg = 0;
1905 t_u8 mp_aggr_pkt_limit = pmadapter->pcard_sd->mp_aggr_pkt_limit;
1906 t_bool new_mode = pmadapter->pcard_sd->supports_sdio_new_mode;
1907
1908 ENTER();
1909
1910 PRINTM(MIF_D, "host_2_card_mp_aggr: next_pkt_len: %d curr_port:%d\n",
1911 next_pkt_len, port);
1912
1913 if (!pmadapter->pcard_sd->mpa_tx.enabled) {
1914 PRINTM(MINFO,
1915 "host_2_card_mp_aggr: tx aggregation disabled !\n");
1916 f_send_cur_buf = 1;
1917 goto tx_curr_single;
1918 }
1919
1920 if (next_pkt_len) {
1921 /* More pkt in TX queue */
1922 PRINTM(MINFO, "host_2_card_mp_aggr: More packets in Queue.\n");
1923
1924 if (MP_TX_AGGR_IN_PROGRESS(pmadapter)) {
1925 if (MP_TX_AGGR_BUF_HAS_ROOM(pmadapter, mbuf,
1926 mbuf->data_len)) {
1927 f_precopy_cur_buf = 1;
1928
1929 if (!(pmadapter->pcard_sd->mp_wr_bitmap &
1930 (1
1931 << pmadapter->pcard_sd->curr_wr_port)) ||
1932 !MP_TX_AGGR_BUF_HAS_ROOM(
1933 pmadapter, mbuf,
1934 mbuf->data_len + next_pkt_len)) {
1935 f_send_aggr_buf = 1;
1936 }
1937 } else {
1938 /* No room in Aggr buf, send it */
1939 f_send_aggr_buf = 1;
1940
1941 if (!(pmadapter->pcard_sd->mp_wr_bitmap &
1942 (1
1943 << pmadapter->pcard_sd->curr_wr_port))) {
1944 f_send_cur_buf = 1;
1945 } else {
1946 f_postcopy_cur_buf = 1;
1947 }
1948 }
1949 } else {
1950 if (MP_TX_AGGR_BUF_HAS_ROOM(pmadapter, mbuf,
1951 mbuf->data_len) &&
1952 (pmadapter->pcard_sd->mp_wr_bitmap &
1953 (1 << pmadapter->pcard_sd->curr_wr_port)))
1954 f_precopy_cur_buf = 1;
1955 else
1956 f_send_cur_buf = 1;
1957 }
1958 } else {
1959 /* Last pkt in TX queue */
1960 PRINTM(MINFO,
1961 "host_2_card_mp_aggr: Last packet in Tx Queue.\n");
1962
1963 if (MP_TX_AGGR_IN_PROGRESS(pmadapter)) {
1964 /* some packs in Aggr buf already */
1965 f_send_aggr_buf = 1;
1966
1967 if (MP_TX_AGGR_BUF_HAS_ROOM(pmadapter, mbuf,
1968 mbuf->data_len)) {
1969 f_precopy_cur_buf = 1;
1970 } else {
1971 /* No room in Aggr buf, send it */
1972 f_send_cur_buf = 1;
1973 }
1974 } else {
1975 f_send_cur_buf = 1;
1976 }
1977 pmadapter->pcard_sd->mpa_sent_last_pkt++;
1978 }
1979
1980 if (f_precopy_cur_buf) {
1981 PRINTM(MINFO, "host_2_card_mp_aggr: Precopy current buffer\n");
1982 if (pmadapter->pcard_sd->mpa_buf)
1983 memcpy_ext(
1984 pmadapter,
1985 pmadapter->pcard_sd->mpa_buf +
1986 (pmadapter->pcard_sd->last_mp_index *
1987 mp_aggr_pkt_limit +
1988 pmadapter->pcard_sd->mpa_tx.pkt_cnt) *
1989 MLAN_SDIO_BLOCK_SIZE,
1990 mbuf->pbuf + mbuf->data_offset,
1991 MLAN_SDIO_BLOCK_SIZE, MLAN_SDIO_BLOCK_SIZE);
1992 if (!pmadapter->pcard_sd->mpa_tx.buf) {
1993 if (new_mode)
1994 MP_TX_AGGR_BUF_PUT_SG(pmadapter, mbuf, port);
1995 else
1996 MP_TX_AGGR_BUF_PUT_SG_NONEWMODE(pmadapter, mbuf,
1997 port);
1998 aggr_sg = MTRUE;
1999 } else {
2000 if (new_mode)
2001 MP_TX_AGGR_BUF_PUT(pmadapter, mbuf, port);
2002 else
2003 MP_TX_AGGR_BUF_PUT_NONEWMODE(pmadapter, mbuf,
2004 port);
2005 }
2006 if (MP_TX_AGGR_PKT_LIMIT_REACHED(pmadapter) ||
2007 (!new_mode && MP_TX_AGGR_PORT_LIMIT_REACHED(pmadapter))) {
2008 PRINTM(MIF_D,
2009 "host_2_card_mp_aggr: Aggregation Pkt limit reached\n");
2010 /* No more pkts allowed in Aggr buf, send it */
2011 f_send_aggr_buf = 1;
2012 }
2013 }
2014
2015 if (f_send_aggr_buf)
2016 ret = wlan_send_mp_aggr_buf(pmadapter);
2017
2018 tx_curr_single:
2019 if (f_send_cur_buf) {
2020 PRINTM(MINFO, "host_2_card_mp_aggr: writing to port #%d\n",
2021 port);
2022 ret = wlan_write_data_sync(pmadapter, mbuf,
2023 pmadapter->pcard_sd->ioport + port);
2024 if (!(pmadapter->pcard_sd->mp_wr_bitmap &
2025 (1 << pmadapter->pcard_sd->curr_wr_port)))
2026 pmadapter->pcard_sd->mpa_sent_no_ports++;
2027 pmadapter->pcard_sd
2028 ->last_mp_wr_bitmap[pmadapter->pcard_sd->last_mp_index] =
2029 pmadapter->pcard_sd->mp_wr_bitmap;
2030 pmadapter->pcard_sd
2031 ->last_mp_wr_ports[pmadapter->pcard_sd->last_mp_index] =
2032 pmadapter->pcard_sd->ioport + port;
2033 pmadapter->pcard_sd
2034 ->last_mp_wr_len[pmadapter->pcard_sd->last_mp_index] =
2035 mbuf->data_len;
2036 memset(pmadapter,
2037 (t_u8 *)&pmadapter->pcard_sd->last_mp_wr_info
2038 [pmadapter->pcard_sd->last_mp_index *
2039 mp_aggr_pkt_limit],
2040 0, sizeof(t_u16) * mp_aggr_pkt_limit);
2041 pmadapter->pcard_sd
2042 ->last_mp_wr_info[pmadapter->pcard_sd->last_mp_index *
2043 mp_aggr_pkt_limit] =
2044 *(t_u16 *)(mbuf->pbuf + mbuf->data_offset);
2045 pmadapter->pcard_sd
2046 ->last_curr_wr_port[pmadapter->pcard_sd->last_mp_index] =
2047 pmadapter->pcard_sd->curr_wr_port;
2048 if (pmadapter->pcard_sd->mpa_buf)
2049 memcpy_ext(pmadapter,
2050 pmadapter->pcard_sd->mpa_buf +
2051 (pmadapter->pcard_sd->last_mp_index *
2052 mp_aggr_pkt_limit *
2053 MLAN_SDIO_BLOCK_SIZE),
2054 mbuf->pbuf + mbuf->data_offset,
2055 MLAN_SDIO_BLOCK_SIZE, MLAN_SDIO_BLOCK_SIZE);
2056 pmadapter->pcard_sd->last_mp_index++;
2057 if (pmadapter->pcard_sd->last_mp_index >= SDIO_MP_DBG_NUM)
2058 pmadapter->pcard_sd->last_mp_index = 0;
2059 pmadapter->pcard_sd->mpa_tx_count[0]++;
2060 }
2061 if (f_postcopy_cur_buf) {
2062 PRINTM(MINFO, "host_2_card_mp_aggr: Postcopy current buffer\n");
2063 if (pmadapter->pcard_sd->mpa_buf)
2064 memcpy_ext(
2065 pmadapter,
2066 pmadapter->pcard_sd->mpa_buf +
2067 (pmadapter->pcard_sd->last_mp_index *
2068 mp_aggr_pkt_limit +
2069 pmadapter->pcard_sd->mpa_tx.pkt_cnt) *
2070 MLAN_SDIO_BLOCK_SIZE,
2071 mbuf->pbuf + mbuf->data_offset,
2072 MLAN_SDIO_BLOCK_SIZE, MLAN_SDIO_BLOCK_SIZE);
2073 if (!pmadapter->pcard_sd->mpa_tx.buf) {
2074 if (new_mode)
2075 MP_TX_AGGR_BUF_PUT_SG(pmadapter, mbuf, port);
2076 else
2077 MP_TX_AGGR_BUF_PUT_SG_NONEWMODE(pmadapter, mbuf,
2078 port);
2079 aggr_sg = MTRUE;
2080 } else {
2081 if (new_mode)
2082 MP_TX_AGGR_BUF_PUT(pmadapter, mbuf, port);
2083 else
2084 MP_TX_AGGR_BUF_PUT_NONEWMODE(pmadapter, mbuf,
2085 port);
2086 }
2087 }
2088 /* Always return PENDING in SG mode */
2089 if (aggr_sg)
2090 ret = MLAN_STATUS_PENDING;
2091
2092 LEAVE();
2093 return ret;
2094 }
2095
2096 /********************************************************
2097 Global functions
2098 ********************************************************/
2099
2100 /**
2101 * @brief This function checks if the interface is ready to download
2102 * or not while other download interface is present
2103 *
2104 * @param pmadapter A pointer to mlan_adapter structure
2105 * @param val Winner status (0: winner)
2106 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
2107 *
2108 */
wlan_sdio_check_winner_status(mlan_adapter * pmadapter,t_u32 * val)2109 static mlan_status wlan_sdio_check_winner_status(mlan_adapter *pmadapter,
2110 t_u32 *val)
2111 {
2112 t_u32 winner = 0;
2113 pmlan_callbacks pcb;
2114 t_u8 card_winner_check_reg = pmadapter->pcard_sd->reg->winner_check_reg;
2115
2116 ENTER();
2117
2118 #ifdef SD8801
2119 if (IS_SD8801(pmadapter->card_type)) {
2120 *val = 0;
2121 return MLAN_STATUS_SUCCESS;
2122 }
2123 #endif
2124 pcb = &pmadapter->callbacks;
2125
2126 if (MLAN_STATUS_SUCCESS != pcb->moal_read_reg(pmadapter->pmoal_handle,
2127 card_winner_check_reg,
2128 &winner)) {
2129 LEAVE();
2130 return MLAN_STATUS_FAILURE;
2131 }
2132 *val = winner;
2133
2134 LEAVE();
2135 return MLAN_STATUS_SUCCESS;
2136 }
2137
2138 /**
2139 * @brief This function checks if the firmware is ready to accept
2140 * command or not.
2141 *
2142 * @param pmadapter A pointer to mlan_adapter structure
2143 * @param pollnum Maximum polling number
2144 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
2145 */
wlan_sdio_check_fw_status(mlan_adapter * pmadapter,t_u32 pollnum)2146 static mlan_status wlan_sdio_check_fw_status(mlan_adapter *pmadapter,
2147 t_u32 pollnum)
2148 {
2149 mlan_status ret = MLAN_STATUS_SUCCESS;
2150 t_u16 firmwarestat = 0;
2151 t_u32 tries;
2152
2153 ENTER();
2154
2155 /* Wait for firmware initialization event */
2156 for (tries = 0; tries < pollnum; tries++) {
2157 ret = wlan_sdio_read_fw_status(pmadapter, &firmwarestat);
2158 if (MLAN_STATUS_SUCCESS != ret)
2159 continue;
2160 if (firmwarestat == SDIO_FIRMWARE_READY) {
2161 ret = MLAN_STATUS_SUCCESS;
2162 break;
2163 } else {
2164 wlan_mdelay(pmadapter, 10);
2165 ret = MLAN_STATUS_FAILURE;
2166 }
2167 }
2168
2169 if (ret != MLAN_STATUS_SUCCESS) {
2170 if (pollnum > 1)
2171 PRINTM(MERROR,
2172 "Fail to poll firmware status: firmwarestat=0x%x\n",
2173 firmwarestat);
2174 goto done;
2175 }
2176
2177 done:
2178 LEAVE();
2179 return ret;
2180 }
2181
2182 /**
2183 * @brief This function enables the host interrupts.
2184 *
2185 * @param pmadapter A pointer to mlan_adapter structure
2186 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
2187 */
wlan_enable_sdio_host_int(pmlan_adapter pmadapter)2188 static mlan_status wlan_enable_sdio_host_int(pmlan_adapter pmadapter)
2189 {
2190 mlan_status ret;
2191 t_u8 mask = pmadapter->pcard_sd->reg->host_int_enable;
2192
2193 ENTER();
2194 ret = wlan_sdio_enable_host_int_mask(pmadapter, mask);
2195 LEAVE();
2196 return ret;
2197 }
2198
2199 /**
2200 * @brief This function downloads firmware to card
2201 *
2202 * @param pmadapter A pointer to mlan_adapter
2203 * @param pmfw A pointer to firmware image
2204 *
2205 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
2206 */
wlan_sdio_dnld_fw(pmlan_adapter pmadapter,pmlan_fw_image pmfw)2207 static mlan_status wlan_sdio_dnld_fw(pmlan_adapter pmadapter,
2208 pmlan_fw_image pmfw)
2209 {
2210 mlan_status ret = MLAN_STATUS_SUCCESS;
2211 t_u32 poll_num = 1;
2212 t_u32 winner = 0;
2213
2214 ENTER();
2215
2216 /*when using GPIO wakeup, don't run the below code.
2217 *if using GPIO wakeup, host will do handshake with FW
2218 *to check if FW wake up and pull up SDIO line, then reload driver.
2219 *So when using GPIO wakeup, don't need driver to do check wakeup status
2220 *again. when using SDIO interface wakeup, run the below code; if using
2221 *SDIO interface wakeup, driver need to do check wakeup status with FW.
2222 */
2223
2224 /* Card specific probing */
2225 ret = wlan_sdio_probe(pmadapter);
2226 if (ret == MLAN_STATUS_FAILURE) {
2227 PRINTM(MERROR, "WLAN SDIO probe failed\n", ret);
2228 LEAVE();
2229 return ret;
2230 }
2231
2232 /* Check if firmware is already running */
2233 ret = wlan_sdio_check_fw_status(pmadapter, poll_num);
2234 if (ret == MLAN_STATUS_SUCCESS) {
2235 #if defined(SDIO)
2236 if (pmfw->fw_reload == FW_RELOAD_SDIO_INBAND_RESET) {
2237 PRINTM(MMSG, "Try reset fw in mlan\n");
2238 ret = wlan_reset_fw(pmadapter);
2239 if (ret == MLAN_STATUS_FAILURE) {
2240 PRINTM(MERROR, "FW reset failure!");
2241 LEAVE();
2242 return ret;
2243 }
2244 } else {
2245 #endif
2246 PRINTM(MMSG,
2247 "WLAN FW already running! Skip FW download\n");
2248 #if defined(SDIO)
2249 pmadapter->ops.wakeup_card(pmadapter, MFALSE);
2250 #endif
2251 goto done;
2252 #if defined(SDIO)
2253 }
2254 #endif
2255 }
2256 poll_num = MAX_FIRMWARE_POLL_TRIES;
2257 /* Check if other interface is downloading */
2258 ret = wlan_sdio_check_winner_status(pmadapter, &winner);
2259 if (ret == MLAN_STATUS_FAILURE) {
2260 PRINTM(MFATAL, "WLAN read winner status failed!\n");
2261 goto done;
2262 }
2263 if (winner) {
2264 PRINTM(MMSG,
2265 "WLAN is not the winner (0x%x). Skip FW download\n",
2266 winner);
2267 poll_num = MAX_MULTI_INTERFACE_POLL_TRIES;
2268 goto poll_fw;
2269 }
2270
2271 /* Download the firmware image via helper */
2272 ret = wlan_sdio_prog_fw_w_helper(pmadapter, pmfw->pfw_buf,
2273 pmfw->fw_len);
2274 if (ret != MLAN_STATUS_SUCCESS) {
2275 PRINTM(MERROR, "wlan_dnld_fw fail ret=0x%x\n", ret);
2276 LEAVE();
2277 return ret;
2278 }
2279
2280 poll_fw:
2281 /* Check if the firmware is downloaded successfully or not */
2282 ret = wlan_sdio_check_fw_status(pmadapter, poll_num);
2283 if (ret != MLAN_STATUS_SUCCESS) {
2284 PRINTM(MFATAL, "FW failed to be active in time!\n");
2285 ret = MLAN_STATUS_FAILURE;
2286 LEAVE();
2287 return ret;
2288 }
2289 #ifdef SD9177
2290 if (IS_SD9177(pmadapter->card_type))
2291 wlan_mdelay(pmadapter, 1000);
2292 #endif
2293 done:
2294
2295 /* re-enable host interrupt for mlan after fw dnld is successful */
2296 wlan_enable_sdio_host_int(pmadapter);
2297
2298 LEAVE();
2299 return ret;
2300 }
2301
2302 /**
2303 * @brief This function probes the driver
2304 *
2305 * @param pmadapter A pointer to mlan_adapter structure
2306 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
2307 */
wlan_sdio_probe(pmlan_adapter pmadapter)2308 mlan_status wlan_sdio_probe(pmlan_adapter pmadapter)
2309 {
2310 mlan_status ret = MLAN_STATUS_SUCCESS;
2311 t_u32 sdio_ireg = 0;
2312 pmlan_callbacks pcb = &pmadapter->callbacks;
2313
2314 ENTER();
2315 /*
2316 * Read the HOST_INT_STATUS_REG for ACK the first interrupt got
2317 * from the bootloader. If we don't do this we get a interrupt
2318 * as soon as we register the irq.
2319 */
2320 pcb->moal_read_reg(pmadapter->pmoal_handle,
2321 pmadapter->pcard_sd->reg->host_int_status_reg,
2322 &sdio_ireg);
2323
2324 /* Disable host interrupt mask register for SDIO */
2325 ret = wlan_disable_sdio_host_int(pmadapter);
2326 if (ret != MLAN_STATUS_SUCCESS) {
2327 LEAVE();
2328 return MLAN_STATUS_FAILURE;
2329 }
2330 /* Get SDIO ioport */
2331 ret = wlan_sdio_init_ioport(pmadapter);
2332 LEAVE();
2333 return ret;
2334 }
2335
2336 /**
2337 * @brief This function get sdio device from card type
2338 *
2339 * @param pmadapter A pointer to mlan_adapter structure
2340 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
2341 */
wlan_get_sdio_device(pmlan_adapter pmadapter)2342 mlan_status wlan_get_sdio_device(pmlan_adapter pmadapter)
2343 {
2344 mlan_status ret = MLAN_STATUS_SUCCESS;
2345 t_u16 card_type = pmadapter->card_type;
2346
2347 ENTER();
2348
2349 ret = pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle,
2350 sizeof(mlan_sdio_card),
2351 MLAN_MEM_DEF,
2352 (t_u8 **)&pmadapter->pcard_sd);
2353 if (ret != MLAN_STATUS_SUCCESS || !pmadapter->pcard_sd) {
2354 PRINTM(MERROR, "Failed to allocate pcard_sd\n");
2355 LEAVE();
2356 return MLAN_STATUS_FAILURE;
2357 }
2358 pmadapter->pcard_sd->max_ports = MAX_PORT;
2359 pmadapter->pcard_sd->mp_aggr_pkt_limit = SDIO_MP_AGGR_DEF_PKT_LIMIT;
2360 pmadapter->pcard_sd->supports_sdio_new_mode = MTRUE;
2361 pmadapter->pcard_sd->mp_tx_aggr_buf_size = SDIO_MP_AGGR_BUF_SIZE_MAX;
2362 pmadapter->pcard_sd->mp_rx_aggr_buf_size = SDIO_MP_AGGR_BUF_SIZE_MAX;
2363
2364 switch (card_type) {
2365 #ifdef SD8801
2366 case CARD_TYPE_SD8801:
2367 pmadapter->pcard_sd->reg = &mlan_reg_sd8801;
2368 pmadapter->pcard_info = &mlan_card_info_sd8801;
2369 pmadapter->pcard_sd->max_ports = MAX_PORT_16;
2370 pmadapter->pcard_sd->mp_aggr_pkt_limit =
2371 SDIO_MP_AGGR_DEF_PKT_LIMIT_8;
2372 pmadapter->pcard_sd->supports_sdio_new_mode = MFALSE;
2373 pmadapter->pcard_sd->mp_tx_aggr_buf_size =
2374 SDIO_MP_AGGR_BUF_SIZE_32K;
2375 pmadapter->pcard_sd->mp_rx_aggr_buf_size =
2376 SDIO_MP_AGGR_BUF_SIZE_32K;
2377 break;
2378 #endif
2379 #ifdef SD8887
2380 case CARD_TYPE_SD8887:
2381 pmadapter->pcard_sd->reg = &mlan_reg_sd8887;
2382 pmadapter->pcard_info = &mlan_card_info_sd8887;
2383 break;
2384 #endif
2385 #ifdef SD8897
2386 case CARD_TYPE_SD8897:
2387 pmadapter->pcard_sd->reg = &mlan_reg_sd8897;
2388 pmadapter->pcard_info = &mlan_card_info_sd8897;
2389 break;
2390 #endif
2391 #if defined(SD8977) || defined(SD8978)
2392 case CARD_TYPE_SD8977:
2393 case CARD_TYPE_SD8978:
2394 pmadapter->pcard_sd->reg = &mlan_reg_sd8977_sd8997;
2395 pmadapter->pcard_info = &mlan_card_info_sd8977;
2396 break;
2397 #endif
2398 #ifdef SD8997
2399 case CARD_TYPE_SD8997:
2400 pmadapter->pcard_sd->reg = &mlan_reg_sd8977_sd8997;
2401 pmadapter->pcard_info = &mlan_card_info_sd8997;
2402 break;
2403 #endif
2404 #ifdef SD8987
2405 case CARD_TYPE_SD8987:
2406 pmadapter->pcard_sd->reg = &mlan_reg_sd8977_sd8997;
2407 pmadapter->pcard_info = &mlan_card_info_sd8987;
2408 break;
2409 #endif
2410 #ifdef SD9098
2411 case CARD_TYPE_SD9098:
2412 pmadapter->pcard_sd->reg = &mlan_reg_sd8977_sd8997;
2413 pmadapter->pcard_info = &mlan_card_info_sd9098;
2414 break;
2415 #endif
2416 #ifdef SD9097
2417 case CARD_TYPE_SD9097:
2418 pmadapter->pcard_sd->reg = &mlan_reg_sd8977_sd8997;
2419 pmadapter->pcard_info = &mlan_card_info_sd9097;
2420 break;
2421 #endif
2422 #ifdef SDNW62X
2423 case CARD_TYPE_SDNW62X:
2424 pmadapter->pcard_sd->reg = &mlan_reg_sd8977_sd8997;
2425 pmadapter->pcard_info = &mlan_card_info_sdnw62x;
2426 break;
2427 #endif
2428 #ifdef SD9177
2429 case CARD_TYPE_SD9177:
2430 pmadapter->pcard_sd->reg = &mlan_reg_sd8977_sd8997;
2431 pmadapter->pcard_info = &mlan_card_info_sd9177;
2432 break;
2433 #endif
2434 default:
2435 PRINTM(MERROR, "can't get right card type \n");
2436 ret = MLAN_STATUS_FAILURE;
2437 break;
2438 }
2439
2440 LEAVE();
2441 return ret;
2442 }
2443
2444 /**
2445 * @brief This function dump the mp registers when issue happened
2446 *
2447 * @param pmadapter A pointer to mlan_adapter structure
2448 * @return N/A
2449 */
wlan_dump_mp_registers(pmlan_adapter pmadapter)2450 void wlan_dump_mp_registers(pmlan_adapter pmadapter)
2451 {
2452 t_u32 mp_wr_bitmap;
2453 t_bool new_mode = pmadapter->pcard_sd->supports_sdio_new_mode;
2454 t_u32 mp_rd_bitmap;
2455 t_u16 rx_len = 0;
2456 const mlan_sdio_card_reg *reg = pmadapter->pcard_sd->reg;
2457 t_u8 cmd_rd_len_0 = reg->cmd_rd_len_0;
2458 t_u8 cmd_rd_len_1 = reg->cmd_rd_len_1;
2459 t_u8 host_int_status_reg = reg->host_int_status_reg;
2460 t_u32 sdio_ireg = 0;
2461
2462 mp_wr_bitmap = (t_u32)pmadapter->pcard_sd->mp_regs[reg->wr_bitmap_l];
2463 mp_wr_bitmap |= ((t_u32)pmadapter->pcard_sd->mp_regs[reg->wr_bitmap_u])
2464 << 8;
2465 if (new_mode) {
2466 mp_wr_bitmap |=
2467 ((t_u32)pmadapter->pcard_sd->mp_regs[reg->wr_bitmap_1l])
2468 << 16;
2469 mp_wr_bitmap |=
2470 ((t_u32)pmadapter->pcard_sd->mp_regs[reg->wr_bitmap_1u])
2471 << 24;
2472 }
2473 PRINTM(MMSG, "wlan: mp_data_port_mask = 0x%x\n",
2474 pmadapter->pcard_sd->mp_data_port_mask);
2475 PRINTM(MMSG, "wlan: HW wr_bitmap=0x%08x Host: wr_bitmap=0x%08x\n",
2476 mp_wr_bitmap, pmadapter->pcard_sd->mp_wr_bitmap);
2477 mp_rd_bitmap = (t_u32)pmadapter->pcard_sd->mp_regs[reg->rd_bitmap_l];
2478 mp_rd_bitmap |= ((t_u32)pmadapter->pcard_sd->mp_regs[reg->rd_bitmap_u])
2479 << 8;
2480 if (new_mode) {
2481 mp_rd_bitmap |=
2482 ((t_u32)pmadapter->pcard_sd->mp_regs[reg->rd_bitmap_1l])
2483 << 16;
2484 mp_rd_bitmap |=
2485 ((t_u32)pmadapter->pcard_sd->mp_regs[reg->rd_bitmap_1u])
2486 << 24;
2487 }
2488 PRINTM(MMSG, "wlan: HW rd_bitmap=0x%08x Host: rd_bitmap=0x%08x\n",
2489 mp_rd_bitmap, pmadapter->pcard_sd->mp_rd_bitmap);
2490
2491 if (new_mode) {
2492 rx_len = ((t_u16)pmadapter->pcard_sd->mp_regs[cmd_rd_len_1])
2493 << 8;
2494 rx_len |= (t_u16)pmadapter->pcard_sd->mp_regs[cmd_rd_len_0];
2495 PRINTM(MMSG, "wlan: cmd rx buffer rx_len = %d\n", rx_len);
2496 }
2497 PRINTM(MMSG, "wlan: HW sdio_ireg = 0x%x\n",
2498 pmadapter->pcard_sd->mp_regs[host_int_status_reg]);
2499 sdio_ireg = pmadapter->pcard_sd->mp_regs[host_int_status_reg];
2500
2501 if (new_mode && rx_len)
2502 sdio_ireg |= UP_LD_CMD_PORT_HOST_INT_STATUS;
2503
2504 if (!(pmadapter->pcard_sd->mp_wr_bitmap &
2505 pmadapter->pcard_sd->mp_data_port_mask)) {
2506 if (mp_wr_bitmap & pmadapter->pcard_sd->mp_data_port_mask)
2507 sdio_ireg |= DN_LD_HOST_INT_STATUS;
2508 }
2509
2510 if ((!pmadapter->pcard_sd->mp_rd_bitmap) && mp_rd_bitmap)
2511 sdio_ireg |= UP_LD_HOST_INT_STATUS;
2512
2513 pmadapter->pcard_sd->mp_regs[host_int_status_reg] = sdio_ireg;
2514 PRINTM(MMSG, "wlan: recovered sdio_ireg=0x%x\n", sdio_ireg);
2515 return;
2516 }
2517
2518 /**
2519 * @brief This function gets interrupt status.
2520 *
2521 * @param pmadapter A pointer to mlan_adapter structure
2522 * @return MLAN_STATUS_SUCCESS
2523 */
wlan_sdio_interrupt(t_u16 msg_id,pmlan_adapter pmadapter)2524 static mlan_status wlan_sdio_interrupt(t_u16 msg_id, pmlan_adapter pmadapter)
2525 {
2526 mlan_status ret = MLAN_STATUS_SUCCESS;
2527 pmlan_callbacks pcb = &pmadapter->callbacks;
2528 mlan_buffer mbuf;
2529 t_u32 sdio_ireg = 0;
2530 t_u8 offset = 0;
2531 t_u8 i = 0;
2532 int max_mp_regs = pmadapter->pcard_sd->reg->max_mp_regs;
2533 t_u8 host_int_status_reg =
2534 pmadapter->pcard_sd->reg->host_int_status_reg;
2535
2536 ENTER();
2537
2538 while (max_mp_regs) {
2539 memset(pmadapter, &mbuf, 0, sizeof(mlan_buffer));
2540 mbuf.pbuf = pmadapter->pcard_sd->mp_regs + offset;
2541 mbuf.data_len = MIN(max_mp_regs, MLAN_SDIO_BLOCK_SIZE);
2542 do {
2543 ret = pcb->moal_read_data_sync(
2544 pmadapter->pmoal_handle, &mbuf,
2545 (REG_PORT + offset) | MLAN_SDIO_BYTE_MODE_MASK,
2546 0);
2547 if (ret != MLAN_STATUS_SUCCESS) {
2548 PRINTM(MERROR,
2549 "wlan: cmd53 read regs failed: %d port=%x retry=%d\n",
2550 ret, REG_PORT + offset, i);
2551 i++;
2552 pcb->moal_write_reg(pmadapter->pmoal_handle,
2553 HOST_TO_CARD_EVENT_REG,
2554 HOST_TERM_CMD53);
2555 if (i > MAX_WRITE_IOMEM_RETRY) {
2556 PRINTM(MERROR,
2557 "wlan: Fail to read mp_regs\n");
2558 pmadapter->dbg.num_int_read_failure++;
2559 goto done;
2560 }
2561 }
2562 } while (ret == MLAN_STATUS_FAILURE);
2563 offset += mbuf.data_len;
2564 max_mp_regs -= mbuf.data_len;
2565 }
2566 if (i > 0)
2567 wlan_dump_mp_registers(pmadapter);
2568
2569 DBG_HEXDUMP(MIF_D, "SDIO MP Registers", pmadapter->pcard_sd->mp_regs,
2570 max_mp_regs);
2571 sdio_ireg = pmadapter->pcard_sd->mp_regs[host_int_status_reg];
2572 pmadapter->dbg.last_int_status = pmadapter->ireg | sdio_ireg;
2573 if (sdio_ireg) {
2574 /*
2575 * DN_LD_HOST_INT_STATUS and/or UP_LD_HOST_INT_STATUS
2576 * DN_LD_CMD_PORT_HOST_INT_STATUS and/or
2577 * UP_LD_CMD_PORT_HOST_INT_STATUS
2578 * Clear the interrupt status register
2579 */
2580 PRINTM(MINTR, "wlan_interrupt: sdio_ireg = 0x%x\n", sdio_ireg);
2581 pmadapter->pcard_sd->num_of_irq++;
2582 pcb->moal_spin_lock(pmadapter->pmoal_handle,
2583 pmadapter->pint_lock);
2584 pmadapter->ireg |= sdio_ireg;
2585 pcb->moal_spin_unlock(pmadapter->pmoal_handle,
2586 pmadapter->pint_lock);
2587 if (!pmadapter->pps_uapsd_mode &&
2588 pmadapter->ps_state == PS_STATE_SLEEP) {
2589 pmadapter->pm_wakeup_fw_try = MFALSE;
2590 pmadapter->ps_state = PS_STATE_AWAKE;
2591 pmadapter->pm_wakeup_card_req = MFALSE;
2592 }
2593 } else {
2594 PRINTM(MMSG, "wlan_interrupt: sdio_ireg = 0x%x\n", sdio_ireg);
2595 }
2596 done:
2597 LEAVE();
2598 return MLAN_STATUS_SUCCESS;
2599 }
2600
2601 /**
2602 * @brief This function try to read the packet when fail to alloc rx buffer
2603 *
2604 * @param pmadapter A pointer to mlan_adapter structure
2605 * @param port Current port on which packet needs to be rxed
2606 * @param rx_len Length of received packet
2607 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
2608 */
wlan_sdio_card_to_host_recovery(mlan_adapter * pmadapter,t_u8 port,t_u16 rx_len)2609 static mlan_status wlan_sdio_card_to_host_recovery(mlan_adapter *pmadapter,
2610 t_u8 port, t_u16 rx_len)
2611 {
2612 mlan_buffer mbuf;
2613 t_u32 pkt_type = 0;
2614 mlan_status ret = MLAN_STATUS_FAILURE;
2615 ENTER();
2616 if (!pmadapter->pcard_sd->supports_sdio_new_mode)
2617 goto done;
2618 if (MP_RX_AGGR_IN_PROGRESS(pmadapter)) {
2619 PRINTM(MDATA, "Recovery:do Rx Aggr\n");
2620 /* do aggr RX now */
2621 wlan_receive_mp_aggr_buf(pmadapter);
2622 }
2623 memset(pmadapter, &mbuf, 0, sizeof(mlan_buffer));
2624 mbuf.pbuf = pmadapter->pcard_sd->rx_buf;
2625 mbuf.data_len = rx_len;
2626
2627 PRINTM(MDATA, "Recovery: Try read port=%d rx_len=%d\n", port, rx_len);
2628 if (MLAN_STATUS_SUCCESS !=
2629 wlan_sdio_card_to_host(pmadapter, &pkt_type,
2630 (t_u32 *)&pmadapter->upld_len, &mbuf, rx_len,
2631 pmadapter->pcard_sd->ioport + port)) {
2632 PRINTM(MERROR, "Recovery: Fail to do cmd53\n");
2633 }
2634 if (pkt_type != MLAN_TYPE_DATA && pkt_type != MLAN_TYPE_SPA_DATA) {
2635 PRINTM(MERROR,
2636 "Recovery: Receive a wrong pkt: type=%d, len=%d\n",
2637 pkt_type, pmadapter->upld_len);
2638 goto done;
2639 }
2640 if (pkt_type == MLAN_TYPE_DATA) {
2641 // TODO fill the hole in Rx reorder table
2642 PRINTM(MDATA, "Recovery: Drop Data packet\n");
2643 pmadapter->dbg.num_pkt_dropped++;
2644 } else if (pkt_type == MLAN_TYPE_SPA_DATA) {
2645 PRINTM(MDATA, "Recovery: SPA Data packet len=%d\n",
2646 pmadapter->upld_len);
2647 wlan_decode_spa_buffer(pmadapter, pmadapter->pcard_sd->rx_buf,
2648 pmadapter->upld_len);
2649 pmadapter->data_received = MTRUE;
2650 }
2651 PRINTM(MMSG, "wlan: Success handle rx port=%d, rx_len=%d \n", port,
2652 rx_len);
2653 ret = MLAN_STATUS_SUCCESS;
2654 done:
2655 LEAVE();
2656 return ret;
2657 }
2658
2659 /**
2660 * @brief This function checks the interrupt status and handle it accordingly.
2661 *
2662 * @param pmadapter A pointer to mlan_adapter structure
2663 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
2664 */
wlan_process_sdio_int_status(mlan_adapter * pmadapter)2665 static mlan_status wlan_process_sdio_int_status(mlan_adapter *pmadapter)
2666 {
2667 mlan_status ret = MLAN_STATUS_SUCCESS;
2668 pmlan_callbacks pcb = &pmadapter->callbacks;
2669 t_u8 sdio_ireg;
2670 mlan_buffer *pmbuf = MNULL;
2671
2672 t_u8 port = 0;
2673 t_u32 len_reg_l, len_reg_u;
2674 t_u32 rx_blocks;
2675 t_u8 bit_count = 0;
2676 t_u32 ps_state = pmadapter->ps_state;
2677 t_u16 rx_len;
2678 t_u32 upld_typ = 0;
2679 t_u32 cr = 0;
2680 const mlan_sdio_card_reg *reg = pmadapter->pcard_sd->reg;
2681 t_u8 rd_len_p0_l = reg->rd_len_p0_l;
2682 t_u8 rd_len_p0_u = reg->rd_len_p0_u;
2683 t_u8 cmd_rd_len_0 = reg->cmd_rd_len_0;
2684 t_u8 cmd_rd_len_1 = reg->cmd_rd_len_1;
2685 t_bool new_mode = pmadapter->pcard_sd->supports_sdio_new_mode;
2686
2687 ENTER();
2688
2689 pcb->moal_spin_lock(pmadapter->pmoal_handle, pmadapter->pint_lock);
2690 sdio_ireg = (t_u8)pmadapter->ireg;
2691 pmadapter->ireg = 0;
2692 pcb->moal_spin_unlock(pmadapter->pmoal_handle, pmadapter->pint_lock);
2693
2694 if (!sdio_ireg)
2695 goto done;
2696
2697 if (new_mode) {
2698 /* check the command port */
2699 if (sdio_ireg & DN_LD_CMD_PORT_HOST_INT_STATUS) {
2700 if (pmadapter->cmd_sent)
2701 pmadapter->cmd_sent = MFALSE;
2702
2703 PRINTM(MINFO, "cmd_sent=%d\n", pmadapter->cmd_sent);
2704 }
2705
2706 if (sdio_ireg & UP_LD_CMD_PORT_HOST_INT_STATUS) {
2707 /* read the len of control packet */
2708 rx_len = ((t_u16)pmadapter->pcard_sd
2709 ->mp_regs[cmd_rd_len_1])
2710 << 8;
2711 rx_len |= (t_u16)pmadapter->pcard_sd
2712 ->mp_regs[cmd_rd_len_0];
2713 PRINTM(MINFO, "RX: cmd port rx_len=%u\n", rx_len);
2714 rx_blocks = (rx_len + MLAN_SDIO_BLOCK_SIZE - 1) /
2715 MLAN_SDIO_BLOCK_SIZE;
2716 if (rx_len <= SDIO_INTF_HEADER_LEN ||
2717 (rx_blocks * MLAN_SDIO_BLOCK_SIZE) >
2718 ALLOC_BUF_SIZE) {
2719 PRINTM(MERROR, "invalid rx_len=%d\n", rx_len);
2720 ret = MLAN_STATUS_FAILURE;
2721 goto done;
2722 }
2723 rx_len = (t_u16)(rx_blocks * MLAN_SDIO_BLOCK_SIZE);
2724 pmbuf = wlan_alloc_mlan_buffer(pmadapter, rx_len, 0,
2725 MOAL_MALLOC_BUFFER);
2726 if (pmbuf == MNULL) {
2727 PRINTM(MERROR,
2728 "Failed to allocate 'mlan_buffer'\n");
2729 ret = MLAN_STATUS_FAILURE;
2730 goto done;
2731 }
2732 PRINTM(MINFO, "cmd rx buffer rx_len = %d\n", rx_len);
2733
2734 /* Transfer data from card */
2735 if (MLAN_STATUS_SUCCESS !=
2736 wlan_sdio_card_to_host(pmadapter, &upld_typ,
2737 (t_u32 *)&pmadapter->upld_len,
2738 pmbuf, rx_len,
2739 pmadapter->pcard_sd->ioport |
2740 CMD_PORT_SLCT)) {
2741 pmadapter->dbg.num_cmdevt_card_to_host_failure++;
2742 PRINTM(MERROR,
2743 "Card-to-host cmd failed: int status=0x%x\n",
2744 sdio_ireg);
2745 wlan_free_mlan_buffer(pmadapter, pmbuf);
2746 ret = MLAN_STATUS_FAILURE;
2747 goto term_cmd53;
2748 }
2749
2750 if ((upld_typ != MLAN_TYPE_CMD) &&
2751 (upld_typ != MLAN_TYPE_EVENT))
2752 PRINTM(MERROR,
2753 "receive a wrong packet from CMD PORT. type =0x%x\n",
2754 upld_typ);
2755
2756 wlan_decode_rx_packet(pmadapter, pmbuf, upld_typ,
2757 MFALSE);
2758
2759 /* We might receive data/sleep_cfm at the same time */
2760 /* reset data_receive flag to avoid ps_state change */
2761 if ((ps_state == PS_STATE_SLEEP_CFM) &&
2762 (pmadapter->ps_state == PS_STATE_SLEEP))
2763 pmadapter->data_received = MFALSE;
2764 }
2765 }
2766
2767 if (sdio_ireg & DN_LD_HOST_INT_STATUS) {
2768 if (pmadapter->pcard_sd->mp_wr_bitmap &
2769 pmadapter->pcard_sd->mp_data_port_mask)
2770 pmadapter->pcard_sd->mp_invalid_update++;
2771 pmadapter->pcard_sd->mp_wr_bitmap =
2772 (t_u32)pmadapter->pcard_sd->mp_regs[reg->wr_bitmap_l];
2773 pmadapter->pcard_sd->mp_wr_bitmap |=
2774 ((t_u32)pmadapter->pcard_sd->mp_regs[reg->wr_bitmap_u])
2775 << 8;
2776 if (new_mode) {
2777 pmadapter->pcard_sd->mp_wr_bitmap |=
2778 ((t_u32)pmadapter->pcard_sd
2779 ->mp_regs[reg->wr_bitmap_1l])
2780 << 16;
2781 pmadapter->pcard_sd->mp_wr_bitmap |=
2782 ((t_u32)pmadapter->pcard_sd
2783 ->mp_regs[reg->wr_bitmap_1u])
2784 << 24;
2785 }
2786 bit_count = bitcount(pmadapter->pcard_sd->mp_wr_bitmap &
2787 pmadapter->pcard_sd->mp_data_port_mask);
2788 if (bit_count) {
2789 pmadapter->pcard_sd->mp_update[bit_count - 1]++;
2790 if (pmadapter->pcard_sd->mp_update[bit_count - 1] ==
2791 0xffffffff)
2792 memset(pmadapter,
2793 pmadapter->pcard_sd->mp_update, 0,
2794 sizeof(pmadapter->pcard_sd->mp_update));
2795 }
2796
2797 pmadapter->pcard_sd->last_recv_wr_bitmap =
2798 pmadapter->pcard_sd->mp_wr_bitmap;
2799 PRINTM(MINTR, "DNLD: wr_bitmap=0x%08x\n",
2800 pmadapter->pcard_sd->mp_wr_bitmap);
2801 if (pmadapter->data_sent &&
2802 (pmadapter->pcard_sd->mp_wr_bitmap &
2803 (1 << pmadapter->pcard_sd->curr_wr_port))) {
2804 pmadapter->callbacks.moal_tp_accounting_rx_param(
2805 pmadapter->pmoal_handle, 3, 0);
2806 PRINTM(MINFO, " <--- Tx DONE Interrupt --->\n");
2807 pmadapter->data_sent = MFALSE;
2808 }
2809 }
2810 if ((!new_mode) && (pmadapter->cmd_sent == MTRUE)) {
2811 /* Check if firmware has attach buffer at command port and
2812 * update just that in wr_bit_map. */
2813 pmadapter->pcard_sd->mp_wr_bitmap |=
2814 (t_u32)pmadapter->pcard_sd->mp_regs[reg->wr_bitmap_l] &
2815 CTRL_PORT_MASK;
2816 if (pmadapter->pcard_sd->mp_wr_bitmap & CTRL_PORT_MASK)
2817 pmadapter->cmd_sent = MFALSE;
2818 }
2819
2820 if (sdio_ireg & UP_LD_HOST_INT_STATUS) {
2821 pmadapter->pcard_sd->mp_rd_bitmap =
2822 (t_u32)pmadapter->pcard_sd->mp_regs[reg->rd_bitmap_l];
2823 pmadapter->pcard_sd->mp_rd_bitmap |=
2824 ((t_u32)pmadapter->pcard_sd->mp_regs[reg->rd_bitmap_u])
2825 << 8;
2826 if (new_mode) {
2827 pmadapter->pcard_sd->mp_rd_bitmap |=
2828 ((t_u32)pmadapter->pcard_sd
2829 ->mp_regs[reg->rd_bitmap_1l])
2830 << 16;
2831 pmadapter->pcard_sd->mp_rd_bitmap |=
2832 ((t_u32)pmadapter->pcard_sd
2833 ->mp_regs[reg->rd_bitmap_1u])
2834 << 24;
2835 }
2836 pmadapter->pcard_sd->last_recv_rd_bitmap =
2837 pmadapter->pcard_sd->mp_rd_bitmap;
2838
2839 PRINTM(MINTR, "UPLD: rd_bitmap=0x%08x\n",
2840 pmadapter->pcard_sd->mp_rd_bitmap);
2841 pmadapter->callbacks.moal_tp_accounting_rx_param(
2842 pmadapter->pmoal_handle, 0, 0);
2843
2844 while (MTRUE) {
2845 ret = wlan_get_rd_port(pmadapter, &port);
2846 if (ret != MLAN_STATUS_SUCCESS) {
2847 PRINTM(MINFO,
2848 "no more rd_port to be handled\n");
2849 break;
2850 }
2851 len_reg_l = rd_len_p0_l + (port << 1);
2852 len_reg_u = rd_len_p0_u + (port << 1);
2853 rx_len =
2854 ((t_u16)pmadapter->pcard_sd->mp_regs[len_reg_u])
2855 << 8;
2856 rx_len |=
2857 (t_u16)pmadapter->pcard_sd->mp_regs[len_reg_l];
2858 PRINTM(MINFO, "RX: port=%d rx_len=%u\n", port, rx_len);
2859 rx_blocks = (rx_len + MLAN_SDIO_BLOCK_SIZE - 1) /
2860 MLAN_SDIO_BLOCK_SIZE;
2861 if (rx_len <= SDIO_INTF_HEADER_LEN ||
2862 (rx_blocks * MLAN_SDIO_BLOCK_SIZE) >
2863 pmadapter->pcard_sd->mpa_rx.buf_size) {
2864 PRINTM(MERROR, "invalid rx_len=%d\n", rx_len);
2865 ret = MLAN_STATUS_FAILURE;
2866 goto done;
2867 }
2868 rx_len = (t_u16)(rx_blocks * MLAN_SDIO_BLOCK_SIZE);
2869
2870 if (!new_mode && (port == CTRL_PORT))
2871 pmbuf = wlan_alloc_mlan_buffer(
2872 pmadapter, rx_len, 0,
2873 MOAL_MALLOC_BUFFER);
2874 else
2875 pmbuf = wlan_alloc_mlan_buffer(
2876 pmadapter, rx_len, MLAN_RX_HEADER_LEN,
2877 MOAL_ALLOC_MLAN_BUFFER);
2878 if (pmbuf == MNULL) {
2879 PRINTM(MERROR,
2880 "Failed to allocate 'mlan_buffer'\n");
2881 pmadapter->dbg.num_alloc_buffer_failure++;
2882 if (MLAN_STATUS_SUCCESS ==
2883 wlan_sdio_card_to_host_recovery(
2884 pmadapter, port, rx_len))
2885 continue;
2886 ret = MLAN_STATUS_FAILURE;
2887 goto done;
2888 }
2889 PRINTM(MINFO, "rx_len = %d\n", rx_len);
2890 if (MLAN_STATUS_SUCCESS !=
2891 wlan_sdio_card_to_host_mp_aggr(pmadapter, pmbuf,
2892 port, rx_len)) {
2893 if ((!new_mode) && (port == CTRL_PORT))
2894 pmadapter->dbg
2895 .num_cmdevt_card_to_host_failure++;
2896 else
2897 pmadapter->dbg
2898 .num_rx_card_to_host_failure++;
2899
2900 PRINTM(MERROR,
2901 "Card to host failed: int status=0x%x\n",
2902 sdio_ireg);
2903 ret = MLAN_STATUS_FAILURE;
2904 goto term_cmd53;
2905 }
2906 }
2907 /* We might receive data/sleep_cfm at the same time */
2908 /* reset data_receive flag to avoid ps_state change */
2909 if ((ps_state == PS_STATE_SLEEP_CFM) &&
2910 (pmadapter->ps_state == PS_STATE_SLEEP))
2911 pmadapter->data_received = MFALSE;
2912 }
2913
2914 ret = MLAN_STATUS_SUCCESS;
2915 goto done;
2916
2917 term_cmd53:
2918 /* terminate cmd53 */
2919 if (MLAN_STATUS_SUCCESS != pcb->moal_read_reg(pmadapter->pmoal_handle,
2920 HOST_TO_CARD_EVENT_REG,
2921 &cr))
2922 PRINTM(MERROR, "read CFG reg failed\n");
2923 PRINTM(MINFO, "Config Reg val = %d\n", cr);
2924 if (MLAN_STATUS_SUCCESS != pcb->moal_write_reg(pmadapter->pmoal_handle,
2925 HOST_TO_CARD_EVENT_REG,
2926 (cr | HOST_TERM_CMD53)))
2927 PRINTM(MERROR, "write CFG reg failed\n");
2928 PRINTM(MINFO, "write success\n");
2929 if (MLAN_STATUS_SUCCESS != pcb->moal_read_reg(pmadapter->pmoal_handle,
2930 HOST_TO_CARD_EVENT_REG,
2931 &cr))
2932 PRINTM(MERROR, "read CFG reg failed\n");
2933 PRINTM(MINFO, "Config reg val =%x\n", cr);
2934
2935 done:
2936 LEAVE();
2937 return ret;
2938 }
2939
2940 /**
2941 * @brief This function sends data to the card.
2942 *
2943 * @param pmadapter A pointer to mlan_adapter structure
2944 * @param type data or command
2945 * @param pmbuf A pointer to mlan_buffer (pmbuf->data_len should include
2946 * SDIO header)
2947 * @param tx_param A pointer to mlan_tx_param
2948 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
2949 */
wlan_sdio_host_to_card(mlan_adapter * pmadapter,t_u8 type,mlan_buffer * pmbuf,mlan_tx_param * tx_param)2950 mlan_status wlan_sdio_host_to_card(mlan_adapter *pmadapter, t_u8 type,
2951 mlan_buffer *pmbuf, mlan_tx_param *tx_param)
2952 {
2953 mlan_status ret = MLAN_STATUS_SUCCESS;
2954 t_u32 buf_block_len;
2955 t_u32 blksz;
2956 t_u8 port = 0;
2957 t_u32 cmd53_port = 0;
2958 t_u8 *payload = pmbuf->pbuf + pmbuf->data_offset;
2959 t_bool new_mode = pmadapter->pcard_sd->supports_sdio_new_mode;
2960
2961 ENTER();
2962
2963 /* Allocate buffer and copy payload */
2964 blksz = MLAN_SDIO_BLOCK_SIZE;
2965 buf_block_len = (pmbuf->data_len + blksz - 1) / blksz;
2966 *(t_u16 *)&payload[0] = wlan_cpu_to_le16((t_u16)pmbuf->data_len);
2967 *(t_u16 *)&payload[2] = wlan_cpu_to_le16(type);
2968
2969 /*
2970 * This is SDIO specific header
2971 * t_u16 length,
2972 * t_u16 type (MLAN_TYPE_DATA = 0,
2973 * MLAN_TYPE_CMD = 1, MLAN_TYPE_EVENT = 3)
2974 */
2975 if (type == MLAN_TYPE_DATA) {
2976 ret = wlan_get_wr_port_data(pmadapter, &port);
2977 if (ret != MLAN_STATUS_SUCCESS) {
2978 PRINTM(MERROR,
2979 "no wr_port available: wr_bitmap=0x%08x curr_wr_port=%d\n",
2980 pmadapter->pcard_sd->mp_wr_bitmap,
2981 pmadapter->pcard_sd->curr_wr_port);
2982 goto exit;
2983 }
2984 /* Transfer data to card */
2985 pmbuf->data_len = buf_block_len * blksz;
2986
2987 if (tx_param)
2988 ret = wlan_host_to_card_mp_aggr(pmadapter, pmbuf, port,
2989 tx_param->next_pkt_len);
2990 else
2991 ret = wlan_host_to_card_mp_aggr(pmadapter, pmbuf, port,
2992 0);
2993 } else {
2994 /*Type must be MLAN_TYPE_CMD*/
2995 pmadapter->cmd_sent = MTRUE;
2996 if (!new_mode)
2997 pmadapter->pcard_sd->mp_wr_bitmap &=
2998 (t_u32)(~(1 << CTRL_PORT));
2999 if (pmbuf->data_len <= SDIO_INTF_HEADER_LEN ||
3000 pmbuf->data_len > WLAN_UPLD_SIZE)
3001 PRINTM(MWARN,
3002 "wlan_sdio_host_to_card(): Error: payload=%p, nb=%d\n",
3003 payload, pmbuf->data_len);
3004 /* Transfer data to card */
3005 pmbuf->data_len = buf_block_len * blksz;
3006 if (new_mode)
3007 cmd53_port =
3008 (pmadapter->pcard_sd->ioport) | CMD_PORT_SLCT;
3009 else
3010 cmd53_port = pmadapter->pcard_sd->ioport + CTRL_PORT;
3011 ret = wlan_write_data_sync(pmadapter, pmbuf, cmd53_port);
3012 }
3013
3014 if (ret == MLAN_STATUS_FAILURE) {
3015 PRINTM(MERROR, "Error: host_to_card failed: 0x%X\n", ret);
3016 if (type == MLAN_TYPE_CMD)
3017 pmadapter->cmd_sent = MFALSE;
3018 if (type == MLAN_TYPE_DATA)
3019 pmadapter->data_sent = MFALSE;
3020 } else {
3021 if (type == MLAN_TYPE_DATA) {
3022 if (!(pmadapter->pcard_sd->mp_wr_bitmap &
3023 (1 << pmadapter->pcard_sd->curr_wr_port)))
3024 pmadapter->data_sent = MTRUE;
3025 else
3026 pmadapter->data_sent = MFALSE;
3027 }
3028 DBG_HEXDUMP(MIF_D, "SDIO Blk Wr",
3029 pmbuf->pbuf + pmbuf->data_offset,
3030 MIN(pmbuf->data_len, MAX_DATA_DUMP_LEN));
3031 }
3032 exit:
3033 LEAVE();
3034 return ret;
3035 }
3036
3037 #if (defined(SD9098) || defined(SD9097) || defined(SDNW62X) || defined(SD9177))
3038 /**
3039 * @brief This function sends vdll data to the card.
3040 *
3041 * @param pmadapter A pointer to mlan_adapter structure
3042 * @param pmbuf A pointer to mlan_buffer (pmbuf->data_len should include
3043 * SDIO header)
3044 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
3045 */
wlan_sdio_send_vdll(mlan_adapter * pmadapter,mlan_buffer * pmbuf)3046 static mlan_status wlan_sdio_send_vdll(mlan_adapter *pmadapter,
3047 mlan_buffer *pmbuf)
3048 {
3049 mlan_status ret = MLAN_STATUS_SUCCESS;
3050 t_u32 buf_block_len;
3051 t_u32 blksz;
3052 t_u8 *payload = pmbuf->pbuf + pmbuf->data_offset;
3053 t_u32 cmd53_port = 0;
3054 ENTER();
3055 blksz = MLAN_SDIO_BLOCK_SIZE;
3056 buf_block_len = (pmbuf->data_len + blksz - 1) / blksz;
3057
3058 *(t_u16 *)&payload[0] = wlan_cpu_to_le16((t_u16)pmbuf->data_len);
3059 *(t_u16 *)&payload[2] = wlan_cpu_to_le16(MLAN_TYPE_VDLL);
3060
3061 pmbuf->data_len = buf_block_len * blksz;
3062
3063 if (pmbuf->data_len > MRVDRV_SIZE_OF_CMD_BUFFER) {
3064 PRINTM(MERROR, "VDLL block is too big: %d\n", pmbuf->data_len);
3065 return MLAN_STATUS_FAILURE;
3066 }
3067 cmd53_port = (pmadapter->pcard_sd->ioport) | CMD_PORT_SLCT;
3068 pmadapter->cmd_sent = MTRUE;
3069 ret = wlan_write_data_sync(pmadapter, pmbuf, cmd53_port);
3070 if (ret == MLAN_STATUS_FAILURE)
3071 PRINTM(MERROR, "Send Vdll: host_to_card failed: 0x%X\n", ret);
3072 else
3073 DBG_HEXDUMP(MIF_D, "SDIO Blk Wr",
3074 pmbuf->pbuf + pmbuf->data_offset,
3075 MIN(pmbuf->data_len, MAX_DATA_DUMP_LEN));
3076 LEAVE();
3077 return ret;
3078 }
3079 #endif
3080
3081 /**
3082 * @brief This function sends data to the card.
3083 *
3084 * @param pmpriv A pointer to mlan_private structure
3085 * @param type data or command
3086 * @param pmbuf A pointer to mlan_buffer (pmbuf->data_len should include
3087 * SDIO header)
3088 * @param tx_param A pointer to mlan_tx_param
3089 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
3090 */
wlan_sdio_host_to_card_ext(pmlan_private pmpriv,t_u8 type,mlan_buffer * pmbuf,mlan_tx_param * tx_param)3091 static mlan_status wlan_sdio_host_to_card_ext(pmlan_private pmpriv, t_u8 type,
3092 mlan_buffer *pmbuf,
3093 mlan_tx_param *tx_param)
3094 {
3095 mlan_status ret = MLAN_STATUS_SUCCESS;
3096 mlan_adapter *pmadapter = pmpriv->adapter;
3097
3098 #if (defined(SD9098) || defined(SD9097) || defined(SDNW62X) || defined(SD9177))
3099 if (type == MLAN_TYPE_VDLL)
3100 return wlan_sdio_send_vdll(pmadapter, pmbuf);
3101 #endif
3102 ret = wlan_sdio_host_to_card(pmadapter, type, pmbuf, tx_param);
3103
3104 if (type == MLAN_TYPE_DATA && ret == MLAN_STATUS_FAILURE)
3105 pmadapter->data_sent = MFALSE;
3106
3107 LEAVE();
3108 return ret;
3109 }
3110
3111 /**
3112 * @brief Deaggregate single port aggregation packet
3113 *
3114 * @param pmadapter A pointer to mlan_adapter structure
3115 * @param buf A pointer to aggregated data packet
3116 * @param len
3117 *
3118 * @return N/A
3119 */
wlan_decode_spa_buffer(mlan_adapter * pmadapter,t_u8 * buf,t_u32 len)3120 void wlan_decode_spa_buffer(mlan_adapter *pmadapter, t_u8 *buf, t_u32 len)
3121 {
3122 int total_pkt_len;
3123 t_u8 block_num = 0;
3124 t_u16 block_size = 0;
3125 t_u8 *data;
3126 t_u32 pkt_len;
3127 mlan_buffer *mbuf_deaggr = MNULL;
3128
3129 ENTER();
3130
3131 data = (t_u8 *)buf;
3132 total_pkt_len = len;
3133 if (total_pkt_len < pmadapter->pcard_sd->sdio_rx_block_size) {
3134 PRINTM(MERROR, "Invalid sp aggr packet size=%d\n",
3135 total_pkt_len);
3136 goto done;
3137 }
3138 while (total_pkt_len >=
3139 (OFFSET_OF_SDIO_HEADER + SDIO_INTF_HEADER_LEN)) {
3140 block_num = *(data + OFFSET_OF_BLOCK_NUMBER);
3141 block_size =
3142 pmadapter->pcard_sd->sdio_rx_block_size * block_num;
3143 if (block_size > total_pkt_len) {
3144 PRINTM(MERROR,
3145 "Error in pkt, block_num=%d, pkt_len=%d\n",
3146 block_num, total_pkt_len);
3147 break;
3148 }
3149 pkt_len = wlan_le16_to_cpu(
3150 *(t_u16 *)(data + OFFSET_OF_SDIO_HEADER));
3151 if ((pkt_len + OFFSET_OF_SDIO_HEADER) > block_size) {
3152 PRINTM(MERROR,
3153 "Error in pkt, pkt_len=%d, block_size=%d\n",
3154 pkt_len, block_size);
3155 break;
3156 }
3157 mbuf_deaggr = wlan_alloc_mlan_buffer(
3158 pmadapter, pkt_len - SDIO_INTF_HEADER_LEN,
3159 MLAN_RX_HEADER_LEN, MOAL_ALLOC_MLAN_BUFFER);
3160 if (mbuf_deaggr == MNULL) {
3161 PRINTM(MERROR, "Error allocating daggr mlan_buffer\n");
3162 break;
3163 }
3164 memcpy_ext(pmadapter,
3165 mbuf_deaggr->pbuf + mbuf_deaggr->data_offset,
3166 data + OFFSET_OF_SDIO_HEADER + SDIO_INTF_HEADER_LEN,
3167 pkt_len - SDIO_INTF_HEADER_LEN,
3168 pkt_len - SDIO_INTF_HEADER_LEN);
3169 mbuf_deaggr->data_len = pkt_len - SDIO_INTF_HEADER_LEN;
3170 wlan_handle_rx_packet(pmadapter, mbuf_deaggr);
3171 data += block_size;
3172 total_pkt_len -= block_size;
3173 if (total_pkt_len < pmadapter->pcard_sd->sdio_rx_block_size)
3174 break;
3175 }
3176 done:
3177 LEAVE();
3178 return;
3179 }
3180
3181 /**
3182 * @brief This function deaggr rx pkt
3183 *
3184 * @param pmadapter A pointer to mlan_adapter structure
3185 * @param pmbuf A pointer to the SDIO mpa data
3186 * @return N/A
3187 */
wlan_sdio_deaggr_rx_pkt(pmlan_adapter pmadapter,mlan_buffer * pmbuf)3188 t_void wlan_sdio_deaggr_rx_pkt(pmlan_adapter pmadapter, mlan_buffer *pmbuf)
3189 {
3190 if (pmbuf->buf_type == MLAN_BUF_TYPE_SPA_DATA) {
3191 wlan_decode_spa_buffer(pmadapter,
3192 pmbuf->pbuf + pmbuf->data_offset,
3193 pmbuf->data_len);
3194 wlan_free_mlan_buffer(pmadapter, pmbuf);
3195 } else
3196 wlan_handle_rx_packet(pmadapter, pmbuf);
3197 }
3198
3199 /**
3200 * @brief This function allocates buffer for the SDIO aggregation buffer
3201 * related members of adapter structure
3202 *
3203 * @param pmadapter A pointer to mlan_adapter structure
3204 * @param mpa_tx_buf_size Tx buffer size to allocate
3205 * @param mpa_rx_buf_size Rx buffer size to allocate
3206 *
3207 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
3208 */
wlan_alloc_sdio_mpa_buffers(mlan_adapter * pmadapter,t_u32 mpa_tx_buf_size,t_u32 mpa_rx_buf_size)3209 mlan_status wlan_alloc_sdio_mpa_buffers(mlan_adapter *pmadapter,
3210 t_u32 mpa_tx_buf_size,
3211 t_u32 mpa_rx_buf_size)
3212 {
3213 mlan_status ret = MLAN_STATUS_SUCCESS;
3214 pmlan_callbacks pcb = &pmadapter->callbacks;
3215 t_u8 mp_aggr_pkt_limit = pmadapter->pcard_sd->mp_aggr_pkt_limit;
3216
3217 ENTER();
3218
3219 if ((pmadapter->pcard_sd->max_segs < mp_aggr_pkt_limit) ||
3220 (pmadapter->pcard_sd->max_seg_size <
3221 pmadapter->pcard_sd->max_sp_tx_size)) {
3222 ret = pcb->moal_malloc(
3223 pmadapter->pmoal_handle,
3224 mpa_tx_buf_size + DMA_ALIGNMENT,
3225 MLAN_MEM_DEF | MLAN_MEM_DMA,
3226 (t_u8 **)&pmadapter->pcard_sd->mpa_tx.head_ptr);
3227 if (ret != MLAN_STATUS_SUCCESS ||
3228 !pmadapter->pcard_sd->mpa_tx.head_ptr) {
3229 PRINTM(MERROR,
3230 "Could not allocate buffer for SDIO MP TX aggr\n");
3231 ret = MLAN_STATUS_FAILURE;
3232 goto error;
3233 }
3234 pmadapter->pcard_sd->mpa_tx.buf = (t_u8 *)ALIGN_ADDR(
3235 pmadapter->pcard_sd->mpa_tx.head_ptr, DMA_ALIGNMENT);
3236 } else {
3237 PRINTM(MMSG, "wlan: Enable TX SG mode\n");
3238 pmadapter->pcard_sd->mpa_tx.head_ptr = MNULL;
3239 pmadapter->pcard_sd->mpa_tx.buf = MNULL;
3240 }
3241 pmadapter->pcard_sd->mpa_tx.buf_size = mpa_tx_buf_size;
3242
3243 if ((pmadapter->pcard_sd->max_segs < mp_aggr_pkt_limit) ||
3244 (pmadapter->pcard_sd->max_seg_size <
3245 pmadapter->pcard_sd->max_sp_rx_size)) {
3246 ret = pcb->moal_malloc(
3247 pmadapter->pmoal_handle,
3248 mpa_rx_buf_size + DMA_ALIGNMENT,
3249 MLAN_MEM_DEF | MLAN_MEM_DMA,
3250 (t_u8 **)&pmadapter->pcard_sd->mpa_rx.head_ptr);
3251 if (ret != MLAN_STATUS_SUCCESS ||
3252 !pmadapter->pcard_sd->mpa_rx.head_ptr) {
3253 PRINTM(MERROR,
3254 "Could not allocate buffer for SDIO MP RX aggr\n");
3255 ret = MLAN_STATUS_FAILURE;
3256 goto error;
3257 }
3258 pmadapter->pcard_sd->mpa_rx.buf = (t_u8 *)ALIGN_ADDR(
3259 pmadapter->pcard_sd->mpa_rx.head_ptr, DMA_ALIGNMENT);
3260 } else {
3261 PRINTM(MMSG, "wlan: Enable RX SG mode\n");
3262 pmadapter->pcard_sd->mpa_rx.head_ptr = MNULL;
3263 pmadapter->pcard_sd->mpa_rx.buf = MNULL;
3264 }
3265 pmadapter->pcard_sd->mpa_rx.buf_size = mpa_rx_buf_size;
3266 error:
3267 if (ret != MLAN_STATUS_SUCCESS)
3268 wlan_free_sdio_mpa_buffers(pmadapter);
3269
3270 LEAVE();
3271 return ret;
3272 }
3273
3274 /**
3275 * @brief This function frees buffers for the SDIO aggregation
3276 *
3277 * @param pmadapter A pointer to mlan_adapter structure
3278 *
3279 * @return MLAN_STATUS_SUCCESS
3280 */
wlan_free_sdio_mpa_buffers(mlan_adapter * pmadapter)3281 mlan_status wlan_free_sdio_mpa_buffers(mlan_adapter *pmadapter)
3282 {
3283 pmlan_callbacks pcb = &pmadapter->callbacks;
3284
3285 ENTER();
3286
3287 if (pmadapter->pcard_sd->mpa_tx.buf) {
3288 pcb->moal_mfree(pmadapter->pmoal_handle,
3289 (t_u8 *)pmadapter->pcard_sd->mpa_tx.head_ptr);
3290 pmadapter->pcard_sd->mpa_tx.head_ptr = MNULL;
3291 pmadapter->pcard_sd->mpa_tx.buf = MNULL;
3292 pmadapter->pcard_sd->mpa_tx.buf_size = 0;
3293 }
3294
3295 if (pmadapter->pcard_sd->mpa_rx.buf) {
3296 pcb->moal_mfree(pmadapter->pmoal_handle,
3297 (t_u8 *)pmadapter->pcard_sd->mpa_rx.head_ptr);
3298 pmadapter->pcard_sd->mpa_rx.head_ptr = MNULL;
3299 pmadapter->pcard_sd->mpa_rx.buf = MNULL;
3300 pmadapter->pcard_sd->mpa_rx.buf_size = 0;
3301 }
3302
3303 LEAVE();
3304 return MLAN_STATUS_SUCCESS;
3305 }
3306
3307 /**
3308 * @brief This function re-allocate rx mpa buffer
3309 *
3310 * @param pmadapter A pointer to mlan_adapter structure
3311 *
3312 * @return MLAN_STATUS_SUCCESS
3313 */
wlan_re_alloc_sdio_rx_mpa_buffer(mlan_adapter * pmadapter)3314 mlan_status wlan_re_alloc_sdio_rx_mpa_buffer(mlan_adapter *pmadapter)
3315 {
3316 mlan_status ret = MLAN_STATUS_SUCCESS;
3317 pmlan_callbacks pcb = &pmadapter->callbacks;
3318 t_u8 mp_aggr_pkt_limit = pmadapter->pcard_sd->mp_aggr_pkt_limit;
3319 t_u32 mpa_rx_buf_size = pmadapter->pcard_sd->mp_tx_aggr_buf_size;
3320
3321 if (pmadapter->pcard_sd->mpa_rx.buf) {
3322 pcb->moal_mfree(pmadapter->pmoal_handle,
3323 (t_u8 *)pmadapter->pcard_sd->mpa_rx.head_ptr);
3324 pmadapter->pcard_sd->mpa_rx.head_ptr = MNULL;
3325 pmadapter->pcard_sd->mpa_rx.buf = MNULL;
3326 pmadapter->pcard_sd->mpa_rx.buf_size = 0;
3327 }
3328 if (pmadapter->pcard_sd->sdio_rx_aggr_enable) {
3329 mpa_rx_buf_size = MAX(mpa_rx_buf_size, SDIO_CMD53_MAX_SIZE);
3330 /** reallocate rx buffer for recover when single port rx
3331 * aggregation enabled */
3332 if (pmadapter->pcard_sd->rx_buffer) {
3333 pcb->moal_mfree(pmadapter->pmoal_handle,
3334 (t_u8 *)pmadapter->pcard_sd->rx_buffer);
3335 pmadapter->pcard_sd->rx_buffer = MNULL;
3336 pmadapter->pcard_sd->rx_buf = MNULL;
3337 }
3338 ret = pmadapter->callbacks.moal_malloc(
3339 pmadapter->pmoal_handle,
3340 SDIO_CMD53_MAX_SIZE + DMA_ALIGNMENT,
3341 MLAN_MEM_DEF | MLAN_MEM_DMA,
3342 (t_u8 **)&pmadapter->pcard_sd->rx_buffer);
3343
3344 if (ret != MLAN_STATUS_SUCCESS ||
3345 !pmadapter->pcard_sd->rx_buffer) {
3346 PRINTM(MERROR, "Failed to allocate receive buffer\n");
3347 ret = MLAN_STATUS_FAILURE;
3348 goto error;
3349 }
3350 pmadapter->pcard_sd->rx_buf = (t_u8 *)ALIGN_ADDR(
3351 pmadapter->pcard_sd->rx_buffer, DMA_ALIGNMENT);
3352 }
3353 if ((pmadapter->pcard_sd->max_segs < mp_aggr_pkt_limit) ||
3354 (pmadapter->pcard_sd->max_seg_size <
3355 pmadapter->pcard_sd->max_sp_rx_size)) {
3356 ret = pcb->moal_malloc(
3357 pmadapter->pmoal_handle,
3358 mpa_rx_buf_size + DMA_ALIGNMENT,
3359 MLAN_MEM_DEF | MLAN_MEM_DMA,
3360 (t_u8 **)&pmadapter->pcard_sd->mpa_rx.head_ptr);
3361 if (ret != MLAN_STATUS_SUCCESS ||
3362 !pmadapter->pcard_sd->mpa_rx.head_ptr) {
3363 PRINTM(MERROR,
3364 "Could not allocate buffer for SDIO MP RX aggr\n");
3365 ret = MLAN_STATUS_FAILURE;
3366 goto error;
3367 }
3368 pmadapter->pcard_sd->mpa_rx.buf = (t_u8 *)ALIGN_ADDR(
3369 pmadapter->pcard_sd->mpa_rx.head_ptr, DMA_ALIGNMENT);
3370 } else {
3371 PRINTM(MMSG, "wlan: Enable RX SG mode\n");
3372 pmadapter->pcard_sd->mpa_rx.head_ptr = MNULL;
3373 pmadapter->pcard_sd->mpa_rx.buf = MNULL;
3374 }
3375 pmadapter->pcard_sd->mpa_rx.buf_size = mpa_rx_buf_size;
3376 PRINTM(MMSG, "mpa_rx_buf_size=%d\n", mpa_rx_buf_size);
3377 error:
3378 return ret;
3379 }
3380
3381 /**
3382 * @brief This function wakes up the card.
3383 *
3384 * @param pmadapter A pointer to mlan_adapter structure
3385 * @param timeout set timeout flag
3386 *
3387 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
3388 */
wlan_pm_sdio_wakeup_card(pmlan_adapter pmadapter,t_u8 timeout)3389 static mlan_status wlan_pm_sdio_wakeup_card(pmlan_adapter pmadapter,
3390 t_u8 timeout)
3391 {
3392 mlan_status ret = MLAN_STATUS_SUCCESS;
3393 t_u32 age_ts_usec;
3394 pmlan_callbacks pcb = &pmadapter->callbacks;
3395
3396 ENTER();
3397 PRINTM(MEVENT, "Wakeup device...\n");
3398 pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle,
3399 &pmadapter->pm_wakeup_in_secs,
3400 &age_ts_usec);
3401
3402 if (timeout) {
3403 pmadapter->callbacks.moal_start_timer(
3404 pmadapter->pmoal_handle, pmadapter->pwakeup_fw_timer,
3405 MFALSE, MRVDRV_TIMER_3S);
3406 pmadapter->wakeup_fw_timer_is_set = MTRUE;
3407 }
3408
3409 ret = pcb->moal_write_reg(pmadapter->pmoal_handle,
3410 HOST_TO_CARD_EVENT_REG, HOST_POWER_UP);
3411
3412 LEAVE();
3413 return ret;
3414 }
3415
3416 /**
3417 * @brief This function resets the PM setting of the card.
3418 *
3419 * @param pmadapter A pointer to mlan_adapter structure
3420 *
3421 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
3422 */
wlan_pm_sdio_reset_card(pmlan_adapter pmadapter)3423 static mlan_status wlan_pm_sdio_reset_card(pmlan_adapter pmadapter)
3424 {
3425 mlan_status ret = MLAN_STATUS_SUCCESS;
3426 pmlan_callbacks pcb = &pmadapter->callbacks;
3427
3428 ENTER();
3429
3430 ret = pcb->moal_write_reg(pmadapter->pmoal_handle,
3431 HOST_TO_CARD_EVENT_REG, 0);
3432
3433 LEAVE();
3434 return ret;
3435 }
3436
3437 /**
3438 * @brief This function issues commands to initialize firmware
3439 *
3440 * @param priv A pointer to mlan_private structure
3441 *
3442 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
3443 */
wlan_set_sdio_gpio_int(pmlan_private priv)3444 mlan_status wlan_set_sdio_gpio_int(pmlan_private priv)
3445 {
3446 mlan_status ret = MLAN_STATUS_SUCCESS;
3447 pmlan_adapter pmadapter = MNULL;
3448 HostCmd_DS_SDIO_GPIO_INT_CONFIG sdio_int_cfg;
3449
3450 if (!priv) {
3451 LEAVE();
3452 return MLAN_STATUS_FAILURE;
3453 }
3454 pmadapter = priv->adapter;
3455
3456 ENTER();
3457
3458 if (pmadapter->pcard_sd->int_mode == INT_MODE_GPIO) {
3459 if (pmadapter->pcard_sd->gpio_pin != GPIO_INT_NEW_MODE) {
3460 PRINTM(MINFO,
3461 "SDIO_GPIO_INT_CONFIG: interrupt mode is GPIO\n");
3462 sdio_int_cfg.action = HostCmd_ACT_GEN_SET;
3463 sdio_int_cfg.gpio_pin = pmadapter->pcard_sd->gpio_pin;
3464 sdio_int_cfg.gpio_int_edge = INT_FALLING_EDGE;
3465 sdio_int_cfg.gpio_pulse_width = DELAY_1_US;
3466 ret = wlan_prepare_cmd(priv,
3467 HostCmd_CMD_SDIO_GPIO_INT_CONFIG,
3468 HostCmd_ACT_GEN_SET, 0, MNULL,
3469 &sdio_int_cfg);
3470
3471 if (ret) {
3472 PRINTM(MERROR,
3473 "SDIO_GPIO_INT_CONFIG: send command fail\n");
3474 ret = MLAN_STATUS_FAILURE;
3475 }
3476 }
3477 } else {
3478 PRINTM(MINFO, "SDIO_GPIO_INT_CONFIG: interrupt mode is SDIO\n");
3479 }
3480
3481 LEAVE();
3482 return ret;
3483 }
3484
3485 /**
3486 * @brief This function prepares command of SDIO GPIO interrupt
3487 *
3488 * @param pmpriv A pointer to mlan_private structure
3489 * @param cmd A pointer to HostCmd_DS_COMMAND structure
3490 * @param cmd_action The action: GET or SET
3491 * @param pdata_buf A pointer to data buffer
3492 * @return MLAN_STATUS_SUCCESS
3493 */
wlan_cmd_sdio_gpio_int(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_u16 cmd_action,t_void * pdata_buf)3494 mlan_status wlan_cmd_sdio_gpio_int(pmlan_private pmpriv,
3495 HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
3496 t_void *pdata_buf)
3497 {
3498 HostCmd_DS_SDIO_GPIO_INT_CONFIG *psdio_gpio_int =
3499 &cmd->params.sdio_gpio_int;
3500
3501 ENTER();
3502
3503 cmd->command = wlan_cpu_to_le16(HostCmd_CMD_SDIO_GPIO_INT_CONFIG);
3504 cmd->size = wlan_cpu_to_le16((sizeof(HostCmd_DS_SDIO_GPIO_INT_CONFIG)) +
3505 S_DS_GEN);
3506
3507 memset(pmpriv->adapter, psdio_gpio_int, 0,
3508 sizeof(HostCmd_DS_SDIO_GPIO_INT_CONFIG));
3509 if (cmd_action == HostCmd_ACT_GEN_SET) {
3510 memcpy_ext(pmpriv->adapter, psdio_gpio_int, pdata_buf,
3511 sizeof(HostCmd_DS_SDIO_GPIO_INT_CONFIG),
3512 sizeof(HostCmd_DS_SDIO_GPIO_INT_CONFIG));
3513 psdio_gpio_int->action =
3514 wlan_cpu_to_le16(psdio_gpio_int->action);
3515 psdio_gpio_int->gpio_pin =
3516 wlan_cpu_to_le16(psdio_gpio_int->gpio_pin);
3517 psdio_gpio_int->gpio_int_edge =
3518 wlan_cpu_to_le16(psdio_gpio_int->gpio_int_edge);
3519 psdio_gpio_int->gpio_pulse_width =
3520 wlan_cpu_to_le16(psdio_gpio_int->gpio_pulse_width);
3521 }
3522
3523 LEAVE();
3524 return MLAN_STATUS_SUCCESS;
3525 }
3526
wlan_reset_fw(pmlan_adapter pmadapter)3527 mlan_status wlan_reset_fw(pmlan_adapter pmadapter)
3528 {
3529 t_u32 tries = 0;
3530 t_u32 value = 1;
3531 t_u32 reset_reg = pmadapter->pcard_sd->reg->fw_reset_reg;
3532 t_u8 reset_val = pmadapter->pcard_sd->reg->fw_reset_val;
3533 pmlan_callbacks pcb = &pmadapter->callbacks;
3534 mlan_status ret = MLAN_STATUS_SUCCESS;
3535
3536 ENTER();
3537 wlan_pm_sdio_wakeup_card(pmadapter, MFALSE);
3538
3539 /** wait SOC fully wake up */
3540 for (tries = 0; tries < MAX_POLL_TRIES; ++tries) {
3541 if (MLAN_STATUS_SUCCESS ==
3542 pcb->moal_write_reg(pmadapter->pmoal_handle, reset_reg,
3543 0xba)) {
3544 pcb->moal_read_reg(pmadapter->pmoal_handle, reset_reg,
3545 &value);
3546 if (value == 0xba) {
3547 PRINTM(MMSG, "FW wake up\n");
3548 break;
3549 }
3550 }
3551 pcb->moal_udelay(pmadapter->pmoal_handle, 1000);
3552 }
3553 /* Write register to notify FW */
3554 if (MLAN_STATUS_FAILURE == pcb->moal_write_reg(pmadapter->pmoal_handle,
3555 reset_reg, reset_val)) {
3556 PRINTM(MERROR, "Failed to write register.\n");
3557 ret = MLAN_STATUS_FAILURE;
3558 goto done;
3559 }
3560 #if defined(SD8997) || defined(SD8977) || defined(SD8987) || \
3561 defined(SD9098) || defined(SD9097) || defined(SDNW62X) || \
3562 defined(SD8978) || defined(SD9177)
3563 if (MFALSE
3564 #ifdef SD8997
3565 || IS_SD8997(pmadapter->card_type)
3566 #endif
3567 #ifdef SD8977
3568 || IS_SD8977(pmadapter->card_type)
3569 #endif
3570 #ifdef SD8978
3571 || IS_SD8978(pmadapter->card_type)
3572 #endif
3573 #ifdef SD8987
3574 || IS_SD8987(pmadapter->card_type)
3575 #endif
3576 #ifdef SD9098
3577 || IS_SD9098(pmadapter->card_type)
3578 #endif
3579 #ifdef SD9097
3580 || IS_SD9097(pmadapter->card_type)
3581 #endif
3582 #ifdef SDNW62X
3583 || IS_SDNW62X(pmadapter->card_type)
3584 #endif
3585 #ifdef SD9177
3586 || IS_SD9177(pmadapter->card_type)
3587 #endif
3588 ) {
3589 pcb->moal_read_reg(pmadapter->pmoal_handle,
3590 HOST_TO_CARD_EVENT_REG, &value);
3591 pcb->moal_write_reg(pmadapter->pmoal_handle,
3592 HOST_TO_CARD_EVENT_REG,
3593 value | HOST_POWER_UP);
3594 }
3595 #endif
3596 /* Poll register around 100 ms */
3597 for (tries = 0; tries < MAX_POLL_TRIES; ++tries) {
3598 pcb->moal_read_reg(pmadapter->pmoal_handle, reset_reg, &value);
3599 if (value == 0)
3600 /* FW is ready */
3601 break;
3602 pcb->moal_udelay(pmadapter->pmoal_handle, 1000);
3603 }
3604
3605 if (value) {
3606 PRINTM(MERROR, "Failed to poll FW reset register %X=0x%x\n",
3607 reset_reg, value);
3608 ret = MLAN_STATUS_FAILURE;
3609 goto done;
3610 }
3611 PRINTM(MMSG, "FW Reset success\n");
3612 ret = wlan_sdio_probe(pmadapter);
3613 done:
3614 LEAVE();
3615 return ret;
3616 }
3617
3618 /**
3619 * @brief This function handle event/data/cmd complete
3620 *
3621 * @param pmadapter A pointer to mlan_adapter structure
3622 * @param pmbuf A pointer to the mlan_buffer
3623 * @return N/A
3624 */
wlan_sdio_data_evt_complete(pmlan_adapter pmadapter,mlan_buffer * pmbuf,mlan_status status)3625 static mlan_status wlan_sdio_data_evt_complete(pmlan_adapter pmadapter,
3626 mlan_buffer *pmbuf,
3627 mlan_status status)
3628 {
3629 ENTER();
3630
3631 wlan_free_mlan_buffer(pmadapter, pmbuf);
3632
3633 LEAVE();
3634 return MLAN_STATUS_SUCCESS;
3635 }
3636
3637 /**
3638 * @brief This function handle receive packet
3639 *
3640 * @param pmadapter A pointer to mlan_adapter structure
3641 * @param pmbuf A pointer to the mlan_buffer
3642 * @return
3643 */
wlan_sdio_handle_rx_packet(mlan_adapter * pmadapter,pmlan_buffer pmbuf)3644 static mlan_status wlan_sdio_handle_rx_packet(mlan_adapter *pmadapter,
3645 pmlan_buffer pmbuf)
3646 {
3647 ENTER();
3648
3649 wlan_sdio_deaggr_rx_pkt(pmadapter, pmbuf);
3650
3651 LEAVE();
3652 return MLAN_STATUS_SUCCESS;
3653 }
3654
3655 mlan_adapter_operations mlan_sdio_ops = {
3656 .dnld_fw = wlan_sdio_dnld_fw,
3657 .interrupt = wlan_sdio_interrupt,
3658 .process_int_status = wlan_process_sdio_int_status,
3659 .host_to_card = wlan_sdio_host_to_card_ext,
3660 .wakeup_card = wlan_pm_sdio_wakeup_card,
3661 .reset_card = wlan_pm_sdio_reset_card,
3662 .event_complete = wlan_sdio_data_evt_complete,
3663 .data_complete = wlan_sdio_data_evt_complete,
3664 .cmdrsp_complete = wlan_sdio_data_evt_complete,
3665 .handle_rx_packet = wlan_sdio_handle_rx_packet,
3666 .disable_host_int = wlan_disable_sdio_host_int,
3667 .enable_host_int = wlan_enable_sdio_host_int,
3668
3669 .intf_header_len = SDIO_INTF_HEADER_LEN,
3670 };
3671