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