xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/nxp/mlan/mlan_pcie.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /** @file mlan_pcie.c
2  *
3  *  @brief This file contains PCI-E 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     02/01/2012: 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_pcie.h"
39 
40 /********************************************************
41 			Local Variables
42 ********************************************************/
43 #ifdef PCIE8897
44 static const struct _mlan_pcie_card_reg mlan_reg_pcie8897 = {
45 	.reg_txbd_rdptr = PCIE8897_RD_DATA_PTR_Q0_Q1,
46 	.reg_txbd_wrptr = PCIE8897_WR_DATA_PTR_Q0_Q1,
47 	.reg_rxbd_rdptr = PCIE8897_RD_DATA_PTR_Q0_Q1,
48 	.reg_rxbd_wrptr = PCIE8897_WR_DATA_PTR_Q0_Q1,
49 	.reg_evtbd_rdptr = REG_EVTBD_RDPTR,
50 	.reg_evtbd_wrptr = REG_EVTBD_WRPTR,
51 	.reg_host_int_mask = PCIE_HOST_INT_MASK,
52 	.reg_host_int_status_mask = PCIE_HOST_INT_STATUS_MASK,
53 	.reg_host_int_status = PCIE_HOST_INT_STATUS,
54 	.reg_cpu_int_event = PCIE_CPU_INT_EVENT,
55 	.reg_ip_rev = PCIE_IP_REV_REG,
56 	.reg_drv_ready = REG_DRV_READY,
57 	.reg_cpu_int_status = PCIE_CPU_INT_STATUS,
58 	.reg_scratch_0 = PCIE_SCRATCH_0_REG,
59 	.reg_scratch_1 = PCIE_SCRATCH_1_REG,
60 	.reg_scratch_2 = PCIE_SCRATCH_2_REG,
61 	.reg_scratch_3 = PCIE_SCRATCH_3_REG,
62 	.host_intr_mask = HOST_INTR_MASK,
63 	.host_intr_dnld_done = HOST_INTR_DNLD_DONE,
64 	.host_intr_upld_rdy = HOST_INTR_UPLD_RDY,
65 	.host_intr_cmd_done = HOST_INTR_CMD_DONE,
66 	.host_intr_event_rdy = HOST_INTR_EVENT_RDY,
67 	.txrx_rw_ptr_mask = 0x000003FF,
68 	.txrx_rw_ptr_wrap_mask = 0x000007FF,
69 	.txrx_rw_ptr_rollover_ind = MBIT(10),
70 	.use_adma = MFALSE,
71 	.msi_int_wr_clr = MTRUE,
72 };
73 
74 static const struct _mlan_card_info mlan_card_info_pcie8897 = {
75 	.max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_4K,
76 	.v16_fw_api = 0,
77 	.supp_ps_handshake = 0,
78 	.default_11n_tx_bf_cap = DEFAULT_11N_TX_BF_CAP_2X2,
79 };
80 #endif
81 
82 #ifdef PCIE8997
83 static const struct _mlan_pcie_card_reg mlan_reg_pcie8997 = {
84 	.reg_txbd_rdptr = PCIE8997_RD_DATA_PTR_Q0_Q1,
85 	.reg_txbd_wrptr = PCIE8997_WR_DATA_PTR_Q0_Q1,
86 	.reg_rxbd_rdptr = PCIE8997_RD_DATA_PTR_Q0_Q1,
87 	.reg_rxbd_wrptr = PCIE8997_WR_DATA_PTR_Q0_Q1,
88 	.reg_evtbd_rdptr = REG_EVTBD_RDPTR,
89 	.reg_evtbd_wrptr = REG_EVTBD_WRPTR,
90 	.reg_host_int_mask = PCIE_HOST_INT_MASK,
91 	.reg_host_int_status_mask = PCIE_HOST_INT_STATUS_MASK,
92 	.reg_host_int_status = PCIE_HOST_INT_STATUS,
93 	.reg_cpu_int_event = PCIE_CPU_INT_EVENT,
94 	.reg_ip_rev = PCIE_IP_REV_REG,
95 	.reg_drv_ready = REG_DRV_READY,
96 	.reg_cpu_int_status = PCIE_CPU_INT_STATUS,
97 	.reg_scratch_0 = PCIE_SCRATCH_0_REG,
98 	.reg_scratch_1 = PCIE_SCRATCH_1_REG,
99 	.reg_scratch_2 = PCIE_SCRATCH_2_REG,
100 	.reg_scratch_3 = PCIE_SCRATCH_3_REG,
101 	.host_intr_mask = HOST_INTR_MASK,
102 	.host_intr_dnld_done = HOST_INTR_DNLD_DONE,
103 	.host_intr_upld_rdy = HOST_INTR_UPLD_RDY,
104 	.host_intr_cmd_done = HOST_INTR_CMD_DONE,
105 	.host_intr_event_rdy = HOST_INTR_EVENT_RDY,
106 	.txrx_rw_ptr_mask = 0x00000FFF,
107 	.txrx_rw_ptr_wrap_mask = 0x00001FFF,
108 	.txrx_rw_ptr_rollover_ind = MBIT(12),
109 	.use_adma = MFALSE,
110 	.msi_int_wr_clr = MTRUE,
111 };
112 
113 static const struct _mlan_card_info mlan_card_info_pcie8997 = {
114 	.max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_4K,
115 	.v16_fw_api = 1,
116 	.supp_ps_handshake = 0,
117 	.default_11n_tx_bf_cap = DEFAULT_11N_TX_BF_CAP_2X2,
118 };
119 #endif
120 
121 #if defined(PCIE9097) || defined(PCIENW62X)
122 static const struct _mlan_pcie_card_reg mlan_reg_pcie9097_b0 = {
123 	.reg_txbd_rdptr = PCIE9098_TXBD_RDPTR,
124 	.reg_txbd_wrptr = PCIE9098_TXBD_WRPTR,
125 	.reg_rxbd_rdptr = PCIE9098_RXBD_RDPTR,
126 	.reg_rxbd_wrptr = PCIE9098_RXBD_WRPTR,
127 	.reg_evtbd_rdptr = PCIE9098_EVTBD_RDPTR,
128 	.reg_evtbd_wrptr = PCIE9098_EVTBD_WRPTR,
129 	.reg_host_int_mask = PCIE9097_B0_HOST_INT_MASK,
130 	.reg_host_int_status_mask = PCIE9097_B0_HOST_INT_STATUS_MASK,
131 	.reg_host_int_status = PCIE9097_B0_HOST_INT_STATUS,
132 	.reg_host_int_clr_sel = PCIE9097_B0_HOST_INT_CLR_SEL,
133 	.reg_cpu_int_event = PCIE9098_CPU_INT_EVENT,
134 	.reg_ip_rev = PCIE9098_DEV_ID_REG,
135 	.reg_drv_ready = PCIE9098_DRV_READY,
136 	.reg_cpu_int_status = PCIE9098_CPU_INT_STATUS,
137 	.reg_rev_id = PCIE9098_REV_ID_REG,
138 	.reg_scratch_0 = PCIE9098_SCRATCH_0_REG,
139 	.reg_scratch_1 = PCIE9098_SCRATCH_1_REG,
140 	.reg_scratch_2 = PCIE9098_SCRATCH_2_REG,
141 	.reg_scratch_3 = PCIE9098_SCRATCH_3_REG,
142 	.reg_scratch_6 = PCIE9098_SCRATCH_6_REG,
143 	.reg_scratch_7 = PCIE9098_SCRATCH_7_REG,
144 	.host_intr_mask = PCIE9098_HOST_INTR_MASK,
145 	.host_intr_dnld_done = PCIE9098_HOST_INTR_DNLD_DONE,
146 	.host_intr_upld_rdy = PCIE9098_HOST_INTR_UPLD_RDY,
147 	.host_intr_cmd_done = PCIE9098_HOST_INTR_CMD_DONE,
148 	.host_intr_event_rdy = PCIE9098_HOST_INTR_EVENT_RDY,
149 	.host_intr_cmd_dnld = PCIE9098_HOST_INTR_CMD_DNLD,
150 	.use_adma = MTRUE,
151 	.msi_int_wr_clr = MTRUE,
152 };
153 #endif
154 
155 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
156 static const struct _mlan_pcie_card_reg mlan_reg_pcie9098 = {
157 	.reg_txbd_rdptr = PCIE9098_TXBD_RDPTR,
158 	.reg_txbd_wrptr = PCIE9098_TXBD_WRPTR,
159 	.reg_rxbd_rdptr = PCIE9098_RXBD_RDPTR,
160 	.reg_rxbd_wrptr = PCIE9098_RXBD_WRPTR,
161 	.reg_evtbd_rdptr = PCIE9098_EVTBD_RDPTR,
162 	.reg_evtbd_wrptr = PCIE9098_EVTBD_WRPTR,
163 	.reg_host_int_mask = PCIE9098_HOST_INT_MASK,
164 	.reg_host_int_status_mask = PCIE9098_HOST_INT_STATUS_MASK,
165 	.reg_host_int_status = PCIE9098_HOST_INT_STATUS,
166 	.reg_host_int_clr_sel = PCIE9098_HOST_INT_CLR_SEL,
167 	.reg_cpu_int_event = PCIE9098_CPU_INT_EVENT,
168 	.reg_ip_rev = PCIE9098_DEV_ID_REG,
169 	.reg_drv_ready = PCIE9098_DRV_READY,
170 	.reg_cpu_int_status = PCIE9098_CPU_INT_STATUS,
171 	.reg_rev_id = PCIE9098_REV_ID_REG,
172 	.reg_scratch_0 = PCIE9098_SCRATCH_0_REG,
173 	.reg_scratch_1 = PCIE9098_SCRATCH_1_REG,
174 	.reg_scratch_2 = PCIE9098_SCRATCH_2_REG,
175 	.reg_scratch_3 = PCIE9098_SCRATCH_3_REG,
176 	.reg_scratch_6 = PCIE9098_SCRATCH_6_REG,
177 	.reg_scratch_7 = PCIE9098_SCRATCH_7_REG,
178 	.host_intr_mask = PCIE9098_HOST_INTR_MASK,
179 	.host_intr_dnld_done = PCIE9098_HOST_INTR_DNLD_DONE,
180 	.host_intr_upld_rdy = PCIE9098_HOST_INTR_UPLD_RDY,
181 	.host_intr_cmd_done = PCIE9098_HOST_INTR_CMD_DONE,
182 	.host_intr_event_rdy = PCIE9098_HOST_INTR_EVENT_RDY,
183 	.host_intr_cmd_dnld = PCIE9098_HOST_INTR_CMD_DNLD,
184 	.use_adma = MTRUE,
185 	.msi_int_wr_clr = MTRUE,
186 };
187 
188 static const struct _mlan_card_info mlan_card_info_pcie9098 = {
189 	.max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_4K,
190 	.v16_fw_api = 1,
191 	.v17_fw_api = 1,
192 	.supp_ps_handshake = 0,
193 	.default_11n_tx_bf_cap = DEFAULT_11N_TX_BF_CAP_2X2,
194 };
195 #endif
196 /********************************************************
197 			Global Variables
198 ********************************************************/
199 
200 /********************************************************
201 			Local Functions
202 ********************************************************/
203 
204 static mlan_status wlan_pcie_delete_evtbd_ring(pmlan_adapter pmadapter);
205 static mlan_status wlan_pcie_delete_rxbd_ring(pmlan_adapter pmadapter);
206 
207 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
208 /**
209  *  @brief This function init the adma setting
210  *
211  *  @param pmadapter  A pointer to mlan_adapter structure
212  *  @param adma_type  TX/RX data, event, cmd/cmdresp
213  *  @param pbase      physical address
214  *  @param size       desc num/dma_size
215  *  @param init       init flag
216  *
217  *  @return 	      MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
218  */
wlan_init_adma(mlan_adapter * pmadapter,t_u8 type,t_u64 pbase,t_u16 size,t_u8 init)219 static mlan_status wlan_init_adma(mlan_adapter *pmadapter, t_u8 type,
220 				  t_u64 pbase, t_u16 size, t_u8 init)
221 {
222 	t_u32 dma_cfg, dma_cfg2, dma_cfg3, int_mapping;
223 	mlan_status ret = MLAN_STATUS_SUCCESS;
224 	t_u32 q_addr = 0;
225 	t_u8 direction = 0;
226 	t_u8 dma_mode = 0;
227 	t_u32 msix_data;
228 	t_u32 msix_vector;
229 	pmlan_callbacks pcb = &pmadapter->callbacks;
230 	ENTER();
231 	if (init)
232 		PRINTM(MCMND, "Init ADMA: type=%d, size=%d init=%d\n", type,
233 		       size, init);
234 	switch (type) {
235 	case ADMA_TX_DATA:
236 		q_addr = ADMA_CHAN0_Q0;
237 		direction = ADMA_HOST_TO_DEVICE;
238 		dma_mode = DMA_MODE_DUAL_DESC;
239 		msix_vector = ADMA_VECTOR_CHAN0_Q0;
240 		break;
241 	case ADMA_RX_DATA:
242 		q_addr = ADMA_CHAN1_Q0;
243 		direction = ADMA_DEVICE_TO_HOST;
244 		dma_mode = DMA_MODE_DUAL_DESC;
245 		msix_vector = AMDA_VECTOR_CHAN1_Q0;
246 		break;
247 	case ADMA_EVENT:
248 		q_addr = ADMA_CHAN1_Q1;
249 		direction = ADMA_DEVICE_TO_HOST;
250 		dma_mode = DMA_MODE_DUAL_DESC;
251 		msix_vector = AMDA_VECTOR_CHAN1_Q1;
252 		break;
253 	case ADMA_CMD:
254 		q_addr = ADMA_CHAN2_Q0;
255 		direction = ADMA_HOST_TO_DEVICE;
256 		dma_mode = DMA_MODE_DIRECT;
257 		msix_vector = AMDA_VECTOR_CHAN2_Q0;
258 		break;
259 	case ADMA_CMDRESP:
260 		q_addr = ADMA_CHAN2_Q1;
261 		direction = ADMA_DEVICE_TO_HOST;
262 		dma_mode = DMA_MODE_DIRECT;
263 		msix_vector = AMDA_VECTOR_CHAN2_Q1;
264 		break;
265 	default:
266 		PRINTM(MERROR, "unknow adma type\n");
267 		ret = MLAN_STATUS_FAILURE;
268 		break;
269 	}
270 	if (ret)
271 		goto done;
272 	if (init) {
273 		if (dma_mode == DMA_MODE_DUAL_DESC) {
274 			if (direction == ADMA_HOST_TO_DEVICE)
275 				int_mapping = DEST_INT_TO_DEVICE;
276 			else
277 				int_mapping = DEST_INT_TO_HOST;
278 		} else {
279 			int_mapping = 0;
280 		}
281 		/* set INT_MAPPING register */
282 		if (pcb->moal_write_reg(pmadapter->pmoal_handle,
283 					q_addr + ADMA_INT_MAPPING,
284 					(t_u32)int_mapping)) {
285 			PRINTM(MERROR,
286 			       "Failed to write ADMA_INT_MAPPING register.\n");
287 			ret = MLAN_STATUS_FAILURE;
288 			goto done;
289 		}
290 
291 		/* Read the dma_cfg2 register */
292 		if (pcb->moal_read_reg(pmadapter->pmoal_handle,
293 				       q_addr + ADMA_DMA_CFG2, &dma_cfg2)) {
294 			PRINTM(MERROR, "Fail to read DMA CFG2 register\n");
295 			ret = MLAN_STATUS_FAILURE;
296 			goto done;
297 		}
298 		dma_cfg2 &= ~(ADMA_SRC_DMA_DONE_INT_BYPASS_EN |
299 			      ADMA_DST_DMA_DONE_INT_BYPASS_EN |
300 			      ADMA_MSI_LEGACY_SRC_DMA_DONE_INT_BYPASS_EN |
301 			      ADMA_MSI_LEGACY_DST_DMA_DONE_INT_BYPASS_EN |
302 			      ADMA_MSI_LEGACY_ENABLE | ADMA_MSIX_ENABLE |
303 			      ADMA_MSIX_INT_SRC_DST_SEL);
304 
305 		if (dma_mode == DMA_MODE_DUAL_DESC) {
306 			if (direction == ADMA_HOST_TO_DEVICE) {
307 				dma_cfg2 |= ADMA_SRC_DMA_DONE_INT_BYPASS_EN;
308 				if (pmadapter->pcard_pcie->pcie_int_mode !=
309 				    PCIE_INT_MODE_MSIX)
310 					dma_cfg2 |=
311 						ADMA_MSI_LEGACY_SRC_DMA_DONE_INT_BYPASS_EN;
312 			} else {
313 				/* Read the dma_cfg3 register */
314 				if (pcb->moal_read_reg(pmadapter->pmoal_handle,
315 						       q_addr + ADMA_DMA_CFG3,
316 						       &dma_cfg3)) {
317 					PRINTM(MERROR,
318 					       "Fail to read DMA CFG3 register\n");
319 					ret = MLAN_STATUS_FAILURE;
320 					goto done;
321 				}
322 				dma_cfg3 |= ADMA_Q_PTR_CLR;
323 				if (pcb->moal_write_reg(pmadapter->pmoal_handle,
324 							q_addr + ADMA_DMA_CFG3,
325 							(t_u32)dma_cfg3)) {
326 					PRINTM(MERROR,
327 					       "Failed to write ADMA_DMA_CFG3.\n");
328 					ret = MLAN_STATUS_FAILURE;
329 					goto done;
330 				}
331 
332 				dma_cfg2 |= ADMA_DST_DMA_DONE_INT_BYPASS_EN;
333 				if (pmadapter->pcard_pcie->pcie_int_mode !=
334 				    PCIE_INT_MODE_MSIX)
335 					dma_cfg2 |=
336 						ADMA_MSI_LEGACY_DST_DMA_DONE_INT_BYPASS_EN;
337 			}
338 		} else {
339 			if (direction == ADMA_HOST_TO_DEVICE)
340 				dma_cfg2 |= ADMA_SRC_ADDR_IS_HOST;
341 			else
342 				dma_cfg2 |= ADMA_DST_ADDR_IS_HOST;
343 		}
344 
345 		if (pmadapter->pcard_pcie->pcie_int_mode ==
346 		    PCIE_INT_MODE_MSIX) {
347 			if (pcb->moal_read_reg(pmadapter->pmoal_handle,
348 					       q_addr + ADMA_MSIX_DOORBELL_DATA,
349 					       &msix_data)) {
350 				PRINTM(MERROR,
351 				       "Fail to read DMA MSIX data register\n");
352 				ret = MLAN_STATUS_FAILURE;
353 				goto done;
354 			}
355 			msix_data &= ~ADMA_MSIX_VECTOR_MASK;
356 			msix_data &= ~ADMA_MSIX_PF_MASK;
357 			msix_data |= msix_vector;
358 			msix_data |= pmadapter->pcard_pcie->func_num
359 				     << ADMA_MSIX_PF_BIT;
360 			PRINTM(MCMND, "msix_data=0x%x\n", msix_data);
361 			if (pcb->moal_write_reg(pmadapter->pmoal_handle,
362 						q_addr +
363 							ADMA_MSIX_DOORBELL_DATA,
364 						(t_u32)msix_data)) {
365 				PRINTM(MERROR,
366 				       "Failed to write DMA DOORBELL_DATA.\n");
367 				ret = MLAN_STATUS_FAILURE;
368 				goto done;
369 			}
370 			dma_cfg2 |= ADMA_MSIX_ENABLE;
371 		} else
372 			dma_cfg2 |= ADMA_MSI_LEGACY_ENABLE;
373 		PRINTM(MCMND, "dma_cfg2=0x%x\n", dma_cfg2);
374 
375 		/* enable INT_BYPASS_EN in the dma_cfg2 register */
376 		if (pcb->moal_write_reg(pmadapter->pmoal_handle,
377 					q_addr + ADMA_DMA_CFG2,
378 					(t_u32)dma_cfg2)) {
379 			PRINTM(MERROR, "Failed to write DMA CFG2.\n");
380 			ret = MLAN_STATUS_FAILURE;
381 			goto done;
382 		}
383 	}
384 	/* Read the TX ring read pointer set by firmware */
385 	if (pcb->moal_read_reg(pmadapter->pmoal_handle, q_addr + ADMA_DMA_CFG,
386 			       &dma_cfg)) {
387 		PRINTM(MERROR, "Fail to read DMA CFG register\n");
388 		ret = MLAN_STATUS_FAILURE;
389 		goto done;
390 	}
391 	if (direction == ADMA_HOST_TO_DEVICE) {
392 		/* Write the lower 32bits of the physical address to
393 		 * ADMA_SRC_LOW */
394 		if (pcb->moal_write_reg(pmadapter->pmoal_handle,
395 					q_addr + ADMA_SRC_LOW, (t_u32)pbase)) {
396 			PRINTM(MERROR, "Failed to write ADMA_SRC_LOW.\n");
397 			ret = MLAN_STATUS_FAILURE;
398 			goto done;
399 		}
400 		/* Write the upper 32bits of the physical address to
401 		 * ADMA_SRC_HIGH */
402 		if (pcb->moal_write_reg(pmadapter->pmoal_handle,
403 					q_addr + ADMA_SRC_HIGH,
404 					(t_u32)((t_u64)pbase >> 32))) {
405 			PRINTM(MERROR, "Failed to write ADMA_SRC_HIGH.\n");
406 			ret = MLAN_STATUS_FAILURE;
407 			goto done;
408 		}
409 		if (init) {
410 			/** Enable DMA done interrupt */
411 			if (pcb->moal_write_reg(
412 				    pmadapter->pmoal_handle,
413 				    q_addr + ADMA_SRC_INT_STATUS_MASK,
414 				    DEF_ADMA_INT_MASK)) {
415 				PRINTM(MERROR,
416 				       "Failed to write ADMA_SRC_INT_STATUS_MASK.\n");
417 				ret = MLAN_STATUS_FAILURE;
418 				goto done;
419 			}
420 			if (pcb->moal_write_reg(pmadapter->pmoal_handle,
421 						q_addr + ADMA_SRC_INT_MASK,
422 						DEF_ADMA_INT_MASK)) {
423 				PRINTM(MERROR,
424 				       "Failed to write ADMA_SRC_INT_MASK.\n");
425 				ret = MLAN_STATUS_FAILURE;
426 				goto done;
427 			}
428 		}
429 		if (dma_mode == DMA_MODE_DUAL_DESC) {
430 			dma_cfg &= ~(DESC_MODE_MASK | DMA_MODE_MASK |
431 				     SRC_NUM_DESC_MASK | DMA_SIZE_MASK);
432 			dma_cfg |= (t_u32)size << SRC_NUM_DESC_BIT;
433 			dma_cfg |= DESC_MODE_RING << 2;
434 		} else {
435 			dma_cfg &= ~(DESC_MODE_MASK | DMA_MODE_MASK |
436 				     SRC_NUM_DESC_MASK | DST_NUM_DESC_MASK |
437 				     DMA_SIZE_MASK);
438 			dma_cfg |= (t_u32)size << DMA_SIZE_BIT;
439 		}
440 	} else {
441 		/* Write the lower 32bits of the physical address to
442 		 * ADMA_DST_LOW */
443 		if (pcb->moal_write_reg(pmadapter->pmoal_handle,
444 					q_addr + ADMA_DST_LOW, (t_u32)pbase)) {
445 			PRINTM(MERROR, "Failed to write ADMA_DST_LOW.\n");
446 			ret = MLAN_STATUS_FAILURE;
447 			goto done;
448 		}
449 		/* Write the upper 32bits of the physical address to
450 		 * ADMA_DST_HIGH */
451 		if (pcb->moal_write_reg(pmadapter->pmoal_handle,
452 					q_addr + ADMA_DST_HIGH,
453 					(t_u32)((t_u64)pbase >> 32))) {
454 			PRINTM(MERROR, "Failed to write ADMA_DST_HIGH.\n");
455 			ret = MLAN_STATUS_FAILURE;
456 			goto done;
457 		}
458 		if (init && (dma_mode == DMA_MODE_DUAL_DESC)) {
459 			/** Enable DMA done interrupt */
460 			if (pcb->moal_write_reg(
461 				    pmadapter->pmoal_handle,
462 				    q_addr + ADMA_DST_INT_STATUS_MASK,
463 				    DEF_ADMA_INT_MASK)) {
464 				PRINTM(MERROR,
465 				       "Failed to write ADMA_SRC_INT_STATUS_MASK.\n");
466 				ret = MLAN_STATUS_FAILURE;
467 				goto done;
468 			}
469 			if (pcb->moal_write_reg(pmadapter->pmoal_handle,
470 						q_addr + ADMA_DST_INT_MASK,
471 						DEF_ADMA_INT_MASK)) {
472 				PRINTM(MERROR,
473 				       "Failed to write ADMA_SRC_INT_MASK.\n");
474 				ret = MLAN_STATUS_FAILURE;
475 				goto done;
476 			}
477 		}
478 		if (dma_mode == DMA_MODE_DUAL_DESC) {
479 			dma_cfg &= ~(DESC_MODE_MASK | DMA_MODE_MASK |
480 				     DST_NUM_DESC_MASK | DMA_SIZE_MASK);
481 			dma_cfg |= (t_u32)size << DST_NUM_DESC_BIT;
482 			dma_cfg |= DESC_MODE_RING << 2;
483 		} else {
484 			dma_cfg &= ~(DESC_MODE_MASK | DMA_MODE_MASK |
485 				     SRC_NUM_DESC_MASK | DST_NUM_DESC_MASK);
486 		}
487 	}
488 	dma_cfg |= (t_u32)dma_mode;
489 	if (pcb->moal_write_reg(pmadapter->pmoal_handle, q_addr + ADMA_DMA_CFG,
490 				dma_cfg)) {
491 		PRINTM(MERROR, "Fail to set DMA CFG register\n");
492 		LEAVE();
493 		return MLAN_STATUS_FAILURE;
494 	}
495 	if (type == ADMA_CMD && !init) {
496 		/* Write 1 to src_wr_ptr to trigger direct dma */
497 		if (pcb->moal_write_reg(pmadapter->pmoal_handle,
498 					q_addr + ADMA_SRC_RW_PTR, 1)) {
499 			PRINTM(MERROR, "Failed to write ADMA_SRC_HIGH.\n");
500 			ret = MLAN_STATUS_FAILURE;
501 			goto done;
502 		}
503 	}
504 done:
505 	LEAVE();
506 	return ret;
507 }
508 
509 /**
510  *  @brief This function init the adma ring size from user input
511  *
512  *  @param pmadapter  A pointer to mlan_adapter structure
513  *
514  *  @return 	      N/A
515  */
wlan_pcie_init_adma_ring_size(mlan_adapter * pmadapter)516 static void wlan_pcie_init_adma_ring_size(mlan_adapter *pmadapter)
517 {
518 	t_u16 num_desc = 0;
519 	t_u16 ring_size = 0;
520 
521 	ring_size = pmadapter->init_para.ring_size;
522 	if (!ring_size)
523 		return;
524 	if (ring_size < MAX_TXRX_BD)
525 		ring_size = MAX_TXRX_BD;
526 	else if (ring_size > ADMA_MAX_TXRX_BD)
527 		ring_size = ADMA_MAX_TXRX_BD;
528 	if (ring_size != pmadapter->pcard_pcie->txrx_bd_size) {
529 		ring_size = ring_size >> 1;
530 		while (ring_size > 0) {
531 			ring_size = ring_size >> 1;
532 			num_desc++;
533 		}
534 		pmadapter->pcard_pcie->txrx_bd_size = 1 << num_desc;
535 		pmadapter->pcard_pcie->txrx_num_desc = num_desc;
536 	}
537 	PRINTM(MMSG, "ring_size =%d num_desc=%d\n",
538 	       pmadapter->pcard_pcie->txrx_bd_size,
539 	       pmadapter->pcard_pcie->txrx_num_desc);
540 	return;
541 }
542 
543 #endif
544 
545 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
546 /**
547  *  @brief This function set the host interrupt select mask
548  *
549  *  @param pmadapter  A pointer to mlan_adapter structure
550  *  @param enable     0-disable 1-enable
551  *
552  *  @return 	      MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
553  */
wlan_pcie_set_host_int_select_mask(mlan_adapter * pmadapter,t_u8 enable)554 static mlan_status wlan_pcie_set_host_int_select_mask(mlan_adapter *pmadapter,
555 						      t_u8 enable)
556 {
557 	pmlan_callbacks pcb = &pmadapter->callbacks;
558 	t_u32 int_sel_mask = 0;
559 	t_u32 int_clr_mask = 0;
560 	ENTER();
561 
562 	if (enable) {
563 		int_sel_mask = PCIE9098_HOST_INTR_SEL_MASK;
564 		int_clr_mask = pmadapter->pcard_pcie->reg->host_intr_mask;
565 	}
566 
567 	/* Simply write the mask to the register */
568 	if (pcb->moal_write_reg(pmadapter->pmoal_handle, PCIE9098_HOST_INT_SEL,
569 				int_sel_mask)) {
570 		PRINTM(MWARN, "Set host interrupt select register failed\n");
571 		LEAVE();
572 		return MLAN_STATUS_FAILURE;
573 	}
574 	if (pmadapter->pcard_pcie->pcie_int_mode == PCIE_INT_MODE_MSI) {
575 		if (!pmadapter->pcard_pcie->reg->msi_int_wr_clr) {
576 			/** enable read to clear interrupt */
577 			if (pcb->moal_write_reg(pmadapter->pmoal_handle,
578 						pmadapter->pcard_pcie->reg
579 							->reg_host_int_clr_sel,
580 						int_clr_mask)) {
581 				PRINTM(MWARN,
582 				       "enable read to clear interrupt failed\n");
583 				LEAVE();
584 				return MLAN_STATUS_FAILURE;
585 			}
586 		}
587 	}
588 	LEAVE();
589 	return MLAN_STATUS_SUCCESS;
590 }
591 #endif
592 
593 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
594 /**
595  *  @brief This function handles command response completion
596  *
597  *  @param pmadapter    A pointer to mlan_adapter structure
598  *  @param pmbuf        A pointer to mlan_buffer
599  *
600  *  @return 	        MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
601  */
wlan_pcie_send_vdll_complete(mlan_adapter * pmadapter)602 static mlan_status wlan_pcie_send_vdll_complete(mlan_adapter *pmadapter)
603 {
604 	mlan_buffer *pcmdbuf;
605 	pmlan_callbacks pcb = &pmadapter->callbacks;
606 	ENTER();
607 	/*unmap the cmd pmbuf, so the cpu can not access the memory in the
608 	 * command node*/
609 	pcmdbuf = pmadapter->pcard_pcie->vdll_cmd_buf;
610 	if (pcmdbuf) {
611 		pcb->moal_unmap_memory(pmadapter->pmoal_handle,
612 				       pcmdbuf->pbuf + pcmdbuf->data_offset,
613 				       pcmdbuf->buf_pa, pcmdbuf->data_len,
614 				       PCI_DMA_TODEVICE);
615 		pmadapter->pcard_pcie->vdll_cmd_buf = MNULL;
616 	}
617 	LEAVE();
618 	return MLAN_STATUS_SUCCESS;
619 }
620 
621 /**
622  *  @brief This function downloads VDLL image to the card.
623  *
624  *  @param pmadapter A pointer to mlan_adapter structure
625  *  @param pmbuf     A pointer to mlan_buffer
626  *
627  *  @return 	     MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
628  */
wlan_pcie_send_vdll(mlan_adapter * pmadapter,mlan_buffer * pmbuf)629 static mlan_status wlan_pcie_send_vdll(mlan_adapter *pmadapter,
630 				       mlan_buffer *pmbuf)
631 {
632 	mlan_status ret = MLAN_STATUS_PENDING;
633 	pmlan_callbacks pcb = &pmadapter->callbacks;
634 	t_u16 *tmp;
635 	t_u8 *payload;
636 
637 	ENTER();
638 	pmadapter->cmd_sent = MTRUE;
639 	payload = pmbuf->pbuf + pmbuf->data_offset;
640 
641 	tmp = (t_u16 *)&payload[0];
642 	*tmp = wlan_cpu_to_le16((t_u16)pmbuf->data_len);
643 	tmp = (t_u16 *)&payload[2];
644 	*tmp = wlan_cpu_to_le16(MLAN_TYPE_VDLL);
645 
646 	if (MLAN_STATUS_FAILURE ==
647 	    pcb->moal_map_memory(
648 		    pmadapter->pmoal_handle, pmbuf->pbuf + pmbuf->data_offset,
649 		    &pmbuf->buf_pa, pmbuf->data_len, PCI_DMA_TODEVICE)) {
650 		PRINTM(MERROR,
651 		       "PCIE - Download VDLL block: moal_map_memory failed\n");
652 		ret = MLAN_STATUS_FAILURE;
653 		goto done;
654 	}
655 	pmadapter->pcard_pcie->vdll_cmd_buf = pmbuf;
656 	/* issue the DMA */
657 	/* send the VDLL block down to the firmware */
658 	wlan_init_adma(pmadapter, ADMA_CMD, pmbuf->buf_pa, pmbuf->data_len,
659 		       MFALSE);
660 
661 	PRINTM(MINFO, "PCIE - Download VDLL Block: successful.\n");
662 done:
663 	if (ret == MLAN_STATUS_FAILURE)
664 		pmadapter->cmd_sent = MFALSE;
665 
666 	LEAVE();
667 	return ret;
668 }
669 #endif
670 
671 /**
672  *  @brief This function disables the host interrupt
673  *
674  *  @param pmadapter  A pointer to mlan_adapter structure
675  *
676  *  @return 	      MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
677  */
wlan_pcie_disable_host_int_mask(mlan_adapter * pmadapter)678 static mlan_status wlan_pcie_disable_host_int_mask(mlan_adapter *pmadapter)
679 {
680 	pmlan_callbacks pcb = &pmadapter->callbacks;
681 
682 	ENTER();
683 	if (pcb->moal_write_reg(pmadapter->pmoal_handle,
684 				pmadapter->pcard_pcie->reg->reg_host_int_mask,
685 				0x00000000)) {
686 		PRINTM(MWARN, "Disable host interrupt failed\n");
687 		LEAVE();
688 		return MLAN_STATUS_FAILURE;
689 	}
690 	LEAVE();
691 	return MLAN_STATUS_SUCCESS;
692 }
693 
694 /**
695  *  @brief This function enables the host interrupt
696  *
697  *  @param pmadapter  A pointer to mlan_adapter structure
698  *
699  *  @return 	      MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
700  */
wlan_pcie_enable_host_int_mask(mlan_adapter * pmadapter)701 static mlan_status wlan_pcie_enable_host_int_mask(mlan_adapter *pmadapter)
702 {
703 	pmlan_callbacks pcb = &pmadapter->callbacks;
704 	ENTER();
705 	/* Simply write the mask to the register */
706 	if (pcb->moal_write_reg(pmadapter->pmoal_handle,
707 				pmadapter->pcard_pcie->reg->reg_host_int_mask,
708 				pmadapter->pcard_pcie->reg->host_intr_mask)) {
709 		PRINTM(MWARN, "Enable host interrupt failed\n");
710 		LEAVE();
711 		return MLAN_STATUS_FAILURE;
712 	}
713 	LEAVE();
714 	return MLAN_STATUS_SUCCESS;
715 }
716 
717 /**
718  *  @brief This function enables the host interrupts.
719  *
720  *  @param pmadapter A pointer to mlan_adapter structure
721  *  @param enable   0-disable 1-enable
722  *
723  *  @return        MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
724  */
725 static mlan_status
wlan_pcie_enable_host_int_status_mask(mlan_adapter * pmadapter,t_u8 enable)726 wlan_pcie_enable_host_int_status_mask(mlan_adapter *pmadapter, t_u8 enable)
727 {
728 	pmlan_callbacks pcb = &pmadapter->callbacks;
729 	t_u32 host_int_status_mask = 0;
730 	ENTER();
731 	if (enable)
732 		host_int_status_mask =
733 			pmadapter->pcard_pcie->reg->host_intr_mask;
734 	/* Enable host int status mask */
735 	if (pcb->moal_write_reg(
736 		    pmadapter->pmoal_handle,
737 		    pmadapter->pcard_pcie->reg->reg_host_int_status_mask,
738 		    host_int_status_mask)) {
739 		PRINTM(MWARN, "Enable host interrupt status mask failed\n");
740 		LEAVE();
741 		return MLAN_STATUS_FAILURE;
742 	}
743 	LEAVE();
744 	return MLAN_STATUS_SUCCESS;
745 }
746 
747 /**
748  *  @brief This function disables the host interrupts.
749  *
750  *  @param pmadapter A pointer to mlan_adapter structure
751  *
752  *  @return        MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
753  */
wlan_disable_pcie_host_int(mlan_adapter * pmadapter)754 static mlan_status wlan_disable_pcie_host_int(mlan_adapter *pmadapter)
755 {
756 	mlan_status ret;
757 
758 	ENTER();
759 	ret = wlan_pcie_enable_host_int_status_mask(pmadapter, MFALSE);
760 	if (ret) {
761 		LEAVE();
762 		return ret;
763 	}
764 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
765 	if ((pmadapter->card_type == CARD_TYPE_PCIE9098) ||
766 	    (pmadapter->card_type == CARD_TYPE_PCIENW62X) ||
767 	    (pmadapter->card_type == CARD_TYPE_PCIE9097)) {
768 		ret = wlan_pcie_set_host_int_select_mask(pmadapter, MFALSE);
769 		if (ret) {
770 			LEAVE();
771 			return ret;
772 		}
773 	}
774 #endif
775 	ret = wlan_pcie_disable_host_int_mask(pmadapter);
776 	LEAVE();
777 	return ret;
778 }
779 
780 /**
781  *  @brief This function checks the interrupt status and
782  *  handle it accordingly.
783  *
784  *  @param pmadapter    A pointer to mlan_adapter structure
785  *
786  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
787  */
wlan_clear_pending_int_status(mlan_adapter * pmadapter)788 static mlan_status wlan_clear_pending_int_status(mlan_adapter *pmadapter)
789 {
790 	mlan_status ret = MLAN_STATUS_SUCCESS;
791 	t_u32 pcie_ireg = 0;
792 	pmlan_callbacks pcb = &pmadapter->callbacks;
793 
794 	ENTER();
795 
796 	if (pmadapter->pcard_pcie->pcie_int_mode == PCIE_INT_MODE_MSIX)
797 		goto done;
798 	if (pcb->moal_read_reg(pmadapter->pmoal_handle,
799 			       pmadapter->pcard_pcie->reg->reg_host_int_status,
800 			       &pcie_ireg)) {
801 		PRINTM(MERROR, "Read host int status register failed\n");
802 		ret = MLAN_STATUS_FAILURE;
803 		goto done;
804 	}
805 	if ((pcie_ireg != 0xFFFFFFFF) && (pcie_ireg)) {
806 		PRINTM(MMSG, "pcie_ireg=0x%x\n", pcie_ireg);
807 		if (pmadapter->pcard_pcie->reg->msi_int_wr_clr) {
808 			if (pcb->moal_write_reg(pmadapter->pmoal_handle,
809 						pmadapter->pcard_pcie->reg
810 							->reg_host_int_status,
811 						~pcie_ireg)) {
812 				PRINTM(MERROR,
813 				       "Write host int status  register failed\n");
814 				ret = MLAN_STATUS_FAILURE;
815 				goto done;
816 			}
817 		}
818 	}
819 done:
820 	LEAVE();
821 	return ret;
822 }
823 
824 /**
825  *  @brief This function enables the host interrupts.
826  *
827  *  @param pmadapter A pointer to mlan_adapter structure
828  *
829  *  @return        MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
830  */
wlan_enable_pcie_host_int(mlan_adapter * pmadapter)831 static mlan_status wlan_enable_pcie_host_int(mlan_adapter *pmadapter)
832 {
833 	mlan_status ret;
834 
835 	ENTER();
836 	wlan_clear_pending_int_status(pmadapter);
837 	ret = wlan_pcie_enable_host_int_status_mask(pmadapter, MTRUE);
838 	if (ret) {
839 		LEAVE();
840 		return ret;
841 	}
842 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
843 	if ((pmadapter->card_type == CARD_TYPE_PCIE9098) ||
844 	    (pmadapter->card_type == CARD_TYPE_PCIENW62X) ||
845 	    (pmadapter->card_type == CARD_TYPE_PCIE9097)) {
846 		ret = wlan_pcie_set_host_int_select_mask(pmadapter, MTRUE);
847 		if (ret) {
848 			LEAVE();
849 			return ret;
850 		}
851 	}
852 #endif
853 	ret = wlan_pcie_enable_host_int_mask(pmadapter);
854 	LEAVE();
855 	return ret;
856 }
857 
858 /**
859  *  @brief This function creates buffer descriptor ring for TX
860  *
861  *  @param pmadapter  A pointer to mlan_adapter structure
862  *
863  *  @return 	      MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
864  */
wlan_pcie_create_txbd_ring(mlan_adapter * pmadapter)865 static mlan_status wlan_pcie_create_txbd_ring(mlan_adapter *pmadapter)
866 {
867 	mlan_status ret = MLAN_STATUS_SUCCESS;
868 	pmlan_callbacks pcb = &pmadapter->callbacks;
869 	t_u32 i;
870 #if defined(PCIE8997) || defined(PCIE8897)
871 	pmlan_pcie_data_buf ptx_bd_buf;
872 #endif
873 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
874 	padma_dual_desc_buf padma_bd_buf;
875 #endif
876 
877 	ENTER();
878 	/*
879 	 * driver maintaines the write pointer and firmware maintaines the read
880 	 * pointer.
881 	 */
882 	pmadapter->pcard_pcie->txbd_wrptr = 0;
883 	pmadapter->pcard_pcie->txbd_pending = 0;
884 	pmadapter->pcard_pcie->txbd_rdptr = 0;
885 
886 	/* allocate shared memory for the BD ring and divide the same in to
887 	   several descriptors */
888 #if defined(PCIE8997) || defined(PCIE8897)
889 	if (!pmadapter->pcard_pcie->reg->use_adma)
890 		pmadapter->pcard_pcie->txbd_ring_size =
891 			sizeof(mlan_pcie_data_buf) *
892 			pmadapter->pcard_pcie->txrx_bd_size;
893 #endif
894 
895 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
896 	if (pmadapter->pcard_pcie->reg->use_adma)
897 		pmadapter->pcard_pcie->txbd_ring_size =
898 			sizeof(adma_dual_desc_buf) *
899 			pmadapter->pcard_pcie->txrx_bd_size;
900 #endif
901 	PRINTM(MINFO, "TX ring: allocating %d bytes\n",
902 	       pmadapter->pcard_pcie->txbd_ring_size);
903 
904 	ret = pcb->moal_malloc_consistent(
905 		pmadapter->pmoal_handle, pmadapter->pcard_pcie->txbd_ring_size,
906 		&pmadapter->pcard_pcie->txbd_ring_vbase,
907 		&pmadapter->pcard_pcie->txbd_ring_pbase);
908 
909 	if (ret != MLAN_STATUS_SUCCESS) {
910 		PRINTM(MERROR, "%s: No free moal_malloc_consistent\n",
911 		       __FUNCTION__);
912 		LEAVE();
913 		return MLAN_STATUS_FAILURE;
914 	}
915 
916 	PRINTM(MINFO,
917 	       "TX ring: - base: %p, pbase: %#x:%x,"
918 	       "len: %x\n",
919 	       pmadapter->pcard_pcie->txbd_ring_vbase,
920 	       (t_u32)((t_u64)pmadapter->pcard_pcie->txbd_ring_pbase >> 32),
921 	       (t_u32)pmadapter->pcard_pcie->txbd_ring_pbase,
922 	       pmadapter->pcard_pcie->txbd_ring_size);
923 
924 	for (i = 0; i < pmadapter->pcard_pcie->txrx_bd_size; i++) {
925 		pmadapter->pcard_pcie->tx_buf_list[i] = MNULL;
926 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
927 		if (pmadapter->pcard_pcie->reg->use_adma) {
928 			padma_bd_buf =
929 				(adma_dual_desc_buf
930 					 *)(pmadapter->pcard_pcie
931 						    ->txbd_ring_vbase +
932 					    (sizeof(adma_dual_desc_buf) * i));
933 			pmadapter->pcard_pcie->txbd_ring[i] =
934 				(t_void *)padma_bd_buf;
935 			padma_bd_buf->paddr = 0;
936 			padma_bd_buf->len = 0;
937 			padma_bd_buf->flags = wlan_cpu_to_le16(
938 				ADMA_BD_FLAG_INT_EN | ADMA_BD_FLAG_SRC_HOST |
939 				ADMA_BD_FLAG_SOP | ADMA_BD_FLAG_EOP);
940 			padma_bd_buf->pkt_size = 0;
941 			padma_bd_buf->reserved = 0;
942 		}
943 #endif
944 
945 #if defined(PCIE8997) || defined(PCIE8897)
946 		if (!pmadapter->pcard_pcie->reg->use_adma) {
947 			ptx_bd_buf =
948 				(mlan_pcie_data_buf
949 					 *)(pmadapter->pcard_pcie
950 						    ->txbd_ring_vbase +
951 					    (sizeof(mlan_pcie_data_buf) * i));
952 			pmadapter->pcard_pcie->txbd_ring[i] =
953 				(t_void *)ptx_bd_buf;
954 			ptx_bd_buf->paddr = 0;
955 			ptx_bd_buf->len = 0;
956 			ptx_bd_buf->flags = 0;
957 			ptx_bd_buf->frag_len = 0;
958 			ptx_bd_buf->offset = 0;
959 		}
960 #endif
961 	}
962 	LEAVE();
963 	return ret;
964 }
965 
966 /**
967  *  @brief This function frees TX buffer descriptor ring
968  *
969  *  @param pmadapter  A pointer to mlan_adapter structure
970  *
971  *  @return 	      MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
972  */
wlan_pcie_delete_txbd_ring(mlan_adapter * pmadapter)973 static mlan_status wlan_pcie_delete_txbd_ring(mlan_adapter *pmadapter)
974 {
975 	t_u32 i;
976 	pmlan_callbacks pcb = &pmadapter->callbacks;
977 	mlan_buffer *pmbuf = MNULL;
978 #if defined(PCIE8997) || defined(PCIE8897)
979 	mlan_pcie_data_buf *ptx_bd_buf;
980 #endif
981 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
982 	adma_dual_desc_buf *padma_bd_buf;
983 #endif
984 
985 	ENTER();
986 
987 	for (i = 0; i < pmadapter->pcard_pcie->txrx_bd_size; i++) {
988 		if (pmadapter->pcard_pcie->tx_buf_list[i]) {
989 			pmbuf = pmadapter->pcard_pcie->tx_buf_list[i];
990 			pcb->moal_unmap_memory(pmadapter->pmoal_handle,
991 					       pmbuf->pbuf + pmbuf->data_offset,
992 					       pmbuf->buf_pa,
993 					       MLAN_RX_DATA_BUF_SIZE,
994 					       PCI_DMA_TODEVICE);
995 			wlan_write_data_complete(pmadapter, pmbuf,
996 						 MLAN_STATUS_FAILURE);
997 		}
998 		pmadapter->pcard_pcie->tx_buf_list[i] = MNULL;
999 #if defined(PCIE8997) || defined(PCIE8897)
1000 		if (!pmadapter->pcard_pcie->reg->use_adma) {
1001 			ptx_bd_buf =
1002 				(mlan_pcie_data_buf *)
1003 					pmadapter->pcard_pcie->txbd_ring[i];
1004 
1005 			if (ptx_bd_buf) {
1006 				ptx_bd_buf->paddr = 0;
1007 				ptx_bd_buf->len = 0;
1008 				ptx_bd_buf->flags = 0;
1009 				ptx_bd_buf->frag_len = 0;
1010 				ptx_bd_buf->offset = 0;
1011 			}
1012 		}
1013 #endif
1014 
1015 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
1016 		if (pmadapter->pcard_pcie->reg->use_adma) {
1017 			padma_bd_buf =
1018 				(adma_dual_desc_buf *)
1019 					pmadapter->pcard_pcie->txbd_ring[i];
1020 
1021 			if (padma_bd_buf) {
1022 				padma_bd_buf->paddr = 0;
1023 				padma_bd_buf->len = 0;
1024 				padma_bd_buf->flags = 0;
1025 				padma_bd_buf->pkt_size = 0;
1026 				padma_bd_buf->reserved = 0;
1027 			}
1028 		}
1029 #endif
1030 		pmadapter->pcard_pcie->txbd_ring[i] = MNULL;
1031 	}
1032 
1033 	if (pmadapter->pcard_pcie->txbd_ring_vbase) {
1034 		pmadapter->callbacks.moal_mfree_consistent(
1035 			pmadapter->pmoal_handle,
1036 			pmadapter->pcard_pcie->txbd_ring_size,
1037 			pmadapter->pcard_pcie->txbd_ring_vbase,
1038 			pmadapter->pcard_pcie->txbd_ring_pbase);
1039 	}
1040 	pmadapter->pcard_pcie->txbd_pending = 0;
1041 	pmadapter->pcard_pcie->txbd_ring_size = 0;
1042 	pmadapter->pcard_pcie->txbd_wrptr = 0;
1043 	pmadapter->pcard_pcie->txbd_rdptr = 0;
1044 	pmadapter->pcard_pcie->txbd_ring_vbase = MNULL;
1045 	pmadapter->pcard_pcie->txbd_ring_pbase = 0;
1046 
1047 	LEAVE();
1048 	return MLAN_STATUS_SUCCESS;
1049 }
1050 
1051 /**
1052  *  @brief This function creates buffer descriptor ring for RX
1053  *
1054  *  @param pmadapter  A pointer to mlan_adapter structure
1055  *
1056  *  @return 	      MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1057  */
wlan_pcie_create_rxbd_ring(mlan_adapter * pmadapter)1058 static mlan_status wlan_pcie_create_rxbd_ring(mlan_adapter *pmadapter)
1059 {
1060 	mlan_status ret = MLAN_STATUS_SUCCESS;
1061 	pmlan_callbacks pcb = &pmadapter->callbacks;
1062 	mlan_buffer *pmbuf = MNULL;
1063 	t_u32 i;
1064 #if defined(PCIE8997) || defined(PCIE8897)
1065 	mlan_pcie_data_buf *prxbd_buf;
1066 #endif
1067 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
1068 	adma_dual_desc_buf *padma_bd_buf;
1069 #endif
1070 
1071 	ENTER();
1072 
1073 	pmadapter->pcard_pcie->rxbd_rdptr = 0;
1074 #if defined(PCIE8997) || defined(PCIE8897)
1075 	/*
1076 	 * driver maintaines the write pointer and firmware maintaines the read
1077 	 * pointer. The read pointer starts at 0 (zero) while the write pointer
1078 	 * starts at zero with rollover bit set
1079 	 */
1080 	if (!pmadapter->pcard_pcie->reg->use_adma) {
1081 		pmadapter->pcard_pcie->rxbd_wrptr =
1082 			pmadapter->pcard_pcie->reg->txrx_rw_ptr_rollover_ind;
1083 		/* allocate shared memory for the BD ring and divide the same in
1084 		to several descriptors */
1085 		pmadapter->pcard_pcie->rxbd_ring_size =
1086 			sizeof(mlan_pcie_data_buf) *
1087 			pmadapter->pcard_pcie->txrx_bd_size;
1088 	}
1089 #endif
1090 
1091 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
1092 	/*
1093 	 * driver maintaines the write pointer and firmware maintaines the read
1094 	 * pointer. The read pointer starts at 0 (zero) while the write pointer
1095 	 * starts at pmadapter->pcard_pcie->txrx_bd_size;
1096 	 */
1097 	if (pmadapter->pcard_pcie->reg->use_adma) {
1098 		pmadapter->pcard_pcie->rxbd_wrptr =
1099 			pmadapter->pcard_pcie->txrx_bd_size;
1100 		pmadapter->pcard_pcie->rxbd_ring_size =
1101 			sizeof(adma_dual_desc_buf) *
1102 			pmadapter->pcard_pcie->txrx_bd_size;
1103 	}
1104 #endif
1105 
1106 	PRINTM(MINFO, "RX ring: allocating %d bytes\n",
1107 	       pmadapter->pcard_pcie->rxbd_ring_size);
1108 
1109 	ret = pcb->moal_malloc_consistent(
1110 		pmadapter->pmoal_handle, pmadapter->pcard_pcie->rxbd_ring_size,
1111 		&pmadapter->pcard_pcie->rxbd_ring_vbase,
1112 		&pmadapter->pcard_pcie->rxbd_ring_pbase);
1113 
1114 	if (ret != MLAN_STATUS_SUCCESS) {
1115 		PRINTM(MERROR, "%s: No free moal_malloc_consistent\n",
1116 		       __FUNCTION__);
1117 		LEAVE();
1118 		return MLAN_STATUS_FAILURE;
1119 	}
1120 
1121 	PRINTM(MINFO,
1122 	       "RX ring: - base: %p, pbase: %#x:%x,"
1123 	       "len: %#x\n",
1124 	       pmadapter->pcard_pcie->rxbd_ring_vbase,
1125 	       (t_u32)((t_u64)pmadapter->pcard_pcie->rxbd_ring_pbase >> 32),
1126 	       (t_u32)pmadapter->pcard_pcie->rxbd_ring_pbase,
1127 	       pmadapter->pcard_pcie->rxbd_ring_size);
1128 
1129 	for (i = 0; i < pmadapter->pcard_pcie->txrx_bd_size; i++) {
1130 		/* Allocate buffer here so that firmware can DMA data on it */
1131 		pmbuf = wlan_alloc_mlan_buffer(pmadapter, MLAN_RX_DATA_BUF_SIZE,
1132 					       MLAN_RX_HEADER_LEN,
1133 					       MOAL_ALLOC_MLAN_BUFFER);
1134 		if (!pmbuf) {
1135 			PRINTM(MERROR,
1136 			       "RX ring create : Unable to allocate mlan_buffer\n");
1137 			wlan_pcie_delete_rxbd_ring(pmadapter);
1138 			LEAVE();
1139 			return MLAN_STATUS_FAILURE;
1140 		}
1141 
1142 		pmadapter->pcard_pcie->rx_buf_list[i] = pmbuf;
1143 
1144 		if (MLAN_STATUS_FAILURE ==
1145 		    pcb->moal_map_memory(pmadapter->pmoal_handle,
1146 					 pmbuf->pbuf + pmbuf->data_offset,
1147 					 &pmbuf->buf_pa, MLAN_RX_DATA_BUF_SIZE,
1148 					 PCI_DMA_FROMDEVICE)) {
1149 			PRINTM(MERROR,
1150 			       "Rx ring create : moal_map_memory failed\n");
1151 			wlan_pcie_delete_rxbd_ring(pmadapter);
1152 			LEAVE();
1153 			return MLAN_STATUS_FAILURE;
1154 		}
1155 
1156 		PRINTM(MINFO,
1157 		       "RX ring: add new mlan_buffer base: %p, "
1158 		       "buf_base: %p, buf_pbase: %#x:%x, "
1159 		       "buf_len: %#x\n",
1160 		       pmbuf, pmbuf->pbuf, (t_u32)((t_u64)pmbuf->buf_pa >> 32),
1161 		       (t_u32)pmbuf->buf_pa, pmbuf->data_len);
1162 
1163 #if defined(PCIE8997) || defined(PCIE8897)
1164 		if (!pmadapter->pcard_pcie->reg->use_adma) {
1165 			prxbd_buf =
1166 				(mlan_pcie_data_buf
1167 					 *)(pmadapter->pcard_pcie
1168 						    ->rxbd_ring_vbase +
1169 					    (sizeof(mlan_pcie_data_buf) * i));
1170 			pmadapter->pcard_pcie->rxbd_ring[i] =
1171 				(t_void *)prxbd_buf;
1172 			prxbd_buf->paddr = wlan_cpu_to_le64(pmbuf->buf_pa);
1173 			prxbd_buf->len =
1174 				wlan_cpu_to_le16((t_u16)pmbuf->data_len);
1175 			prxbd_buf->flags = wlan_cpu_to_le16(MLAN_BD_FLAG_SOP |
1176 							    MLAN_BD_FLAG_EOP);
1177 			prxbd_buf->offset = 0;
1178 			prxbd_buf->frag_len =
1179 				wlan_cpu_to_le16((t_u16)pmbuf->data_len);
1180 		}
1181 #endif
1182 
1183 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
1184 		if (pmadapter->pcard_pcie->reg->use_adma) {
1185 			padma_bd_buf =
1186 				(adma_dual_desc_buf
1187 					 *)(pmadapter->pcard_pcie
1188 						    ->rxbd_ring_vbase +
1189 					    (sizeof(adma_dual_desc_buf) * i));
1190 			pmadapter->pcard_pcie->rxbd_ring[i] =
1191 				(t_void *)padma_bd_buf;
1192 			padma_bd_buf->paddr = wlan_cpu_to_le64(pmbuf->buf_pa);
1193 			padma_bd_buf->len = wlan_cpu_to_le16(
1194 				ALIGN_SZ(pmbuf->data_len, ADMA_ALIGN_SIZE));
1195 			padma_bd_buf->flags = wlan_cpu_to_le16(
1196 				ADMA_BD_FLAG_INT_EN | ADMA_BD_FLAG_DST_HOST);
1197 			padma_bd_buf->pkt_size = 0;
1198 			padma_bd_buf->reserved = 0;
1199 		}
1200 #endif
1201 	}
1202 
1203 	LEAVE();
1204 	return MLAN_STATUS_SUCCESS;
1205 }
1206 
1207 /**
1208  *  @brief This function frees RX buffer descriptor ring
1209  *
1210  *  @param pmadapter  A pointer to mlan_adapter structure
1211  *
1212  *  @return 	      MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1213  */
wlan_pcie_delete_rxbd_ring(mlan_adapter * pmadapter)1214 static mlan_status wlan_pcie_delete_rxbd_ring(mlan_adapter *pmadapter)
1215 {
1216 	t_u32 i;
1217 	pmlan_callbacks pcb = &pmadapter->callbacks;
1218 	mlan_buffer *pmbuf = MNULL;
1219 #if defined(PCIE8997) || defined(PCIE8897)
1220 	mlan_pcie_data_buf *prxbd_buf;
1221 #endif
1222 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
1223 	adma_dual_desc_buf *padma_bd_buf;
1224 #endif
1225 
1226 	ENTER();
1227 	for (i = 0; i < pmadapter->pcard_pcie->txrx_bd_size; i++) {
1228 		if (pmadapter->pcard_pcie->rx_buf_list[i]) {
1229 			pmbuf = pmadapter->pcard_pcie->rx_buf_list[i];
1230 			pcb->moal_unmap_memory(pmadapter->pmoal_handle,
1231 					       pmbuf->pbuf + pmbuf->data_offset,
1232 					       pmbuf->buf_pa,
1233 					       MLAN_RX_DATA_BUF_SIZE,
1234 					       PCI_DMA_FROMDEVICE);
1235 			wlan_free_mlan_buffer(
1236 				pmadapter,
1237 				pmadapter->pcard_pcie->rx_buf_list[i]);
1238 		}
1239 		pmadapter->pcard_pcie->rx_buf_list[i] = MNULL;
1240 #if defined(PCIE8997) || defined(PCIE8897)
1241 		if (!pmadapter->pcard_pcie->reg->use_adma) {
1242 			prxbd_buf = (mlan_pcie_data_buf *)
1243 					    pmadapter->pcard_pcie->rxbd_ring[i];
1244 
1245 			if (prxbd_buf) {
1246 				prxbd_buf->paddr = 0;
1247 				prxbd_buf->offset = 0;
1248 				prxbd_buf->frag_len = 0;
1249 			}
1250 		}
1251 #endif
1252 
1253 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
1254 		if (pmadapter->pcard_pcie->reg->use_adma) {
1255 			padma_bd_buf =
1256 				(adma_dual_desc_buf *)
1257 					pmadapter->pcard_pcie->rxbd_ring[i];
1258 
1259 			if (padma_bd_buf) {
1260 				padma_bd_buf->paddr = 0;
1261 				padma_bd_buf->flags = 0;
1262 				padma_bd_buf->pkt_size = 0;
1263 				padma_bd_buf->reserved = 0;
1264 				padma_bd_buf->len = 0;
1265 			}
1266 		}
1267 #endif
1268 		pmadapter->pcard_pcie->rxbd_ring[i] = MNULL;
1269 	}
1270 
1271 	if (pmadapter->pcard_pcie->rxbd_ring_vbase)
1272 		pmadapter->callbacks.moal_mfree_consistent(
1273 			pmadapter->pmoal_handle,
1274 			pmadapter->pcard_pcie->rxbd_ring_size,
1275 			pmadapter->pcard_pcie->rxbd_ring_vbase,
1276 			pmadapter->pcard_pcie->rxbd_ring_pbase);
1277 	pmadapter->pcard_pcie->rxbd_ring_size = 0;
1278 	pmadapter->pcard_pcie->rxbd_rdptr = 0;
1279 	pmadapter->pcard_pcie->rxbd_wrptr = 0;
1280 	pmadapter->pcard_pcie->rxbd_ring_vbase = MNULL;
1281 	pmadapter->pcard_pcie->rxbd_ring_pbase = 0;
1282 
1283 	LEAVE();
1284 	return MLAN_STATUS_SUCCESS;
1285 }
1286 
1287 /**
1288  *  @brief This function creates buffer descriptor ring for Events
1289  *
1290  *  @param pmadapter  A pointer to mlan_adapter structure
1291  *
1292  *  @return 	      MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1293  */
wlan_pcie_create_evtbd_ring(mlan_adapter * pmadapter)1294 static mlan_status wlan_pcie_create_evtbd_ring(mlan_adapter *pmadapter)
1295 {
1296 	mlan_status ret = MLAN_STATUS_SUCCESS;
1297 	pmlan_callbacks pcb = &pmadapter->callbacks;
1298 	mlan_buffer *pmbuf = MNULL;
1299 	t_u32 i;
1300 #if defined(PCIE8997) || defined(PCIE8897)
1301 	pmlan_pcie_evt_buf pevtbd_buf;
1302 #endif
1303 
1304 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
1305 	adma_dual_desc_buf *padma_bd_buf;
1306 #endif
1307 
1308 	ENTER();
1309 	/*
1310 	 * driver maintaines the write pointer and firmware maintaines the read
1311 	 * pointer. The read pointer starts at 0 (zero) while the write pointer
1312 	 * starts at zero with rollover bit set
1313 	 */
1314 	pmadapter->pcard_pcie->evtbd_rdptr = 0;
1315 #if defined(PCIE8997) || defined(PCIE8897)
1316 	if (!pmadapter->pcard_pcie->reg->use_adma) {
1317 		pmadapter->pcard_pcie->evtbd_wrptr = EVT_RW_PTR_ROLLOVER_IND;
1318 		pmadapter->pcard_pcie->evtbd_ring_size =
1319 			sizeof(mlan_pcie_evt_buf) * MLAN_MAX_EVT_BD;
1320 	}
1321 #endif
1322 
1323 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
1324 	if (pmadapter->pcard_pcie->reg->use_adma) {
1325 		pmadapter->pcard_pcie->evtbd_wrptr = MLAN_MAX_EVT_BD;
1326 		pmadapter->pcard_pcie->evtbd_ring_size =
1327 			sizeof(adma_dual_desc_buf) * MLAN_MAX_EVT_BD;
1328 	}
1329 #endif
1330 	PRINTM(MINFO, "Evt ring: allocating %d bytes\n",
1331 	       pmadapter->pcard_pcie->evtbd_ring_size);
1332 
1333 	ret = pcb->moal_malloc_consistent(
1334 		pmadapter->pmoal_handle, pmadapter->pcard_pcie->evtbd_ring_size,
1335 		&pmadapter->pcard_pcie->evtbd_ring_vbase,
1336 		&pmadapter->pcard_pcie->evtbd_ring_pbase);
1337 
1338 	if (ret != MLAN_STATUS_SUCCESS) {
1339 		PRINTM(MERROR, "%s: No free moal_malloc_consistent\n",
1340 		       __FUNCTION__);
1341 		LEAVE();
1342 		return MLAN_STATUS_FAILURE;
1343 	}
1344 	PRINTM(MINFO,
1345 	       "Evt ring: - base: %p, pbase: %#x:%x,"
1346 	       "len: %#x\n",
1347 	       pmadapter->pcard_pcie->evtbd_ring_vbase,
1348 	       (t_u32)((t_u64)pmadapter->pcard_pcie->evtbd_ring_pbase >> 32),
1349 	       (t_u32)pmadapter->pcard_pcie->evtbd_ring_pbase,
1350 	       pmadapter->pcard_pcie->evtbd_ring_size);
1351 
1352 	for (i = 0; i < MLAN_MAX_EVT_BD; i++) {
1353 		/* Allocate buffer here so that firmware can DMA data on it */
1354 		pmbuf = wlan_alloc_mlan_buffer(pmadapter, MAX_EVENT_SIZE,
1355 					       MLAN_RX_HEADER_LEN,
1356 					       MOAL_ALLOC_MLAN_BUFFER);
1357 		if (!pmbuf) {
1358 			PRINTM(MERROR,
1359 			       "Event ring create : Unable to allocate mlan_buffer\n");
1360 			wlan_pcie_delete_evtbd_ring(pmadapter);
1361 			LEAVE();
1362 			return MLAN_STATUS_FAILURE;
1363 		}
1364 
1365 		pmadapter->pcard_pcie->evt_buf_list[i] = pmbuf;
1366 
1367 		if (MLAN_STATUS_FAILURE ==
1368 		    pcb->moal_map_memory(pmadapter->pmoal_handle,
1369 					 pmbuf->pbuf + pmbuf->data_offset,
1370 					 &pmbuf->buf_pa, MAX_EVENT_SIZE,
1371 					 PCI_DMA_FROMDEVICE)) {
1372 			PRINTM(MERROR,
1373 			       "Event ring create : moal_map_memory failed\n");
1374 			wlan_pcie_delete_evtbd_ring(pmadapter);
1375 			LEAVE();
1376 			return MLAN_STATUS_FAILURE;
1377 		}
1378 
1379 #if defined(PCIE8997) || defined(PCIE8897)
1380 		if (!pmadapter->pcard_pcie->reg->use_adma) {
1381 			pevtbd_buf =
1382 				(mlan_pcie_evt_buf
1383 					 *)(pmadapter->pcard_pcie
1384 						    ->evtbd_ring_vbase +
1385 					    (sizeof(mlan_pcie_evt_buf) * i));
1386 			pmadapter->pcard_pcie->evtbd_ring[i] =
1387 				(t_void *)pevtbd_buf;
1388 			pevtbd_buf->paddr = wlan_cpu_to_le64(pmbuf->buf_pa);
1389 			pevtbd_buf->len =
1390 				wlan_cpu_to_le16((t_u16)pmbuf->data_len);
1391 			pevtbd_buf->flags = 0;
1392 		}
1393 #endif
1394 
1395 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
1396 		if (pmadapter->pcard_pcie->reg->use_adma) {
1397 			padma_bd_buf =
1398 				(adma_dual_desc_buf
1399 					 *)(pmadapter->pcard_pcie
1400 						    ->evtbd_ring_vbase +
1401 					    (sizeof(adma_dual_desc_buf) * i));
1402 			pmadapter->pcard_pcie->evtbd_ring[i] =
1403 				(t_void *)padma_bd_buf;
1404 			padma_bd_buf->paddr = wlan_cpu_to_le64(pmbuf->buf_pa);
1405 			padma_bd_buf->len = wlan_cpu_to_le16(
1406 				ALIGN_SZ(pmbuf->data_len, ADMA_ALIGN_SIZE));
1407 			padma_bd_buf->flags = wlan_cpu_to_le16(
1408 				ADMA_BD_FLAG_INT_EN | ADMA_BD_FLAG_DST_HOST);
1409 			padma_bd_buf->pkt_size = 0;
1410 			padma_bd_buf->reserved = 0;
1411 		}
1412 #endif
1413 	}
1414 
1415 	LEAVE();
1416 	return MLAN_STATUS_SUCCESS;
1417 }
1418 
1419 /**
1420  *  @brief This function frees event buffer descriptor ring
1421  *
1422  *  @param pmadapter  A pointer to mlan_adapter structure
1423  *
1424  *  @return 	      MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1425  */
wlan_pcie_delete_evtbd_ring(mlan_adapter * pmadapter)1426 static mlan_status wlan_pcie_delete_evtbd_ring(mlan_adapter *pmadapter)
1427 {
1428 	t_u32 i;
1429 	pmlan_callbacks pcb = &pmadapter->callbacks;
1430 	mlan_buffer *pmbuf = MNULL;
1431 #if defined(PCIE8997) || defined(PCIE8897)
1432 	mlan_pcie_evt_buf *pevtbd_buf;
1433 #endif
1434 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
1435 	adma_dual_desc_buf *padma_bd_buf;
1436 #endif
1437 
1438 	ENTER();
1439 	for (i = 0; i < MLAN_MAX_EVT_BD; i++) {
1440 		if (pmadapter->pcard_pcie->evt_buf_list[i]) {
1441 			pmbuf = pmadapter->pcard_pcie->evt_buf_list[i];
1442 			pcb->moal_unmap_memory(pmadapter->pmoal_handle,
1443 					       pmbuf->pbuf + pmbuf->data_offset,
1444 					       pmbuf->buf_pa, MAX_EVENT_SIZE,
1445 					       PCI_DMA_FROMDEVICE);
1446 			wlan_free_mlan_buffer(pmadapter, pmbuf);
1447 		}
1448 
1449 		pmadapter->pcard_pcie->evt_buf_list[i] = MNULL;
1450 #if defined(PCIE8997) || defined(PCIE8897)
1451 		if (!pmadapter->pcard_pcie->reg->use_adma) {
1452 			pevtbd_buf =
1453 				(mlan_pcie_evt_buf *)
1454 					pmadapter->pcard_pcie->evtbd_ring[i];
1455 
1456 			if (pevtbd_buf) {
1457 				pevtbd_buf->paddr = 0;
1458 				pevtbd_buf->len = 0;
1459 				pevtbd_buf->flags = 0;
1460 			}
1461 		}
1462 #endif
1463 
1464 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
1465 		if (pmadapter->pcard_pcie->reg->use_adma) {
1466 			padma_bd_buf =
1467 				(adma_dual_desc_buf *)
1468 					pmadapter->pcard_pcie->evtbd_ring[i];
1469 
1470 			if (padma_bd_buf) {
1471 				padma_bd_buf->paddr = 0;
1472 				padma_bd_buf->len = 0;
1473 				padma_bd_buf->flags = 0;
1474 				padma_bd_buf->pkt_size = 0;
1475 				padma_bd_buf->reserved = 0;
1476 			}
1477 		}
1478 #endif
1479 		pmadapter->pcard_pcie->evtbd_ring[i] = MNULL;
1480 	}
1481 
1482 	if (pmadapter->pcard_pcie->evtbd_ring_vbase)
1483 		pmadapter->callbacks.moal_mfree_consistent(
1484 			pmadapter->pmoal_handle,
1485 			pmadapter->pcard_pcie->evtbd_ring_size,
1486 			pmadapter->pcard_pcie->evtbd_ring_vbase,
1487 			pmadapter->pcard_pcie->evtbd_ring_pbase);
1488 
1489 	pmadapter->pcard_pcie->evtbd_rdptr = 0;
1490 	pmadapter->pcard_pcie->evtbd_wrptr = 0;
1491 	pmadapter->pcard_pcie->evtbd_ring_size = 0;
1492 	pmadapter->pcard_pcie->evtbd_ring_vbase = MNULL;
1493 	pmadapter->pcard_pcie->evtbd_ring_pbase = 0;
1494 
1495 	LEAVE();
1496 	return MLAN_STATUS_SUCCESS;
1497 }
1498 
1499 /**
1500  *  @brief This function allocates buffer for CMD and CMDRSP
1501  *
1502  *  @param pmadapter  A pointer to mlan_adapter structure
1503  *
1504  *  @return 	      MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1505  */
wlan_pcie_alloc_cmdrsp_buf(mlan_adapter * pmadapter)1506 static mlan_status wlan_pcie_alloc_cmdrsp_buf(mlan_adapter *pmadapter)
1507 {
1508 	mlan_buffer *pmbuf = MNULL;
1509 	pmlan_callbacks pcb = &pmadapter->callbacks;
1510 	mlan_status ret = MLAN_STATUS_SUCCESS;
1511 	/** Virtual base address of command response */
1512 	t_u8 *cmdrsp_vbase;
1513 	/** Physical base address of command response */
1514 	t_u64 cmdrsp_pbase = 0;
1515 
1516 	ENTER();
1517 
1518 	/* Allocate memory for receiving command response data */
1519 	pmbuf = wlan_alloc_mlan_buffer(pmadapter, 0, 0, MOAL_MALLOC_BUFFER);
1520 	if (!pmbuf) {
1521 		PRINTM(MERROR,
1522 		       "Command resp buffer create : Unable to allocate mlan_buffer\n");
1523 		LEAVE();
1524 		return MLAN_STATUS_FAILURE;
1525 	}
1526 	ret = pcb->moal_malloc_consistent(pmadapter->pmoal_handle,
1527 					  MRVDRV_SIZE_OF_CMD_BUFFER,
1528 					  &cmdrsp_vbase, &cmdrsp_pbase);
1529 
1530 	if (ret != MLAN_STATUS_SUCCESS) {
1531 		PRINTM(MERROR, "%s: No free moal_malloc_consistent\n",
1532 		       __FUNCTION__);
1533 		/* free pmbuf */
1534 		wlan_free_mlan_buffer(pmadapter, pmbuf);
1535 		LEAVE();
1536 		return MLAN_STATUS_FAILURE;
1537 	}
1538 
1539 	pmbuf->buf_pa = cmdrsp_pbase;
1540 	pmbuf->pbuf = cmdrsp_vbase;
1541 	pmbuf->data_offset = 0;
1542 	pmbuf->data_len = MRVDRV_SIZE_OF_CMD_BUFFER;
1543 	pmbuf->total_pcie_buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
1544 	pmadapter->pcard_pcie->cmdrsp_buf = pmbuf;
1545 	LEAVE();
1546 	return MLAN_STATUS_SUCCESS;
1547 }
1548 
1549 /**
1550  *  @brief This function frees CMD and CMDRSP buffer
1551  *
1552  *  @param pmadapter  A pointer to mlan_adapter structure
1553  *
1554  *  @return 	      MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1555  */
wlan_pcie_delete_cmdrsp_buf(mlan_adapter * pmadapter)1556 static mlan_status wlan_pcie_delete_cmdrsp_buf(mlan_adapter *pmadapter)
1557 {
1558 	mlan_buffer *pmbuf = MNULL;
1559 	pmlan_callbacks pcb = &pmadapter->callbacks;
1560 	t_u8 *cmdrsp_vbase;
1561 	t_u64 cmdrsp_pbase;
1562 	ENTER();
1563 
1564 	if (!pmadapter) {
1565 		LEAVE();
1566 		return MLAN_STATUS_FAILURE;
1567 	}
1568 
1569 	if (pmadapter->pcard_pcie->cmdrsp_buf) {
1570 		pmbuf = pmadapter->pcard_pcie->cmdrsp_buf;
1571 		cmdrsp_vbase = pmbuf->pbuf;
1572 		cmdrsp_pbase = pmbuf->buf_pa;
1573 		if (cmdrsp_vbase)
1574 			pmadapter->callbacks.moal_mfree_consistent(
1575 				pmadapter->pmoal_handle,
1576 				pmbuf->total_pcie_buf_len, cmdrsp_vbase,
1577 				cmdrsp_pbase);
1578 		wlan_free_mlan_buffer(pmadapter, pmbuf);
1579 		pmadapter->pcard_pcie->cmdrsp_buf = MNULL;
1580 	}
1581 	if (pmadapter->pcard_pcie->cmd_buf) {
1582 		pmbuf = pmadapter->pcard_pcie->cmd_buf;
1583 		pcb->moal_unmap_memory(pmadapter->pmoal_handle,
1584 				       pmbuf->pbuf + pmbuf->data_offset,
1585 				       pmbuf->buf_pa, MRVDRV_SIZE_OF_CMD_BUFFER,
1586 				       PCI_DMA_TODEVICE);
1587 	}
1588 
1589 	LEAVE();
1590 	return MLAN_STATUS_SUCCESS;
1591 }
1592 
1593 #if defined(PCIE8997) || defined(PCIE8897)
1594 #define PCIE_TXBD_EMPTY(wrptr, rdptr, mask, rollover_ind)                      \
1595 	(((wrptr & mask) == (rdptr & mask)) &&                                 \
1596 	 ((wrptr & rollover_ind) == (rdptr & rollover_ind)))
1597 
1598 /**
1599  *  @brief This function flushes the TX buffer descriptor ring
1600  *
1601  *  @param pmadapter  A pointer to mlan_adapter structure
1602  *
1603  *  @return 	      MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1604  */
wlan_pcie_flush_txbd_ring(mlan_adapter * pmadapter)1605 static mlan_status wlan_pcie_flush_txbd_ring(mlan_adapter *pmadapter)
1606 {
1607 	mlan_status ret = MLAN_STATUS_SUCCESS;
1608 	pmlan_callbacks pcb = &pmadapter->callbacks;
1609 	t_u32 txrx_rw_ptr_mask = pmadapter->pcard_pcie->reg->txrx_rw_ptr_mask;
1610 	t_u32 txrx_rw_ptr_rollover_ind =
1611 		pmadapter->pcard_pcie->reg->txrx_rw_ptr_rollover_ind;
1612 
1613 	ENTER();
1614 
1615 	if (!PCIE_TXBD_EMPTY(pmadapter->pcard_pcie->txbd_wrptr,
1616 			     pmadapter->pcard_pcie->txbd_rdptr,
1617 			     txrx_rw_ptr_mask, txrx_rw_ptr_rollover_ind)) {
1618 		pmadapter->pcard_pcie->txbd_flush = MTRUE;
1619 		/* write pointer already set at last send */
1620 		/* send dnld-rdy intr again, wait for completion */
1621 		if (pcb->moal_write_reg(
1622 			    pmadapter->pmoal_handle,
1623 			    pmadapter->pcard_pcie->reg->reg_cpu_int_event,
1624 			    CPU_INTR_DNLD_RDY)) {
1625 			PRINTM(MERROR,
1626 			       "SEND DATA (FLUSH): failed to assert dnld-rdy interrupt.\n");
1627 			ret = MLAN_STATUS_FAILURE;
1628 		}
1629 	}
1630 
1631 	LEAVE();
1632 	return ret;
1633 }
1634 #endif
1635 
1636 /**
1637  *  @brief This function check the tx pending buffer
1638  *
1639  *  @param pmadapter  A pointer to mlan_adapter structure
1640  *  @param rdptr      tx rdptr
1641  *
1642  *  @return           MTRUE/MFALSE;
1643  */
wlan_check_tx_pending_buffer(mlan_adapter * pmadapter,t_u32 rdptr)1644 static t_u8 wlan_check_tx_pending_buffer(mlan_adapter *pmadapter, t_u32 rdptr)
1645 {
1646 #if defined(PCIE8997) || defined(PCIE8897)
1647 	t_u32 txrx_rw_ptr_mask = pmadapter->pcard_pcie->reg->txrx_rw_ptr_mask;
1648 	t_u32 txrx_rw_ptr_rollover_ind =
1649 		pmadapter->pcard_pcie->reg->txrx_rw_ptr_rollover_ind;
1650 	if (!pmadapter->pcard_pcie->reg->use_adma) {
1651 		if (((pmadapter->pcard_pcie->txbd_rdptr & txrx_rw_ptr_mask) !=
1652 		     (rdptr & txrx_rw_ptr_mask)) ||
1653 		    ((pmadapter->pcard_pcie->txbd_rdptr &
1654 		      txrx_rw_ptr_rollover_ind) !=
1655 		     (rdptr & txrx_rw_ptr_rollover_ind)))
1656 			return MTRUE;
1657 		else
1658 			return MFALSE;
1659 	}
1660 #endif
1661 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
1662 	if (pmadapter->pcard_pcie->reg->use_adma) {
1663 		if ((pmadapter->pcard_pcie->txbd_rdptr &
1664 		     ADMA_RW_PTR_WRAP_MASK) != (rdptr & ADMA_RW_PTR_WRAP_MASK))
1665 			return MTRUE;
1666 		else
1667 			return MFALSE;
1668 	}
1669 #endif
1670 	return MFALSE;
1671 }
1672 
1673 /**
1674  *  @brief This function unmaps and frees downloaded data buffer
1675  *
1676  *  @param pmadapter  A pointer to mlan_adapter structure
1677  *
1678  *  @return           MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1679  */
wlan_pcie_send_data_complete(mlan_adapter * pmadapter)1680 static mlan_status wlan_pcie_send_data_complete(mlan_adapter *pmadapter)
1681 {
1682 	const t_u32 num_tx_buffs = pmadapter->pcard_pcie->txrx_bd_size;
1683 	mlan_status ret = MLAN_STATUS_SUCCESS;
1684 	pmlan_callbacks pcb = &pmadapter->callbacks;
1685 	mlan_buffer *pmbuf;
1686 	t_u32 wrdoneidx;
1687 	t_u32 rdptr;
1688 	t_u32 unmap_count = 0;
1689 #if defined(PCIE8997) || defined(PCIE8897)
1690 	t_u32 txrx_rw_ptr_mask = pmadapter->pcard_pcie->reg->txrx_rw_ptr_mask;
1691 	t_u32 txrx_rw_ptr_rollover_ind =
1692 		pmadapter->pcard_pcie->reg->txrx_rw_ptr_rollover_ind;
1693 	mlan_pcie_data_buf *ptx_bd_buf;
1694 #endif
1695 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
1696 	adma_dual_desc_buf *padma_bd_buf;
1697 	t_u32 wrptr;
1698 #endif
1699 
1700 	ENTER();
1701 
1702 	/* Read the TX ring read pointer set by firmware */
1703 	if (pcb->moal_read_reg(pmadapter->pmoal_handle,
1704 			       pmadapter->pcard_pcie->reg->reg_txbd_rdptr,
1705 			       &rdptr)) {
1706 		PRINTM(MERROR,
1707 		       "SEND DATA COMP: failed to read REG_TXBD_RDPTR\n");
1708 		ret = MLAN_STATUS_FAILURE;
1709 		goto done;
1710 	}
1711 	PRINTM(MINFO, "SEND DATA COMP:  rdptr_prev=0x%x, rdptr=0x%x\n",
1712 	       pmadapter->pcard_pcie->txbd_rdptr, rdptr);
1713 
1714 #if defined(PCIE8997) || defined(PCIE8897)
1715 	if (!pmadapter->pcard_pcie->reg->use_adma)
1716 		rdptr = rdptr >> TXBD_RW_PTR_START;
1717 #endif
1718 
1719 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
1720 	if (pmadapter->pcard_pcie->reg->use_adma) {
1721 		wrptr = rdptr & 0xffff;
1722 		rdptr = rdptr >> ADMA_RPTR_START;
1723 		if (wrptr != pmadapter->pcard_pcie->txbd_wrptr)
1724 			PRINTM(MERROR, "wlan: Unexpected wrptr 0x%x 0x%x\n",
1725 			       wrptr, pmadapter->pcard_pcie->txbd_wrptr);
1726 	}
1727 #endif
1728 
1729 	/* free from previous txbd_rdptr to current txbd_rdptr */
1730 	while (wlan_check_tx_pending_buffer(pmadapter, rdptr)) {
1731 		wrdoneidx =
1732 			pmadapter->pcard_pcie->txbd_rdptr & (num_tx_buffs - 1);
1733 		pmbuf = pmadapter->pcard_pcie->tx_buf_list[wrdoneidx];
1734 		if (pmbuf) {
1735 			PRINTM(MDAT_D,
1736 			       "SEND DATA COMP: Detach pmbuf %p at tx_ring[%d], pmadapter->txbd_rdptr=0x%x\n",
1737 			       pmbuf, wrdoneidx,
1738 			       pmadapter->pcard_pcie->txbd_rdptr);
1739 			ret = pcb->moal_unmap_memory(
1740 				pmadapter->pmoal_handle,
1741 				pmbuf->pbuf + pmbuf->data_offset, pmbuf->buf_pa,
1742 				pmbuf->data_len, PCI_DMA_TODEVICE);
1743 			if (ret == MLAN_STATUS_FAILURE) {
1744 				PRINTM(MERROR, "%s: moal_unmap_memory failed\n",
1745 				       __FUNCTION__);
1746 				break;
1747 			}
1748 			unmap_count++;
1749 			pmadapter->pcard_pcie->txbd_pending--;
1750 #if defined(PCIE8997) || defined(PCIE8897)
1751 			if (pmadapter->pcard_pcie->txbd_flush)
1752 				wlan_write_data_complete(pmadapter, pmbuf,
1753 							 MLAN_STATUS_FAILURE);
1754 			else
1755 #endif
1756 				wlan_write_data_complete(pmadapter, pmbuf,
1757 							 MLAN_STATUS_SUCCESS);
1758 		}
1759 
1760 		pmadapter->pcard_pcie->tx_buf_list[wrdoneidx] = MNULL;
1761 #if defined(PCIE8997) || defined(PCIE8897)
1762 		if (!pmadapter->pcard_pcie->reg->use_adma) {
1763 			ptx_bd_buf = (mlan_pcie_data_buf *)pmadapter->pcard_pcie
1764 					     ->txbd_ring[wrdoneidx];
1765 			ptx_bd_buf->paddr = 0;
1766 			ptx_bd_buf->len = 0;
1767 			ptx_bd_buf->flags = 0;
1768 			ptx_bd_buf->frag_len = 0;
1769 			ptx_bd_buf->offset = 0;
1770 			pmadapter->pcard_pcie->txbd_rdptr++;
1771 			if ((pmadapter->pcard_pcie->txbd_rdptr &
1772 			     txrx_rw_ptr_mask) == num_tx_buffs)
1773 				pmadapter->pcard_pcie->txbd_rdptr =
1774 					((pmadapter->pcard_pcie->txbd_rdptr &
1775 					  txrx_rw_ptr_rollover_ind) ^
1776 					 txrx_rw_ptr_rollover_ind);
1777 		}
1778 #endif
1779 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
1780 		if (pmadapter->pcard_pcie->reg->use_adma) {
1781 			padma_bd_buf =
1782 				(adma_dual_desc_buf *)pmadapter->pcard_pcie
1783 					->txbd_ring[wrdoneidx];
1784 			padma_bd_buf->paddr = 0;
1785 			padma_bd_buf->len = 0;
1786 			padma_bd_buf->flags = 0;
1787 			padma_bd_buf->pkt_size = 0;
1788 			padma_bd_buf->reserved = 0;
1789 			pmadapter->pcard_pcie->txbd_rdptr++;
1790 			pmadapter->pcard_pcie->txbd_rdptr &=
1791 				ADMA_RW_PTR_WRAP_MASK;
1792 		}
1793 #endif
1794 	}
1795 
1796 	if (unmap_count)
1797 		pmadapter->data_sent = MFALSE;
1798 #if defined(PCIE8997) || defined(PCIE8897)
1799 	if (pmadapter->pcard_pcie->txbd_flush) {
1800 		if (PCIE_TXBD_EMPTY(pmadapter->pcard_pcie->txbd_wrptr,
1801 				    pmadapter->pcard_pcie->txbd_rdptr,
1802 				    txrx_rw_ptr_mask, txrx_rw_ptr_rollover_ind))
1803 			pmadapter->pcard_pcie->txbd_flush = MFALSE;
1804 		else
1805 			wlan_pcie_flush_txbd_ring(pmadapter);
1806 	}
1807 #endif
1808 done:
1809 	LEAVE();
1810 	return ret;
1811 }
1812 
1813 #if defined(PCIE8997) || defined(PCIE8897)
1814 #define PCIE_TXBD_NOT_FULL(wrptr, rdptr, mask, rollover_ind)                   \
1815 	(((wrptr & mask) != (rdptr & mask)) ||                                 \
1816 	 ((wrptr & rollover_ind) == (rdptr & rollover_ind)))
1817 #endif
1818 
1819 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
1820 #define ADMA_TXBD_IS_FULL(wrptr, rdptr, mask, rollover_ind)                    \
1821 	(((wrptr & mask) == (rdptr & mask)) &&                                 \
1822 	 ((wrptr & rollover_ind) != (rdptr & rollover_ind)))
1823 #endif
1824 
wlan_check_txbd_not_full(mlan_adapter * pmadapter)1825 static t_u8 wlan_check_txbd_not_full(mlan_adapter *pmadapter)
1826 {
1827 	t_u32 txrx_rw_ptr_mask;
1828 	t_u32 txrx_rw_ptr_rollover_ind;
1829 #if defined(PCIE8997) || defined(PCIE8897)
1830 	if (!pmadapter->pcard_pcie->reg->use_adma) {
1831 		txrx_rw_ptr_mask = pmadapter->pcard_pcie->reg->txrx_rw_ptr_mask;
1832 		txrx_rw_ptr_rollover_ind =
1833 			pmadapter->pcard_pcie->reg->txrx_rw_ptr_rollover_ind;
1834 		if (PCIE_TXBD_NOT_FULL(pmadapter->pcard_pcie->txbd_wrptr,
1835 				       pmadapter->pcard_pcie->txbd_rdptr,
1836 				       txrx_rw_ptr_mask,
1837 				       txrx_rw_ptr_rollover_ind))
1838 			return MTRUE;
1839 		else
1840 			return MFALSE;
1841 	}
1842 #endif
1843 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
1844 	if (pmadapter->pcard_pcie->reg->use_adma) {
1845 		txrx_rw_ptr_mask = pmadapter->pcard_pcie->txrx_bd_size - 1;
1846 		txrx_rw_ptr_rollover_ind = pmadapter->pcard_pcie->txrx_bd_size;
1847 		if (!ADMA_TXBD_IS_FULL(pmadapter->pcard_pcie->txbd_wrptr,
1848 				       pmadapter->pcard_pcie->txbd_rdptr,
1849 				       txrx_rw_ptr_mask,
1850 				       txrx_rw_ptr_rollover_ind))
1851 			return MTRUE;
1852 		else
1853 			return MFALSE;
1854 	}
1855 #endif
1856 	return MFALSE;
1857 }
1858 
1859 /**
1860  *  @brief This function downloads data to the card.
1861  *
1862  *  @param pmadapter A pointer to mlan_adapter structure
1863  *  @param type      packet type
1864  *  @param pmbuf     A pointer to mlan_buffer (pmbuf->data_len should include
1865  * PCIE header)
1866  *  @param tx_param  A pointer to mlan_tx_param
1867  *
1868  *  @return          MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1869  */
wlan_pcie_send_data(mlan_adapter * pmadapter,t_u8 type,mlan_buffer * pmbuf,mlan_tx_param * tx_param)1870 static mlan_status wlan_pcie_send_data(mlan_adapter *pmadapter, t_u8 type,
1871 				       mlan_buffer *pmbuf,
1872 				       mlan_tx_param *tx_param)
1873 {
1874 	t_u32 reg_txbd_wrptr = pmadapter->pcard_pcie->reg->reg_txbd_wrptr;
1875 #if defined(PCIE8997) || defined(PCIE8897)
1876 	t_u32 txrx_rw_ptr_mask = pmadapter->pcard_pcie->reg->txrx_rw_ptr_mask;
1877 	t_u32 txrx_rw_ptr_rollover_ind =
1878 		pmadapter->pcard_pcie->reg->txrx_rw_ptr_rollover_ind;
1879 	mlan_pcie_data_buf *ptx_bd_buf = MNULL;
1880 #endif
1881 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
1882 	adma_dual_desc_buf *padma_bd_buf = MNULL;
1883 #endif
1884 	const t_u32 num_tx_buffs = pmadapter->pcard_pcie->txrx_bd_size;
1885 	mlan_status ret = MLAN_STATUS_PENDING;
1886 	pmlan_callbacks pcb = &pmadapter->callbacks;
1887 	t_u32 rxbd_val = 0;
1888 	t_u32 wrindx;
1889 	t_u16 *tmp;
1890 	t_u8 *payload;
1891 	t_u32 wr_ptr_start = 0;
1892 
1893 	ENTER();
1894 
1895 	if (!pmbuf) {
1896 		PRINTM(MERROR, "%s() has no buffer", __FUNCTION__);
1897 		ret = MLAN_STATUS_FAILURE;
1898 		goto done;
1899 	}
1900 	if (!(pmbuf->pbuf && pmbuf->data_len)) {
1901 		PRINTM(MERROR, "Invalid parameter <%p, %#x>\n", pmbuf->pbuf,
1902 		       pmbuf->data_len);
1903 		ret = MLAN_STATUS_FAILURE;
1904 		goto done;
1905 	}
1906 
1907 	PRINTM(MINFO, "SEND DATA: <Rd: %#x, Wr: %#x>\n",
1908 	       pmadapter->pcard_pcie->txbd_rdptr,
1909 	       pmadapter->pcard_pcie->txbd_wrptr);
1910 
1911 	if (wlan_check_txbd_not_full(pmadapter)) {
1912 		pmadapter->data_sent = MTRUE;
1913 
1914 		payload = pmbuf->pbuf + pmbuf->data_offset;
1915 		tmp = (t_u16 *)&payload[0];
1916 		*tmp = wlan_cpu_to_le16((t_u16)pmbuf->data_len);
1917 		tmp = (t_u16 *)&payload[2];
1918 		*tmp = wlan_cpu_to_le16(type);
1919 
1920 		/* Map pmbuf, and attach to tx ring */
1921 		if (MLAN_STATUS_FAILURE ==
1922 		    pcb->moal_map_memory(pmadapter->pmoal_handle,
1923 					 pmbuf->pbuf + pmbuf->data_offset,
1924 					 &pmbuf->buf_pa, pmbuf->data_len,
1925 					 PCI_DMA_TODEVICE)) {
1926 			PRINTM(MERROR,
1927 			       "SEND DATA: failed to moal_map_memory\n");
1928 			ret = MLAN_STATUS_FAILURE;
1929 			goto done;
1930 		}
1931 		wrindx = pmadapter->pcard_pcie->txbd_wrptr & (num_tx_buffs - 1);
1932 		PRINTM(MDAT_D,
1933 		       "SEND DATA: Attach pmbuf %p at tx_ring[%d], txbd_wrptr=0x%x\n",
1934 		       pmbuf, wrindx, pmadapter->pcard_pcie->txbd_wrptr);
1935 		pmadapter->pcard_pcie->tx_buf_list[wrindx] = pmbuf;
1936 #if defined(PCIE8997) || defined(PCIE8897)
1937 		if (!pmadapter->pcard_pcie->reg->use_adma) {
1938 			wr_ptr_start = TXBD_RW_PTR_START;
1939 			ptx_bd_buf = (mlan_pcie_data_buf *)pmadapter->pcard_pcie
1940 					     ->txbd_ring[wrindx];
1941 			ptx_bd_buf->paddr = wlan_cpu_to_le64(pmbuf->buf_pa);
1942 			ptx_bd_buf->len =
1943 				wlan_cpu_to_le16((t_u16)pmbuf->data_len);
1944 			ptx_bd_buf->flags = wlan_cpu_to_le16(MLAN_BD_FLAG_SOP |
1945 							     MLAN_BD_FLAG_EOP);
1946 			ptx_bd_buf->frag_len =
1947 				wlan_cpu_to_le16((t_u16)pmbuf->data_len);
1948 			ptx_bd_buf->offset = 0;
1949 			pmadapter->pcard_pcie->last_tx_pkt_size[wrindx] =
1950 				pmbuf->data_len;
1951 			pmadapter->pcard_pcie->txbd_wrptr++;
1952 			if ((pmadapter->pcard_pcie->txbd_wrptr &
1953 			     txrx_rw_ptr_mask) == num_tx_buffs)
1954 				pmadapter->pcard_pcie->txbd_wrptr =
1955 					((pmadapter->pcard_pcie->txbd_wrptr &
1956 					  txrx_rw_ptr_rollover_ind) ^
1957 					 txrx_rw_ptr_rollover_ind);
1958 			rxbd_val = pmadapter->pcard_pcie->rxbd_wrptr &
1959 				   pmadapter->pcard_pcie->reg
1960 					   ->txrx_rw_ptr_wrap_mask;
1961 		}
1962 #endif
1963 
1964 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
1965 		if (pmadapter->pcard_pcie->reg->use_adma) {
1966 			wr_ptr_start = ADMA_WPTR_START;
1967 			padma_bd_buf = (adma_dual_desc_buf *)pmadapter
1968 					       ->pcard_pcie->txbd_ring[wrindx];
1969 			padma_bd_buf->paddr = wlan_cpu_to_le64(pmbuf->buf_pa);
1970 			padma_bd_buf->len =
1971 				ALIGN_SZ(pmbuf->data_len, ADMA_ALIGN_SIZE);
1972 			padma_bd_buf->flags = wlan_cpu_to_le16(
1973 				ADMA_BD_FLAG_SOP | ADMA_BD_FLAG_EOP |
1974 				ADMA_BD_FLAG_INT_EN | ADMA_BD_FLAG_SRC_HOST);
1975 			if (padma_bd_buf->len < ADMA_MIN_PKT_SIZE)
1976 				padma_bd_buf->len = ADMA_MIN_PKT_SIZE;
1977 			padma_bd_buf->len = wlan_cpu_to_le16(padma_bd_buf->len);
1978 			padma_bd_buf->pkt_size = padma_bd_buf->len;
1979 			pmadapter->pcard_pcie->last_tx_pkt_size[wrindx] =
1980 				pmbuf->data_len;
1981 			pmadapter->pcard_pcie->txbd_wrptr++;
1982 			pmadapter->pcard_pcie->txbd_wrptr &=
1983 				ADMA_RW_PTR_WRAP_MASK;
1984 		}
1985 #endif
1986 		pmadapter->pcard_pcie->txbd_pending++;
1987 		PRINTM(MINFO, "REG_TXBD_WRPT(0x%x) = 0x%x\n", reg_txbd_wrptr,
1988 		       ((pmadapter->pcard_pcie->txbd_wrptr << wr_ptr_start) |
1989 			rxbd_val));
1990 		/* Write the TX ring write pointer in to REG_TXBD_WRPTR */
1991 		if (pcb->moal_write_reg(pmadapter->pmoal_handle, reg_txbd_wrptr,
1992 					(pmadapter->pcard_pcie->txbd_wrptr
1993 					 << wr_ptr_start) |
1994 						rxbd_val)) {
1995 			PRINTM(MERROR,
1996 			       "SEND DATA: failed to write REG_TXBD_WRPTR\n");
1997 			ret = MLAN_STATUS_FAILURE;
1998 			goto done_unmap;
1999 		}
2000 		PRINTM(MINFO, "SEND DATA: Updated <Rd: %#x, Wr: %#x>\n",
2001 		       pmadapter->pcard_pcie->txbd_rdptr,
2002 		       pmadapter->pcard_pcie->txbd_wrptr);
2003 
2004 		if (wlan_check_txbd_not_full(pmadapter))
2005 			pmadapter->data_sent = MFALSE;
2006 		else
2007 			wlan_pcie_send_data_complete(pmadapter);
2008 		if (pmadapter->data_sent)
2009 			pmadapter->data_sent_cnt++;
2010 
2011 		PRINTM(MINFO, "Sent packet to firmware successfully\n");
2012 	} else {
2013 		PRINTM(MERROR,
2014 		       "TX Ring full, can't send anymore packets to firmware\n");
2015 		PRINTM(MINFO, "SEND DATA (FULL!): <Rd: %#x, Wr: %#x>\n",
2016 		       pmadapter->pcard_pcie->txbd_rdptr,
2017 		       pmadapter->pcard_pcie->txbd_wrptr);
2018 		pmadapter->data_sent = MTRUE;
2019 #if defined(PCIE8997) || defined(PCIE8897)
2020 		if (!pmadapter->pcard_pcie->reg->use_adma) {
2021 			/* Send the TX ready interrupt */
2022 			if (pcb->moal_write_reg(pmadapter->pmoal_handle,
2023 						pmadapter->pcard_pcie->reg
2024 							->reg_cpu_int_event,
2025 						CPU_INTR_DNLD_RDY))
2026 				PRINTM(MERROR,
2027 				       "SEND DATA (FULL): failed to assert dnld-rdy interrupt\n");
2028 		}
2029 #endif
2030 		ret = MLAN_STATUS_FAILURE;
2031 		goto done;
2032 	}
2033 
2034 	LEAVE();
2035 	return ret;
2036 
2037 done_unmap:
2038 	if (MLAN_STATUS_FAILURE ==
2039 	    pcb->moal_unmap_memory(
2040 		    pmadapter->pmoal_handle, pmbuf->pbuf + pmbuf->data_offset,
2041 		    pmbuf->buf_pa, pmbuf->data_len, PCI_DMA_TODEVICE)) {
2042 		PRINTM(MERROR, "SEND DATA: failed to moal_unmap_memory\n");
2043 		ret = MLAN_STATUS_FAILURE;
2044 	}
2045 	pmadapter->pcard_pcie->txbd_pending--;
2046 	pmadapter->pcard_pcie->tx_buf_list[wrindx] = MNULL;
2047 #if defined(PCIE8997) || defined(PCIE8897)
2048 	if (!pmadapter->pcard_pcie->reg->use_adma && ptx_bd_buf) {
2049 		ptx_bd_buf->paddr = 0;
2050 		ptx_bd_buf->len = 0;
2051 		ptx_bd_buf->flags = 0;
2052 		ptx_bd_buf->frag_len = 0;
2053 		ptx_bd_buf->offset = 0;
2054 	}
2055 #endif
2056 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
2057 	if (pmadapter->pcard_pcie->reg->use_adma && padma_bd_buf) {
2058 		padma_bd_buf->paddr = 0;
2059 		padma_bd_buf->len = 0;
2060 		padma_bd_buf->flags = 0;
2061 		padma_bd_buf->pkt_size = 0;
2062 		padma_bd_buf->reserved = 0;
2063 	}
2064 #endif
2065 done:
2066 	LEAVE();
2067 	return ret;
2068 }
2069 
2070 /**
2071  *  @brief This function check the rx pending buffer
2072  *
2073  *  @param pmadapter  A pointer to mlan_adapter structure
2074  *  @param rdptr      rx rdptr
2075  *
2076  *  @return           MTRUE/MFALSE;
2077  */
wlan_check_rx_pending_buffer(mlan_adapter * pmadapter,t_u32 rdptr)2078 static t_u8 wlan_check_rx_pending_buffer(mlan_adapter *pmadapter, t_u32 rdptr)
2079 {
2080 #if defined(PCIE8997) || defined(PCIE8897)
2081 	t_u32 txrx_rw_ptr_mask = pmadapter->pcard_pcie->reg->txrx_rw_ptr_mask;
2082 	t_u32 txrx_rw_ptr_rollover_ind =
2083 		pmadapter->pcard_pcie->reg->txrx_rw_ptr_rollover_ind;
2084 	if (!pmadapter->pcard_pcie->reg->use_adma) {
2085 		if (((rdptr & txrx_rw_ptr_mask) !=
2086 		     (pmadapter->pcard_pcie->rxbd_rdptr & txrx_rw_ptr_mask)) ||
2087 		    ((rdptr & txrx_rw_ptr_rollover_ind) !=
2088 		     (pmadapter->pcard_pcie->rxbd_rdptr &
2089 		      txrx_rw_ptr_rollover_ind)))
2090 			return MTRUE;
2091 		else
2092 			return MFALSE;
2093 	}
2094 #endif
2095 
2096 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
2097 	if (pmadapter->pcard_pcie->reg->use_adma) {
2098 		if ((pmadapter->pcard_pcie->rxbd_rdptr &
2099 		     ADMA_RW_PTR_WRAP_MASK) != (rdptr & ADMA_RW_PTR_WRAP_MASK))
2100 			return MTRUE;
2101 		else
2102 			return MFALSE;
2103 	}
2104 #endif
2105 	return MFALSE;
2106 }
2107 
2108 /**
2109  *  @brief This function check if the rx pending buffer is full
2110  *
2111  *  @param pmadapter  A pointer to mlan_adapter structure
2112  *  @param rdptr           rx rdptr
2113  *  @param rxbd_rdptr      rxbd_rdptr
2114  *
2115  *  @return           MTRUE/MFALSE;
2116  */
wlan_is_rx_pending_full(mlan_adapter * pmadapter,t_u32 rdptr)2117 static t_u8 wlan_is_rx_pending_full(mlan_adapter *pmadapter, t_u32 rdptr)
2118 {
2119 #if defined(PCIE8997) || defined(PCIE8897)
2120 	t_u32 txrx_rw_ptr_mask = pmadapter->pcard_pcie->reg->txrx_rw_ptr_mask;
2121 	t_u32 txrx_rw_ptr_rollover_ind =
2122 		pmadapter->pcard_pcie->reg->txrx_rw_ptr_rollover_ind;
2123 	if (!pmadapter->pcard_pcie->reg->use_adma) {
2124 		PRINTM(MDATA,
2125 		       "local wrptr: 0x%x(0x%x) -> reg rdptr: 0x%x(0x%x)\n",
2126 		       (pmadapter->pcard_pcie->rxbd_wrptr & txrx_rw_ptr_mask),
2127 		       (pmadapter->pcard_pcie->rxbd_wrptr &
2128 			txrx_rw_ptr_rollover_ind),
2129 		       (rdptr & txrx_rw_ptr_mask),
2130 		       (rdptr & txrx_rw_ptr_rollover_ind));
2131 		if (((rdptr & txrx_rw_ptr_mask) ==
2132 		     (pmadapter->pcard_pcie->rxbd_wrptr & txrx_rw_ptr_mask)) &&
2133 		    ((rdptr & txrx_rw_ptr_rollover_ind) ==
2134 		     (pmadapter->pcard_pcie->rxbd_wrptr &
2135 		      txrx_rw_ptr_rollover_ind)))
2136 			return MTRUE;
2137 		else
2138 			return MFALSE;
2139 	}
2140 #endif
2141 
2142 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
2143 	if (pmadapter->pcard_pcie->reg->use_adma) {
2144 		PRINTM(MDATA, "local wrptr: 0x%x -> reg rdptr: 0x%x\n",
2145 		       (pmadapter->pcard_pcie->rxbd_wrptr &
2146 			ADMA_RW_PTR_WRAP_MASK),
2147 		       (rdptr & ADMA_RW_PTR_WRAP_MASK));
2148 		if ((rdptr & ADMA_RW_PTR_WRAP_MASK) ==
2149 		    (pmadapter->pcard_pcie->rxbd_wrptr & ADMA_RW_PTR_WRAP_MASK))
2150 			return MTRUE;
2151 		else
2152 			return MFALSE;
2153 	}
2154 #endif
2155 	return MFALSE;
2156 }
2157 
2158 /**
2159  *  @brief This function handles received buffer ring and
2160  *  dispatches packets to upper
2161  *
2162  *  @param pmadapter  A pointer to mlan_adapter structure
2163  *
2164  *  @return 	      MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
2165  */
wlan_pcie_process_recv_data(mlan_adapter * pmadapter)2166 static mlan_status wlan_pcie_process_recv_data(mlan_adapter *pmadapter)
2167 {
2168 	mlan_status ret = MLAN_STATUS_SUCCESS;
2169 	pmlan_callbacks pcb = &pmadapter->callbacks;
2170 	t_u32 rdptr, rd_index;
2171 	mlan_buffer *pmbuf = MNULL;
2172 	t_u32 txbd_val = 0;
2173 	t_u16 rx_len, rx_type;
2174 	const t_u32 num_rx_buffs = pmadapter->pcard_pcie->txrx_bd_size;
2175 	t_u32 reg_rxbd_rdptr = pmadapter->pcard_pcie->reg->reg_rxbd_rdptr;
2176 #if defined(PCIE8997) || defined(PCIE8897)
2177 	t_u32 txrx_rw_ptr_mask = pmadapter->pcard_pcie->reg->txrx_rw_ptr_mask;
2178 	t_u32 txrx_rw_ptr_rollover_ind =
2179 		pmadapter->pcard_pcie->reg->txrx_rw_ptr_rollover_ind;
2180 	mlan_pcie_data_buf *prxbd_buf;
2181 #endif
2182 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
2183 	adma_dual_desc_buf *padma_bd_buf;
2184 #endif
2185 	t_u32 in_ts_sec, in_ts_usec;
2186 
2187 	ENTER();
2188 
2189 	/* Read the RX ring Read pointer set by firmware */
2190 	if (pcb->moal_read_reg(pmadapter->pmoal_handle, reg_rxbd_rdptr,
2191 			       &rdptr)) {
2192 		PRINTM(MERROR, "RECV DATA: failed to read REG_RXBD_RDPTR\n");
2193 		ret = MLAN_STATUS_FAILURE;
2194 		goto done;
2195 	}
2196 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
2197 	if (pmadapter->pcard_pcie->reg->use_adma)
2198 		rdptr = rdptr >> ADMA_RPTR_START;
2199 #endif
2200 
2201 	if (pmadapter->tp_state_on &&
2202 	    wlan_is_rx_pending_full(pmadapter, rdptr)) {
2203 		PRINTM(MDATA, "RX FULL!\n");
2204 		pmadapter->callbacks.moal_tp_accounting_rx_param(
2205 			pmadapter->pmoal_handle, 6, 0);
2206 	}
2207 	while (wlan_check_rx_pending_buffer(pmadapter, rdptr)) {
2208 		/* detach pmbuf (with data) from Rx Ring */
2209 		rd_index =
2210 			pmadapter->pcard_pcie->rxbd_rdptr & (num_rx_buffs - 1);
2211 		if (rd_index >
2212 		    (t_u32)(pmadapter->pcard_pcie->txrx_bd_size - 1)) {
2213 			PRINTM(MERROR, "RECV DATA: Invalid Rx buffer index.\n");
2214 			ret = MLAN_STATUS_FAILURE;
2215 			goto done;
2216 		}
2217 		pmbuf = pmadapter->pcard_pcie->rx_buf_list[rd_index];
2218 		if (MLAN_STATUS_FAILURE ==
2219 		    pcb->moal_unmap_memory(pmadapter->pmoal_handle,
2220 					   pmbuf->pbuf + pmbuf->data_offset,
2221 					   pmbuf->buf_pa, MLAN_RX_DATA_BUF_SIZE,
2222 					   PCI_DMA_FROMDEVICE)) {
2223 			PRINTM(MERROR,
2224 			       "RECV DATA: moal_unmap_memory failed.\n");
2225 			ret = MLAN_STATUS_FAILURE;
2226 			goto done;
2227 		}
2228 		pmadapter->pcard_pcie->rx_buf_list[rd_index] = MNULL;
2229 		PRINTM(MDAT_D,
2230 		       "RECV DATA: Detach pmbuf %p at rx_ring[%d], pmadapter->rxbd_rdptr=0x%x\n",
2231 		       pmbuf, rd_index, pmadapter->pcard_pcie->rxbd_rdptr);
2232 
2233 		/* Get data length from interface header -
2234 		   first 2 bytes are len, second 2 bytes are type */
2235 		rx_len = *((t_u16 *)(pmbuf->pbuf + pmbuf->data_offset));
2236 		rx_len = wlan_le16_to_cpu(rx_len);
2237 		rx_type = *((t_u16 *)(pmbuf->pbuf + pmbuf->data_offset + 2));
2238 		rx_type = wlan_le16_to_cpu(rx_type);
2239 
2240 		PRINTM(MINFO,
2241 		       "RECV DATA: <Wr: %#x, Rd: %#x>, Len=%d rx_type=%d\n",
2242 		       pmadapter->pcard_pcie->rxbd_wrptr, rdptr, rx_len,
2243 		       rx_type);
2244 
2245 		if (rx_len <= MLAN_RX_DATA_BUF_SIZE) {
2246 			/* send buffer to host (which will free it) */
2247 			pmbuf->data_len = rx_len - PCIE_INTF_HEADER_LEN;
2248 			pmbuf->data_offset += PCIE_INTF_HEADER_LEN;
2249 			// rx_trace 5
2250 			if (pmadapter->tp_state_on) {
2251 				pmadapter->callbacks.moal_tp_accounting(
2252 					pmadapter->pmoal_handle, pmbuf,
2253 					5 /*RX_DROP_P1*/);
2254 				pcb->moal_get_system_time(
2255 					pmadapter->pmoal_handle, &in_ts_sec,
2256 					&in_ts_usec);
2257 				pmbuf->in_ts_sec = in_ts_sec;
2258 				pmbuf->in_ts_usec = in_ts_usec;
2259 			}
2260 			if (pmadapter->tp_state_drop_point ==
2261 			    5 /*RX_DROP_P1*/) {
2262 				pmadapter->ops.data_complete(pmadapter, pmbuf,
2263 							     ret);
2264 			} else {
2265 				PRINTM(MINFO,
2266 				       "RECV DATA: Received packet from FW successfully\n");
2267 				pmadapter->callbacks.moal_spin_lock(
2268 					pmadapter->pmoal_handle,
2269 					pmadapter->rx_data_queue.plock);
2270 				util_enqueue_list_tail(
2271 					pmadapter->pmoal_handle,
2272 					&pmadapter->rx_data_queue,
2273 					(pmlan_linked_list)pmbuf, MNULL, MNULL);
2274 				pmadapter->rx_pkts_queued++;
2275 				if (pmadapter->tp_state_on)
2276 					pmadapter->callbacks
2277 						.moal_tp_accounting_rx_param(
2278 							pmadapter->pmoal_handle,
2279 							1,
2280 							pmadapter
2281 								->rx_pkts_queued);
2282 				pmadapter->callbacks.moal_spin_unlock(
2283 					pmadapter->pmoal_handle,
2284 					pmadapter->rx_data_queue.plock);
2285 
2286 				pmadapter->data_received = MTRUE;
2287 			}
2288 			/* Create new buffer and attach it to Rx Ring */
2289 			pmbuf = wlan_alloc_mlan_buffer(pmadapter,
2290 						       MLAN_RX_DATA_BUF_SIZE,
2291 						       MLAN_RX_HEADER_LEN,
2292 						       MOAL_ALLOC_MLAN_BUFFER);
2293 			if (!pmbuf) {
2294 				PRINTM(MERROR,
2295 				       "RECV DATA: Unable to allocate mlan_buffer\n");
2296 				ret = MLAN_STATUS_FAILURE;
2297 				goto done;
2298 			}
2299 		} else {
2300 			/* Queue the mlan_buffer again */
2301 			PRINTM(MERROR, "PCIE: Drop invalid packet, length=%d",
2302 			       rx_len);
2303 		}
2304 
2305 		if (MLAN_STATUS_FAILURE ==
2306 		    pcb->moal_map_memory(pmadapter->pmoal_handle,
2307 					 pmbuf->pbuf + pmbuf->data_offset,
2308 					 &pmbuf->buf_pa, MLAN_RX_DATA_BUF_SIZE,
2309 					 PCI_DMA_FROMDEVICE)) {
2310 			PRINTM(MERROR, "RECV DATA: moal_map_memory failed\n");
2311 			ret = MLAN_STATUS_FAILURE;
2312 			goto done;
2313 		}
2314 
2315 		PRINTM(MDAT_D,
2316 		       "RECV DATA: Attach new pmbuf %p at rx_ring[%d]\n", pmbuf,
2317 		       rd_index);
2318 		pmadapter->pcard_pcie->rx_buf_list[rd_index] = pmbuf;
2319 #if defined(PCIE8997) || defined(PCIE8897)
2320 		if (!pmadapter->pcard_pcie->reg->use_adma) {
2321 			prxbd_buf = (mlan_pcie_data_buf *)pmadapter->pcard_pcie
2322 					    ->rxbd_ring[rd_index];
2323 			prxbd_buf->paddr = wlan_cpu_to_le64(pmbuf->buf_pa);
2324 			prxbd_buf->len =
2325 				wlan_cpu_to_le16((t_u16)pmbuf->data_len);
2326 			prxbd_buf->flags = wlan_cpu_to_le16(MLAN_BD_FLAG_SOP |
2327 							    MLAN_BD_FLAG_EOP);
2328 			prxbd_buf->offset = 0;
2329 			prxbd_buf->frag_len =
2330 				wlan_cpu_to_le16((t_u16)pmbuf->data_len);
2331 
2332 			/* update rxbd's rdptrs */
2333 			if ((++pmadapter->pcard_pcie->rxbd_rdptr &
2334 			     txrx_rw_ptr_mask) ==
2335 			    pmadapter->pcard_pcie->txrx_bd_size) {
2336 				pmadapter->pcard_pcie->rxbd_rdptr =
2337 					((pmadapter->pcard_pcie->rxbd_rdptr &
2338 					  txrx_rw_ptr_rollover_ind) ^
2339 					 txrx_rw_ptr_rollover_ind);
2340 			}
2341 
2342 			/* update rxbd's wrptrs */
2343 			if ((++pmadapter->pcard_pcie->rxbd_wrptr &
2344 			     txrx_rw_ptr_mask) ==
2345 			    pmadapter->pcard_pcie->txrx_bd_size) {
2346 				pmadapter->pcard_pcie->rxbd_wrptr =
2347 					((pmadapter->pcard_pcie->rxbd_wrptr &
2348 					  txrx_rw_ptr_rollover_ind) ^
2349 					 txrx_rw_ptr_rollover_ind);
2350 			}
2351 			txbd_val = pmadapter->pcard_pcie->txbd_wrptr &
2352 				   pmadapter->pcard_pcie->reg
2353 					   ->txrx_rw_ptr_wrap_mask;
2354 			txbd_val = txbd_val << TXBD_RW_PTR_START;
2355 		}
2356 #endif
2357 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
2358 		if (pmadapter->pcard_pcie->reg->use_adma) {
2359 			padma_bd_buf =
2360 				(adma_dual_desc_buf *)pmadapter->pcard_pcie
2361 					->rxbd_ring[rd_index];
2362 			padma_bd_buf->paddr = wlan_cpu_to_le64(pmbuf->buf_pa);
2363 			padma_bd_buf->len = wlan_cpu_to_le16(
2364 				ALIGN_SZ(pmbuf->data_len, ADMA_ALIGN_SIZE));
2365 			padma_bd_buf->flags = wlan_cpu_to_le16(
2366 				ADMA_BD_FLAG_INT_EN | ADMA_BD_FLAG_DST_HOST);
2367 			padma_bd_buf->pkt_size = 0;
2368 			padma_bd_buf->reserved = 0;
2369 			pmadapter->pcard_pcie->rxbd_rdptr++;
2370 			pmadapter->pcard_pcie->rxbd_wrptr++;
2371 			pmadapter->pcard_pcie->rxbd_rdptr &=
2372 				ADMA_RW_PTR_WRAP_MASK;
2373 			pmadapter->pcard_pcie->rxbd_wrptr &=
2374 				ADMA_RW_PTR_WRAP_MASK;
2375 		}
2376 #endif
2377 		PRINTM(MINFO, "RECV DATA: Updated <Wr: %#x, Rd: %#x>\n",
2378 		       pmadapter->pcard_pcie->rxbd_wrptr, rdptr);
2379 
2380 		/* Write the RX ring write pointer in to REG_RXBD_WRPTR */
2381 		if (pcb->moal_write_reg(
2382 			    pmadapter->pmoal_handle,
2383 			    pmadapter->pcard_pcie->reg->reg_rxbd_wrptr,
2384 			    pmadapter->pcard_pcie->rxbd_wrptr | txbd_val)) {
2385 			PRINTM(MERROR,
2386 			       "RECV DATA: failed to write REG_RXBD_WRPTR\n");
2387 			ret = MLAN_STATUS_FAILURE;
2388 			goto done;
2389 		}
2390 
2391 		/* Read the RX ring read pointer set by firmware */
2392 		if (pcb->moal_read_reg(pmadapter->pmoal_handle, reg_rxbd_rdptr,
2393 				       &rdptr)) {
2394 			PRINTM(MERROR,
2395 			       "RECV DATA: failed to read REG_RXBD_RDPTR\n");
2396 			ret = MLAN_STATUS_FAILURE;
2397 			goto done;
2398 		}
2399 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
2400 		if (pmadapter->pcard_pcie->reg->use_adma)
2401 			rdptr = rdptr >> ADMA_RPTR_START;
2402 #endif
2403 	}
2404 
2405 done:
2406 	LEAVE();
2407 	return ret;
2408 }
2409 
2410 /**
2411  *  @brief This function downloads command to the card.
2412  *
2413  *  @param pmadapter A pointer to mlan_adapter structure
2414  *  @param pmbuf     A pointer to mlan_buffer (pmbuf->data_len should include
2415  * PCIE header)
2416  *
2417  *  @return 	     MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
2418  */
wlan_pcie_send_cmd(mlan_adapter * pmadapter,mlan_buffer * pmbuf)2419 static mlan_status wlan_pcie_send_cmd(mlan_adapter *pmadapter,
2420 				      mlan_buffer *pmbuf)
2421 {
2422 	mlan_status ret = MLAN_STATUS_PENDING;
2423 	pmlan_callbacks pcb = &pmadapter->callbacks;
2424 	t_u8 *payload = MNULL;
2425 
2426 	ENTER();
2427 	if (!(pmadapter && pmbuf)) {
2428 		PRINTM(MERROR, "%s() has no buffer", __FUNCTION__);
2429 		ret = MLAN_STATUS_FAILURE;
2430 		goto done;
2431 	}
2432 	if (!(pmbuf->pbuf && pmbuf->data_len)) {
2433 		PRINTM(MERROR, "Invalid parameter <%p, %#x>\n", pmbuf->pbuf,
2434 		       pmbuf->data_len);
2435 		ret = MLAN_STATUS_FAILURE;
2436 		goto done;
2437 	}
2438 
2439 	/* Make sure a command response buffer is available */
2440 	if (!pmadapter->pcard_pcie->cmdrsp_buf) {
2441 		PRINTM(MERROR,
2442 		       "No response buffer available, send command failed\n");
2443 		ret = MLAN_STATUS_FAILURE;
2444 		goto done;
2445 	}
2446 
2447 	pmadapter->cmd_sent = MTRUE;
2448 	payload = pmbuf->pbuf + pmbuf->data_offset;
2449 	*(t_u16 *)&payload[0] = wlan_cpu_to_le16((t_u16)pmbuf->data_len);
2450 	*(t_u16 *)&payload[2] = wlan_cpu_to_le16(MLAN_TYPE_CMD);
2451 
2452 	if (MLAN_STATUS_FAILURE ==
2453 	    pcb->moal_map_memory(
2454 		    pmadapter->pmoal_handle, pmbuf->pbuf + pmbuf->data_offset,
2455 		    &pmbuf->buf_pa, MLAN_RX_CMD_BUF_SIZE, PCI_DMA_TODEVICE)) {
2456 		PRINTM(MERROR, "Command buffer : moal_map_memory failed\n");
2457 		LEAVE();
2458 		return MLAN_STATUS_FAILURE;
2459 	}
2460 	pmadapter->pcard_pcie->cmd_buf = pmbuf;
2461 
2462 #if defined(PCIE8997) || defined(PCIE8897)
2463 	if (!pmadapter->pcard_pcie->reg->use_adma) {
2464 		/* To send a command, the driver will:
2465 		    1. Write the 64bit physical address of the data buffer to
2466 			SCRATCH1 + SCRATCH0
2467 		    2. Ring the door bell (i.e. set the door bell interrupt)
2468 
2469 		    In response to door bell interrupt, the firmware will
2470 		   perform the DMA of the command packet (first header to obtain
2471 		   the total length and then rest of the command).
2472 		*/
2473 
2474 		if (pmadapter->pcard_pcie->cmdrsp_buf) {
2475 			/* Write the lower 32bits of the cmdrsp buffer physical
2476 			   address */
2477 			if (pcb->moal_write_reg(pmadapter->pmoal_handle,
2478 						REG_CMDRSP_ADDR_LO,
2479 						(t_u32)pmadapter->pcard_pcie
2480 							->cmdrsp_buf->buf_pa)) {
2481 				PRINTM(MERROR,
2482 				       "Failed to write download command to boot code.\n");
2483 				ret = MLAN_STATUS_FAILURE;
2484 				goto done;
2485 			}
2486 			/* Write the upper 32bits of the cmdrsp buffer physical
2487 			    address */
2488 			if (pcb->moal_write_reg(
2489 				    pmadapter->pmoal_handle, REG_CMDRSP_ADDR_HI,
2490 				    (t_u32)((t_u64)pmadapter->pcard_pcie
2491 						    ->cmdrsp_buf->buf_pa >>
2492 					    32))) {
2493 				PRINTM(MERROR,
2494 				       "Failed to write download command to boot code.\n");
2495 				ret = MLAN_STATUS_FAILURE;
2496 				goto done;
2497 			}
2498 		}
2499 
2500 		/* Write the lower 32bits of the physical address to
2501 		 * REG_CMD_ADDR_LO */
2502 		if (pcb->moal_write_reg(
2503 			    pmadapter->pmoal_handle, REG_CMD_ADDR_LO,
2504 			    (t_u32)pmadapter->pcard_pcie->cmd_buf->buf_pa)) {
2505 			PRINTM(MERROR,
2506 			       "Failed to write download command to boot code.\n");
2507 			ret = MLAN_STATUS_FAILURE;
2508 			goto done;
2509 		}
2510 		/* Write the upper 32bits of the physical address to
2511 		 * REG_CMD_ADDR_HI */
2512 		if (pcb->moal_write_reg(pmadapter->pmoal_handle,
2513 					REG_CMD_ADDR_HI,
2514 					(t_u32)((t_u64)pmadapter->pcard_pcie
2515 							->cmd_buf->buf_pa >>
2516 						32))) {
2517 			PRINTM(MERROR,
2518 			       "Failed to write download command to boot code.\n");
2519 			ret = MLAN_STATUS_FAILURE;
2520 			goto done;
2521 		}
2522 
2523 		/* Write the command length to REG_CMD_SIZE */
2524 		if (pcb->moal_write_reg(
2525 			    pmadapter->pmoal_handle, REG_CMD_SIZE,
2526 			    pmadapter->pcard_pcie->cmd_buf->data_len)) {
2527 			PRINTM(MERROR,
2528 			       "Failed to write command length to REG_CMD_SIZE\n");
2529 			ret = MLAN_STATUS_FAILURE;
2530 			goto done;
2531 		}
2532 
2533 		/* Ring the door bell */
2534 		if (pcb->moal_write_reg(
2535 			    pmadapter->pmoal_handle,
2536 			    pmadapter->pcard_pcie->reg->reg_cpu_int_event,
2537 			    CPU_INTR_DOOR_BELL)) {
2538 			PRINTM(MERROR,
2539 			       "Failed to assert door-bell interrupt.\n");
2540 			ret = MLAN_STATUS_FAILURE;
2541 			goto done;
2542 		}
2543 	}
2544 #endif
2545 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
2546 	if (pmadapter->pcard_pcie->reg->use_adma) {
2547 		/* To send a command, the driver will:
2548 		   1. driver prepare the cmdrep buffer for adma
2549 		   2. driver programs dma_mode field to direct programming mode
2550 		   and programs dma_size field to define DMA data transfer size.
2551 		   3. driver programs src_base_addr register to define source
2552 		   location of DMA data
2553 		   4. driver sets src_wptr to 1 to initiate DMA operation
2554 		*/
2555 		wlan_init_adma(pmadapter, ADMA_CMDRESP,
2556 			       pmadapter->pcard_pcie->cmdrsp_buf->buf_pa,
2557 			       MRVDRV_SIZE_OF_CMD_BUFFER, MFALSE);
2558 		wlan_init_adma(pmadapter, ADMA_CMD,
2559 			       pmadapter->pcard_pcie->cmd_buf->buf_pa,
2560 			       pmadapter->pcard_pcie->cmd_buf->data_len,
2561 			       MFALSE);
2562 	}
2563 #endif
2564 done:
2565 	if ((ret == MLAN_STATUS_FAILURE) && pmadapter)
2566 		pmadapter->cmd_sent = MFALSE;
2567 
2568 	LEAVE();
2569 	return ret;
2570 }
2571 
2572 #if defined(PCIE8997) || defined(PCIE8897)
2573 #define MLAN_SLEEP_COOKIE_DEF 0xBEEFBEEF
2574 #define MAX_DELAY_LOOP_COUNT 100
2575 
mlan_delay_for_sleep_cookie(mlan_adapter * pmadapter,t_u32 max_delay_loop_cnt)2576 static void mlan_delay_for_sleep_cookie(mlan_adapter *pmadapter,
2577 					t_u32 max_delay_loop_cnt)
2578 {
2579 	t_u8 *buffer;
2580 	t_u32 sleep_cookie = 0;
2581 	t_u32 count = 0;
2582 	pmlan_buffer pmbuf = pmadapter->pcard_pcie->cmdrsp_buf;
2583 
2584 	for (count = 0; count < max_delay_loop_cnt; count++) {
2585 		buffer = pmbuf->pbuf;
2586 		sleep_cookie = *(t_u32 *)buffer;
2587 
2588 		if (sleep_cookie == MLAN_SLEEP_COOKIE_DEF) {
2589 			PRINTM(MINFO, "sleep cookie FOUND at count = %d!!\n",
2590 			       count);
2591 			break;
2592 		}
2593 		wlan_udelay(pmadapter, 20);
2594 	}
2595 
2596 	if (count >= max_delay_loop_cnt)
2597 		PRINTM(MINFO, "sleep cookie not found!!\n");
2598 }
2599 #endif
2600 
2601 /**
2602  *  @brief This function handles command complete interrupt
2603  *
2604  *  @param pmadapter  A pointer to mlan_adapter structure
2605  *
2606  *  @return 	      MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
2607  */
wlan_pcie_process_cmd_resp(mlan_adapter * pmadapter)2608 static mlan_status wlan_pcie_process_cmd_resp(mlan_adapter *pmadapter)
2609 {
2610 	mlan_status ret = MLAN_STATUS_SUCCESS;
2611 	pmlan_callbacks pcb = &pmadapter->callbacks;
2612 	pmlan_buffer pmbuf = pmadapter->pcard_pcie->cmdrsp_buf;
2613 	pmlan_buffer cmd_buf = MNULL;
2614 	t_u16 resp_len = 0;
2615 
2616 	ENTER();
2617 
2618 	PRINTM(MINFO, "Rx CMD Response\n");
2619 
2620 	if (pmbuf == MNULL) {
2621 		PRINTM(MMSG, "Rx CMD response pmbuf is null\n");
2622 		LEAVE();
2623 		return MLAN_STATUS_FAILURE;
2624 	}
2625 
2626 	/* Get data length from interface header -
2627 	   first 2 bytes are len, second 2 bytes are type */
2628 	resp_len = *((t_u16 *)(pmbuf->pbuf + pmbuf->data_offset));
2629 
2630 	pmadapter->upld_len = wlan_le16_to_cpu(resp_len);
2631 	pmadapter->upld_len -= PCIE_INTF_HEADER_LEN;
2632 	cmd_buf = pmadapter->pcard_pcie->cmd_buf;
2633 	if (cmd_buf) {
2634 		pcb->moal_unmap_memory(pmadapter->pmoal_handle,
2635 				       cmd_buf->pbuf + cmd_buf->data_offset,
2636 				       cmd_buf->buf_pa, WLAN_UPLD_SIZE,
2637 				       PCI_DMA_TODEVICE);
2638 		pmadapter->pcard_pcie->cmd_buf = MNULL;
2639 	}
2640 	if (!pmadapter->curr_cmd) {
2641 		if (pmadapter->ps_state == PS_STATE_SLEEP_CFM) {
2642 			wlan_process_sleep_confirm_resp(
2643 				pmadapter,
2644 				pmbuf->pbuf + pmbuf->data_offset +
2645 					PCIE_INTF_HEADER_LEN,
2646 				pmadapter->upld_len);
2647 			/* We are sending sleep confirm done interrupt in the
2648 			 * middle of sleep handshake. There is a corner case
2649 			 * when Tx done interrupt is received from firmware
2650 			 * during sleep handshake due to which host and firmware
2651 			 * power states go out of sync causing Tx data timeout
2652 			 * problem. Hence sleep confirm done interrupt is sent
2653 			 * at the end of sleep handshake to fix the problem
2654 			 *
2655 			 * Host could be reading the interrupt during polling
2656 			 * (while loop) or to address a FW interrupt. In either
2657 			 * case, after clearing the interrupt driver needs to
2658 			 * send a sleep confirm event at the end of processing
2659 			 * command response right here. This marks the end of
2660 			 * the sleep handshake with firmware.
2661 			 */
2662 			wlan_pcie_enable_host_int_mask(pmadapter);
2663 			if (pcb->moal_write_reg(pmadapter->pmoal_handle,
2664 						pmadapter->pcard_pcie->reg
2665 							->reg_cpu_int_event,
2666 						CPU_INTR_SLEEP_CFM_DONE)) {
2667 				PRINTM(MERROR, "Write register failed\n");
2668 				LEAVE();
2669 				return MLAN_STATUS_FAILURE;
2670 			}
2671 #if defined(PCIE8997) || defined(PCIE8897)
2672 			mlan_delay_for_sleep_cookie(pmadapter,
2673 						    MAX_DELAY_LOOP_COUNT);
2674 #endif
2675 		}
2676 		memcpy_ext(pmadapter, pmadapter->upld_buf,
2677 			   pmbuf->pbuf + pmbuf->data_offset +
2678 				   PCIE_INTF_HEADER_LEN,
2679 			   pmadapter->upld_len, MRVDRV_SIZE_OF_CMD_BUFFER);
2680 
2681 	} else {
2682 		pmadapter->cmd_resp_received = MTRUE;
2683 		pmbuf->data_len = pmadapter->upld_len;
2684 		pmbuf->data_offset += PCIE_INTF_HEADER_LEN;
2685 		pmadapter->curr_cmd->respbuf = pmbuf;
2686 
2687 		/* Take the pointer and set it to CMD node and will
2688 		   return in the response complete callback */
2689 		pmadapter->pcard_pcie->cmdrsp_buf = MNULL;
2690 #if defined(PCIE8997) || defined(PCIE8897)
2691 		if (!pmadapter->pcard_pcie->reg->use_adma) {
2692 			/* Clear the cmd-rsp buffer address in scratch
2693 			registers. This will prevent firmware from writing to
2694 			the same response buffer again. */
2695 			if (pcb->moal_write_reg(pmadapter->pmoal_handle,
2696 						REG_CMDRSP_ADDR_LO, 0)) {
2697 				PRINTM(MERROR,
2698 				       "Rx CMD: failed to clear cmd_rsp address.\n");
2699 				ret = MLAN_STATUS_FAILURE;
2700 				goto done;
2701 			}
2702 			/* Write the upper 32bits of the cmdrsp buffer physical
2703 			    address */
2704 			if (pcb->moal_write_reg(pmadapter->pmoal_handle,
2705 						REG_CMDRSP_ADDR_HI, 0)) {
2706 				PRINTM(MERROR,
2707 				       "Rx CMD: failed to clear cmd_rsp address.\n");
2708 				ret = MLAN_STATUS_FAILURE;
2709 				goto done;
2710 			}
2711 		}
2712 #endif
2713 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
2714 		if (pmadapter->pcard_pcie->reg->use_adma) {
2715 			/* Clear the cmd-rsp buffer address in adma registers.
2716 			   This will prevent firmware from writing to the same
2717 			   response buffer again. */
2718 			if (wlan_init_adma(pmadapter, ADMA_CMDRESP, 0, 0,
2719 					   MFALSE)) {
2720 				PRINTM(MERROR,
2721 				       "Rx CMD: failed to clear cmd_rsp address.\n");
2722 				ret = MLAN_STATUS_FAILURE;
2723 				goto done;
2724 			}
2725 		}
2726 #endif
2727 	}
2728 
2729 done:
2730 	LEAVE();
2731 	return ret;
2732 }
2733 
2734 /**
2735  *  @brief This function handles command response completion
2736  *
2737  *  @param pmadapter    A pointer to mlan_adapter structure
2738  *  @param pmbuf        A pointer to mlan_buffer
2739  *
2740  *  @return 	        MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
2741  */
wlan_pcie_cmdrsp_complete(mlan_adapter * pmadapter,mlan_buffer * pmbuf,mlan_status status)2742 static mlan_status wlan_pcie_cmdrsp_complete(mlan_adapter *pmadapter,
2743 					     mlan_buffer *pmbuf,
2744 					     mlan_status status)
2745 {
2746 	ENTER();
2747 
2748 	/*return the cmd response pmbuf*/
2749 	if (pmbuf) {
2750 		pmbuf->data_len = MRVDRV_SIZE_OF_CMD_BUFFER;
2751 		pmbuf->data_offset -= PCIE_INTF_HEADER_LEN;
2752 		pmadapter->pcard_pcie->cmdrsp_buf = pmbuf;
2753 	}
2754 
2755 	LEAVE();
2756 	return MLAN_STATUS_SUCCESS;
2757 }
2758 
2759 /**
2760  *  @brief This function check pending evt buffer
2761  *
2762  *  @param pmadapter  A pointer to mlan_adapter structure
2763  *  @param rdptr      evt rdptr
2764  *
2765  *  @return           MTRUE/MFALSE;
2766  */
wlan_check_evt_buffer(mlan_adapter * pmadapter,t_u32 rdptr)2767 static t_u8 wlan_check_evt_buffer(mlan_adapter *pmadapter, t_u32 rdptr)
2768 {
2769 #if defined(PCIE8997) || defined(PCIE8897)
2770 	if (!pmadapter->pcard_pcie->reg->use_adma) {
2771 		if (((rdptr & EVT_RW_PTR_MASK) !=
2772 		     (pmadapter->pcard_pcie->evtbd_rdptr & EVT_RW_PTR_MASK)) ||
2773 		    ((rdptr & EVT_RW_PTR_ROLLOVER_IND) !=
2774 		     (pmadapter->pcard_pcie->evtbd_rdptr &
2775 		      EVT_RW_PTR_ROLLOVER_IND)))
2776 			return MTRUE;
2777 		else
2778 			return MFALSE;
2779 	}
2780 #endif
2781 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
2782 	if (pmadapter->pcard_pcie->reg->use_adma) {
2783 		if ((pmadapter->pcard_pcie->evtbd_rdptr &
2784 		     ADMA_RW_PTR_WRAP_MASK) != (rdptr & ADMA_RW_PTR_WRAP_MASK))
2785 			return MTRUE;
2786 		else
2787 			return MFALSE;
2788 	}
2789 #endif
2790 	return MFALSE;
2791 }
2792 
2793 /**
2794  *  @brief This function handles FW event ready interrupt
2795  *
2796  *  @param pmadapter  A pointer to mlan_adapter structure
2797  *
2798  *  @return 	      MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
2799  */
wlan_pcie_process_event_ready(mlan_adapter * pmadapter)2800 static mlan_status wlan_pcie_process_event_ready(mlan_adapter *pmadapter)
2801 {
2802 	t_u32 rd_index =
2803 		pmadapter->pcard_pcie->evtbd_rdptr & (MLAN_MAX_EVT_BD - 1);
2804 	t_u32 rdptr, event;
2805 	pmlan_callbacks pcb = &pmadapter->callbacks;
2806 #if defined(PCIE8997) || defined(PCIE8897)
2807 	mlan_pcie_evt_buf *pevtbd_buf;
2808 #endif
2809 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
2810 	adma_dual_desc_buf *padma_bd_buf;
2811 #endif
2812 	ENTER();
2813 
2814 	if (pmadapter->event_received) {
2815 		PRINTM(MINFO, "Event being processed, do not "
2816 			      "process this interrupt just yet\n");
2817 		LEAVE();
2818 		return MLAN_STATUS_SUCCESS;
2819 	}
2820 
2821 	if (rd_index >= MLAN_MAX_EVT_BD) {
2822 		PRINTM(MINFO, "Invalid rd_index...\n");
2823 		LEAVE();
2824 		return MLAN_STATUS_FAILURE;
2825 	}
2826 
2827 	/* Read the event ring read pointer set by firmware */
2828 	if (pcb->moal_read_reg(pmadapter->pmoal_handle,
2829 			       pmadapter->pcard_pcie->reg->reg_evtbd_rdptr,
2830 			       &rdptr)) {
2831 		PRINTM(MERROR, "EvtRdy: failed to read REG_EVTBD_RDPTR\n");
2832 		LEAVE();
2833 		return MLAN_STATUS_FAILURE;
2834 	}
2835 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
2836 	if (pmadapter->pcard_pcie->reg->use_adma)
2837 		rdptr = rdptr >> ADMA_RPTR_START;
2838 #endif
2839 	PRINTM(MINFO, "EvtRdy: Initial <Wr: 0x%x, Rd: 0x%x>\n",
2840 	       pmadapter->pcard_pcie->evtbd_wrptr, rdptr);
2841 	if (wlan_check_evt_buffer(pmadapter, rdptr)) {
2842 		mlan_buffer *pmbuf_evt;
2843 		t_u16 evt_len;
2844 
2845 		PRINTM(MINFO, "EvtRdy: Read Index: %d\n", rd_index);
2846 		pmbuf_evt = pmadapter->pcard_pcie->evt_buf_list[rd_index];
2847 
2848 		/*unmap the pmbuf for CPU Access*/
2849 		pcb->moal_unmap_memory(pmadapter->pmoal_handle,
2850 				       pmbuf_evt->pbuf + pmbuf_evt->data_offset,
2851 				       pmbuf_evt->buf_pa, MAX_EVENT_SIZE,
2852 				       PCI_DMA_FROMDEVICE);
2853 
2854 		/* Take the pointer and set it to event pointer in adapter
2855 		   and will return back after event handling callback */
2856 #if defined(PCIE8997) || defined(PCIE8897)
2857 		if (!pmadapter->pcard_pcie->reg->use_adma) {
2858 			pevtbd_buf = (mlan_pcie_evt_buf *)pmadapter->pcard_pcie
2859 					     ->evtbd_ring[rd_index];
2860 			pevtbd_buf->paddr = 0;
2861 			pevtbd_buf->len = 0;
2862 			pevtbd_buf->flags = 0;
2863 		}
2864 #endif
2865 
2866 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
2867 		if (pmadapter->pcard_pcie->reg->use_adma) {
2868 			padma_bd_buf =
2869 				(adma_dual_desc_buf *)pmadapter->pcard_pcie
2870 					->evtbd_ring[rd_index];
2871 			padma_bd_buf->paddr = 0;
2872 			padma_bd_buf->len = 0;
2873 			padma_bd_buf->flags = 0;
2874 			padma_bd_buf->pkt_size = 0;
2875 			padma_bd_buf->reserved = 0;
2876 		}
2877 #endif
2878 		pmadapter->pcard_pcie->evt_buf_list[rd_index] = MNULL;
2879 
2880 		event = *((t_u32 *)&pmbuf_evt->pbuf[pmbuf_evt->data_offset +
2881 						    PCIE_INTF_HEADER_LEN]);
2882 		pmadapter->event_cause = wlan_le32_to_cpu(event);
2883 		/* The first 4bytes will be the event transfer header
2884 		   len is 2 bytes followed by type which is 2 bytes */
2885 		evt_len = *((t_u16 *)&pmbuf_evt->pbuf[pmbuf_evt->data_offset]);
2886 		evt_len = wlan_le16_to_cpu(evt_len);
2887 
2888 		if ((evt_len > 0) && (evt_len > MLAN_EVENT_HEADER_LEN) &&
2889 		    (evt_len - MLAN_EVENT_HEADER_LEN < MAX_EVENT_SIZE))
2890 			memcpy_ext(pmadapter, pmadapter->event_body,
2891 				   pmbuf_evt->pbuf + pmbuf_evt->data_offset +
2892 					   MLAN_EVENT_HEADER_LEN,
2893 				   evt_len - MLAN_EVENT_HEADER_LEN,
2894 				   sizeof(pmadapter->event_body));
2895 
2896 		pmbuf_evt->data_offset += PCIE_INTF_HEADER_LEN;
2897 		pmbuf_evt->data_len = evt_len - PCIE_INTF_HEADER_LEN;
2898 		PRINTM(MINFO, "Event length: %d\n", pmbuf_evt->data_len);
2899 
2900 		pmadapter->event_received = MTRUE;
2901 		pmadapter->pmlan_buffer_event = pmbuf_evt;
2902 		pmadapter->pcard_pcie->evtbd_rdptr++;
2903 #if defined(PCIE8997) || defined(PCIE8897)
2904 		if (!pmadapter->pcard_pcie->reg->use_adma) {
2905 			if ((pmadapter->pcard_pcie->evtbd_rdptr &
2906 			     EVT_RW_PTR_MASK) == MLAN_MAX_EVT_BD) {
2907 				pmadapter->pcard_pcie->evtbd_rdptr =
2908 					((pmadapter->pcard_pcie->evtbd_rdptr &
2909 					  EVT_RW_PTR_ROLLOVER_IND) ^
2910 					 EVT_RW_PTR_ROLLOVER_IND);
2911 			}
2912 		}
2913 #endif
2914 
2915 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
2916 		if (pmadapter->pcard_pcie->reg->use_adma)
2917 			pmadapter->pcard_pcie->evtbd_rdptr &=
2918 				ADMA_RW_PTR_WRAP_MASK;
2919 #endif
2920 
2921 		/* Do not update the event write pointer here, wait till the
2922 		   buffer is released. This is just to make things simpler,
2923 		   we need to find a better method of managing these buffers.
2924 		*/
2925 	} else {
2926 		PRINTM(MINTR, "------>EVENT DONE\n");
2927 		if (pcb->moal_write_reg(
2928 			    pmadapter->pmoal_handle,
2929 			    pmadapter->pcard_pcie->reg->reg_cpu_int_event,
2930 			    CPU_INTR_EVENT_DONE)) {
2931 			PRINTM(MERROR,
2932 			       "Failed to asset event done interrupt\n");
2933 			return MLAN_STATUS_FAILURE;
2934 		}
2935 	}
2936 	LEAVE();
2937 	return MLAN_STATUS_SUCCESS;
2938 }
2939 
2940 /**
2941  *  @brief This function handles event completion
2942  *
2943  *  @param pmadapter    A pointer to mlan_adapter structure
2944  *  @param pmbuf        A pointer to mlan_buffer
2945  *
2946  *  @return 	        MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
2947  */
wlan_pcie_event_complete(mlan_adapter * pmadapter,mlan_buffer * pmbuf,mlan_status status)2948 static mlan_status wlan_pcie_event_complete(mlan_adapter *pmadapter,
2949 					    mlan_buffer *pmbuf,
2950 					    mlan_status status)
2951 {
2952 	mlan_status ret = MLAN_STATUS_SUCCESS;
2953 	pmlan_callbacks pcb = &pmadapter->callbacks;
2954 	t_u32 wrptr =
2955 		pmadapter->pcard_pcie->evtbd_wrptr & (MLAN_MAX_EVT_BD - 1);
2956 	t_u32 rdptr;
2957 #if defined(PCIE8997) || defined(PCIE8897)
2958 	mlan_pcie_evt_buf *pevtbd_buf;
2959 #endif
2960 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
2961 	adma_dual_desc_buf *padma_bd_buf;
2962 #endif
2963 
2964 	ENTER();
2965 	if (!pmbuf) {
2966 		LEAVE();
2967 		return MLAN_STATUS_FAILURE;
2968 	}
2969 
2970 	if (wrptr >= MLAN_MAX_EVT_BD) {
2971 		PRINTM(MERROR, "EvtCom: Invalid wrptr 0x%x\n", wrptr);
2972 		ret = MLAN_STATUS_FAILURE;
2973 		goto done;
2974 	}
2975 
2976 	/* Read the event ring read pointer set by firmware */
2977 	if (pcb->moal_read_reg(pmadapter->pmoal_handle,
2978 			       pmadapter->pcard_pcie->reg->reg_evtbd_rdptr,
2979 			       &rdptr)) {
2980 		PRINTM(MERROR, "EvtCom: failed to read REG_EVTBD_RDPTR\n");
2981 		ret = MLAN_STATUS_FAILURE;
2982 		goto done;
2983 	}
2984 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
2985 	if (pmadapter->pcard_pcie->reg->use_adma)
2986 		rdptr = rdptr >> ADMA_RPTR_START;
2987 #endif
2988 
2989 	if (!pmadapter->pcard_pcie->evt_buf_list[wrptr]) {
2990 		pmbuf->data_len = MAX_EVENT_SIZE;
2991 		pmbuf->data_offset -= PCIE_INTF_HEADER_LEN;
2992 
2993 		if (MLAN_STATUS_FAILURE ==
2994 		    pcb->moal_map_memory(pmadapter->pmoal_handle,
2995 					 pmbuf->pbuf + pmbuf->data_offset,
2996 					 &pmbuf->buf_pa, MAX_EVENT_SIZE,
2997 					 PCI_DMA_FROMDEVICE)) {
2998 			PRINTM(MERROR, "EvtCom: failed to moal_map_memory\n");
2999 			LEAVE();
3000 			return MLAN_STATUS_FAILURE;
3001 		}
3002 
3003 		pmadapter->pcard_pcie->evt_buf_list[wrptr] = pmbuf;
3004 #if defined(PCIE8997) || defined(PCIE8897)
3005 		if (!pmadapter->pcard_pcie->reg->use_adma) {
3006 			pevtbd_buf = (mlan_pcie_evt_buf *)pmadapter->pcard_pcie
3007 					     ->evtbd_ring[wrptr];
3008 			pevtbd_buf->paddr = wlan_cpu_to_le64(pmbuf->buf_pa);
3009 			pevtbd_buf->len =
3010 				wlan_cpu_to_le16((t_u16)pmbuf->data_len);
3011 			pevtbd_buf->flags = 0;
3012 		}
3013 #endif
3014 
3015 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
3016 		if (pmadapter->pcard_pcie->reg->use_adma) {
3017 			padma_bd_buf = (adma_dual_desc_buf *)pmadapter
3018 					       ->pcard_pcie->evtbd_ring[wrptr];
3019 			padma_bd_buf->paddr = wlan_cpu_to_le64(pmbuf->buf_pa);
3020 			padma_bd_buf->len = wlan_cpu_to_le16(
3021 				ALIGN_SZ(pmbuf->data_len, ADMA_ALIGN_SIZE));
3022 			padma_bd_buf->flags = 0;
3023 			padma_bd_buf->flags = wlan_cpu_to_le16(
3024 				ADMA_BD_FLAG_INT_EN | ADMA_BD_FLAG_DST_HOST);
3025 			padma_bd_buf->pkt_size = 0;
3026 			padma_bd_buf->reserved = 0;
3027 		}
3028 #endif
3029 		pmbuf = MNULL;
3030 	} else {
3031 		PRINTM(MINFO,
3032 		       "EvtCom: ERROR: Buffer is still valid at "
3033 		       "index %d, <%p, %p>\n",
3034 		       wrptr, pmadapter->pcard_pcie->evt_buf_list[wrptr],
3035 		       pmbuf);
3036 	}
3037 
3038 	pmadapter->pcard_pcie->evtbd_wrptr++;
3039 
3040 #if defined(PCIE8997) || defined(PCIE8897)
3041 	if (!pmadapter->pcard_pcie->reg->use_adma) {
3042 		if ((pmadapter->pcard_pcie->evtbd_wrptr & EVT_RW_PTR_MASK) ==
3043 		    MLAN_MAX_EVT_BD) {
3044 			pmadapter->pcard_pcie->evtbd_wrptr =
3045 				((pmadapter->pcard_pcie->evtbd_wrptr &
3046 				  EVT_RW_PTR_ROLLOVER_IND) ^
3047 				 EVT_RW_PTR_ROLLOVER_IND);
3048 		}
3049 	}
3050 #endif
3051 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
3052 	if (pmadapter->pcard_pcie->reg->use_adma)
3053 		pmadapter->pcard_pcie->evtbd_wrptr &= ADMA_RW_PTR_WRAP_MASK;
3054 #endif
3055 	PRINTM(MINFO, "EvtCom: Updated <Wr: 0x%x, Rd: 0x%x>\n",
3056 	       pmadapter->pcard_pcie->evtbd_wrptr, rdptr);
3057 
3058 	/* Write the event ring write pointer in to REG_EVTBD_WRPTR */
3059 	if (pcb->moal_write_reg(pmadapter->pmoal_handle,
3060 				pmadapter->pcard_pcie->reg->reg_evtbd_wrptr,
3061 				pmadapter->pcard_pcie->evtbd_wrptr)) {
3062 		PRINTM(MERROR, "EvtCom: failed to write REG_EVTBD_WRPTR\n");
3063 		ret = MLAN_STATUS_FAILURE;
3064 		goto done;
3065 	}
3066 
3067 done:
3068 	/* Free the buffer for failure case */
3069 	if (ret && pmbuf)
3070 		wlan_free_mlan_buffer(pmadapter, pmbuf);
3071 
3072 	PRINTM(MINFO, "EvtCom: Check Events Again\n");
3073 	ret = wlan_pcie_process_event_ready(pmadapter);
3074 
3075 	LEAVE();
3076 	return ret;
3077 }
3078 
3079 /**
3080  *  @brief This function downloads boot command to the card.
3081  *
3082  *  @param pmadapter    A pointer to mlan_adapter structure
3083  *  @param pmbuf        A pointer to mlan_buffer
3084  *
3085  *  @return 	        MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
3086  */
wlan_pcie_send_boot_cmd(mlan_adapter * pmadapter,mlan_buffer * pmbuf)3087 static mlan_status wlan_pcie_send_boot_cmd(mlan_adapter *pmadapter,
3088 					   mlan_buffer *pmbuf)
3089 {
3090 	mlan_status ret = MLAN_STATUS_SUCCESS;
3091 	pmlan_callbacks pcb = &pmadapter->callbacks;
3092 
3093 	ENTER();
3094 
3095 	if (!pmadapter || !pmbuf) {
3096 		PRINTM(MERROR, "NULL Pointer\n");
3097 		LEAVE();
3098 		return MLAN_STATUS_FAILURE;
3099 	}
3100 
3101 	if (MLAN_STATUS_FAILURE ==
3102 	    pcb->moal_map_memory(
3103 		    pmadapter->pmoal_handle, pmbuf->pbuf + pmbuf->data_offset,
3104 		    &pmbuf->buf_pa, WLAN_UPLD_SIZE, PCI_DMA_TODEVICE)) {
3105 		PRINTM(MERROR, "BootCmd: failed to moal_map_memory\n");
3106 		LEAVE();
3107 		return MLAN_STATUS_FAILURE;
3108 	}
3109 
3110 	if (!(pmbuf->pbuf && pmbuf->data_len && pmbuf->buf_pa)) {
3111 		PRINTM(MERROR, "%s: Invalid buffer <%p, %#x:%x, len=%d>\n",
3112 		       __func__, pmbuf->pbuf,
3113 		       (t_u32)((t_u64)pmbuf->buf_pa >> 32),
3114 		       (t_u32)pmbuf->buf_pa, pmbuf->data_len);
3115 		ret = MLAN_STATUS_FAILURE;
3116 		goto done;
3117 	}
3118 
3119 	/* Write the lower 32bits of the physical address to scratch
3120 	 * register 0 */
3121 	if (pcb->moal_write_reg(pmadapter->pmoal_handle,
3122 				pmadapter->pcard_pcie->reg->reg_scratch_0,
3123 				(t_u32)pmbuf->buf_pa)) {
3124 		PRINTM(MERROR,
3125 		       "Failed to write download command to boot code\n");
3126 		ret = MLAN_STATUS_FAILURE;
3127 		goto done;
3128 	}
3129 
3130 	/* Write the upper 32bits of the physical address to scratch
3131 	 * register 1 */
3132 	if (pcb->moal_write_reg(pmadapter->pmoal_handle,
3133 				pmadapter->pcard_pcie->reg->reg_scratch_1,
3134 				(t_u32)((t_u64)pmbuf->buf_pa >> 32))) {
3135 		PRINTM(MERROR,
3136 		       "Failed to write download command to boot code\n");
3137 		ret = MLAN_STATUS_FAILURE;
3138 		goto done;
3139 	}
3140 
3141 	/* Write the command length to scratch register 2 */
3142 	if (pcb->moal_write_reg(pmadapter->pmoal_handle,
3143 				pmadapter->pcard_pcie->reg->reg_scratch_2,
3144 				pmbuf->data_len)) {
3145 		PRINTM(MERROR,
3146 		       "Failed to write command length to scratch register 2\n");
3147 		ret = MLAN_STATUS_FAILURE;
3148 		goto done;
3149 	}
3150 
3151 	/* Ring the door bell */
3152 	if (pcb->moal_write_reg(pmadapter->pmoal_handle,
3153 				pmadapter->pcard_pcie->reg->reg_cpu_int_event,
3154 				CPU_INTR_DOOR_BELL)) {
3155 		PRINTM(MERROR, "Failed to assert door-bell interrupt\n");
3156 		ret = MLAN_STATUS_FAILURE;
3157 		goto done;
3158 	}
3159 
3160 	LEAVE();
3161 	return ret;
3162 
3163 done:
3164 	if (MLAN_STATUS_FAILURE ==
3165 	    pcb->moal_unmap_memory(
3166 		    pmadapter->pmoal_handle, pmbuf->pbuf + pmbuf->data_offset,
3167 		    pmbuf->buf_pa, WLAN_UPLD_SIZE, PCI_DMA_TODEVICE))
3168 		PRINTM(MERROR, "BootCmd: failed to moal_unmap_memory\n");
3169 	LEAVE();
3170 	return ret;
3171 }
3172 
3173 /**
3174  *  @brief  This function init rx port in firmware
3175  *
3176  *  @param pmadapter	A pointer to mlan_adapter
3177  *
3178  *  @return		MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
3179  */
wlan_pcie_init_fw(pmlan_adapter pmadapter)3180 mlan_status wlan_pcie_init_fw(pmlan_adapter pmadapter)
3181 {
3182 	pmlan_callbacks pcb = &pmadapter->callbacks;
3183 	t_u32 txbd_val = 0;
3184 	mlan_status ret = MLAN_STATUS_SUCCESS;
3185 #if defined(PCIE8997) || defined(PCIE8897)
3186 	if (!pmadapter->pcard_pcie->reg->use_adma) {
3187 		txbd_val = pmadapter->pcard_pcie->txbd_wrptr &
3188 			   pmadapter->pcard_pcie->reg->txrx_rw_ptr_wrap_mask;
3189 		txbd_val = txbd_val << TXBD_RW_PTR_START;
3190 	}
3191 #endif
3192 	/* Write the RX ring write pointer in to REG_RXBD_WRPTR */
3193 	if (pcb->moal_write_reg(pmadapter->pmoal_handle,
3194 				pmadapter->pcard_pcie->reg->reg_rxbd_wrptr,
3195 				pmadapter->pcard_pcie->rxbd_wrptr | txbd_val)) {
3196 		PRINTM(MERROR, "Init FW: failed to write REG_RXBD_WRPTR\n");
3197 		ret = MLAN_STATUS_FAILURE;
3198 		goto done;
3199 	}
3200 	/* Write the event ring write pointer in to REG_EVTBD_WRPTR */
3201 	if (pcb->moal_write_reg(pmadapter->pmoal_handle,
3202 				pmadapter->pcard_pcie->reg->reg_evtbd_wrptr,
3203 				pmadapter->pcard_pcie->evtbd_wrptr)) {
3204 		PRINTM(MERROR, "Init FW: failed to write REG_EVTBD_WRPTR\n");
3205 		ret = MLAN_STATUS_FAILURE;
3206 	}
3207 done:
3208 	return ret;
3209 }
3210 
3211 /**
3212  *  @brief  This function downloads FW blocks to device
3213  *
3214  *  @param pmadapter	A pointer to mlan_adapter
3215  *  @param fw			A pointer to firmware image
3216  *
3217  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
3218  */
wlan_pcie_prog_fw_w_helper(mlan_adapter * pmadapter,mlan_fw_image * fw)3219 static mlan_status wlan_pcie_prog_fw_w_helper(mlan_adapter *pmadapter,
3220 					      mlan_fw_image *fw)
3221 {
3222 	mlan_status ret = MLAN_STATUS_FAILURE;
3223 	t_u8 *firmware = fw->pfw_buf;
3224 	t_u32 firmware_len = fw->fw_len;
3225 	t_u32 offset = 0;
3226 	mlan_buffer *pmbuf = MNULL;
3227 	t_u32 txlen, tries, len;
3228 	t_u32 block_retry_cnt = 0;
3229 	pmlan_callbacks pcb = &pmadapter->callbacks;
3230 #if defined(PCIE9098)
3231 	t_u32 rev_id_reg = 0;
3232 	t_u32 revision_id = 0;
3233 #endif
3234 	t_u8 check_fw_status = MFALSE;
3235 	t_u32 fw_dnld_status = 0;
3236 	t_u32 fw_dnld_offset = 0;
3237 	t_u8 mic_retry = 0;
3238 
3239 	ENTER();
3240 	if (!pmadapter) {
3241 		PRINTM(MERROR, "adapter structure is not valid\n");
3242 		goto done;
3243 	}
3244 
3245 	if (!firmware || !firmware_len) {
3246 		PRINTM(MERROR,
3247 		       "No firmware image found! Terminating download\n");
3248 		goto done;
3249 	}
3250 
3251 	PRINTM(MINFO, "Downloading FW image (%d bytes)\n", firmware_len);
3252 
3253 	if (wlan_disable_pcie_host_int(pmadapter)) {
3254 		PRINTM(MERROR, "prog_fw: Disabling interrupts failed\n");
3255 		goto done;
3256 	}
3257 
3258 	pmbuf = wlan_alloc_mlan_buffer(pmadapter, WLAN_UPLD_SIZE, 0,
3259 				       MOAL_ALLOC_MLAN_BUFFER);
3260 	if (!pmbuf) {
3261 		PRINTM(MERROR, "prog_fw: Unable to allocate mlan_buffer\n");
3262 		goto done;
3263 	}
3264 #if defined(PCIE9098)
3265 	if (IS_PCIE9098(pmadapter->card_type)) {
3266 		rev_id_reg = pmadapter->pcard_pcie->reg->reg_rev_id;
3267 		ret = pcb->moal_read_reg(pmadapter->pmoal_handle, rev_id_reg,
3268 					 &revision_id);
3269 		if (ret != MLAN_STATUS_SUCCESS) {
3270 			PRINTM(MERROR,
3271 			       "Failed to read PCIe revision id register\n");
3272 			goto done;
3273 		}
3274 		/* Skyhawk A0, need to check both CRC and MIC error */
3275 		if (revision_id >= CHIP_9098_REV_A0)
3276 			check_fw_status = MTRUE;
3277 	}
3278 #endif
3279 	/* For PCIE9097, need check both CRC and MIC error */
3280 #if defined(PCIE9097)
3281 	if (IS_PCIE9097(pmadapter->card_type))
3282 		check_fw_status = MTRUE;
3283 #endif
3284 #if defined(PCIENW62X)
3285 	if (IS_PCIENW62X(pmadapter->card_type))
3286 		check_fw_status = MTRUE;
3287 #endif
3288 
3289 	/* Perform firmware data transfer */
3290 	do {
3291 		t_u32 ireg_intr = 0;
3292 		t_u32 read_retry_cnt = 0;
3293 
3294 		/* More data? */
3295 		if (offset >= firmware_len)
3296 			break;
3297 
3298 		for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
3299 			ret = pcb->moal_read_reg(
3300 				pmadapter->pmoal_handle,
3301 				pmadapter->pcard_pcie->reg->reg_scratch_2,
3302 				&len);
3303 			if (ret) {
3304 				PRINTM(MWARN,
3305 				       "Failed reading length from boot code\n");
3306 				goto done;
3307 			}
3308 			if (len || offset)
3309 				break;
3310 			wlan_udelay(pmadapter, 10);
3311 		}
3312 
3313 		if (!len) {
3314 			break;
3315 		} else if (len > WLAN_UPLD_SIZE) {
3316 			PRINTM(MERROR,
3317 			       "FW download failure @ %d, invalid length %d\n",
3318 			       offset, len);
3319 			goto done;
3320 		}
3321 
3322 		txlen = len;
3323 
3324 		if (len & MBIT(0)) {
3325 			if (check_fw_status) {
3326 				/* Get offset from fw dnld offset Register */
3327 				ret = pcb->moal_read_reg(
3328 					pmadapter->pmoal_handle,
3329 					pmadapter->pcard_pcie->reg
3330 						->reg_scratch_6,
3331 					&fw_dnld_offset);
3332 				if (ret != MLAN_STATUS_SUCCESS) {
3333 					PRINTM(MERROR,
3334 					       "FW download failure @ %d, reading fw dnld offset failed\n",
3335 					       offset);
3336 					goto done;
3337 				}
3338 				/* Get CRC MIC error from fw dnld status
3339 				 * Register */
3340 				ret = pcb->moal_read_reg(
3341 					pmadapter->pmoal_handle,
3342 					pmadapter->pcard_pcie->reg
3343 						->reg_scratch_7,
3344 					&fw_dnld_status);
3345 				if (ret != MLAN_STATUS_SUCCESS) {
3346 					PRINTM(MERROR,
3347 					       "FW download failure @ %d, reading fw dnld status failed\n",
3348 					       offset);
3349 					goto done;
3350 				}
3351 				PRINTM(MERROR,
3352 				       "FW download error: status=0x%x offset = 0x%x fw offset = 0x%x\n",
3353 				       fw_dnld_status, offset, fw_dnld_offset);
3354 			}
3355 			block_retry_cnt++;
3356 			if (block_retry_cnt > MAX_WRITE_IOMEM_RETRY) {
3357 				PRINTM(MERROR,
3358 				       "FW download failure @ %d, over max "
3359 				       "retry count\n",
3360 				       offset);
3361 				goto done;
3362 			}
3363 			PRINTM(MERROR,
3364 			       "FW CRC error indicated by the "
3365 			       "helper: len = 0x%04X, txlen = %d\n",
3366 			       len, txlen);
3367 			len &= ~MBIT(0);
3368 			/* Setting this to 0 to resend from same offset */
3369 			txlen = 0;
3370 			if (fw_dnld_status & (MBIT(6) | MBIT(7))) {
3371 				offset = 0;
3372 				mic_retry++;
3373 				if (mic_retry > MAX_FW_RETRY) {
3374 					PRINTM(MERROR,
3375 					       "FW download failure @ %d, over max "
3376 					       "mic retry count\n",
3377 					       offset);
3378 					goto done;
3379 				}
3380 			}
3381 		} else {
3382 			block_retry_cnt = 0;
3383 			/* Set blocksize to transfer - checking for last block
3384 			 */
3385 			if (firmware_len - offset < txlen)
3386 				txlen = firmware_len - offset;
3387 
3388 			PRINTM(MINFO, ".");
3389 
3390 			/* Copy payload to buffer */
3391 			memmove(pmadapter, pmbuf->pbuf + pmbuf->data_offset,
3392 				&firmware[offset], txlen);
3393 			pmbuf->data_len = txlen;
3394 		}
3395 
3396 		/* Send the boot command to device */
3397 		if (wlan_pcie_send_boot_cmd(pmadapter, pmbuf)) {
3398 			PRINTM(MERROR,
3399 			       "Failed to send firmware download command\n");
3400 			goto done;
3401 		}
3402 		/* Wait for the command done interrupt */
3403 		do {
3404 			if (read_retry_cnt > MAX_READ_REG_RETRY) {
3405 				PRINTM(MERROR,
3406 				       "prog_fw: Failed to get command done interrupt "
3407 				       "retry count = %d\n",
3408 				       read_retry_cnt);
3409 				goto done;
3410 			}
3411 			if (pcb->moal_read_reg(pmadapter->pmoal_handle,
3412 					       pmadapter->pcard_pcie->reg
3413 						       ->reg_cpu_int_status,
3414 					       &ireg_intr)) {
3415 				PRINTM(MERROR,
3416 				       "prog_fw: Failed to read "
3417 				       "interrupt status during fw dnld\n");
3418 				/* buffer was mapped in send_boot_cmd, unmap
3419 				 * first */
3420 				pcb->moal_unmap_memory(
3421 					pmadapter->pmoal_handle,
3422 					pmbuf->pbuf + pmbuf->data_offset,
3423 					pmbuf->buf_pa, WLAN_UPLD_SIZE,
3424 					PCI_DMA_TODEVICE);
3425 				goto done;
3426 			}
3427 			read_retry_cnt++;
3428 			pcb->moal_usleep_range(pmadapter->pmoal_handle, 10, 20);
3429 		} while ((ireg_intr & CPU_INTR_DOOR_BELL) ==
3430 			 CPU_INTR_DOOR_BELL);
3431 		/* got interrupt - can unmap buffer now */
3432 		if (MLAN_STATUS_FAILURE ==
3433 		    pcb->moal_unmap_memory(pmadapter->pmoal_handle,
3434 					   pmbuf->pbuf + pmbuf->data_offset,
3435 					   pmbuf->buf_pa, WLAN_UPLD_SIZE,
3436 					   PCI_DMA_TODEVICE)) {
3437 			PRINTM(MERROR,
3438 			       "prog_fw: failed to moal_unmap_memory\n");
3439 			goto done;
3440 		}
3441 		offset += txlen;
3442 	} while (MTRUE);
3443 
3444 	PRINTM(MMSG, "FW download over, size %d bytes\n", offset);
3445 
3446 	ret = MLAN_STATUS_SUCCESS;
3447 done:
3448 	if (pmbuf)
3449 		wlan_free_mlan_buffer(pmadapter, pmbuf);
3450 
3451 	LEAVE();
3452 	return ret;
3453 }
3454 
3455 /********************************************************
3456 			Global Functions
3457 ********************************************************/
3458 /**
3459  *	@brief This function get pcie device from card type
3460  *
3461  *	@param pmadapter  A pointer to mlan_adapter structure
3462  *	@return 		  MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
3463  */
wlan_get_pcie_device(pmlan_adapter pmadapter)3464 mlan_status wlan_get_pcie_device(pmlan_adapter pmadapter)
3465 {
3466 	mlan_status ret = MLAN_STATUS_SUCCESS;
3467 	t_u16 card_type = pmadapter->card_type;
3468 
3469 	ENTER();
3470 
3471 	ret = pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle,
3472 					       sizeof(mlan_pcie_card),
3473 					       MLAN_MEM_DEF,
3474 					       (t_u8 **)&pmadapter->pcard_pcie);
3475 	if (ret != MLAN_STATUS_SUCCESS || !pmadapter->pcard_pcie) {
3476 		PRINTM(MERROR, "Failed to allocate pcard_pcie\n");
3477 		LEAVE();
3478 		return MLAN_STATUS_FAILURE;
3479 	}
3480 
3481 	switch (card_type) {
3482 #ifdef PCIE8897
3483 	case CARD_TYPE_PCIE8897:
3484 		pmadapter->pcard_pcie->reg = &mlan_reg_pcie8897;
3485 		pmadapter->pcard_info = &mlan_card_info_pcie8897;
3486 		pmadapter->pcard_pcie->txrx_bd_size = MAX_TXRX_BD;
3487 		break;
3488 #endif
3489 #ifdef PCIE8997
3490 	case CARD_TYPE_PCIE8997:
3491 		pmadapter->pcard_pcie->reg = &mlan_reg_pcie8997;
3492 		pmadapter->pcard_info = &mlan_card_info_pcie8997;
3493 		pmadapter->pcard_pcie->txrx_bd_size = MAX_TXRX_BD;
3494 		break;
3495 #endif
3496 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
3497 	case CARD_TYPE_PCIE9097:
3498 	case CARD_TYPE_PCIE9098:
3499 	case CARD_TYPE_PCIENW62X:
3500 		pmadapter->pcard_pcie->reg = &mlan_reg_pcie9098;
3501 		pmadapter->pcard_info = &mlan_card_info_pcie9098;
3502 		pmadapter->pcard_pcie->txrx_bd_size = ADMA_DEF_TXRX_BD;
3503 		pmadapter->pcard_pcie->txrx_num_desc = TXRX_DEF_NUM_DESC;
3504 #if defined(PCIE9097) || defined(PCIENW62X)
3505 		if ((card_type == CARD_TYPE_PCIE9097 &&
3506 		     pmadapter->card_rev == CHIP_9097_REV_B0) ||
3507 		    (card_type == CARD_TYPE_PCIENW62X))
3508 			pmadapter->pcard_pcie->reg = &mlan_reg_pcie9097_b0;
3509 #endif
3510 
3511 		break;
3512 #endif
3513 	default:
3514 		PRINTM(MERROR, "can't get right pcie card type \n");
3515 		ret = MLAN_STATUS_FAILURE;
3516 		break;
3517 	}
3518 
3519 	LEAVE();
3520 	return ret;
3521 }
3522 
3523 /**
3524  *  @brief PCIE wakeup handler
3525  *
3526  *  @param pmadapter  A pointer to mlan_adapter structure
3527  *
3528  *  @return 	      MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
3529  */
wlan_pcie_wakeup(mlan_adapter * pmadapter)3530 mlan_status wlan_pcie_wakeup(mlan_adapter *pmadapter)
3531 {
3532 	mlan_status ret = MLAN_STATUS_SUCCESS;
3533 	t_u32 data = 0;
3534 	ENTER();
3535 	/* Enable interrupts or any chip access will wakeup device */
3536 	ret = pmadapter->callbacks.moal_read_reg(
3537 		pmadapter->pmoal_handle, pmadapter->pcard_pcie->reg->reg_ip_rev,
3538 		&data);
3539 
3540 	if (ret == MLAN_STATUS_SUCCESS) {
3541 		PRINTM(MINFO,
3542 		       "PCIE wakeup: Read PCI register to wakeup device ...\n");
3543 	} else {
3544 		PRINTM(MINFO, "PCIE wakeup: Failed to wakeup device ...\n");
3545 		ret = MLAN_STATUS_FAILURE;
3546 	}
3547 	LEAVE();
3548 	return ret;
3549 }
3550 
3551 /**
3552  *  @brief This function gets interrupt status.
3553  *
3554  */
3555 /**
3556  *  @param msg_id  A message id
3557  *  @param pmadapter  A pointer to mlan_adapter structure
3558  *  @return         MLAN_STATUS_FAILURE -- if the intererupt is not for us
3559  */
wlan_pcie_interrupt(t_u16 msg_id,pmlan_adapter pmadapter)3560 static mlan_status wlan_pcie_interrupt(t_u16 msg_id, pmlan_adapter pmadapter)
3561 {
3562 	t_u32 pcie_ireg;
3563 	pmlan_callbacks pcb = &pmadapter->callbacks;
3564 	t_void *pmoal_handle = pmadapter->pmoal_handle;
3565 	t_void *pint_lock = pmadapter->pint_lock;
3566 	mlan_status ret = MLAN_STATUS_SUCCESS;
3567 
3568 	ENTER();
3569 
3570 	if (pmadapter->pcard_pcie->pcie_int_mode == PCIE_INT_MODE_MSI) {
3571 		pcb->moal_spin_lock(pmoal_handle, pint_lock);
3572 		pmadapter->ireg = 1;
3573 		pcb->moal_spin_unlock(pmoal_handle, pint_lock);
3574 	} else if (pmadapter->pcard_pcie->pcie_int_mode == PCIE_INT_MODE_MSIX) {
3575 		pcie_ireg = (1 << msg_id) &
3576 			    pmadapter->pcard_pcie->reg->host_intr_mask;
3577 		if (pcie_ireg) {
3578 			if (!pmadapter->pps_uapsd_mode &&
3579 			    (pmadapter->ps_state == PS_STATE_SLEEP)) {
3580 				pmadapter->pm_wakeup_fw_try = MFALSE;
3581 				pmadapter->ps_state = PS_STATE_AWAKE;
3582 				pmadapter->pm_wakeup_card_req = MFALSE;
3583 			}
3584 		}
3585 		pcb->moal_spin_lock(pmoal_handle, pint_lock);
3586 		pmadapter->ireg |= pcie_ireg;
3587 		pcb->moal_spin_unlock(pmoal_handle, pint_lock);
3588 
3589 		PRINTM(MINTR, "ireg: 0x%08x\n", pcie_ireg);
3590 	} else {
3591 		wlan_pcie_disable_host_int_mask(pmadapter);
3592 		if (pcb->moal_read_reg(
3593 			    pmoal_handle,
3594 			    pmadapter->pcard_pcie->reg->reg_host_int_status,
3595 			    &pcie_ireg)) {
3596 			PRINTM(MERROR, "Read func%d register failed\n",
3597 			       pmadapter->pcard_pcie->func_num);
3598 			LEAVE();
3599 			return MLAN_STATUS_FAILURE;
3600 		}
3601 
3602 		if ((pcie_ireg != 0xFFFFFFFF) && (pcie_ireg)) {
3603 			PRINTM(MINTR, "func%d: pcie_ireg=0x%x\n",
3604 			       pmadapter->pcard_pcie->func_num, pcie_ireg);
3605 			if (!pmadapter->pps_uapsd_mode &&
3606 			    (pmadapter->ps_state == PS_STATE_SLEEP)) {
3607 				/* Potentially for PCIe we could get other
3608 				 * interrupts like shared. */
3609 				pmadapter->pm_wakeup_fw_try = MFALSE;
3610 				pmadapter->ps_state = PS_STATE_AWAKE;
3611 				pmadapter->pm_wakeup_card_req = MFALSE;
3612 			}
3613 			pcb->moal_spin_lock(pmoal_handle, pint_lock);
3614 			pmadapter->ireg |= pcie_ireg;
3615 			pcb->moal_spin_unlock(pmoal_handle, pint_lock);
3616 
3617 			/* Clear the pending interrupts */
3618 			if (pcb->moal_write_reg(pmoal_handle,
3619 						pmadapter->pcard_pcie->reg
3620 							->reg_host_int_status,
3621 						~pcie_ireg)) {
3622 				PRINTM(MWARN, "Write register failed\n");
3623 				LEAVE();
3624 				return ret;
3625 			}
3626 		} else {
3627 			wlan_pcie_enable_host_int_mask(pmadapter);
3628 			PRINTM(MINFO, "This is not our interrupt\n");
3629 			ret = MLAN_STATUS_FAILURE;
3630 		}
3631 	}
3632 
3633 	LEAVE();
3634 	return ret;
3635 }
3636 
3637 /**
3638  *  @brief This function checks the msix interrupt status and
3639  *  handle it accordingly.
3640  *
3641  *  @param pmadapter    A pointer to mlan_adapter structure
3642  *
3643  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
3644  */
wlan_process_msix_int(mlan_adapter * pmadapter)3645 mlan_status wlan_process_msix_int(mlan_adapter *pmadapter)
3646 {
3647 	mlan_status ret = MLAN_STATUS_SUCCESS;
3648 	t_u32 pcie_ireg = 0;
3649 	pmlan_callbacks pcb = &pmadapter->callbacks;
3650 
3651 	ENTER();
3652 
3653 	pcb->moal_spin_lock(pmadapter->pmoal_handle, pmadapter->pint_lock);
3654 	pcie_ireg =
3655 		pmadapter->ireg & pmadapter->pcard_pcie->reg->host_intr_mask;
3656 	pmadapter->ireg = 0;
3657 	pcb->moal_spin_unlock(pmadapter->pmoal_handle, pmadapter->pint_lock);
3658 
3659 	if (pcie_ireg & pmadapter->pcard_pcie->reg->host_intr_dnld_done) {
3660 		PRINTM(MINFO, "<--- DATA sent Interrupt --->\n");
3661 		ret = wlan_pcie_send_data_complete(pmadapter);
3662 		if (ret)
3663 			goto done;
3664 	}
3665 	if (pcie_ireg & pmadapter->pcard_pcie->reg->host_intr_upld_rdy) {
3666 		PRINTM(MINFO, "Rx DATA\n");
3667 		ret = wlan_pcie_process_recv_data(pmadapter);
3668 		if (ret)
3669 			goto done;
3670 	}
3671 	if (pcie_ireg & pmadapter->pcard_pcie->reg->host_intr_event_rdy) {
3672 		PRINTM(MINFO, "Rx EVENT\n");
3673 		ret = wlan_pcie_process_event_ready(pmadapter);
3674 		if (ret)
3675 			goto done;
3676 	}
3677 	if (pcie_ireg & pmadapter->pcard_pcie->reg->host_intr_cmd_done) {
3678 		if (pmadapter->cmd_sent) {
3679 			PRINTM(MINFO, "<--- CMD sent Interrupt --->\n");
3680 			pmadapter->cmd_sent = MFALSE;
3681 		}
3682 		ret = wlan_pcie_process_cmd_resp(pmadapter);
3683 		if (ret)
3684 			goto done;
3685 	}
3686 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
3687 	if (pmadapter->pcard_pcie->reg->host_intr_cmd_dnld &&
3688 	    (pcie_ireg & pmadapter->pcard_pcie->reg->host_intr_cmd_dnld)) {
3689 		if (pmadapter->cmd_sent)
3690 			pmadapter->cmd_sent = MFALSE;
3691 		if (pmadapter->pcard_pcie->vdll_cmd_buf)
3692 			wlan_pcie_send_vdll_complete(pmadapter);
3693 		PRINTM(MINFO, "<--- CMD DNLD DONE Interrupt --->\n");
3694 	}
3695 #endif
3696 	PRINTM(MINFO, "cmd_sent=%d data_sent=%d\n", pmadapter->cmd_sent,
3697 	       pmadapter->data_sent);
3698 
3699 done:
3700 	LEAVE();
3701 	return ret;
3702 }
3703 
3704 /**
3705  *  @brief This function checks the interrupt status and
3706  *  handle it accordingly.
3707  *
3708  *  @param pmadapter    A pointer to mlan_adapter structure
3709  *
3710  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
3711  */
wlan_process_pcie_int_status(mlan_adapter * pmadapter)3712 static mlan_status wlan_process_pcie_int_status(mlan_adapter *pmadapter)
3713 {
3714 	mlan_status ret = MLAN_STATUS_SUCCESS;
3715 	t_u32 pcie_ireg = 0;
3716 	pmlan_callbacks pcb = &pmadapter->callbacks;
3717 
3718 	ENTER();
3719 
3720 	if (pmadapter->pcard_pcie->pcie_int_mode == PCIE_INT_MODE_MSIX) {
3721 		wlan_process_msix_int(pmadapter);
3722 		goto done;
3723 	}
3724 	pcb->moal_spin_lock(pmadapter->pmoal_handle, pmadapter->pint_lock);
3725 	if (pmadapter->pcard_pcie->pcie_int_mode != PCIE_INT_MODE_MSI)
3726 		pcie_ireg = pmadapter->ireg;
3727 	pmadapter->ireg = 0;
3728 	pcb->moal_spin_unlock(pmadapter->pmoal_handle, pmadapter->pint_lock);
3729 	if (pmadapter->pcard_pcie->pcie_int_mode == PCIE_INT_MODE_MSI) {
3730 		if (pcb->moal_read_reg(
3731 			    pmadapter->pmoal_handle,
3732 			    pmadapter->pcard_pcie->reg->reg_host_int_status,
3733 			    &pcie_ireg)) {
3734 			PRINTM(MERROR, "Read func%d register failed\n",
3735 			       pmadapter->pcard_pcie->func_num);
3736 			ret = MLAN_STATUS_FAILURE;
3737 			goto done;
3738 		}
3739 
3740 		if ((pcie_ireg != 0xFFFFFFFF) && (pcie_ireg)) {
3741 			PRINTM(MINTR, "func%d: pcie_ireg=0x%x\n",
3742 			       pmadapter->pcard_pcie->func_num, pcie_ireg);
3743 			if (pmadapter->pcard_pcie->reg->msi_int_wr_clr) {
3744 				if (pcb->moal_write_reg(
3745 					    pmadapter->pmoal_handle,
3746 					    pmadapter->pcard_pcie->reg
3747 						    ->reg_host_int_status,
3748 					    ~pcie_ireg)) {
3749 					PRINTM(MERROR,
3750 					       "Write register failed\n");
3751 					ret = MLAN_STATUS_FAILURE;
3752 					goto done;
3753 				}
3754 			}
3755 			if (!pmadapter->pps_uapsd_mode &&
3756 			    (pmadapter->ps_state == PS_STATE_SLEEP)) {
3757 				/* Potentially for PCIe we could get other
3758 				 * interrupts like shared. */
3759 				pmadapter->pm_wakeup_fw_try = MFALSE;
3760 				pmadapter->ps_state = PS_STATE_AWAKE;
3761 				pmadapter->pm_wakeup_card_req = MFALSE;
3762 			}
3763 		}
3764 	}
3765 	while (pcie_ireg & pmadapter->pcard_pcie->reg->host_intr_mask) {
3766 		if (pcie_ireg &
3767 		    pmadapter->pcard_pcie->reg->host_intr_dnld_done) {
3768 			pcie_ireg &=
3769 				~pmadapter->pcard_pcie->reg->host_intr_dnld_done;
3770 			PRINTM(MINFO, "<--- DATA sent Interrupt --->\n");
3771 			pmadapter->callbacks.moal_tp_accounting_rx_param(
3772 				pmadapter->pmoal_handle, 3, 0);
3773 
3774 			ret = wlan_pcie_send_data_complete(pmadapter);
3775 			if (ret)
3776 				goto done;
3777 		}
3778 		if (pcie_ireg &
3779 		    pmadapter->pcard_pcie->reg->host_intr_upld_rdy) {
3780 			pcie_ireg &=
3781 				~pmadapter->pcard_pcie->reg->host_intr_upld_rdy;
3782 			PRINTM(MINFO, "Rx DATA\n");
3783 			pmadapter->callbacks.moal_tp_accounting_rx_param(
3784 				pmadapter->pmoal_handle, 0, 0);
3785 			ret = wlan_pcie_process_recv_data(pmadapter);
3786 			if (ret)
3787 				goto done;
3788 		}
3789 		if (pcie_ireg &
3790 		    pmadapter->pcard_pcie->reg->host_intr_event_rdy) {
3791 			pcie_ireg &=
3792 				~pmadapter->pcard_pcie->reg->host_intr_event_rdy;
3793 			PRINTM(MINFO, "Rx EVENT\n");
3794 			ret = wlan_pcie_process_event_ready(pmadapter);
3795 			if (ret)
3796 				goto done;
3797 		}
3798 		if (pcie_ireg &
3799 		    pmadapter->pcard_pcie->reg->host_intr_cmd_done) {
3800 			pcie_ireg &=
3801 				~pmadapter->pcard_pcie->reg->host_intr_cmd_done;
3802 			if (pmadapter->cmd_sent) {
3803 				PRINTM(MINFO, "<--- CMD sent Interrupt --->\n");
3804 				pmadapter->cmd_sent = MFALSE;
3805 			}
3806 			ret = wlan_pcie_process_cmd_resp(pmadapter);
3807 			if (ret)
3808 				goto done;
3809 		}
3810 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
3811 		if (pmadapter->pcard_pcie->reg->host_intr_cmd_dnld &&
3812 		    (pcie_ireg &
3813 		     pmadapter->pcard_pcie->reg->host_intr_cmd_dnld)) {
3814 			pcie_ireg &=
3815 				~pmadapter->pcard_pcie->reg->host_intr_cmd_dnld;
3816 			if (pmadapter->cmd_sent)
3817 				pmadapter->cmd_sent = MFALSE;
3818 			if (pmadapter->pcard_pcie->vdll_cmd_buf)
3819 				wlan_pcie_send_vdll_complete(pmadapter);
3820 			PRINTM(MINFO, "<--- CMD DNLD DONE Interrupt --->\n");
3821 		}
3822 #endif
3823 		if (pmadapter->pcard_pcie->pcie_int_mode == PCIE_INT_MODE_MSI) {
3824 			pcb->moal_spin_lock(pmadapter->pmoal_handle,
3825 					    pmadapter->pint_lock);
3826 			pmadapter->ireg = 0;
3827 			pcb->moal_spin_unlock(pmadapter->pmoal_handle,
3828 					      pmadapter->pint_lock);
3829 		}
3830 		if (pcb->moal_read_reg(
3831 			    pmadapter->pmoal_handle,
3832 			    pmadapter->pcard_pcie->reg->reg_host_int_status,
3833 			    &pcie_ireg)) {
3834 			PRINTM(MERROR, "Read func%d register failed\n",
3835 			       pmadapter->pcard_pcie->func_num);
3836 			ret = MLAN_STATUS_FAILURE;
3837 			goto done;
3838 		}
3839 
3840 		if ((pcie_ireg != 0xFFFFFFFF) && (pcie_ireg)) {
3841 			PRINTM(MINTR, "func%d: Poll pcie_ireg=0x%x\n",
3842 			       pmadapter->pcard_pcie->func_num, pcie_ireg);
3843 			if ((pmadapter->pcard_pcie->pcie_int_mode ==
3844 			     PCIE_INT_MODE_LEGACY) ||
3845 			    pmadapter->pcard_pcie->reg->msi_int_wr_clr) {
3846 				if (pcb->moal_write_reg(
3847 					    pmadapter->pmoal_handle,
3848 					    pmadapter->pcard_pcie->reg
3849 						    ->reg_host_int_status,
3850 					    ~pcie_ireg)) {
3851 					PRINTM(MWARN,
3852 					       "Write register failed\n");
3853 					return MLAN_STATUS_FAILURE;
3854 				}
3855 			}
3856 			if (pmadapter->pcard_pcie->pcie_int_mode !=
3857 			    PCIE_INT_MODE_MSI) {
3858 				pcb->moal_spin_lock(pmadapter->pmoal_handle,
3859 						    pmadapter->pint_lock);
3860 				pcie_ireg |= pmadapter->ireg;
3861 				pmadapter->ireg = 0;
3862 				pcb->moal_spin_unlock(pmadapter->pmoal_handle,
3863 						      pmadapter->pint_lock);
3864 			}
3865 			/* Don't update the pmadapter->pcie_ireg,
3866 			 * serving the status right now */
3867 		}
3868 	}
3869 	PRINTM(MINFO, "cmd_sent=%d data_sent=%d\n", pmadapter->cmd_sent,
3870 	       pmadapter->data_sent);
3871 	if (pmadapter->pcard_pcie->pcie_int_mode != PCIE_INT_MODE_MSI) {
3872 		if (pmadapter->ps_state != PS_STATE_SLEEP ||
3873 		    pmadapter->pcard_info->supp_ps_handshake)
3874 			wlan_pcie_enable_host_int_mask(pmadapter);
3875 	}
3876 done:
3877 	LEAVE();
3878 	return ret;
3879 }
3880 
3881 /**
3882  *  @brief This function sets DRV_READY register
3883  *
3884  *  @param pmadapter  A pointer to mlan_adapter structure
3885  *  @param val        Value
3886  *
3887  *  @return           MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
3888  *
3889  */
wlan_set_drv_ready_reg(mlan_adapter * pmadapter,t_u32 val)3890 mlan_status wlan_set_drv_ready_reg(mlan_adapter *pmadapter, t_u32 val)
3891 {
3892 	pmlan_callbacks pcb = &pmadapter->callbacks;
3893 
3894 	ENTER();
3895 
3896 	if (pcb->moal_write_reg(pmadapter->pmoal_handle,
3897 				pmadapter->pcard_pcie->reg->reg_drv_ready,
3898 				val)) {
3899 		LEAVE();
3900 		return MLAN_STATUS_FAILURE;
3901 	}
3902 
3903 	LEAVE();
3904 	return MLAN_STATUS_SUCCESS;
3905 }
3906 
3907 /**
3908  *  @brief This function checks if the interface is ready to download
3909  *  or not while other download interface is present
3910  *
3911  *  @param pmadapter  A pointer to mlan_adapter structure
3912  *  @param val        Winner status (0: winner)
3913  *
3914  *  @return           MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
3915  *
3916  */
wlan_pcie_check_winner_status(mlan_adapter * pmadapter,t_u32 * val)3917 static mlan_status wlan_pcie_check_winner_status(mlan_adapter *pmadapter,
3918 						 t_u32 *val)
3919 {
3920 	t_u32 winner = 0;
3921 	pmlan_callbacks pcb = &pmadapter->callbacks;
3922 
3923 	ENTER();
3924 
3925 	if (MLAN_STATUS_SUCCESS !=
3926 	    pcb->moal_read_reg(pmadapter->pmoal_handle,
3927 			       pmadapter->pcard_pcie->reg->reg_scratch_3,
3928 			       &winner)) {
3929 		LEAVE();
3930 		return MLAN_STATUS_FAILURE;
3931 	}
3932 	*val = winner;
3933 
3934 	LEAVE();
3935 	return MLAN_STATUS_SUCCESS;
3936 }
3937 
3938 /**
3939  *  @brief This function checks if the firmware is ready to accept
3940  *  command or not.
3941  *
3942  *  @param pmadapter  A pointer to mlan_adapter structure
3943  *  @param pollnum    Maximum polling number
3944  *
3945  *  @return           MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
3946  */
wlan_pcie_check_fw_status(mlan_adapter * pmadapter,t_u32 pollnum)3947 static mlan_status wlan_pcie_check_fw_status(mlan_adapter *pmadapter,
3948 					     t_u32 pollnum)
3949 {
3950 	mlan_status ret = MLAN_STATUS_SUCCESS;
3951 	pmlan_callbacks pcb = &pmadapter->callbacks;
3952 	t_u32 firmware_stat;
3953 	t_u32 tries;
3954 
3955 	ENTER();
3956 
3957 	/* Wait for firmware initialization event */
3958 	for (tries = 0; tries < pollnum; tries++) {
3959 		if (pcb->moal_read_reg(pmadapter->pmoal_handle,
3960 				       pmadapter->pcard_pcie->reg->reg_scratch_3,
3961 				       &firmware_stat))
3962 			ret = MLAN_STATUS_FAILURE;
3963 		else
3964 			ret = MLAN_STATUS_SUCCESS;
3965 		if (ret)
3966 			continue;
3967 		if (firmware_stat == PCIE_FIRMWARE_READY) {
3968 			ret = MLAN_STATUS_SUCCESS;
3969 			break;
3970 		} else {
3971 			wlan_mdelay(pmadapter, 10);
3972 			ret = MLAN_STATUS_FAILURE;
3973 		}
3974 	}
3975 
3976 	LEAVE();
3977 	return ret;
3978 }
3979 
3980 /**
3981  *  @brief This function init the pcie interface
3982  *
3983  *  @param pmadapter  A pointer to mlan_adapter structure
3984  *
3985  *  @return           MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
3986  */
wlan_pcie_init(mlan_adapter * pmadapter)3987 mlan_status wlan_pcie_init(mlan_adapter *pmadapter)
3988 {
3989 	ENTER();
3990 
3991 	PRINTM(MINFO, "Setting driver ready signature\n");
3992 	if (wlan_set_drv_ready_reg(pmadapter, PCIE_FIRMWARE_READY)) {
3993 		PRINTM(MERROR, "Failed to write driver ready signature\n");
3994 		LEAVE();
3995 		return MLAN_STATUS_FAILURE;
3996 	}
3997 	LEAVE();
3998 	return MLAN_STATUS_SUCCESS;
3999 }
4000 
4001 /**
4002  *  @brief  This function downloads firmware to card
4003  *
4004  *  @param pmadapter	A pointer to mlan_adapter
4005  *  @param pmfw			A pointer to firmware image
4006  *
4007  *  @return		MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
4008  */
wlan_pcie_dnld_fw(pmlan_adapter pmadapter,pmlan_fw_image pmfw)4009 static mlan_status wlan_pcie_dnld_fw(pmlan_adapter pmadapter,
4010 				     pmlan_fw_image pmfw)
4011 {
4012 	mlan_status ret = MLAN_STATUS_SUCCESS;
4013 	t_u32 poll_num = 1;
4014 	t_u32 winner = 0;
4015 
4016 	ENTER();
4017 
4018 	ret = wlan_pcie_init(pmadapter);
4019 	if (ret == MLAN_STATUS_FAILURE) {
4020 		PRINTM(MERROR, "WLAN PCIE init failed\n", ret);
4021 		LEAVE();
4022 		return ret;
4023 	}
4024 	/* Check if firmware is already running */
4025 	ret = wlan_pcie_check_fw_status(pmadapter, poll_num);
4026 	if (ret == MLAN_STATUS_SUCCESS) {
4027 		PRINTM(MMSG, "WLAN FW already running! Skip FW download\n");
4028 		goto done;
4029 	}
4030 	poll_num = MAX_FIRMWARE_POLL_TRIES;
4031 
4032 	/* Check if other interface is downloading */
4033 	ret = wlan_pcie_check_winner_status(pmadapter, &winner);
4034 	if (ret == MLAN_STATUS_FAILURE) {
4035 		PRINTM(MFATAL, "WLAN read winner status failed!\n");
4036 		goto done;
4037 	}
4038 	if (winner) {
4039 		PRINTM(MMSG,
4040 		       "WLAN is not the winner (0x%x). Skip FW download\n",
4041 		       winner);
4042 		poll_num = MAX_MULTI_INTERFACE_POLL_TRIES;
4043 		goto poll_fw;
4044 	}
4045 
4046 	/* Download the firmware image via helper */
4047 	ret = wlan_pcie_prog_fw_w_helper(pmadapter, pmfw);
4048 	if (ret != MLAN_STATUS_SUCCESS) {
4049 		PRINTM(MERROR, "prog_fw failed ret=%#x\n", ret);
4050 		LEAVE();
4051 		return ret;
4052 	}
4053 poll_fw:
4054 	/* Check if the firmware is downloaded successfully or not */
4055 	ret = wlan_pcie_check_fw_status(pmadapter, poll_num);
4056 	if (ret != MLAN_STATUS_SUCCESS) {
4057 		PRINTM(MFATAL, "FW failed to be active in time!\n");
4058 		ret = MLAN_STATUS_FAILURE;
4059 		LEAVE();
4060 		return ret;
4061 	}
4062 done:
4063 
4064 	/* re-enable host interrupt for mlan after fw dnld is successful */
4065 	wlan_enable_pcie_host_int(pmadapter);
4066 
4067 	LEAVE();
4068 	return ret;
4069 }
4070 
4071 /**
4072  *  @brief This function downloads data from driver to card.
4073  *
4074  *  Both commands and data packets are transferred to the card
4075  *  by this function. This function adds the PCIE specific header
4076  *  to the front of the buffer before transferring. The header
4077  *  contains the length of the packet and the type. The firmware
4078  *  handles the packets based upon this set type.
4079  *
4080  *  @param pmpriv    A pointer to mlan_private structure
4081  *  @param type	     data or command
4082  *  @param pmbuf     A pointer to mlan_buffer (pmbuf->data_len should include
4083  * PCIE header)
4084  *  @param tx_param  A pointer to mlan_tx_param (can be MNULL if type is
4085  * command)
4086  *
4087  *  @return 	     MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
4088  */
wlan_pcie_host_to_card(pmlan_private pmpriv,t_u8 type,mlan_buffer * pmbuf,mlan_tx_param * tx_param)4089 mlan_status wlan_pcie_host_to_card(pmlan_private pmpriv, t_u8 type,
4090 				   mlan_buffer *pmbuf, mlan_tx_param *tx_param)
4091 {
4092 	mlan_status ret = MLAN_STATUS_SUCCESS;
4093 	pmlan_adapter pmadapter = pmpriv->adapter;
4094 
4095 	ENTER();
4096 
4097 	if (!pmbuf) {
4098 		PRINTM(MERROR, "Passed NULL pmbuf to %s\n", __FUNCTION__);
4099 		return MLAN_STATUS_FAILURE;
4100 	}
4101 
4102 	if (type == MLAN_TYPE_DATA)
4103 		ret = wlan_pcie_send_data(pmadapter, type, pmbuf, tx_param);
4104 	else if (type == MLAN_TYPE_CMD)
4105 		ret = wlan_pcie_send_cmd(pmadapter, pmbuf);
4106 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
4107 	else if (type == MLAN_TYPE_VDLL)
4108 		ret = wlan_pcie_send_vdll(pmadapter, pmbuf);
4109 #endif
4110 	LEAVE();
4111 	return ret;
4112 }
4113 
4114 /**
4115  *  @brief This function allocates the PCIE buffer for SSU
4116  *
4117  *  @param pmadapter  A pointer to mlan_adapter structure
4118  *
4119  *  @return           MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
4120  */
wlan_alloc_ssu_pcie_buf(pmlan_adapter pmadapter)4121 mlan_status wlan_alloc_ssu_pcie_buf(pmlan_adapter pmadapter)
4122 {
4123 	mlan_status ret = MLAN_STATUS_SUCCESS;
4124 	pmlan_callbacks pcb = &pmadapter->callbacks;
4125 	mlan_buffer *pmbuf = MNULL;
4126 	/** Virtual base address of ssu buffer */
4127 	t_u8 *ssu_vbase;
4128 	/** Physical base address of ssu buffer */
4129 	t_u64 ssu_pbase = 0;
4130 
4131 	ENTER();
4132 
4133 	if (pmadapter->ssu_buf) {
4134 		PRINTM(MCMND, "ssu buffer already allocated\n");
4135 		LEAVE();
4136 		return ret;
4137 	}
4138 	/* Allocate buffer here so that firmware can DMA data on it */
4139 	pmbuf = wlan_alloc_mlan_buffer(pmadapter, 0, 0, MOAL_MALLOC_BUFFER);
4140 	if (!pmbuf) {
4141 		PRINTM(MERROR,
4142 		       "SSU buffer create : Unable to allocate mlan_buffer\n");
4143 		LEAVE();
4144 		return MLAN_STATUS_FAILURE;
4145 	}
4146 	ret = pcb->moal_malloc_consistent(pmadapter->pmoal_handle,
4147 					  MLAN_SSU_BUF_SIZE, &ssu_vbase,
4148 					  &ssu_pbase);
4149 
4150 	if (ret != MLAN_STATUS_SUCCESS) {
4151 		PRINTM(MERROR, "%s: No free moal_malloc_consistent\n",
4152 		       __FUNCTION__);
4153 		/* free pmbuf */
4154 		wlan_free_mlan_buffer(pmadapter, pmbuf);
4155 		LEAVE();
4156 		return MLAN_STATUS_FAILURE;
4157 	}
4158 
4159 	pmbuf->buf_pa = ssu_pbase;
4160 	pmbuf->pbuf = ssu_vbase;
4161 	pmbuf->data_offset = 0;
4162 	pmbuf->data_len = MLAN_SSU_BUF_SIZE;
4163 	pmbuf->total_pcie_buf_len = MLAN_SSU_BUF_SIZE;
4164 
4165 	PRINTM(MCMND,
4166 	       "SSU buffer: add new mlan_buffer base: %p, "
4167 	       "buf_base: %p, data_offset: %x, buf_pbase: %#x:%x, "
4168 	       "buf_len: %#x\n",
4169 	       pmbuf, pmbuf->pbuf, pmbuf->data_offset,
4170 	       (t_u32)((t_u64)pmbuf->buf_pa >> 32), (t_u32)pmbuf->buf_pa,
4171 	       pmbuf->data_len);
4172 
4173 	pmadapter->ssu_buf = pmbuf;
4174 
4175 	LEAVE();
4176 	return ret;
4177 }
4178 
4179 /**
4180  *  @brief This function frees the allocated ssu buffer.
4181  *
4182  *  @param pmadapter  A pointer to mlan_adapter structure
4183  *
4184  *  @return           MLAN_STATUS_SUCCESS
4185  */
wlan_free_ssu_pcie_buf(pmlan_adapter pmadapter)4186 mlan_status wlan_free_ssu_pcie_buf(pmlan_adapter pmadapter)
4187 {
4188 	pmlan_callbacks pcb = &pmadapter->callbacks;
4189 	mlan_buffer *pmbuf = MNULL;
4190 	t_u8 *ssu_vbase;
4191 	t_u64 ssu_pbase;
4192 
4193 	ENTER();
4194 	if (!pmadapter) {
4195 		LEAVE();
4196 		return MLAN_STATUS_FAILURE;
4197 	}
4198 
4199 	if (pmadapter->ssu_buf) {
4200 		pmbuf = pmadapter->ssu_buf;
4201 		ssu_vbase = pmbuf->pbuf;
4202 		ssu_pbase = pmbuf->buf_pa;
4203 		if (ssu_vbase)
4204 			pcb->moal_mfree_consistent(pmadapter->pmoal_handle,
4205 						   pmbuf->total_pcie_buf_len,
4206 						   ssu_vbase, ssu_pbase);
4207 		wlan_free_mlan_buffer(pmadapter, pmbuf);
4208 	}
4209 	pmadapter->ssu_buf = MNULL;
4210 
4211 	LEAVE();
4212 	return MLAN_STATUS_SUCCESS;
4213 }
4214 
4215 /**
4216  *  @brief This function allocates the PCIE ring buffers
4217  *
4218  *  The following initializations steps are followed -
4219  *      - Allocate TXBD ring buffers
4220  *      - Allocate RXBD ring buffers
4221  *      - Allocate event BD ring buffers
4222  *      - Allocate command and command response buffer
4223  *      - Allocate sleep cookie buffer
4224  *
4225  *  @param pmadapter  A pointer to mlan_adapter structure
4226  *
4227  *  @return           MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
4228  */
wlan_alloc_pcie_ring_buf(pmlan_adapter pmadapter)4229 mlan_status wlan_alloc_pcie_ring_buf(pmlan_adapter pmadapter)
4230 {
4231 	mlan_status ret = MLAN_STATUS_SUCCESS;
4232 
4233 	ENTER();
4234 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
4235 	if ((pmadapter->card_type == CARD_TYPE_PCIE9098) ||
4236 	    (pmadapter->card_type == CARD_TYPE_PCIENW62X) ||
4237 	    (pmadapter->card_type == CARD_TYPE_PCIE9097)) {
4238 		wlan_pcie_init_adma_ring_size(pmadapter);
4239 	}
4240 #endif
4241 	pmadapter->pcard_pcie->cmdrsp_buf = MNULL;
4242 	ret = wlan_pcie_create_txbd_ring(pmadapter);
4243 	if (ret)
4244 		goto err_cre_txbd;
4245 	ret = wlan_pcie_create_rxbd_ring(pmadapter);
4246 	if (ret)
4247 		goto err_cre_rxbd;
4248 	ret = wlan_pcie_create_evtbd_ring(pmadapter);
4249 	if (ret)
4250 		goto err_cre_evtbd;
4251 	ret = wlan_pcie_alloc_cmdrsp_buf(pmadapter);
4252 	if (ret)
4253 		goto err_alloc_cmdbuf;
4254 	return ret;
4255 err_alloc_cmdbuf:
4256 	wlan_pcie_delete_evtbd_ring(pmadapter);
4257 err_cre_evtbd:
4258 	wlan_pcie_delete_rxbd_ring(pmadapter);
4259 err_cre_rxbd:
4260 	wlan_pcie_delete_txbd_ring(pmadapter);
4261 err_cre_txbd:
4262 
4263 	LEAVE();
4264 	return ret;
4265 }
4266 
4267 /**
4268  *  @brief This function frees the allocated ring buffers.
4269  *
4270  *  The following are freed by this function -
4271  *      - TXBD ring buffers
4272  *      - RXBD ring buffers
4273  *      - Event BD ring buffers
4274  *      - Command and command response buffer
4275  *      - Sleep cookie buffer
4276  *
4277  *  @param pmadapter  A pointer to mlan_adapter structure
4278  *
4279  *  @return           MLAN_STATUS_SUCCESS
4280  */
wlan_free_pcie_ring_buf(pmlan_adapter pmadapter)4281 mlan_status wlan_free_pcie_ring_buf(pmlan_adapter pmadapter)
4282 {
4283 	ENTER();
4284 
4285 	wlan_pcie_delete_cmdrsp_buf(pmadapter);
4286 	wlan_pcie_delete_evtbd_ring(pmadapter);
4287 	wlan_pcie_delete_rxbd_ring(pmadapter);
4288 	wlan_pcie_delete_txbd_ring(pmadapter);
4289 	pmadapter->pcard_pcie->cmdrsp_buf = MNULL;
4290 #ifdef RPTR_MEM_COP
4291 	if ((pmadapter->card_type == CARD_TYPE_PCIE9098) ||
4292 	    (pmadapter->card_type ==
4293 	     CARD_TYPE_PCIENW62X)(pmadapter->card_type == CARD_TYPE_PCIE9097))
4294 		wlan_pcie_free_rdptrs(pmadapter);
4295 #endif
4296 
4297 	LEAVE();
4298 	return MLAN_STATUS_SUCCESS;
4299 }
4300 
4301 /**
4302  *  @brief This function cleans up packets in the ring buffers.
4303  *
4304  *  The following are cleaned by this function -
4305  *      - TXBD ring buffers
4306  *
4307  *  @param pmadapter  A pointer to mlan_adapter structure
4308  *
4309  *  @return           MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
4310  */
wlan_clean_pcie_ring_buf(pmlan_adapter pmadapter)4311 mlan_status wlan_clean_pcie_ring_buf(pmlan_adapter pmadapter)
4312 {
4313 	ENTER();
4314 #if defined(PCIE8997) || defined(PCIE8897)
4315 	if (!pmadapter->pcard_pcie->reg->use_adma)
4316 		wlan_pcie_flush_txbd_ring(pmadapter);
4317 #endif
4318 	LEAVE();
4319 	return MLAN_STATUS_SUCCESS;
4320 }
4321 
4322 /**
4323  *  @brief This function prepares command to set PCI-Express
4324  *  host buffer configuration
4325  *
4326  *  @param pmpriv       A pointer to mlan_private structure
4327  *
4328  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
4329  */
wlan_set_pcie_buf_config(mlan_private * pmpriv)4330 mlan_status wlan_set_pcie_buf_config(mlan_private *pmpriv)
4331 {
4332 	pmlan_adapter pmadapter = MNULL;
4333 #if defined(PCIE8997) || defined(PCIE8897)
4334 	HostCmd_DS_PCIE_HOST_BUF_DETAILS host_spec;
4335 #endif
4336 	mlan_status ret = MLAN_STATUS_SUCCESS;
4337 
4338 	ENTER();
4339 	if (!pmpriv) {
4340 		LEAVE();
4341 		return MLAN_STATUS_FAILURE;
4342 	}
4343 	pmadapter = pmpriv->adapter;
4344 #if defined(PCIE8997) || defined(PCIE8897)
4345 	if (!pmadapter->pcard_pcie->reg->use_adma) {
4346 		memset(pmadapter, &host_spec, 0,
4347 		       sizeof(HostCmd_DS_PCIE_HOST_BUF_DETAILS));
4348 
4349 		/* Send the ring base addresses and count to firmware */
4350 		host_spec.txbd_addr_lo = wlan_cpu_to_le32(
4351 			(t_u32)(pmadapter->pcard_pcie->txbd_ring_pbase));
4352 		host_spec.txbd_addr_hi = wlan_cpu_to_le32((t_u32)(
4353 			((t_u64)pmadapter->pcard_pcie->txbd_ring_pbase) >> 32));
4354 		host_spec.txbd_count =
4355 			wlan_cpu_to_le32(pmadapter->pcard_pcie->txrx_bd_size);
4356 		host_spec.rxbd_addr_lo = wlan_cpu_to_le32(
4357 			(t_u32)(pmadapter->pcard_pcie->rxbd_ring_pbase));
4358 		host_spec.rxbd_addr_hi = wlan_cpu_to_le32((t_u32)(
4359 			((t_u64)pmadapter->pcard_pcie->rxbd_ring_pbase) >> 32));
4360 		host_spec.rxbd_count =
4361 			wlan_cpu_to_le32(pmadapter->pcard_pcie->txrx_bd_size);
4362 		host_spec.evtbd_addr_lo = wlan_cpu_to_le32(
4363 			(t_u32)(pmadapter->pcard_pcie->evtbd_ring_pbase));
4364 		host_spec.evtbd_addr_hi = wlan_cpu_to_le32((t_u32)(
4365 			((t_u64)pmadapter->pcard_pcie->evtbd_ring_pbase) >>
4366 			32));
4367 		host_spec.evtbd_count = wlan_cpu_to_le32(MLAN_MAX_EVT_BD);
4368 
4369 		ret = wlan_prepare_cmd(pmpriv,
4370 				       HostCmd_CMD_PCIE_HOST_BUF_DETAILS,
4371 				       HostCmd_ACT_GEN_SET, 0, MNULL,
4372 				       &host_spec);
4373 		if (ret) {
4374 			PRINTM(MERROR,
4375 			       "PCIE_HOST_BUF_CFG: send command failed\n");
4376 			ret = MLAN_STATUS_FAILURE;
4377 		}
4378 	}
4379 #endif
4380 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
4381 	if (pmadapter->pcard_pcie->reg->use_adma) {
4382 		/** config ADMA for Tx Data */
4383 		wlan_init_adma(pmadapter, ADMA_TX_DATA,
4384 			       pmadapter->pcard_pcie->txbd_ring_pbase,
4385 			       pmadapter->pcard_pcie->txrx_num_desc, MTRUE);
4386 		/** config ADMA for Rx Data */
4387 		wlan_init_adma(pmadapter, ADMA_RX_DATA,
4388 			       pmadapter->pcard_pcie->rxbd_ring_pbase,
4389 			       pmadapter->pcard_pcie->txrx_num_desc, MTRUE);
4390 		/** config ADMA for Rx Event */
4391 		wlan_init_adma(pmadapter, ADMA_EVENT,
4392 			       pmadapter->pcard_pcie->evtbd_ring_pbase,
4393 			       EVT_NUM_DESC, MTRUE);
4394 		/** config ADMA for cmd */
4395 		wlan_init_adma(pmadapter, ADMA_CMD, 0, 0, MTRUE);
4396 		/** config ADMA for cmdresp */
4397 		wlan_init_adma(pmadapter, ADMA_CMDRESP,
4398 			       pmadapter->pcard_pcie->cmdrsp_buf->buf_pa, 0,
4399 			       MTRUE);
4400 	}
4401 #endif
4402 	wlan_pcie_init_fw(pmadapter);
4403 	LEAVE();
4404 	return ret;
4405 }
4406 
4407 #if defined(PCIE8997) || defined(PCIE8897)
4408 /**
4409  *  @brief This function prepares command PCIE host buffer config.
4410  *
4411  *  @param pmpriv       A pointer to mlan_private structure
4412  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
4413  *  @param cmd_action   The action: GET or SET
4414  *  @param pdata_buf    A pointer to data buffer
4415  *
4416  *  @return             MLAN_STATUS_SUCCESS
4417  */
wlan_cmd_pcie_host_buf_cfg(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_u16 cmd_action,t_pvoid pdata_buf)4418 mlan_status wlan_cmd_pcie_host_buf_cfg(pmlan_private pmpriv,
4419 				       HostCmd_DS_COMMAND *cmd,
4420 				       t_u16 cmd_action, t_pvoid pdata_buf)
4421 {
4422 	HostCmd_DS_PCIE_HOST_BUF_DETAILS *ppcie_hoost_spec =
4423 		&cmd->params.pcie_host_spec;
4424 
4425 	ENTER();
4426 
4427 	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_PCIE_HOST_BUF_DETAILS);
4428 	cmd->size = wlan_cpu_to_le16(
4429 		(sizeof(HostCmd_DS_PCIE_HOST_BUF_DETAILS)) + S_DS_GEN);
4430 
4431 	if (cmd_action == HostCmd_ACT_GEN_SET) {
4432 		memcpy_ext(pmpriv->adapter, ppcie_hoost_spec, pdata_buf,
4433 			   sizeof(HostCmd_DS_PCIE_HOST_BUF_DETAILS),
4434 			   sizeof(HostCmd_DS_PCIE_HOST_BUF_DETAILS));
4435 	}
4436 
4437 	LEAVE();
4438 	return MLAN_STATUS_SUCCESS;
4439 }
4440 #endif
4441 
4442 /**
4443  *  @brief This function wakes up the card.
4444  *
4445  *  @param pmadapter		A pointer to mlan_adapter structure
4446  *  @param timeout          set timeout flag
4447  *
4448  *  @return			MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
4449  */
wlan_pm_pcie_wakeup_card(pmlan_adapter pmadapter,t_u8 timeout)4450 static mlan_status wlan_pm_pcie_wakeup_card(pmlan_adapter pmadapter,
4451 					    t_u8 timeout)
4452 {
4453 	mlan_status ret = MLAN_STATUS_SUCCESS;
4454 	t_u32 age_ts_usec;
4455 
4456 	ENTER();
4457 	PRINTM(MEVENT, "func%d: Wakeup device...\n",
4458 	       pmadapter->pcard_pcie->func_num);
4459 	pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle,
4460 						  &pmadapter->pm_wakeup_in_secs,
4461 						  &age_ts_usec);
4462 
4463 	if (timeout) {
4464 		pmadapter->callbacks.moal_start_timer(
4465 			pmadapter->pmoal_handle, pmadapter->pwakeup_fw_timer,
4466 			MFALSE, MRVDRV_TIMER_3S);
4467 		pmadapter->wakeup_fw_timer_is_set = MTRUE;
4468 	}
4469 
4470 	ret = wlan_pcie_wakeup(pmadapter);
4471 
4472 	LEAVE();
4473 	return ret;
4474 }
4475 
wlan_pcie_debug_dump(pmlan_adapter pmadapter)4476 static mlan_status wlan_pcie_debug_dump(pmlan_adapter pmadapter)
4477 {
4478 	mlan_status ret = MLAN_STATUS_SUCCESS;
4479 	pmlan_buffer pmbuf = pmadapter->pcard_pcie->cmdrsp_buf;
4480 	ENTER();
4481 
4482 	if (pmbuf == MNULL) {
4483 		PRINTM(MMSG, "Rx CMD response pmbuf is null\n");
4484 		LEAVE();
4485 		return MLAN_STATUS_FAILURE;
4486 	}
4487 	PRINTM(MERROR, "Dump Rx CMD Response Buf:\n");
4488 	DBG_HEXDUMP(MERROR, "CmdResp Buf", pmbuf->pbuf + pmbuf->data_offset,
4489 		    64);
4490 
4491 	LEAVE();
4492 	return ret;
4493 }
4494 
4495 /**
4496  *  @brief This function handle data complete
4497  *
4498  *  @param pmadapter A pointer to mlan_adapter structure
4499  *  @param pmbuf     A pointer to the mlan_buffer
4500  *  @return          N/A
4501  */
wlan_pcie_data_complete(pmlan_adapter pmadapter,mlan_buffer * pmbuf,mlan_status status)4502 static mlan_status wlan_pcie_data_complete(pmlan_adapter pmadapter,
4503 					   mlan_buffer *pmbuf,
4504 					   mlan_status status)
4505 {
4506 	ENTER();
4507 
4508 	wlan_free_mlan_buffer(pmadapter, pmbuf);
4509 
4510 	LEAVE();
4511 	return MLAN_STATUS_SUCCESS;
4512 }
4513 
4514 mlan_adapter_operations mlan_pcie_ops = {
4515 	.dnld_fw = wlan_pcie_dnld_fw,
4516 	.interrupt = wlan_pcie_interrupt,
4517 	.process_int_status = wlan_process_pcie_int_status,
4518 	.host_to_card = wlan_pcie_host_to_card,
4519 	.wakeup_card = wlan_pm_pcie_wakeup_card,
4520 	.reset_card = wlan_pcie_wakeup,
4521 	.event_complete = wlan_pcie_event_complete,
4522 	.data_complete = wlan_pcie_data_complete,
4523 	.cmdrsp_complete = wlan_pcie_cmdrsp_complete,
4524 	.handle_rx_packet = wlan_handle_rx_packet,
4525 	.debug_dump = wlan_pcie_debug_dump,
4526 	.intf_header_len = PCIE_INTF_HEADER_LEN,
4527 };
4528