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