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