net: wireless: rockchip: add rtl8822be pcie wifi driver
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / rockchip_wlan / rtl8822be / hal / rtl8822b / pci / rtl8822be_ops.c
diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/rtl8822b/pci/rtl8822be_ops.c b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/rtl8822b/pci/rtl8822be_ops.c
new file mode 100644 (file)
index 0000000..6c08bef
--- /dev/null
@@ -0,0 +1,900 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2015 - 2016 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ *
+ ******************************************************************************/
+
+#define _HCI_OPS_OS_C_
+
+#include <drv_types.h>         /* PADAPTER, basic_types.h and etc. */
+#include <hal_data.h>          /* HAL_DATA_TYPE, GET_HAL_DATA() and etc. */
+#include <hal_intf.h>          /* struct hal_ops */
+#include "../rtl8822b.h"
+#include "rtl8822be.h"
+
+static void init_bd_ring_var(_adapter *padapter)
+{
+       struct recv_priv *r_priv = &padapter->recvpriv;
+       struct xmit_priv *t_priv = &padapter->xmitpriv;
+       u8 i = 0;
+
+       for (i = 0; i < HW_QUEUE_ENTRY; i++)
+               t_priv->txringcount[i] = TX_BD_NUM_8822BE;
+
+       /*
+        * we just alloc 2 desc for beacon queue,
+        * because we just need first desc in hw beacon.
+        */
+       t_priv->txringcount[BCN_QUEUE_INX] = TX_BD_NUM_8822BE_BCN;
+       t_priv->txringcount[TXCMD_QUEUE_INX] = TX_BD_NUM_8822BE_CMD;
+
+       /*
+        * BE queue need more descriptor for performance consideration
+        * or, No more tx desc will happen, and may cause mac80211 mem leakage.
+        */
+       r_priv->rxbuffersize = MAX_RECVBUF_SZ;
+       r_priv->rxringcount = PCI_MAX_RX_COUNT;
+}
+
+static void rtl8822be_reset_bd(_adapter *padapter)
+{
+       _irqL   irqL;
+       struct xmit_priv *t_priv = &padapter->xmitpriv;
+       struct recv_priv *r_priv = &padapter->recvpriv;
+       struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
+       struct xmit_buf *pxmitbuf = NULL;
+       u8 *tx_bd, *rx_bd;
+       int i, rx_queue_idx;
+
+       for (rx_queue_idx = 0; rx_queue_idx < 1; rx_queue_idx++) {
+               if (r_priv->rx_ring[rx_queue_idx].buf_desc) {
+                       rx_bd = NULL;
+                       for (i = 0; i < r_priv->rxringcount; i++) {
+                               rx_bd = (u8 *)
+                                       &r_priv->rx_ring[rx_queue_idx].buf_desc[i];
+                       }
+                       r_priv->rx_ring[rx_queue_idx].idx = 0;
+               }
+       }
+
+       _enter_critical(&pdvobjpriv->irq_th_lock, &irqL);
+       for (i = 0; i < PCI_MAX_TX_QUEUE_COUNT; i++) {
+               if (t_priv->tx_ring[i].buf_desc) {
+                       struct rtw_tx_ring *ring = &t_priv->tx_ring[i];
+
+                       while (ring->qlen) {
+                               tx_bd = (u8 *)(&ring->buf_desc[ring->idx]);
+                               SET_TX_BD_OWN(tx_bd, 0);
+
+                               if (i != BCN_QUEUE_INX)
+                                       ring->idx =
+                                               (ring->idx + 1) % ring->entries;
+
+                               pxmitbuf = rtl8822be_dequeue_xmitbuf(ring);
+                               if (pxmitbuf) {
+                                       pci_unmap_single(pdvobjpriv->ppcidev,
+                                               GET_TX_BD_PHYSICAL_ADDR0_LOW(tx_bd),
+                                               pxmitbuf->len, PCI_DMA_TODEVICE);
+                                       rtw_free_xmitbuf(t_priv, pxmitbuf);
+                               } else {
+                                       RTW_INFO("%s(): qlen(%d) is not zero, but have xmitbuf in pending queue\n",
+                                                __func__, ring->qlen);
+                                       break;
+                               }
+                       }
+                       ring->idx = 0;
+               }
+       }
+       _exit_critical(&pdvobjpriv->irq_th_lock, &irqL);
+}
+
+static void intf_chip_configure(PADAPTER Adapter)
+{
+       HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);
+       struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(Adapter);
+       struct pwrctrl_priv *pwrpriv = dvobj_to_pwrctl(pdvobjpriv);
+
+
+       /* close ASPM for AMD defaultly */
+       pdvobjpriv->const_amdpci_aspm = 0;
+
+       /* ASPM PS mode. */
+       /* 0 - Disable ASPM, 1 - Enable ASPM without Clock Req, */
+       /* 2 - Enable ASPM with Clock Req, 3- Alwyas Enable ASPM with Clock Req, */
+       /* 4-  Always Enable ASPM without Clock Req. */
+       /* set defult to rtl8188ee:3 RTL8192E:2 */
+       pdvobjpriv->const_pci_aspm = 0;
+
+       /* Setting for PCI-E device */
+       pdvobjpriv->const_devicepci_aspm_setting = 0x03;
+
+       /* Setting for PCI-E bridge */
+       pdvobjpriv->const_hostpci_aspm_setting = 0x03;
+
+       /* In Hw/Sw Radio Off situation. */
+       /* 0 - Default, 1 - From ASPM setting without low Mac Pwr, */
+       /* 2 - From ASPM setting with low Mac Pwr, 3 - Bus D3 */
+       /* set default to RTL8192CE:0 RTL8192SE:2 */
+       pdvobjpriv->const_hwsw_rfoff_d3 = 0;
+
+       /* This setting works for those device with backdoor ASPM setting such as EPHY setting. */
+       /* 0: Not support ASPM, 1: Support ASPM, 2: According to chipset. */
+       pdvobjpriv->const_support_pciaspm = 1;
+
+       pwrpriv->reg_rfoff = 0;
+       pwrpriv->rfoff_reason = 0;
+
+       pHalData->bL1OffSupport = _FALSE;
+}
+
+/*
+ * Description:
+ *     Collect all hardware information, fill "HAL_DATA_TYPE".
+ *     Sometimes this would be used to read MAC address.
+ *     This function will do
+ *     1. Read Efuse/EEPROM to initialize
+ *     2. Read registers to initialize
+ *     3. Other vaiables initialization
+ */
+static u8 read_adapter_info(PADAPTER padapter)
+{
+       /*
+        * 1. Read Efuse/EEPROM to initialize
+        */
+       if (rtl8822b_read_efuse(padapter) == _FAIL)
+               return _FAIL;
+
+       /*
+        * 2. Read registers to initialize
+        */
+
+       /*
+        * 3. Other Initialization
+        */
+       return _SUCCESS;
+}
+
+#ifndef CONFIG_NAPI
+static BOOLEAN rtl8822be_InterruptRecognized(PADAPTER Adapter)
+{
+       HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);
+       BOOLEAN bRecognized = _FALSE;
+
+       /* 2013.11.18 Glayrainx suggests that turn off IMR and
+        * restore after cleaning ISR.
+        */
+       rtw_write32(Adapter, REG_HIMR0, 0);
+       rtw_write32(Adapter, REG_HIMR1, 0);
+       rtw_write32(Adapter, REG_HIMR3, 0);
+
+       pHalData->IntArray[0] = rtw_read32(Adapter, REG_HISR0);
+       pHalData->IntArray[0] &= pHalData->IntrMask[0];
+       rtw_write32(Adapter, REG_HISR0, pHalData->IntArray[0]);
+
+       /* For HISR extension. Added by tynli. 2009.10.07. */
+       pHalData->IntArray[1] = rtw_read32(Adapter, REG_HISR1);
+       pHalData->IntArray[1] &= pHalData->IntrMask[1];
+       rtw_write32(Adapter, REG_HISR1, pHalData->IntArray[1]);
+
+       /* for H2C cmd queue */
+       pHalData->IntArray[3] = rtw_read32(Adapter, REG_HISR3);
+       pHalData->IntArray[3] &= pHalData->IntrMask[3];
+       rtw_write32(Adapter, REG_HISR3, pHalData->IntArray[3]);
+
+       if (((pHalData->IntArray[0]) & pHalData->IntrMask[0]) != 0 ||
+           ((pHalData->IntArray[1]) & pHalData->IntrMask[1]) != 0)
+               bRecognized = _TRUE;
+
+       /* restore IMR */
+       rtw_write32(Adapter, REG_HIMR0, pHalData->IntrMask[0] & 0xFFFFFFFF);
+       rtw_write32(Adapter, REG_HIMR1, pHalData->IntrMask[1] & 0xFFFFFFFF);
+       rtw_write32(Adapter, REG_HIMR3, pHalData->IntrMask[3] & 0xFFFFFFFF);
+
+       return bRecognized;
+}
+#endif
+
+static VOID DisableInterrupt8822be(PADAPTER Adapter)
+{
+       struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(Adapter);
+
+       rtw_write32(Adapter, REG_HIMR0, 0x0);
+       rtw_write32(Adapter, REG_HIMR1, 0x0);
+       rtw_write32(Adapter, REG_HIMR3, 0x0);
+       pdvobjpriv->irq_enabled = 0;
+}
+
+static VOID rtl8822be_enable_interrupt(PADAPTER Adapter)
+{
+       HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);
+       struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(Adapter);
+
+       pdvobjpriv->irq_enabled = 1;
+
+       rtw_write32(Adapter, REG_HIMR0, pHalData->IntrMask[0] & 0xFFFFFFFF);
+       rtw_write32(Adapter, REG_HIMR1, pHalData->IntrMask[1] & 0xFFFFFFFF);
+       rtw_write32(Adapter, REG_HIMR3, pHalData->IntrMask[3] & 0xFFFFFFFF);
+
+}
+
+static VOID rtl8822be_clear_interrupt(PADAPTER Adapter)
+{
+       u32 u32b;
+       HAL_DATA_TYPE   *pHalData = GET_HAL_DATA(Adapter);
+
+       u32b = rtw_read32(Adapter, REG_HISR0_8822B);
+       rtw_write32(Adapter, REG_HISR0_8822B, u32b);
+       pHalData->IntArray[0] = 0;
+
+       u32b = rtw_read32(Adapter, REG_HISR1_8822B);
+       rtw_write32(Adapter, REG_HISR1_8822B, u32b);
+       pHalData->IntArray[1] = 0;
+}
+
+static VOID rtl8822be_disable_interrupt(PADAPTER Adapter)
+{
+       struct dvobj_priv       *pdvobjpriv = adapter_to_dvobj(Adapter);
+
+       rtw_write32(Adapter, REG_HIMR0, 0x0);
+       rtw_write32(Adapter, REG_HIMR1, 0x0);   /* by tynli */
+       pdvobjpriv->irq_enabled = 0;
+}
+
+VOID UpdateInterruptMask8822BE(PADAPTER Adapter, u32 AddMSR, u32 AddMSR1,
+                              u32 RemoveMSR, u32 RemoveMSR1)
+{
+       PHAL_DATA_TYPE pHalData = GET_HAL_DATA(Adapter);
+
+       DisableInterrupt8822be(Adapter);
+
+       if (AddMSR)
+               pHalData->IntrMask[0] |= AddMSR;
+
+       if (AddMSR1)
+               pHalData->IntrMask[1] |= AddMSR1;
+
+       if (RemoveMSR)
+               pHalData->IntrMask[0] &= (~RemoveMSR);
+
+       if (RemoveMSR1)
+               pHalData->IntrMask[1] &= (~RemoveMSR1);
+
+#if 0 /* TODO */
+       if (RemoveMSR3)
+               pHalData->IntrMask[3] &= (~RemoveMSR3);
+#endif
+
+       rtl8822be_enable_interrupt(Adapter);
+}
+
+static void rtl8822be_bcn_handler(PADAPTER Adapter, u32 handled[])
+{
+       PHAL_DATA_TYPE pHalData = GET_HAL_DATA(Adapter);
+
+       if (pHalData->IntArray[0] & BIT_TXBCN0OK_MSK) {
+               DBG_COUNTER(Adapter->int_logs.tbdok);
+#ifdef CONFIG_BCN_ICF
+               /* do nothing */
+#else
+               /* Modify for MI temporary,
+                * this processor cannot apply to multi-ap */
+               PADAPTER bcn_adapter = rtw_mi_get_ap_adapter(Adapter);
+
+               if (bcn_adapter->xmitpriv.beaconDMAing) {
+                       bcn_adapter->xmitpriv.beaconDMAing = _FAIL;
+                       rtl8822be_tx_isr(Adapter, BCN_QUEUE_INX);
+               }
+#endif /* CONFIG_BCN_ICF */
+               handled[0] |= BIT_TXBCN0OK_MSK;
+       }
+
+       if (pHalData->IntArray[0] & BIT_TXBCN0ERR_MSK) {
+               DBG_COUNTER(Adapter->int_logs.tbder);
+#ifdef CONFIG_BCN_ICF
+               RTW_INFO("IMR_TXBCN0ERR isr!\n");
+#else /* !CONFIG_BCN_ICF */
+               /* Modify for MI temporary,
+                * this processor cannot apply to multi-ap */
+               PADAPTER bcn_adapter = rtw_mi_get_ap_adapter(Adapter);
+
+               if (bcn_adapter->xmitpriv.beaconDMAing) {
+                       bcn_adapter->xmitpriv.beaconDMAing = _FAIL;
+                       rtl8822be_tx_isr(Adapter, BCN_QUEUE_INX);
+               }
+#endif /* CONFIG_BCN_ICF */
+               handled[0] |= BIT_TXBCN0ERR_MSK;
+       }
+
+       if (pHalData->IntArray[0] & BIT_BCNDERR0_MSK) {
+               DBG_COUNTER(Adapter->int_logs.bcnderr);
+#ifdef CONFIG_BCN_ICF
+               RTW_INFO("BIT_BCNDERR0_MSK isr!\n");
+#else /* !CONFIG_BCN_ICF */
+               /* Release resource and re-transmit beacon to HW */
+               struct tasklet_struct  *bcn_tasklet;
+               /* Modify for MI temporary,
+                * this processor cannot apply to multi-ap */
+               PADAPTER bcn_adapter = rtw_mi_get_ap_adapter(Adapter);
+
+               rtl8822be_tx_isr(Adapter, BCN_QUEUE_INX);
+               bcn_adapter->mlmepriv.update_bcn = _TRUE;
+               bcn_tasklet = &bcn_adapter->recvpriv.irq_prepare_beacon_tasklet;
+               tasklet_hi_schedule(bcn_tasklet);
+#endif /* CONFIG_BCN_ICF */
+               handled[0] |= BIT_BCNDERR0_MSK;
+       }
+
+       if (pHalData->IntArray[0] & BIT_BCNDMAINT0_MSK) {
+               struct tasklet_struct  *bcn_tasklet;
+               /* Modify for MI temporary,
+                 this processor cannot apply to multi-ap */
+               PADAPTER bcn_adapter = rtw_mi_get_ap_adapter(Adapter);
+
+               DBG_COUNTER(Adapter->int_logs.bcndma);
+               bcn_tasklet = &bcn_adapter->recvpriv.irq_prepare_beacon_tasklet;
+               tasklet_hi_schedule(bcn_tasklet);
+               handled[0] |= BIT_BCNDMAINT0_MSK;
+       }
+}
+
+#ifndef CONFIG_NAPI
+static void rtl8822be_rx_handler(PADAPTER Adapter, u32 handled[])
+{
+       PHAL_DATA_TYPE pHalData = GET_HAL_DATA(Adapter);
+
+       if ((pHalData->IntArray[0] & (BIT_RXOK | BIT_RDU)) ||
+           (pHalData->IntArray[1] & (BIT_FOVW | BIT_RXERR_INT))) {
+               DBG_COUNTER(Adapter->int_logs.rx);
+
+               if (pHalData->IntArray[0] & BIT_RDU) {
+                       DBG_COUNTER(Adapter->int_logs.rx_rdu);
+               }
+
+               if (pHalData->IntArray[1] & BIT_FOVW) {
+                       DBG_COUNTER(Adapter->int_logs.rx_fovw);
+               }
+
+               pHalData->IntrMask[0] &= (~(BIT_RXOK_MSK | BIT_RDU_MSK));
+               pHalData->IntrMask[1] &= (~(BIT_FOVW_MSK | BIT_RXERR_MSK));
+               rtw_write32(Adapter, REG_HIMR0, pHalData->IntrMask[0]);
+               rtw_write32(Adapter, REG_HIMR1, pHalData->IntrMask[1]);
+               tasklet_hi_schedule(&Adapter->recvpriv.recv_tasklet);
+               handled[0] |= pHalData->IntArray[0] & (BIT_RXOK | BIT_RDU);
+               handled[1] |= pHalData->IntArray[1] & (BIT_FOVW | BIT_RXERR_INT);
+       }
+}
+#endif
+
+static void rtl8822be_tx_handler(PADAPTER Adapter, u32 events[], u32 handled[])
+{
+       PHAL_DATA_TYPE pHalData = GET_HAL_DATA(Adapter);
+
+       if (events[0] & BIT_MGTDOK_MSK) {
+               DBG_COUNTER(Adapter->int_logs.mgntok);
+               rtl8822be_tx_isr(Adapter, MGT_QUEUE_INX);
+               handled[0] |= BIT_MGTDOK_MSK;
+       }
+
+       if (events[0] & BIT_HIGHDOK_MSK) {
+               DBG_COUNTER(Adapter->int_logs.highdok);
+               rtl8822be_tx_isr(Adapter, HIGH_QUEUE_INX);
+               handled[0] |= BIT_HIGHDOK_MSK;
+       }
+
+       if (events[0] & BIT_BKDOK_MSK) {
+               DBG_COUNTER(Adapter->int_logs.bkdok);
+               rtl8822be_tx_isr(Adapter, BK_QUEUE_INX);
+               handled[0] |= BIT_BKDOK_MSK;
+       }
+
+       if (events[0] & BIT_BEDOK_MSK) {
+               DBG_COUNTER(Adapter->int_logs.bedok);
+               rtl8822be_tx_isr(Adapter, BE_QUEUE_INX);
+               handled[0] |= BIT_BEDOK_MSK;
+       }
+
+       if (events[0] & BIT_VIDOK_MSK) {
+               DBG_COUNTER(Adapter->int_logs.vidok);
+               rtl8822be_tx_isr(Adapter, VI_QUEUE_INX);
+               handled[0] |= BIT_VIDOK_MSK;
+       }
+
+       if (events[0] & BIT_VODOK_MSK) {
+               DBG_COUNTER(Adapter->int_logs.vodok);
+               rtl8822be_tx_isr(Adapter, VO_QUEUE_INX);
+               handled[0] |= BIT_VODOK_MSK;
+       }
+}
+
+static void rtl8822be_cmd_handler(PADAPTER Adapter, u32 handled[])
+{
+       PHAL_DATA_TYPE pHalData = GET_HAL_DATA(Adapter);
+
+       if (pHalData->IntArray[3] & BIT_SETH2CDOK_MASK) {
+               rtl8822be_tx_isr(Adapter, TXCMD_QUEUE_INX);
+               handled[3] |= BIT_SETH2CDOK_MASK;
+       }
+}
+
+#ifndef CONFIG_NAPI
+static s32 rtl8822be_interrupt(PADAPTER Adapter)
+{
+       _irqL irqL;
+       HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);
+       struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(Adapter);
+       struct xmit_priv *t_priv = &Adapter->xmitpriv;
+       int ret = _SUCCESS;
+       u32 handled[4] = {0};
+
+       _enter_critical(&pdvobjpriv->irq_th_lock, &irqL);
+
+       DBG_COUNTER(Adapter->int_logs.all);
+
+       /* read ISR: 4/8bytes */
+       if (rtl8822be_InterruptRecognized(Adapter) == _FALSE) {
+               DBG_COUNTER(Adapter->int_logs.err);
+               ret = _FAIL;
+               goto done;
+       }
+
+       /* <1> beacon related */
+       rtl8822be_bcn_handler(Adapter, handled);
+
+       /* <2> Rx related */
+       rtl8822be_rx_handler(Adapter, handled);
+
+       /* <3> Tx related */
+       rtl8822be_tx_handler(Adapter, pHalData->IntArray, handled);
+
+       if (pHalData->IntArray[1] & BIT_TXFOVW) {
+               DBG_COUNTER(Adapter->int_logs.txfovw);
+               if (printk_ratelimit())
+                       RTW_WARN("[TXFOVW]\n");
+               handled[1] |= BIT_TXFOVW;
+       }
+
+       /* <4> Cmd related */
+       rtl8822be_cmd_handler(Adapter, handled);
+
+       if ((pHalData->IntArray[0] & (~handled[0])) ||
+               (pHalData->IntArray[1] & (~handled[1])) ||
+               (pHalData->IntArray[3] & (~handled[3]))) {
+
+               if (printk_ratelimit()) {
+                       RTW_WARN("Unhandled ISR = %x, %x, %x\n",
+                               (pHalData->IntArray[0] & (~handled[0])),
+                               (pHalData->IntArray[1] & (~handled[1])),
+                               (pHalData->IntArray[3] & (~handled[3])));
+               }
+       }
+done:
+       _exit_critical(&pdvobjpriv->irq_th_lock, &irqL);
+       return ret;
+}
+#endif
+
+u32 rtl8822be_init_bd(_adapter *padapter)
+{
+       struct xmit_priv *t_priv = &padapter->xmitpriv;
+       int     i, ret = _SUCCESS;
+
+       _func_enter_;
+
+       init_bd_ring_var(padapter);
+       ret = rtl8822be_init_rxbd_ring(padapter);
+
+       if (ret == _FAIL)
+               return ret;
+
+       /* general process for other queue */
+       for (i = 0; i < PCI_MAX_TX_QUEUE_COUNT; i++) {
+               ret = rtl8822be_init_txbd_ring(padapter, i,
+                                              t_priv->txringcount[i]);
+               if (ret == _FAIL)
+                       goto err_free_rings;
+       }
+
+       return ret;
+
+err_free_rings:
+
+       rtl8822be_free_rxbd_ring(padapter);
+
+       for (i = 0; i < PCI_MAX_TX_QUEUE_COUNT; i++)
+               if (t_priv->tx_ring[i].buf_desc)
+                       rtl8822be_free_txbd_ring(padapter, i);
+
+       _func_exit_;
+
+       return ret;
+}
+
+u32 rtl8822be_free_bd(_adapter *padapter)
+{
+       struct xmit_priv        *t_priv = &padapter->xmitpriv;
+       u32 i;
+
+       _func_enter_;
+
+       /* free rxbd rings */
+       rtl8822be_free_rxbd_ring(padapter);
+
+       /* free txbd rings */
+       for (i = 0; i < HW_QUEUE_ENTRY; i++)
+               rtl8822be_free_txbd_ring(padapter, i);
+
+       _func_exit_;
+
+       return _SUCCESS;
+}
+
+u8 rtl8822be_sethaldefvar(PADAPTER adapter, HAL_DEF_VARIABLE variable, void *pval)
+{
+       PHAL_DATA_TYPE hal;
+       u8 bResult;
+
+
+       hal = GET_HAL_DATA(adapter);
+       bResult = _SUCCESS;
+
+       switch (variable) {
+
+       case HAL_DEF_PCI_SUUPORT_L1_BACKDOOR:
+               hal->bSupportBackDoor = *((BOOLEAN *)pval);
+               break;
+
+       default:
+               bResult = rtl8822b_sethaldefvar(adapter, variable, pval);
+               break;
+       }
+
+       return bResult;
+}
+
+/*
+       Description:
+               Query setting of specified variable.
+*/
+static u8 rtl8822be_gethaldefvar(PADAPTER      padapter, HAL_DEF_VARIABLE eVariable, PVOID pValue)
+{
+       HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
+       u8 bResult = _SUCCESS;
+
+       switch (eVariable) {
+
+       case HAL_DEF_PCI_SUUPORT_L1_BACKDOOR:
+               *((PBOOLEAN)pValue) = pHalData->bSupportBackDoor;
+               break;
+
+       case HAL_DEF_PCI_AMD_L1_SUPPORT:
+               *((PBOOLEAN)pValue) = _TRUE;/* Support L1 patch on AMD platform in default, added by Roger, 2012.04.30. */
+               break;
+
+       case HAL_DEF_MAX_RECVBUF_SZ:
+               *((u32 *)pValue) = MAX_RECVBUF_SZ;
+               break;
+
+       case HW_VAR_MAX_RX_AMPDU_FACTOR:
+               *(HT_CAP_AMPDU_FACTOR *)pValue = MAX_AMPDU_FACTOR_64K;
+               break;
+       default:
+               bResult = rtl8822b_gethaldefvar(padapter, eVariable, pValue);
+               break;
+       }
+
+       return bResult;
+}
+
+#ifdef CONFIG_NAPI
+
+#define NAPI_EVENT_BCN0        ( \
+                       BIT_TXBCN0OK_MSK | \
+                       BIT_TXBCN0ERR_MSK | \
+                       BIT_BCNDERR0_MSK | \
+                       BIT_BCNDMAINT0_MSK \
+                       )
+
+#define NAPI_EVENT_RX0 ( \
+                       BIT_RXOK | \
+                       BIT_RDU \
+                       )
+
+#define NAPI_EVENT_RX1 ( \
+                       BIT_FOVW | \
+                       BIT_RXERR_INT \
+                       )
+
+#define NAPI_EVENT_TX0 ( \
+                       BIT_MGTDOK_MSK | \
+                       BIT_HIGHDOK_MSK | \
+                       BIT_BKDOK_MSK | \
+                       BIT_BEDOK_MSK | \
+                       BIT_VIDOK_MSK | \
+                       BIT_VODOK_MSK \
+                       )
+
+#define NAPI_EVENT_TX1 ( \
+                       BIT_TXFOVW | \
+                       BIT_TXERR_INT \
+                       )
+
+#define NAPI_EVENT_CMD3        ( \
+                       BIT_SETH2CDOK_MASK \
+                       )
+
+#define NAPI_EVENT0    (BIT_RXOK)
+
+#define NAPI_EVENT1    (0)
+
+static void rtl8822be_napi_irq_disable(PADAPTER adapter)
+{
+       HAL_DATA_TYPE *pHalData = GET_HAL_DATA(adapter);
+
+       pHalData->IntrMask[0] &= (~NAPI_EVENT0);
+/*     pHalData->IntrMask[1] &= (~NAPI_EVENT1);        */
+       rtw_write32(adapter, REG_HIMR0, pHalData->IntrMask[0]);
+/*     rtw_write32(adapter, REG_HIMR1, pHalData->IntrMask[1]); */
+}
+
+static void rtl8822be_napi_irq_enable(PADAPTER adapter)
+{
+       HAL_DATA_TYPE *pHalData = GET_HAL_DATA(adapter);
+
+       pHalData->IntrMask[0] |= NAPI_EVENT0;
+/*     pHalData->IntrMask[1] |= NAPI_EVENT1;   */
+       rtw_write32(adapter, REG_HIMR0, pHalData->IntrMask[0]);
+/*     rtw_write32(adapter, REG_HIMR1, pHalData->IntrMask[1]); */
+}
+
+static void rtl8822be_napi_get_events(PADAPTER adapter)
+{
+       HAL_DATA_TYPE *pHalData = GET_HAL_DATA(adapter);
+
+       pHalData->IntArray[0] = rtw_read32(adapter, REG_HISR0);
+       pHalData->IntArray[1] = rtw_read32(adapter, REG_HISR1);
+       pHalData->IntArray[3] = rtw_read32(adapter, REG_HISR3);
+}
+
+static s32 rtl8822be_napi_interrupt(PADAPTER adapter)
+{
+       struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(adapter);
+       HAL_DATA_TYPE *pHalData = GET_HAL_DATA(adapter);
+       _irqL irqL;
+       u32 handled[4] = {0}; /* no interrupt handled on default */
+
+       _enter_critical(&pdvobjpriv->irq_th_lock, &irqL);
+
+       DBG_COUNTER(adapter->int_logs.all);
+
+#if 1
+       /* 2013.11.18 Glayrainx suggests that turn off IMR and
+        * restore after cleaning ISR.
+        */
+       rtw_write32(adapter, REG_HIMR0, 0);
+       rtw_write32(adapter, REG_HIMR1, 0);
+       rtw_write32(adapter, REG_HIMR3, 0);
+#endif
+
+       rtl8822be_napi_get_events(adapter);
+       pHalData->IntArray[0] &= pHalData->IntrMask[0];
+       pHalData->IntArray[1] &= pHalData->IntrMask[1];
+       pHalData->IntArray[3] &= pHalData->IntrMask[3];
+#if 0
+       RTW_INFO("[I %x, %x, %x]\n",
+                       pHalData->IntArray[0],
+                       pHalData->IntArray[1],
+                       pHalData->IntArray[3]);
+#endif
+
+       /* ack non-NAPI event directly */
+       if (pHalData->IntArray[3])
+               rtw_write32(adapter, REG_HISR3, pHalData->IntArray[3]);
+       if (pHalData->IntArray[0])
+               rtw_write32(adapter, REG_HISR0, pHalData->IntArray[0]);
+       if (pHalData->IntArray[1])
+               rtw_write32(adapter, REG_HISR1, pHalData->IntArray[1]);
+
+#if 1
+       /* restore IMR */
+       rtw_write32(adapter, REG_HIMR0, pHalData->IntrMask[0] & 0xFFFFFFFF);
+       rtw_write32(adapter, REG_HIMR1, pHalData->IntrMask[1] & 0xFFFFFFFF);
+       rtw_write32(adapter, REG_HIMR3, pHalData->IntrMask[3] & 0xFFFFFFFF);
+#endif
+
+       /* <0> handle cmd directly */
+       if (pHalData->IntArray[3] & NAPI_EVENT_CMD3)
+               rtl8822be_cmd_handler(adapter, handled);
+
+       /* <1> handle beacon directly */
+       if (pHalData->IntArray[0] & NAPI_EVENT_BCN0)
+               rtl8822be_bcn_handler(adapter, handled);
+
+       /* <2> Rx first */
+       if (pHalData->IntArray[0] & BIT_RDU) {
+               DBG_COUNTER(adapter->int_logs.rx_rdu);
+
+               if (printk_ratelimit())
+                       RTW_WARN("[RDU]\n");
+               handled[0] |= BIT_RDU;
+       }
+
+       if (pHalData->IntArray[1] & BIT_FOVW) {
+               DBG_COUNTER(adapter->int_logs.rx_fovw);
+
+               if (printk_ratelimit())
+                       RTW_WARN("[FOVW]\n");
+               handled[1] |= BIT_FOVW;
+       }
+
+       if (pHalData->IntArray[1] & BIT_RXERR_INT) {
+               DBG_COUNTER(adapter->int_logs.err);
+               RTW_WARN("[RXERR]\n");
+               handled[1] |= BIT_RXERR_INT;
+       }
+
+       /* <2> handle rx in napi poll */
+       if (pHalData->IntArray[0] & NAPI_EVENT0) {
+               DBG_COUNTER(adapter->int_logs.rx);
+
+               if (napi_schedule_prep(&adapter->napi)) {
+                       handled[0] |= (pHalData->IntArray[0] & NAPI_EVENT0);
+                       /* disable irq */
+                       rtl8822be_napi_irq_disable(adapter);
+                       /* tell system we have work to be done */
+                       __napi_schedule(&adapter->napi);
+               } else {
+                       RTW_WARN("driver bug! interrupt while in poll\n");
+                        /* FIX by disabling interrupts  */
+                       rtl8822be_napi_irq_disable(adapter);
+               }
+       }
+
+       /* <3> handle tx directly */
+       if (pHalData->IntArray[1] & BIT_TXFOVW) {
+               DBG_COUNTER(adapter->int_logs.txfovw);
+
+               if (printk_ratelimit())
+                       RTW_WARN("[TXFOVW]\n");
+               handled[1] |= BIT_TXFOVW;
+       }
+
+       if (pHalData->IntArray[1] & BIT_TXERR_INT) {
+               DBG_COUNTER(adapter->int_logs.err);
+               RTW_WARN("[TXERR]\n");
+               handled[1] |= BIT_TXERR_INT;
+       }
+
+       if (pHalData->IntArray[0] & NAPI_EVENT_TX0)
+               rtl8822be_tx_handler(adapter, pHalData->IntArray, handled);
+
+       /* check un-handled interrupt */
+       if ((pHalData->IntArray[0] & (~handled[0])) ||
+               (pHalData->IntArray[1] & (~handled[1])) ||
+               (pHalData->IntArray[3] & (~handled[3]))) {
+
+               RTW_WARN("Unhandled ISR = %x, %x, %x\n",
+                       (pHalData->IntArray[0] & (~handled[0])),
+                       (pHalData->IntArray[1] & (~handled[1])),
+                       (pHalData->IntArray[3] & (~handled[3])));
+       }
+
+       _exit_critical(&pdvobjpriv->irq_th_lock, &irqL);
+
+       return IRQ_RETVAL(handled[0] || handled[1] || handled[3]);
+}
+
+static int rtl8822be_napi_poll(PADAPTER adapter, int budget)
+{
+       int remaing_rxdesc;
+       int work_done = 0;
+       struct registry_priv *reg = &adapter->registrypriv;
+
+       remaing_rxdesc = rtl8822be_check_rxdesc_remain(adapter, RX_MPDU_QUEUE);
+       do {
+               work_done += rtl8822be_rx_mpdu(adapter, remaing_rxdesc,
+                               budget);
+               budget -= work_done;
+
+               /* check rx again */
+               remaing_rxdesc = rtl8822be_check_rxdesc_remain(adapter,
+                               RX_MPDU_QUEUE);
+
+               if (remaing_rxdesc) {
+                       if (reg->napi_debug && printk_ratelimit())
+                               RTW_INFO("[RX %d]\n", remaing_rxdesc);
+                       break;
+               }
+
+       } while (remaing_rxdesc > 0 && budget > 0);
+
+       return work_done;
+}
+#endif /* CONFIG_NAPI */
+
+void rtl8822be_set_hal_ops(PADAPTER padapter)
+{
+       struct hal_ops *ops;
+       int err;
+
+       err = rtl8822be_halmac_init_adapter(padapter);
+       if (err) {
+               RTW_INFO("%s: [ERROR]HALMAC initialize FAIL!\n", __func__);
+               return;
+       }
+
+       rtl8822b_set_hal_ops(padapter);
+
+       ops = &padapter->HalFunc;
+
+       ops->hal_init = rtl8822be_init;
+       ops->inirp_init = rtl8822be_init_bd;
+       ops->inirp_deinit = rtl8822be_free_bd;
+       ops->irp_reset = rtl8822be_reset_bd;
+       ops->init_xmit_priv = rtl8822be_init_xmit_priv;
+       ops->free_xmit_priv = rtl8822be_free_xmit_priv;
+       ops->init_recv_priv = rtl8822be_init_recv_priv;
+       ops->free_recv_priv = rtl8822be_free_recv_priv;
+
+#ifdef CONFIG_SW_LED
+       ops->InitSwLeds = rtl8822be_InitSwLeds;
+       ops->DeInitSwLeds = rtl8822be_DeInitSwLeds;
+#else /* case of hw led or no led */
+       ops->InitSwLeds = NULL;
+       ops->DeInitSwLeds = NULL;
+#endif
+
+       ops->init_default_value = rtl8822be_init_default_value;
+       ops->intf_chip_configure = intf_chip_configure;
+       ops->read_adapter_info = read_adapter_info;
+
+       ops->enable_interrupt = rtl8822be_enable_interrupt;
+       ops->disable_interrupt = rtl8822be_disable_interrupt;
+#ifdef CONFIG_NAPI
+       ops->interrupt_handler = rtl8822be_napi_interrupt;
+#else
+       ops->interrupt_handler = rtl8822be_interrupt;
+#endif
+       /*
+               ops->check_ips_status = check_ips_status;
+       */
+       ops->clear_interrupt = rtl8822be_clear_interrupt;
+#if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN) ||\
+       defined(CONFIG_PCI_HCI)
+       /*
+               ops->clear_interrupt = clear_interrupt_all;
+       */
+#endif
+       ops->GetHalDefVarHandler = rtl8822be_gethaldefvar;
+       ops->SetHalDefVarHandler = rtl8822be_sethaldefvar;
+       ops->hal_xmit = rtl8822be_hal_xmit;
+       ops->mgnt_xmit = rtl8822be_mgnt_xmit;
+       ops->hal_xmitframe_enqueue = rtl8822be_hal_xmitframe_enqueue;
+#ifdef CONFIG_HOSTAPD_MLME
+       ops->hostap_mgnt_xmit_entry = rtl8822be_hostap_mgnt_xmit_entry;
+#endif
+
+#ifdef CONFIG_XMIT_THREAD_MODE
+       /* vincent TODO */
+       ops->xmit_thread_handler = rtl8822be_xmit_buf_handler;
+#endif
+
+#ifdef CONFIG_NAPI
+       ops->napi_irq_disable = rtl8822be_napi_irq_disable;
+       ops->napi_irq_enable = rtl8822be_napi_irq_enable;
+       ops->napi_poll = rtl8822be_napi_poll;
+#endif
+}