xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/rtl8822b/pci/rtl8822be_ops.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /******************************************************************************
2  *
3  * Copyright(c) 2015 - 2016 Realtek Corporation. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along with
15  * this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
17  *
18  *
19  ******************************************************************************/
20 
21 #define _HCI_OPS_OS_C_
22 
23 #include <drv_types.h>		/* PADAPTER, basic_types.h and etc. */
24 #include <hal_data.h>		/* HAL_DATA_TYPE, GET_HAL_DATA() and etc. */
25 #include <hal_intf.h>		/* struct hal_ops */
26 #include "../rtl8822b.h"
27 #include "rtl8822be.h"
28 
init_bd_ring_var(_adapter * padapter)29 static void init_bd_ring_var(_adapter *padapter)
30 {
31 	struct recv_priv *r_priv = &padapter->recvpriv;
32 	struct xmit_priv *t_priv = &padapter->xmitpriv;
33 	u8 i = 0;
34 
35 	for (i = 0; i < HW_QUEUE_ENTRY; i++)
36 		t_priv->txringcount[i] = TX_BD_NUM_8822BE;
37 
38 	/*
39 	 * we just alloc 2 desc for beacon queue,
40 	 * because we just need first desc in hw beacon.
41 	 */
42 	t_priv->txringcount[BCN_QUEUE_INX] = TX_BD_NUM_8822BE_BCN;
43 	t_priv->txringcount[TXCMD_QUEUE_INX] = TX_BD_NUM_8822BE_CMD;
44 
45 	/*
46 	 * BE queue need more descriptor for performance consideration
47 	 * or, No more tx desc will happen, and may cause mac80211 mem leakage.
48 	 */
49 	r_priv->rxbuffersize = MAX_RECVBUF_SZ;
50 	r_priv->rxringcount = PCI_MAX_RX_COUNT;
51 }
52 
rtl8822be_reset_bd(_adapter * padapter)53 static void rtl8822be_reset_bd(_adapter *padapter)
54 {
55 	_irqL	irqL;
56 	struct xmit_priv *t_priv = &padapter->xmitpriv;
57 	struct recv_priv *r_priv = &padapter->recvpriv;
58 	struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
59 	struct xmit_buf	*pxmitbuf = NULL;
60 	u8 *tx_bd, *rx_bd;
61 	int i, rx_queue_idx;
62 
63 	for (rx_queue_idx = 0; rx_queue_idx < 1; rx_queue_idx++) {
64 		if (r_priv->rx_ring[rx_queue_idx].buf_desc) {
65 			rx_bd = NULL;
66 			for (i = 0; i < r_priv->rxringcount; i++) {
67 				rx_bd = (u8 *)
68 					&r_priv->rx_ring[rx_queue_idx].buf_desc[i];
69 			}
70 			r_priv->rx_ring[rx_queue_idx].idx = 0;
71 		}
72 	}
73 
74 	_enter_critical(&pdvobjpriv->irq_th_lock, &irqL);
75 	for (i = 0; i < PCI_MAX_TX_QUEUE_COUNT; i++) {
76 		if (t_priv->tx_ring[i].buf_desc) {
77 			struct rtw_tx_ring *ring = &t_priv->tx_ring[i];
78 
79 			while (ring->qlen) {
80 				tx_bd = (u8 *)(&ring->buf_desc[ring->idx]);
81 				SET_TX_BD_OWN(tx_bd, 0);
82 
83 				if (i != BCN_QUEUE_INX)
84 					ring->idx =
85 						(ring->idx + 1) % ring->entries;
86 
87 				pxmitbuf = rtl8822be_dequeue_xmitbuf(ring);
88 				if (pxmitbuf) {
89 					pci_unmap_single(pdvobjpriv->ppcidev,
90 						GET_TX_BD_PHYSICAL_ADDR0_LOW(tx_bd),
91 						pxmitbuf->len, PCI_DMA_TODEVICE);
92 					rtw_free_xmitbuf(t_priv, pxmitbuf);
93 				} else {
94 					RTW_INFO("%s(): qlen(%d) is not zero, but have xmitbuf in pending queue\n",
95 						 __func__, ring->qlen);
96 					break;
97 				}
98 			}
99 			ring->idx = 0;
100 		}
101 	}
102 	_exit_critical(&pdvobjpriv->irq_th_lock, &irqL);
103 }
104 
intf_chip_configure(PADAPTER Adapter)105 static void intf_chip_configure(PADAPTER Adapter)
106 {
107 	HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);
108 	struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(Adapter);
109 	struct pwrctrl_priv *pwrpriv = dvobj_to_pwrctl(pdvobjpriv);
110 
111 
112 	/* close ASPM for AMD defaultly */
113 	pdvobjpriv->const_amdpci_aspm = 0;
114 
115 	/* ASPM PS mode. */
116 	/* 0 - Disable ASPM, 1 - Enable ASPM without Clock Req, */
117 	/* 2 - Enable ASPM with Clock Req, 3- Alwyas Enable ASPM with Clock Req, */
118 	/* 4-  Always Enable ASPM without Clock Req. */
119 	/* set defult to rtl8188ee:3 RTL8192E:2 */
120 	pdvobjpriv->const_pci_aspm = 0;
121 
122 	/* Setting for PCI-E device */
123 	pdvobjpriv->const_devicepci_aspm_setting = 0x03;
124 
125 	/* Setting for PCI-E bridge */
126 	pdvobjpriv->const_hostpci_aspm_setting = 0x03;
127 
128 	/* In Hw/Sw Radio Off situation. */
129 	/* 0 - Default, 1 - From ASPM setting without low Mac Pwr, */
130 	/* 2 - From ASPM setting with low Mac Pwr, 3 - Bus D3 */
131 	/* set default to RTL8192CE:0 RTL8192SE:2 */
132 	pdvobjpriv->const_hwsw_rfoff_d3 = 0;
133 
134 	/* This setting works for those device with backdoor ASPM setting such as EPHY setting. */
135 	/* 0: Not support ASPM, 1: Support ASPM, 2: According to chipset. */
136 	pdvobjpriv->const_support_pciaspm = 1;
137 
138 	pwrpriv->reg_rfoff = 0;
139 	pwrpriv->rfoff_reason = 0;
140 
141 	pHalData->bL1OffSupport = _FALSE;
142 }
143 
144 /*
145  * Description:
146  *	Collect all hardware information, fill "HAL_DATA_TYPE".
147  *	Sometimes this would be used to read MAC address.
148  *	This function will do
149  *	1. Read Efuse/EEPROM to initialize
150  *	2. Read registers to initialize
151  *	3. Other vaiables initialization
152  */
read_adapter_info(PADAPTER padapter)153 static u8 read_adapter_info(PADAPTER padapter)
154 {
155 	/*
156 	 * 1. Read Efuse/EEPROM to initialize
157 	 */
158 	if (rtl8822b_read_efuse(padapter) == _FAIL)
159 		return _FAIL;
160 
161 	/*
162 	 * 2. Read registers to initialize
163 	 */
164 
165 	/*
166 	 * 3. Other Initialization
167 	 */
168 	return _SUCCESS;
169 }
170 
171 #ifndef CONFIG_NAPI
rtl8822be_InterruptRecognized(PADAPTER Adapter)172 static BOOLEAN rtl8822be_InterruptRecognized(PADAPTER Adapter)
173 {
174 	HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);
175 	BOOLEAN bRecognized = _FALSE;
176 
177 	/* 2013.11.18 Glayrainx suggests that turn off IMR and
178 	 * restore after cleaning ISR.
179 	 */
180 	rtw_write32(Adapter, REG_HIMR0, 0);
181 	rtw_write32(Adapter, REG_HIMR1, 0);
182 	rtw_write32(Adapter, REG_HIMR3, 0);
183 
184 	pHalData->IntArray[0] = rtw_read32(Adapter, REG_HISR0);
185 	pHalData->IntArray[0] &= pHalData->IntrMask[0];
186 	rtw_write32(Adapter, REG_HISR0, pHalData->IntArray[0]);
187 
188 	/* For HISR extension. Added by tynli. 2009.10.07. */
189 	pHalData->IntArray[1] = rtw_read32(Adapter, REG_HISR1);
190 	pHalData->IntArray[1] &= pHalData->IntrMask[1];
191 	rtw_write32(Adapter, REG_HISR1, pHalData->IntArray[1]);
192 
193 	/* for H2C cmd queue */
194 	pHalData->IntArray[3] = rtw_read32(Adapter, REG_HISR3);
195 	pHalData->IntArray[3] &= pHalData->IntrMask[3];
196 	rtw_write32(Adapter, REG_HISR3, pHalData->IntArray[3]);
197 
198 	if (((pHalData->IntArray[0]) & pHalData->IntrMask[0]) != 0 ||
199 	    ((pHalData->IntArray[1]) & pHalData->IntrMask[1]) != 0)
200 		bRecognized = _TRUE;
201 
202 	/* restore IMR */
203 	rtw_write32(Adapter, REG_HIMR0, pHalData->IntrMask[0] & 0xFFFFFFFF);
204 	rtw_write32(Adapter, REG_HIMR1, pHalData->IntrMask[1] & 0xFFFFFFFF);
205 	rtw_write32(Adapter, REG_HIMR3, pHalData->IntrMask[3] & 0xFFFFFFFF);
206 
207 	return bRecognized;
208 }
209 #endif
210 
DisableInterrupt8822be(PADAPTER Adapter)211 static VOID DisableInterrupt8822be(PADAPTER Adapter)
212 {
213 	struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(Adapter);
214 
215 	rtw_write32(Adapter, REG_HIMR0, 0x0);
216 	rtw_write32(Adapter, REG_HIMR1, 0x0);
217 	rtw_write32(Adapter, REG_HIMR3, 0x0);
218 	pdvobjpriv->irq_enabled = 0;
219 }
220 
rtl8822be_enable_interrupt(PADAPTER Adapter)221 static VOID rtl8822be_enable_interrupt(PADAPTER Adapter)
222 {
223 	HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);
224 	struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(Adapter);
225 
226 	pdvobjpriv->irq_enabled = 1;
227 
228 	rtw_write32(Adapter, REG_HIMR0, pHalData->IntrMask[0] & 0xFFFFFFFF);
229 	rtw_write32(Adapter, REG_HIMR1, pHalData->IntrMask[1] & 0xFFFFFFFF);
230 	rtw_write32(Adapter, REG_HIMR3, pHalData->IntrMask[3] & 0xFFFFFFFF);
231 
232 }
233 
rtl8822be_clear_interrupt(PADAPTER Adapter)234 static VOID rtl8822be_clear_interrupt(PADAPTER Adapter)
235 {
236 	u32 u32b;
237 	HAL_DATA_TYPE   *pHalData = GET_HAL_DATA(Adapter);
238 
239 	u32b = rtw_read32(Adapter, REG_HISR0_8822B);
240 	rtw_write32(Adapter, REG_HISR0_8822B, u32b);
241 	pHalData->IntArray[0] = 0;
242 
243 	u32b = rtw_read32(Adapter, REG_HISR1_8822B);
244 	rtw_write32(Adapter, REG_HISR1_8822B, u32b);
245 	pHalData->IntArray[1] = 0;
246 }
247 
rtl8822be_disable_interrupt(PADAPTER Adapter)248 static VOID rtl8822be_disable_interrupt(PADAPTER Adapter)
249 {
250 	struct dvobj_priv	*pdvobjpriv = adapter_to_dvobj(Adapter);
251 
252 	rtw_write32(Adapter, REG_HIMR0, 0x0);
253 	rtw_write32(Adapter, REG_HIMR1, 0x0);	/* by tynli */
254 	pdvobjpriv->irq_enabled = 0;
255 }
256 
UpdateInterruptMask8822BE(PADAPTER Adapter,u32 AddMSR,u32 AddMSR1,u32 RemoveMSR,u32 RemoveMSR1)257 VOID UpdateInterruptMask8822BE(PADAPTER Adapter, u32 AddMSR, u32 AddMSR1,
258 			       u32 RemoveMSR, u32 RemoveMSR1)
259 {
260 	PHAL_DATA_TYPE pHalData = GET_HAL_DATA(Adapter);
261 
262 	DisableInterrupt8822be(Adapter);
263 
264 	if (AddMSR)
265 		pHalData->IntrMask[0] |= AddMSR;
266 
267 	if (AddMSR1)
268 		pHalData->IntrMask[1] |= AddMSR1;
269 
270 	if (RemoveMSR)
271 		pHalData->IntrMask[0] &= (~RemoveMSR);
272 
273 	if (RemoveMSR1)
274 		pHalData->IntrMask[1] &= (~RemoveMSR1);
275 
276 #if 0 /* TODO */
277 	if (RemoveMSR3)
278 		pHalData->IntrMask[3] &= (~RemoveMSR3);
279 #endif
280 
281 	rtl8822be_enable_interrupt(Adapter);
282 }
283 
rtl8822be_bcn_handler(PADAPTER Adapter,u32 handled[])284 static void rtl8822be_bcn_handler(PADAPTER Adapter, u32 handled[])
285 {
286 	PHAL_DATA_TYPE pHalData = GET_HAL_DATA(Adapter);
287 
288 	if (pHalData->IntArray[0] & BIT_TXBCN0OK_MSK) {
289 		DBG_COUNTER(Adapter->int_logs.tbdok);
290 #ifdef CONFIG_BCN_ICF
291 		/* do nothing */
292 #else
293 		/* Modify for MI temporary,
294 		 * this processor cannot apply to multi-ap */
295 		PADAPTER bcn_adapter = rtw_mi_get_ap_adapter(Adapter);
296 
297 		if (bcn_adapter->xmitpriv.beaconDMAing) {
298 			bcn_adapter->xmitpriv.beaconDMAing = _FAIL;
299 			rtl8822be_tx_isr(Adapter, BCN_QUEUE_INX);
300 		}
301 #endif /* CONFIG_BCN_ICF */
302 		handled[0] |= BIT_TXBCN0OK_MSK;
303 	}
304 
305 	if (pHalData->IntArray[0] & BIT_TXBCN0ERR_MSK) {
306 		DBG_COUNTER(Adapter->int_logs.tbder);
307 #ifdef CONFIG_BCN_ICF
308 		RTW_INFO("IMR_TXBCN0ERR isr!\n");
309 #else /* !CONFIG_BCN_ICF */
310 		/* Modify for MI temporary,
311 		 * this processor cannot apply to multi-ap */
312 		PADAPTER bcn_adapter = rtw_mi_get_ap_adapter(Adapter);
313 
314 		if (bcn_adapter->xmitpriv.beaconDMAing) {
315 			bcn_adapter->xmitpriv.beaconDMAing = _FAIL;
316 			rtl8822be_tx_isr(Adapter, BCN_QUEUE_INX);
317 		}
318 #endif /* CONFIG_BCN_ICF */
319 		handled[0] |= BIT_TXBCN0ERR_MSK;
320 	}
321 
322 	if (pHalData->IntArray[0] & BIT_BCNDERR0_MSK) {
323 		DBG_COUNTER(Adapter->int_logs.bcnderr);
324 #ifdef CONFIG_BCN_ICF
325 		RTW_INFO("BIT_BCNDERR0_MSK isr!\n");
326 #else /* !CONFIG_BCN_ICF */
327 		/* Release resource and re-transmit beacon to HW */
328 		struct tasklet_struct  *bcn_tasklet;
329 		/* Modify for MI temporary,
330 		 * this processor cannot apply to multi-ap */
331 		PADAPTER bcn_adapter = rtw_mi_get_ap_adapter(Adapter);
332 
333 		rtl8822be_tx_isr(Adapter, BCN_QUEUE_INX);
334 		bcn_adapter->mlmepriv.update_bcn = _TRUE;
335 		bcn_tasklet = &bcn_adapter->recvpriv.irq_prepare_beacon_tasklet;
336 		tasklet_hi_schedule(bcn_tasklet);
337 #endif /* CONFIG_BCN_ICF */
338 		handled[0] |= BIT_BCNDERR0_MSK;
339 	}
340 
341 	if (pHalData->IntArray[0] & BIT_BCNDMAINT0_MSK) {
342 		struct tasklet_struct  *bcn_tasklet;
343 		/* Modify for MI temporary,
344 		  this processor cannot apply to multi-ap */
345 		PADAPTER bcn_adapter = rtw_mi_get_ap_adapter(Adapter);
346 
347 		DBG_COUNTER(Adapter->int_logs.bcndma);
348 		bcn_tasklet = &bcn_adapter->recvpriv.irq_prepare_beacon_tasklet;
349 		tasklet_hi_schedule(bcn_tasklet);
350 		handled[0] |= BIT_BCNDMAINT0_MSK;
351 	}
352 }
353 
354 #ifndef CONFIG_NAPI
rtl8822be_rx_handler(PADAPTER Adapter,u32 handled[])355 static void rtl8822be_rx_handler(PADAPTER Adapter, u32 handled[])
356 {
357 	PHAL_DATA_TYPE pHalData = GET_HAL_DATA(Adapter);
358 
359 	if ((pHalData->IntArray[0] & (BIT_RXOK | BIT_RDU)) ||
360 	    (pHalData->IntArray[1] & (BIT_FOVW | BIT_RXERR_INT))) {
361 		DBG_COUNTER(Adapter->int_logs.rx);
362 
363 		if (pHalData->IntArray[0] & BIT_RDU) {
364 			DBG_COUNTER(Adapter->int_logs.rx_rdu);
365 		}
366 
367 		if (pHalData->IntArray[1] & BIT_FOVW) {
368 			DBG_COUNTER(Adapter->int_logs.rx_fovw);
369 		}
370 
371 		pHalData->IntrMask[0] &= (~(BIT_RXOK_MSK | BIT_RDU_MSK));
372 		pHalData->IntrMask[1] &= (~(BIT_FOVW_MSK | BIT_RXERR_MSK));
373 		rtw_write32(Adapter, REG_HIMR0, pHalData->IntrMask[0]);
374 		rtw_write32(Adapter, REG_HIMR1, pHalData->IntrMask[1]);
375 		tasklet_hi_schedule(&Adapter->recvpriv.recv_tasklet);
376 		handled[0] |= pHalData->IntArray[0] & (BIT_RXOK | BIT_RDU);
377 		handled[1] |= pHalData->IntArray[1] & (BIT_FOVW | BIT_RXERR_INT);
378 	}
379 }
380 #endif
381 
rtl8822be_tx_handler(PADAPTER Adapter,u32 events[],u32 handled[])382 static void rtl8822be_tx_handler(PADAPTER Adapter, u32 events[], u32 handled[])
383 {
384 	PHAL_DATA_TYPE pHalData = GET_HAL_DATA(Adapter);
385 
386 	if (events[0] & BIT_MGTDOK_MSK) {
387 		DBG_COUNTER(Adapter->int_logs.mgntok);
388 		rtl8822be_tx_isr(Adapter, MGT_QUEUE_INX);
389 		handled[0] |= BIT_MGTDOK_MSK;
390 	}
391 
392 	if (events[0] & BIT_HIGHDOK_MSK) {
393 		DBG_COUNTER(Adapter->int_logs.highdok);
394 		rtl8822be_tx_isr(Adapter, HIGH_QUEUE_INX);
395 		handled[0] |= BIT_HIGHDOK_MSK;
396 	}
397 
398 	if (events[0] & BIT_BKDOK_MSK) {
399 		DBG_COUNTER(Adapter->int_logs.bkdok);
400 		rtl8822be_tx_isr(Adapter, BK_QUEUE_INX);
401 		handled[0] |= BIT_BKDOK_MSK;
402 	}
403 
404 	if (events[0] & BIT_BEDOK_MSK) {
405 		DBG_COUNTER(Adapter->int_logs.bedok);
406 		rtl8822be_tx_isr(Adapter, BE_QUEUE_INX);
407 		handled[0] |= BIT_BEDOK_MSK;
408 	}
409 
410 	if (events[0] & BIT_VIDOK_MSK) {
411 		DBG_COUNTER(Adapter->int_logs.vidok);
412 		rtl8822be_tx_isr(Adapter, VI_QUEUE_INX);
413 		handled[0] |= BIT_VIDOK_MSK;
414 	}
415 
416 	if (events[0] & BIT_VODOK_MSK) {
417 		DBG_COUNTER(Adapter->int_logs.vodok);
418 		rtl8822be_tx_isr(Adapter, VO_QUEUE_INX);
419 		handled[0] |= BIT_VODOK_MSK;
420 	}
421 }
422 
rtl8822be_cmd_handler(PADAPTER Adapter,u32 handled[])423 static void rtl8822be_cmd_handler(PADAPTER Adapter, u32 handled[])
424 {
425 	PHAL_DATA_TYPE pHalData = GET_HAL_DATA(Adapter);
426 
427 	if (pHalData->IntArray[3] & BIT_SETH2CDOK_MASK) {
428 		rtl8822be_tx_isr(Adapter, TXCMD_QUEUE_INX);
429 		handled[3] |= BIT_SETH2CDOK_MASK;
430 	}
431 }
432 
433 #ifndef CONFIG_NAPI
rtl8822be_interrupt(PADAPTER Adapter)434 static s32 rtl8822be_interrupt(PADAPTER Adapter)
435 {
436 	_irqL irqL;
437 	HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);
438 	struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(Adapter);
439 	struct xmit_priv *t_priv = &Adapter->xmitpriv;
440 	int ret = _SUCCESS;
441 	u32 handled[4] = {0};
442 
443 	_enter_critical(&pdvobjpriv->irq_th_lock, &irqL);
444 
445 	DBG_COUNTER(Adapter->int_logs.all);
446 
447 	/* read ISR: 4/8bytes */
448 	if (rtl8822be_InterruptRecognized(Adapter) == _FALSE) {
449 		DBG_COUNTER(Adapter->int_logs.err);
450 		ret = _FAIL;
451 		goto done;
452 	}
453 
454 	/* <1> beacon related */
455 	rtl8822be_bcn_handler(Adapter, handled);
456 
457 	/* <2> Rx related */
458 	rtl8822be_rx_handler(Adapter, handled);
459 
460 	/* <3> Tx related */
461 	rtl8822be_tx_handler(Adapter, pHalData->IntArray, handled);
462 
463 	if (pHalData->IntArray[1] & BIT_TXFOVW) {
464 		DBG_COUNTER(Adapter->int_logs.txfovw);
465 		if (printk_ratelimit())
466 			RTW_WARN("[TXFOVW]\n");
467 		handled[1] |= BIT_TXFOVW;
468 	}
469 
470 	/* <4> Cmd related */
471 	rtl8822be_cmd_handler(Adapter, handled);
472 
473 	if ((pHalData->IntArray[0] & (~handled[0])) ||
474 		(pHalData->IntArray[1] & (~handled[1])) ||
475 		(pHalData->IntArray[3] & (~handled[3]))) {
476 
477 		if (printk_ratelimit()) {
478 			RTW_WARN("Unhandled ISR = %x, %x, %x\n",
479 				(pHalData->IntArray[0] & (~handled[0])),
480 				(pHalData->IntArray[1] & (~handled[1])),
481 				(pHalData->IntArray[3] & (~handled[3])));
482 		}
483 	}
484 done:
485 	_exit_critical(&pdvobjpriv->irq_th_lock, &irqL);
486 	return ret;
487 }
488 #endif
489 
rtl8822be_init_bd(_adapter * padapter)490 u32 rtl8822be_init_bd(_adapter *padapter)
491 {
492 	struct xmit_priv *t_priv = &padapter->xmitpriv;
493 	int	i, ret = _SUCCESS;
494 
495 	_func_enter_;
496 
497 	init_bd_ring_var(padapter);
498 	ret = rtl8822be_init_rxbd_ring(padapter);
499 
500 	if (ret == _FAIL)
501 		return ret;
502 
503 	/* general process for other queue */
504 	for (i = 0; i < PCI_MAX_TX_QUEUE_COUNT; i++) {
505 		ret = rtl8822be_init_txbd_ring(padapter, i,
506 					       t_priv->txringcount[i]);
507 		if (ret == _FAIL)
508 			goto err_free_rings;
509 	}
510 
511 	return ret;
512 
513 err_free_rings:
514 
515 	rtl8822be_free_rxbd_ring(padapter);
516 
517 	for (i = 0; i < PCI_MAX_TX_QUEUE_COUNT; i++)
518 		if (t_priv->tx_ring[i].buf_desc)
519 			rtl8822be_free_txbd_ring(padapter, i);
520 
521 	_func_exit_;
522 
523 	return ret;
524 }
525 
rtl8822be_free_bd(_adapter * padapter)526 u32 rtl8822be_free_bd(_adapter *padapter)
527 {
528 	struct xmit_priv	*t_priv = &padapter->xmitpriv;
529 	u32 i;
530 
531 	_func_enter_;
532 
533 	/* free rxbd rings */
534 	rtl8822be_free_rxbd_ring(padapter);
535 
536 	/* free txbd rings */
537 	for (i = 0; i < HW_QUEUE_ENTRY; i++)
538 		rtl8822be_free_txbd_ring(padapter, i);
539 
540 	_func_exit_;
541 
542 	return _SUCCESS;
543 }
544 
rtl8822be_sethaldefvar(PADAPTER adapter,HAL_DEF_VARIABLE variable,void * pval)545 u8 rtl8822be_sethaldefvar(PADAPTER adapter, HAL_DEF_VARIABLE variable, void *pval)
546 {
547 	PHAL_DATA_TYPE hal;
548 	u8 bResult;
549 
550 
551 	hal = GET_HAL_DATA(adapter);
552 	bResult = _SUCCESS;
553 
554 	switch (variable) {
555 
556 	case HAL_DEF_PCI_SUUPORT_L1_BACKDOOR:
557 		hal->bSupportBackDoor = *((BOOLEAN *)pval);
558 		break;
559 
560 	default:
561 		bResult = rtl8822b_sethaldefvar(adapter, variable, pval);
562 		break;
563 	}
564 
565 	return bResult;
566 }
567 
568 /*
569 	Description:
570 		Query setting of specified variable.
571 */
rtl8822be_gethaldefvar(PADAPTER padapter,HAL_DEF_VARIABLE eVariable,PVOID pValue)572 static u8 rtl8822be_gethaldefvar(PADAPTER	padapter, HAL_DEF_VARIABLE eVariable, PVOID pValue)
573 {
574 	HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
575 	u8 bResult = _SUCCESS;
576 
577 	switch (eVariable) {
578 
579 	case HAL_DEF_PCI_SUUPORT_L1_BACKDOOR:
580 		*((PBOOLEAN)pValue) = pHalData->bSupportBackDoor;
581 		break;
582 
583 	case HAL_DEF_PCI_AMD_L1_SUPPORT:
584 		*((PBOOLEAN)pValue) = _TRUE;/* Support L1 patch on AMD platform in default, added by Roger, 2012.04.30. */
585 		break;
586 
587 	case HAL_DEF_MAX_RECVBUF_SZ:
588 		*((u32 *)pValue) = MAX_RECVBUF_SZ;
589 		break;
590 
591 	case HW_VAR_MAX_RX_AMPDU_FACTOR:
592 		*(HT_CAP_AMPDU_FACTOR *)pValue = MAX_AMPDU_FACTOR_64K;
593 		break;
594 	default:
595 		bResult = rtl8822b_gethaldefvar(padapter, eVariable, pValue);
596 		break;
597 	}
598 
599 	return bResult;
600 }
601 
602 #ifdef CONFIG_NAPI
603 
604 #define NAPI_EVENT_BCN0	( \
605 			BIT_TXBCN0OK_MSK | \
606 			BIT_TXBCN0ERR_MSK | \
607 			BIT_BCNDERR0_MSK | \
608 			BIT_BCNDMAINT0_MSK \
609 			)
610 
611 #define NAPI_EVENT_RX0	( \
612 			BIT_RXOK | \
613 			BIT_RDU \
614 			)
615 
616 #define NAPI_EVENT_RX1	( \
617 			BIT_FOVW | \
618 			BIT_RXERR_INT \
619 			)
620 
621 #define NAPI_EVENT_TX0	( \
622 			BIT_MGTDOK_MSK | \
623 			BIT_HIGHDOK_MSK | \
624 			BIT_BKDOK_MSK | \
625 			BIT_BEDOK_MSK | \
626 			BIT_VIDOK_MSK | \
627 			BIT_VODOK_MSK \
628 			)
629 
630 #define NAPI_EVENT_TX1	( \
631 			BIT_TXFOVW | \
632 			BIT_TXERR_INT \
633 			)
634 
635 #define NAPI_EVENT_CMD3	( \
636 			BIT_SETH2CDOK_MASK \
637 			)
638 
639 #define NAPI_EVENT0	(BIT_RXOK)
640 
641 #define NAPI_EVENT1	(0)
642 
rtl8822be_napi_irq_disable(PADAPTER adapter)643 static void rtl8822be_napi_irq_disable(PADAPTER adapter)
644 {
645 	HAL_DATA_TYPE *pHalData = GET_HAL_DATA(adapter);
646 
647 	pHalData->IntrMask[0] &= (~NAPI_EVENT0);
648 /*	pHalData->IntrMask[1] &= (~NAPI_EVENT1);	*/
649 	rtw_write32(adapter, REG_HIMR0, pHalData->IntrMask[0]);
650 /*	rtw_write32(adapter, REG_HIMR1, pHalData->IntrMask[1]); */
651 }
652 
rtl8822be_napi_irq_enable(PADAPTER adapter)653 static void rtl8822be_napi_irq_enable(PADAPTER adapter)
654 {
655 	HAL_DATA_TYPE *pHalData = GET_HAL_DATA(adapter);
656 
657 	pHalData->IntrMask[0] |= NAPI_EVENT0;
658 /*	pHalData->IntrMask[1] |= NAPI_EVENT1;	*/
659 	rtw_write32(adapter, REG_HIMR0, pHalData->IntrMask[0]);
660 /*	rtw_write32(adapter, REG_HIMR1, pHalData->IntrMask[1]);	*/
661 }
662 
rtl8822be_napi_get_events(PADAPTER adapter)663 static void rtl8822be_napi_get_events(PADAPTER adapter)
664 {
665 	HAL_DATA_TYPE *pHalData = GET_HAL_DATA(adapter);
666 
667 	pHalData->IntArray[0] = rtw_read32(adapter, REG_HISR0);
668 	pHalData->IntArray[1] = rtw_read32(adapter, REG_HISR1);
669 	pHalData->IntArray[3] = rtw_read32(adapter, REG_HISR3);
670 }
671 
rtl8822be_napi_interrupt(PADAPTER adapter)672 static s32 rtl8822be_napi_interrupt(PADAPTER adapter)
673 {
674 	struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(adapter);
675 	HAL_DATA_TYPE *pHalData = GET_HAL_DATA(adapter);
676 	_irqL irqL;
677 	u32 handled[4] = {0}; /* no interrupt handled on default */
678 
679 	_enter_critical(&pdvobjpriv->irq_th_lock, &irqL);
680 
681 	DBG_COUNTER(adapter->int_logs.all);
682 
683 #if 1
684 	/* 2013.11.18 Glayrainx suggests that turn off IMR and
685 	 * restore after cleaning ISR.
686 	 */
687 	rtw_write32(adapter, REG_HIMR0, 0);
688 	rtw_write32(adapter, REG_HIMR1, 0);
689 	rtw_write32(adapter, REG_HIMR3, 0);
690 #endif
691 
692 	rtl8822be_napi_get_events(adapter);
693 	pHalData->IntArray[0] &= pHalData->IntrMask[0];
694 	pHalData->IntArray[1] &= pHalData->IntrMask[1];
695 	pHalData->IntArray[3] &= pHalData->IntrMask[3];
696 #if 0
697 	RTW_INFO("[I %x, %x, %x]\n",
698 			pHalData->IntArray[0],
699 			pHalData->IntArray[1],
700 			pHalData->IntArray[3]);
701 #endif
702 
703 	/* ack non-NAPI event directly */
704 	if (pHalData->IntArray[3])
705 		rtw_write32(adapter, REG_HISR3, pHalData->IntArray[3]);
706 	if (pHalData->IntArray[0])
707 		rtw_write32(adapter, REG_HISR0, pHalData->IntArray[0]);
708 	if (pHalData->IntArray[1])
709 		rtw_write32(adapter, REG_HISR1, pHalData->IntArray[1]);
710 
711 #if 1
712 	/* restore IMR */
713 	rtw_write32(adapter, REG_HIMR0, pHalData->IntrMask[0] & 0xFFFFFFFF);
714 	rtw_write32(adapter, REG_HIMR1, pHalData->IntrMask[1] & 0xFFFFFFFF);
715 	rtw_write32(adapter, REG_HIMR3, pHalData->IntrMask[3] & 0xFFFFFFFF);
716 #endif
717 
718 	/* <0> handle cmd directly */
719 	if (pHalData->IntArray[3] & NAPI_EVENT_CMD3)
720 		rtl8822be_cmd_handler(adapter, handled);
721 
722 	/* <1> handle beacon directly */
723 	if (pHalData->IntArray[0] & NAPI_EVENT_BCN0)
724 		rtl8822be_bcn_handler(adapter, handled);
725 
726 	/* <2> Rx first */
727 	if (pHalData->IntArray[0] & BIT_RDU) {
728 		DBG_COUNTER(adapter->int_logs.rx_rdu);
729 
730 		if (printk_ratelimit())
731 			RTW_WARN("[RDU]\n");
732 		handled[0] |= BIT_RDU;
733 	}
734 
735 	if (pHalData->IntArray[1] & BIT_FOVW) {
736 		DBG_COUNTER(adapter->int_logs.rx_fovw);
737 
738 		if (printk_ratelimit())
739 			RTW_WARN("[FOVW]\n");
740 		handled[1] |= BIT_FOVW;
741 	}
742 
743 	if (pHalData->IntArray[1] & BIT_RXERR_INT) {
744 		DBG_COUNTER(adapter->int_logs.err);
745 		RTW_WARN("[RXERR]\n");
746 		handled[1] |= BIT_RXERR_INT;
747 	}
748 
749 	/* <2> handle rx in napi poll */
750 	if (pHalData->IntArray[0] & NAPI_EVENT0) {
751 		DBG_COUNTER(adapter->int_logs.rx);
752 
753 		if (napi_schedule_prep(&adapter->napi)) {
754 			handled[0] |= (pHalData->IntArray[0] & NAPI_EVENT0);
755 			/* disable irq */
756 			rtl8822be_napi_irq_disable(adapter);
757 			/* tell system we have work to be done */
758 			__napi_schedule(&adapter->napi);
759 		} else {
760 			RTW_WARN("driver bug! interrupt while in poll\n");
761 			 /* FIX by disabling interrupts  */
762 			rtl8822be_napi_irq_disable(adapter);
763 		}
764 	}
765 
766 	/* <3> handle tx directly */
767 	if (pHalData->IntArray[1] & BIT_TXFOVW) {
768 		DBG_COUNTER(adapter->int_logs.txfovw);
769 
770 		if (printk_ratelimit())
771 			RTW_WARN("[TXFOVW]\n");
772 		handled[1] |= BIT_TXFOVW;
773 	}
774 
775 	if (pHalData->IntArray[1] & BIT_TXERR_INT) {
776 		DBG_COUNTER(adapter->int_logs.err);
777 		RTW_WARN("[TXERR]\n");
778 		handled[1] |= BIT_TXERR_INT;
779 	}
780 
781 	if (pHalData->IntArray[0] & NAPI_EVENT_TX0)
782 		rtl8822be_tx_handler(adapter, pHalData->IntArray, handled);
783 
784 	/* check un-handled interrupt */
785 	if ((pHalData->IntArray[0] & (~handled[0])) ||
786 		(pHalData->IntArray[1] & (~handled[1])) ||
787 		(pHalData->IntArray[3] & (~handled[3]))) {
788 
789 		RTW_WARN("Unhandled ISR = %x, %x, %x\n",
790 			(pHalData->IntArray[0] & (~handled[0])),
791 			(pHalData->IntArray[1] & (~handled[1])),
792 			(pHalData->IntArray[3] & (~handled[3])));
793 	}
794 
795 	_exit_critical(&pdvobjpriv->irq_th_lock, &irqL);
796 
797 	return IRQ_RETVAL(handled[0] || handled[1] || handled[3]);
798 }
799 
rtl8822be_napi_poll(PADAPTER adapter,int budget)800 static int rtl8822be_napi_poll(PADAPTER adapter, int budget)
801 {
802 	int remaing_rxdesc;
803 	int work_done = 0;
804 	struct registry_priv *reg = &adapter->registrypriv;
805 
806 	remaing_rxdesc = rtl8822be_check_rxdesc_remain(adapter, RX_MPDU_QUEUE);
807 	do {
808 		work_done += rtl8822be_rx_mpdu(adapter, remaing_rxdesc,
809 				budget);
810 		budget -= work_done;
811 
812 		/* check rx again */
813 		remaing_rxdesc = rtl8822be_check_rxdesc_remain(adapter,
814 				RX_MPDU_QUEUE);
815 
816 		if (remaing_rxdesc) {
817 			if (reg->napi_debug && printk_ratelimit())
818 				RTW_INFO("[RX %d]\n", remaing_rxdesc);
819 			break;
820 		}
821 
822 	} while (remaing_rxdesc > 0 && budget > 0);
823 
824 	return work_done;
825 }
826 #endif /* CONFIG_NAPI */
827 
rtl8822be_set_hal_ops(PADAPTER padapter)828 void rtl8822be_set_hal_ops(PADAPTER padapter)
829 {
830 	struct hal_ops *ops;
831 	int err;
832 
833 	err = rtl8822be_halmac_init_adapter(padapter);
834 	if (err) {
835 		RTW_INFO("%s: [ERROR]HALMAC initialize FAIL!\n", __func__);
836 		return;
837 	}
838 
839 	rtl8822b_set_hal_ops(padapter);
840 
841 	ops = &padapter->HalFunc;
842 
843 	ops->hal_init = rtl8822be_init;
844 	ops->inirp_init = rtl8822be_init_bd;
845 	ops->inirp_deinit = rtl8822be_free_bd;
846 	ops->irp_reset = rtl8822be_reset_bd;
847 	ops->init_xmit_priv = rtl8822be_init_xmit_priv;
848 	ops->free_xmit_priv = rtl8822be_free_xmit_priv;
849 	ops->init_recv_priv = rtl8822be_init_recv_priv;
850 	ops->free_recv_priv = rtl8822be_free_recv_priv;
851 
852 #ifdef CONFIG_SW_LED
853 	ops->InitSwLeds = rtl8822be_InitSwLeds;
854 	ops->DeInitSwLeds = rtl8822be_DeInitSwLeds;
855 #else /* case of hw led or no led */
856 	ops->InitSwLeds = NULL;
857 	ops->DeInitSwLeds = NULL;
858 #endif
859 
860 	ops->init_default_value = rtl8822be_init_default_value;
861 	ops->intf_chip_configure = intf_chip_configure;
862 	ops->read_adapter_info = read_adapter_info;
863 
864 	ops->enable_interrupt = rtl8822be_enable_interrupt;
865 	ops->disable_interrupt = rtl8822be_disable_interrupt;
866 #ifdef CONFIG_NAPI
867 	ops->interrupt_handler = rtl8822be_napi_interrupt;
868 #else
869 	ops->interrupt_handler = rtl8822be_interrupt;
870 #endif
871 	/*
872 		ops->check_ips_status = check_ips_status;
873 	*/
874 	ops->clear_interrupt = rtl8822be_clear_interrupt;
875 #if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN) ||\
876 	defined(CONFIG_PCI_HCI)
877 	/*
878 		ops->clear_interrupt = clear_interrupt_all;
879 	*/
880 #endif
881 	ops->GetHalDefVarHandler = rtl8822be_gethaldefvar;
882 	ops->SetHalDefVarHandler = rtl8822be_sethaldefvar;
883 	ops->hal_xmit = rtl8822be_hal_xmit;
884 	ops->mgnt_xmit = rtl8822be_mgnt_xmit;
885 	ops->hal_xmitframe_enqueue = rtl8822be_hal_xmitframe_enqueue;
886 #ifdef CONFIG_HOSTAPD_MLME
887 	ops->hostap_mgnt_xmit_entry = rtl8822be_hostap_mgnt_xmit_entry;
888 #endif
889 
890 #ifdef CONFIG_XMIT_THREAD_MODE
891 	/* vincent TODO */
892 	ops->xmit_thread_handler = rtl8822be_xmit_buf_handler;
893 #endif
894 
895 #ifdef CONFIG_NAPI
896 	ops->napi_irq_disable = rtl8822be_napi_irq_disable;
897 	ops->napi_irq_enable = rtl8822be_napi_irq_enable;
898 	ops->napi_poll = rtl8822be_napi_poll;
899 #endif
900 }
901