xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/nxp/mlan/mlan_sdio.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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 				       &reg))
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 				       &reg))
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 				       &reg))
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, &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 				       &reg)) {
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 				       &reg)) {
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, &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 						      &reg)) {
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