18e93258fSBjoern A. Zeeb // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 28e93258fSBjoern A. Zeeb /* Copyright(c) 2020 Realtek Corporation 38e93258fSBjoern A. Zeeb */ 48e93258fSBjoern A. Zeeb 58e93258fSBjoern A. Zeeb #if defined(__FreeBSD__) 68e93258fSBjoern A. Zeeb #define LINUXKPI_PARAM_PREFIX rtw89_pci_ 78e93258fSBjoern A. Zeeb #endif 88e93258fSBjoern A. Zeeb 98e93258fSBjoern A. Zeeb #include <linux/pci.h> 10c8e7f78aSBjoern A. Zeeb #if defined(__FreeBSD__) 11c8e7f78aSBjoern A. Zeeb #include <sys/rman.h> 12c8e7f78aSBjoern A. Zeeb #endif 138e93258fSBjoern A. Zeeb 148e93258fSBjoern A. Zeeb #include "mac.h" 158e93258fSBjoern A. Zeeb #include "pci.h" 168e93258fSBjoern A. Zeeb #include "reg.h" 178e93258fSBjoern A. Zeeb #include "ser.h" 188e93258fSBjoern A. Zeeb 198e93258fSBjoern A. Zeeb static bool rtw89_pci_disable_clkreq; 208e93258fSBjoern A. Zeeb static bool rtw89_pci_disable_aspm_l1; 218e93258fSBjoern A. Zeeb static bool rtw89_pci_disable_l1ss; 228e93258fSBjoern A. Zeeb module_param_named(disable_clkreq, rtw89_pci_disable_clkreq, bool, 0644); 238e93258fSBjoern A. Zeeb module_param_named(disable_aspm_l1, rtw89_pci_disable_aspm_l1, bool, 0644); 248e93258fSBjoern A. Zeeb module_param_named(disable_aspm_l1ss, rtw89_pci_disable_l1ss, bool, 0644); 258e93258fSBjoern A. Zeeb MODULE_PARM_DESC(disable_clkreq, "Set Y to disable PCI clkreq support"); 268e93258fSBjoern A. Zeeb MODULE_PARM_DESC(disable_aspm_l1, "Set Y to disable PCI ASPM L1 support"); 278e93258fSBjoern A. Zeeb MODULE_PARM_DESC(disable_aspm_l1ss, "Set Y to disable PCI L1SS support"); 288e93258fSBjoern A. Zeeb 29*6d67aabdSBjoern A. Zeeb static int rtw89_pci_get_phy_offset_by_link_speed(struct rtw89_dev *rtwdev, 30*6d67aabdSBjoern A. Zeeb u32 *phy_offset) 31*6d67aabdSBjoern A. Zeeb { 32*6d67aabdSBjoern A. Zeeb struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; 33*6d67aabdSBjoern A. Zeeb struct pci_dev *pdev = rtwpci->pdev; 34*6d67aabdSBjoern A. Zeeb u32 val; 35*6d67aabdSBjoern A. Zeeb int ret; 36*6d67aabdSBjoern A. Zeeb 37*6d67aabdSBjoern A. Zeeb ret = pci_read_config_dword(pdev, RTW89_PCIE_L1_STS_V1, &val); 38*6d67aabdSBjoern A. Zeeb if (ret) 39*6d67aabdSBjoern A. Zeeb return ret; 40*6d67aabdSBjoern A. Zeeb 41*6d67aabdSBjoern A. Zeeb val = u32_get_bits(val, RTW89_BCFG_LINK_SPEED_MASK); 42*6d67aabdSBjoern A. Zeeb if (val == RTW89_PCIE_GEN1_SPEED) { 43*6d67aabdSBjoern A. Zeeb *phy_offset = R_RAC_DIRECT_OFFSET_G1; 44*6d67aabdSBjoern A. Zeeb } else if (val == RTW89_PCIE_GEN2_SPEED) { 45*6d67aabdSBjoern A. Zeeb *phy_offset = R_RAC_DIRECT_OFFSET_G2; 46*6d67aabdSBjoern A. Zeeb } else { 47*6d67aabdSBjoern A. Zeeb rtw89_warn(rtwdev, "Unknown PCI link speed %d\n", val); 48*6d67aabdSBjoern A. Zeeb return -EFAULT; 49*6d67aabdSBjoern A. Zeeb } 50*6d67aabdSBjoern A. Zeeb 51*6d67aabdSBjoern A. Zeeb return 0; 52*6d67aabdSBjoern A. Zeeb } 53*6d67aabdSBjoern A. Zeeb 54*6d67aabdSBjoern A. Zeeb static int rtw89_pci_rst_bdram_ax(struct rtw89_dev *rtwdev) 558e93258fSBjoern A. Zeeb { 568e93258fSBjoern A. Zeeb u32 val; 578e93258fSBjoern A. Zeeb int ret; 588e93258fSBjoern A. Zeeb 59*6d67aabdSBjoern A. Zeeb rtw89_write32_set(rtwdev, R_AX_PCIE_INIT_CFG1, B_AX_RST_BDRAM); 608e93258fSBjoern A. Zeeb 618e93258fSBjoern A. Zeeb ret = read_poll_timeout_atomic(rtw89_read32, val, !(val & B_AX_RST_BDRAM), 628e93258fSBjoern A. Zeeb 1, RTW89_PCI_POLL_BDRAM_RST_CNT, false, 638e93258fSBjoern A. Zeeb rtwdev, R_AX_PCIE_INIT_CFG1); 648e93258fSBjoern A. Zeeb 65*6d67aabdSBjoern A. Zeeb return ret; 668e93258fSBjoern A. Zeeb } 678e93258fSBjoern A. Zeeb 688e93258fSBjoern A. Zeeb static u32 rtw89_pci_dma_recalc(struct rtw89_dev *rtwdev, 698e93258fSBjoern A. Zeeb struct rtw89_pci_dma_ring *bd_ring, 708e93258fSBjoern A. Zeeb u32 cur_idx, bool tx) 718e93258fSBjoern A. Zeeb { 72*6d67aabdSBjoern A. Zeeb const struct rtw89_pci_info *info = rtwdev->pci_info; 738e93258fSBjoern A. Zeeb u32 cnt, cur_rp, wp, rp, len; 748e93258fSBjoern A. Zeeb 758e93258fSBjoern A. Zeeb rp = bd_ring->rp; 768e93258fSBjoern A. Zeeb wp = bd_ring->wp; 778e93258fSBjoern A. Zeeb len = bd_ring->len; 788e93258fSBjoern A. Zeeb 798e93258fSBjoern A. Zeeb cur_rp = FIELD_GET(TXBD_HW_IDX_MASK, cur_idx); 80*6d67aabdSBjoern A. Zeeb if (tx) { 818e93258fSBjoern A. Zeeb cnt = cur_rp >= rp ? cur_rp - rp : len - (rp - cur_rp); 82*6d67aabdSBjoern A. Zeeb } else { 83*6d67aabdSBjoern A. Zeeb if (info->rx_ring_eq_is_full) 84*6d67aabdSBjoern A. Zeeb wp += 1; 85*6d67aabdSBjoern A. Zeeb 868e93258fSBjoern A. Zeeb cnt = cur_rp >= wp ? cur_rp - wp : len - (wp - cur_rp); 87*6d67aabdSBjoern A. Zeeb } 888e93258fSBjoern A. Zeeb 898e93258fSBjoern A. Zeeb bd_ring->rp = cur_rp; 908e93258fSBjoern A. Zeeb 918e93258fSBjoern A. Zeeb return cnt; 928e93258fSBjoern A. Zeeb } 938e93258fSBjoern A. Zeeb 948e93258fSBjoern A. Zeeb static u32 rtw89_pci_txbd_recalc(struct rtw89_dev *rtwdev, 958e93258fSBjoern A. Zeeb struct rtw89_pci_tx_ring *tx_ring) 968e93258fSBjoern A. Zeeb { 978e93258fSBjoern A. Zeeb struct rtw89_pci_dma_ring *bd_ring = &tx_ring->bd_ring; 988e93258fSBjoern A. Zeeb u32 addr_idx = bd_ring->addr.idx; 998e93258fSBjoern A. Zeeb u32 cnt, idx; 1008e93258fSBjoern A. Zeeb 1018e93258fSBjoern A. Zeeb idx = rtw89_read32(rtwdev, addr_idx); 1028e93258fSBjoern A. Zeeb cnt = rtw89_pci_dma_recalc(rtwdev, bd_ring, idx, true); 1038e93258fSBjoern A. Zeeb 1048e93258fSBjoern A. Zeeb return cnt; 1058e93258fSBjoern A. Zeeb } 1068e93258fSBjoern A. Zeeb 1078e93258fSBjoern A. Zeeb static void rtw89_pci_release_fwcmd(struct rtw89_dev *rtwdev, 1088e93258fSBjoern A. Zeeb struct rtw89_pci *rtwpci, 1098e93258fSBjoern A. Zeeb u32 cnt, bool release_all) 1108e93258fSBjoern A. Zeeb { 1118e93258fSBjoern A. Zeeb struct rtw89_pci_tx_data *tx_data; 1128e93258fSBjoern A. Zeeb struct sk_buff *skb; 1138e93258fSBjoern A. Zeeb u32 qlen; 1148e93258fSBjoern A. Zeeb 1158e93258fSBjoern A. Zeeb while (cnt--) { 1168e93258fSBjoern A. Zeeb skb = skb_dequeue(&rtwpci->h2c_queue); 1178e93258fSBjoern A. Zeeb if (!skb) { 1188e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "failed to pre-release fwcmd\n"); 1198e93258fSBjoern A. Zeeb return; 1208e93258fSBjoern A. Zeeb } 1218e93258fSBjoern A. Zeeb skb_queue_tail(&rtwpci->h2c_release_queue, skb); 1228e93258fSBjoern A. Zeeb } 1238e93258fSBjoern A. Zeeb 1248e93258fSBjoern A. Zeeb qlen = skb_queue_len(&rtwpci->h2c_release_queue); 1258e93258fSBjoern A. Zeeb if (!release_all) 1268e93258fSBjoern A. Zeeb qlen = qlen > RTW89_PCI_MULTITAG ? qlen - RTW89_PCI_MULTITAG : 0; 1278e93258fSBjoern A. Zeeb 1288e93258fSBjoern A. Zeeb while (qlen--) { 1298e93258fSBjoern A. Zeeb skb = skb_dequeue(&rtwpci->h2c_release_queue); 1308e93258fSBjoern A. Zeeb if (!skb) { 1318e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "failed to release fwcmd\n"); 1328e93258fSBjoern A. Zeeb return; 1338e93258fSBjoern A. Zeeb } 1348e93258fSBjoern A. Zeeb tx_data = RTW89_PCI_TX_SKB_CB(skb); 1358e93258fSBjoern A. Zeeb dma_unmap_single(&rtwpci->pdev->dev, tx_data->dma, skb->len, 1368e93258fSBjoern A. Zeeb DMA_TO_DEVICE); 1378e93258fSBjoern A. Zeeb dev_kfree_skb_any(skb); 1388e93258fSBjoern A. Zeeb } 1398e93258fSBjoern A. Zeeb } 1408e93258fSBjoern A. Zeeb 1418e93258fSBjoern A. Zeeb static void rtw89_pci_reclaim_tx_fwcmd(struct rtw89_dev *rtwdev, 1428e93258fSBjoern A. Zeeb struct rtw89_pci *rtwpci) 1438e93258fSBjoern A. Zeeb { 1448e93258fSBjoern A. Zeeb struct rtw89_pci_tx_ring *tx_ring = &rtwpci->tx_rings[RTW89_TXCH_CH12]; 1458e93258fSBjoern A. Zeeb u32 cnt; 1468e93258fSBjoern A. Zeeb 1478e93258fSBjoern A. Zeeb cnt = rtw89_pci_txbd_recalc(rtwdev, tx_ring); 1488e93258fSBjoern A. Zeeb if (!cnt) 1498e93258fSBjoern A. Zeeb return; 1508e93258fSBjoern A. Zeeb rtw89_pci_release_fwcmd(rtwdev, rtwpci, cnt, false); 1518e93258fSBjoern A. Zeeb } 1528e93258fSBjoern A. Zeeb 1538e93258fSBjoern A. Zeeb static u32 rtw89_pci_rxbd_recalc(struct rtw89_dev *rtwdev, 1548e93258fSBjoern A. Zeeb struct rtw89_pci_rx_ring *rx_ring) 1558e93258fSBjoern A. Zeeb { 1568e93258fSBjoern A. Zeeb struct rtw89_pci_dma_ring *bd_ring = &rx_ring->bd_ring; 1578e93258fSBjoern A. Zeeb u32 addr_idx = bd_ring->addr.idx; 1588e93258fSBjoern A. Zeeb u32 cnt, idx; 1598e93258fSBjoern A. Zeeb 1608e93258fSBjoern A. Zeeb idx = rtw89_read32(rtwdev, addr_idx); 1618e93258fSBjoern A. Zeeb cnt = rtw89_pci_dma_recalc(rtwdev, bd_ring, idx, false); 1628e93258fSBjoern A. Zeeb 1638e93258fSBjoern A. Zeeb return cnt; 1648e93258fSBjoern A. Zeeb } 1658e93258fSBjoern A. Zeeb 1668e93258fSBjoern A. Zeeb static void rtw89_pci_sync_skb_for_cpu(struct rtw89_dev *rtwdev, 1678e93258fSBjoern A. Zeeb struct sk_buff *skb) 1688e93258fSBjoern A. Zeeb { 1698e93258fSBjoern A. Zeeb struct rtw89_pci_rx_info *rx_info; 1708e93258fSBjoern A. Zeeb dma_addr_t dma; 1718e93258fSBjoern A. Zeeb 1728e93258fSBjoern A. Zeeb rx_info = RTW89_PCI_RX_SKB_CB(skb); 1738e93258fSBjoern A. Zeeb dma = rx_info->dma; 1748e93258fSBjoern A. Zeeb dma_sync_single_for_cpu(rtwdev->dev, dma, RTW89_PCI_RX_BUF_SIZE, 1758e93258fSBjoern A. Zeeb DMA_FROM_DEVICE); 1768e93258fSBjoern A. Zeeb } 1778e93258fSBjoern A. Zeeb 1788e93258fSBjoern A. Zeeb static void rtw89_pci_sync_skb_for_device(struct rtw89_dev *rtwdev, 1798e93258fSBjoern A. Zeeb struct sk_buff *skb) 1808e93258fSBjoern A. Zeeb { 1818e93258fSBjoern A. Zeeb struct rtw89_pci_rx_info *rx_info; 1828e93258fSBjoern A. Zeeb dma_addr_t dma; 1838e93258fSBjoern A. Zeeb 1848e93258fSBjoern A. Zeeb rx_info = RTW89_PCI_RX_SKB_CB(skb); 1858e93258fSBjoern A. Zeeb dma = rx_info->dma; 1868e93258fSBjoern A. Zeeb dma_sync_single_for_device(rtwdev->dev, dma, RTW89_PCI_RX_BUF_SIZE, 1878e93258fSBjoern A. Zeeb DMA_FROM_DEVICE); 1888e93258fSBjoern A. Zeeb } 1898e93258fSBjoern A. Zeeb 190*6d67aabdSBjoern A. Zeeb static void rtw89_pci_rxbd_info_update(struct rtw89_dev *rtwdev, 1918e93258fSBjoern A. Zeeb struct sk_buff *skb) 1928e93258fSBjoern A. Zeeb { 1938e93258fSBjoern A. Zeeb struct rtw89_pci_rx_info *rx_info = RTW89_PCI_RX_SKB_CB(skb); 194*6d67aabdSBjoern A. Zeeb struct rtw89_pci_rxbd_info *rxbd_info; 195*6d67aabdSBjoern A. Zeeb __le32 info; 1968e93258fSBjoern A. Zeeb 1978e93258fSBjoern A. Zeeb rxbd_info = (struct rtw89_pci_rxbd_info *)skb->data; 198*6d67aabdSBjoern A. Zeeb info = rxbd_info->dword; 199*6d67aabdSBjoern A. Zeeb 200*6d67aabdSBjoern A. Zeeb rx_info->fs = le32_get_bits(info, RTW89_PCI_RXBD_FS); 201*6d67aabdSBjoern A. Zeeb rx_info->ls = le32_get_bits(info, RTW89_PCI_RXBD_LS); 202*6d67aabdSBjoern A. Zeeb rx_info->len = le32_get_bits(info, RTW89_PCI_RXBD_WRITE_SIZE); 203*6d67aabdSBjoern A. Zeeb rx_info->tag = le32_get_bits(info, RTW89_PCI_RXBD_TAG); 204*6d67aabdSBjoern A. Zeeb } 205*6d67aabdSBjoern A. Zeeb 206*6d67aabdSBjoern A. Zeeb static int rtw89_pci_validate_rx_tag(struct rtw89_dev *rtwdev, 207*6d67aabdSBjoern A. Zeeb struct rtw89_pci_rx_ring *rx_ring, 208*6d67aabdSBjoern A. Zeeb struct sk_buff *skb) 209*6d67aabdSBjoern A. Zeeb { 210*6d67aabdSBjoern A. Zeeb struct rtw89_pci_rx_info *rx_info = RTW89_PCI_RX_SKB_CB(skb); 211*6d67aabdSBjoern A. Zeeb const struct rtw89_pci_info *info = rtwdev->pci_info; 212*6d67aabdSBjoern A. Zeeb u32 target_rx_tag; 213*6d67aabdSBjoern A. Zeeb 214*6d67aabdSBjoern A. Zeeb if (!info->check_rx_tag) 215*6d67aabdSBjoern A. Zeeb return 0; 216*6d67aabdSBjoern A. Zeeb 217*6d67aabdSBjoern A. Zeeb /* valid range is 1 ~ 0x1FFF */ 218*6d67aabdSBjoern A. Zeeb if (rx_ring->target_rx_tag == 0) 219*6d67aabdSBjoern A. Zeeb target_rx_tag = 1; 220*6d67aabdSBjoern A. Zeeb else 221*6d67aabdSBjoern A. Zeeb target_rx_tag = rx_ring->target_rx_tag; 222*6d67aabdSBjoern A. Zeeb 223*6d67aabdSBjoern A. Zeeb if (rx_info->tag != target_rx_tag) { 224*6d67aabdSBjoern A. Zeeb rtw89_debug(rtwdev, RTW89_DBG_UNEXP, "mismatch RX tag 0x%x 0x%x\n", 225*6d67aabdSBjoern A. Zeeb rx_info->tag, target_rx_tag); 226*6d67aabdSBjoern A. Zeeb return -EAGAIN; 227*6d67aabdSBjoern A. Zeeb } 2288e93258fSBjoern A. Zeeb 2298e93258fSBjoern A. Zeeb return 0; 2308e93258fSBjoern A. Zeeb } 2318e93258fSBjoern A. Zeeb 232*6d67aabdSBjoern A. Zeeb static 233*6d67aabdSBjoern A. Zeeb int rtw89_pci_sync_skb_for_device_and_validate_rx_info(struct rtw89_dev *rtwdev, 234*6d67aabdSBjoern A. Zeeb struct rtw89_pci_rx_ring *rx_ring, 235*6d67aabdSBjoern A. Zeeb struct sk_buff *skb) 236*6d67aabdSBjoern A. Zeeb { 237*6d67aabdSBjoern A. Zeeb struct rtw89_pci_rx_info *rx_info = RTW89_PCI_RX_SKB_CB(skb); 238*6d67aabdSBjoern A. Zeeb int rx_tag_retry = 100; 239*6d67aabdSBjoern A. Zeeb int ret; 240*6d67aabdSBjoern A. Zeeb 241*6d67aabdSBjoern A. Zeeb do { 242*6d67aabdSBjoern A. Zeeb rtw89_pci_sync_skb_for_cpu(rtwdev, skb); 243*6d67aabdSBjoern A. Zeeb rtw89_pci_rxbd_info_update(rtwdev, skb); 244*6d67aabdSBjoern A. Zeeb 245*6d67aabdSBjoern A. Zeeb ret = rtw89_pci_validate_rx_tag(rtwdev, rx_ring, skb); 246*6d67aabdSBjoern A. Zeeb if (ret != -EAGAIN) 247*6d67aabdSBjoern A. Zeeb break; 248*6d67aabdSBjoern A. Zeeb } while (rx_tag_retry--); 249*6d67aabdSBjoern A. Zeeb 250*6d67aabdSBjoern A. Zeeb /* update target rx_tag for next RX */ 251*6d67aabdSBjoern A. Zeeb rx_ring->target_rx_tag = rx_info->tag + 1; 252*6d67aabdSBjoern A. Zeeb 253*6d67aabdSBjoern A. Zeeb return ret; 254*6d67aabdSBjoern A. Zeeb } 255*6d67aabdSBjoern A. Zeeb 256*6d67aabdSBjoern A. Zeeb static void rtw89_pci_ctrl_txdma_ch_ax(struct rtw89_dev *rtwdev, bool enable) 257e2340276SBjoern A. Zeeb { 258e2340276SBjoern A. Zeeb const struct rtw89_pci_info *info = rtwdev->pci_info; 259e2340276SBjoern A. Zeeb const struct rtw89_reg_def *dma_stop1 = &info->dma_stop1; 260e2340276SBjoern A. Zeeb const struct rtw89_reg_def *dma_stop2 = &info->dma_stop2; 261e2340276SBjoern A. Zeeb 262e2340276SBjoern A. Zeeb if (enable) { 263e2340276SBjoern A. Zeeb rtw89_write32_clr(rtwdev, dma_stop1->addr, dma_stop1->mask); 264e2340276SBjoern A. Zeeb if (dma_stop2->addr) 265e2340276SBjoern A. Zeeb rtw89_write32_clr(rtwdev, dma_stop2->addr, dma_stop2->mask); 266e2340276SBjoern A. Zeeb } else { 267e2340276SBjoern A. Zeeb rtw89_write32_set(rtwdev, dma_stop1->addr, dma_stop1->mask); 268e2340276SBjoern A. Zeeb if (dma_stop2->addr) 269e2340276SBjoern A. Zeeb rtw89_write32_set(rtwdev, dma_stop2->addr, dma_stop2->mask); 270e2340276SBjoern A. Zeeb } 271e2340276SBjoern A. Zeeb } 272e2340276SBjoern A. Zeeb 273*6d67aabdSBjoern A. Zeeb static void rtw89_pci_ctrl_txdma_fw_ch_ax(struct rtw89_dev *rtwdev, bool enable) 274e2340276SBjoern A. Zeeb { 275e2340276SBjoern A. Zeeb const struct rtw89_pci_info *info = rtwdev->pci_info; 276e2340276SBjoern A. Zeeb const struct rtw89_reg_def *dma_stop1 = &info->dma_stop1; 277e2340276SBjoern A. Zeeb 278e2340276SBjoern A. Zeeb if (enable) 279e2340276SBjoern A. Zeeb rtw89_write32_clr(rtwdev, dma_stop1->addr, B_AX_STOP_CH12); 280e2340276SBjoern A. Zeeb else 281e2340276SBjoern A. Zeeb rtw89_write32_set(rtwdev, dma_stop1->addr, B_AX_STOP_CH12); 282e2340276SBjoern A. Zeeb } 283e2340276SBjoern A. Zeeb 2848e93258fSBjoern A. Zeeb static bool 2858e93258fSBjoern A. Zeeb rtw89_skb_put_rx_data(struct rtw89_dev *rtwdev, bool fs, bool ls, 2868e93258fSBjoern A. Zeeb struct sk_buff *new, 2878e93258fSBjoern A. Zeeb const struct sk_buff *skb, u32 offset, 2888e93258fSBjoern A. Zeeb const struct rtw89_pci_rx_info *rx_info, 2898e93258fSBjoern A. Zeeb const struct rtw89_rx_desc_info *desc_info) 2908e93258fSBjoern A. Zeeb { 2918e93258fSBjoern A. Zeeb u32 copy_len = rx_info->len - offset; 2928e93258fSBjoern A. Zeeb 2938e93258fSBjoern A. Zeeb if (unlikely(skb_tailroom(new) < copy_len)) { 2948e93258fSBjoern A. Zeeb rtw89_debug(rtwdev, RTW89_DBG_TXRX, 2958e93258fSBjoern A. Zeeb "invalid rx data length bd_len=%d desc_len=%d offset=%d (fs=%d ls=%d)\n", 2968e93258fSBjoern A. Zeeb rx_info->len, desc_info->pkt_size, offset, fs, ls); 2978e93258fSBjoern A. Zeeb rtw89_hex_dump(rtwdev, RTW89_DBG_TXRX, "rx_data: ", 2988e93258fSBjoern A. Zeeb skb->data, rx_info->len); 2998e93258fSBjoern A. Zeeb /* length of a single segment skb is desc_info->pkt_size */ 3008e93258fSBjoern A. Zeeb if (fs && ls) { 3018e93258fSBjoern A. Zeeb copy_len = desc_info->pkt_size; 3028e93258fSBjoern A. Zeeb } else { 3038e93258fSBjoern A. Zeeb rtw89_info(rtwdev, "drop rx data due to invalid length\n"); 3048e93258fSBjoern A. Zeeb return false; 3058e93258fSBjoern A. Zeeb } 3068e93258fSBjoern A. Zeeb } 3078e93258fSBjoern A. Zeeb 3088e93258fSBjoern A. Zeeb skb_put_data(new, skb->data + offset, copy_len); 3098e93258fSBjoern A. Zeeb 3108e93258fSBjoern A. Zeeb return true; 3118e93258fSBjoern A. Zeeb } 3128e93258fSBjoern A. Zeeb 313*6d67aabdSBjoern A. Zeeb static u32 rtw89_pci_get_rx_skb_idx(struct rtw89_dev *rtwdev, 314*6d67aabdSBjoern A. Zeeb struct rtw89_pci_dma_ring *bd_ring) 315*6d67aabdSBjoern A. Zeeb { 316*6d67aabdSBjoern A. Zeeb const struct rtw89_pci_info *info = rtwdev->pci_info; 317*6d67aabdSBjoern A. Zeeb u32 wp = bd_ring->wp; 318*6d67aabdSBjoern A. Zeeb 319*6d67aabdSBjoern A. Zeeb if (!info->rx_ring_eq_is_full) 320*6d67aabdSBjoern A. Zeeb return wp; 321*6d67aabdSBjoern A. Zeeb 322*6d67aabdSBjoern A. Zeeb if (++wp >= bd_ring->len) 323*6d67aabdSBjoern A. Zeeb wp = 0; 324*6d67aabdSBjoern A. Zeeb 325*6d67aabdSBjoern A. Zeeb return wp; 326*6d67aabdSBjoern A. Zeeb } 327*6d67aabdSBjoern A. Zeeb 3288e93258fSBjoern A. Zeeb static u32 rtw89_pci_rxbd_deliver_skbs(struct rtw89_dev *rtwdev, 3298e93258fSBjoern A. Zeeb struct rtw89_pci_rx_ring *rx_ring) 3308e93258fSBjoern A. Zeeb { 3318e93258fSBjoern A. Zeeb struct rtw89_pci_dma_ring *bd_ring = &rx_ring->bd_ring; 3328e93258fSBjoern A. Zeeb struct rtw89_pci_rx_info *rx_info; 3338e93258fSBjoern A. Zeeb struct rtw89_rx_desc_info *desc_info = &rx_ring->diliver_desc; 3348e93258fSBjoern A. Zeeb struct sk_buff *new = rx_ring->diliver_skb; 3358e93258fSBjoern A. Zeeb struct sk_buff *skb; 3368e93258fSBjoern A. Zeeb u32 rxinfo_size = sizeof(struct rtw89_pci_rxbd_info); 337*6d67aabdSBjoern A. Zeeb u32 skb_idx; 3388e93258fSBjoern A. Zeeb u32 offset; 3398e93258fSBjoern A. Zeeb u32 cnt = 1; 3408e93258fSBjoern A. Zeeb bool fs, ls; 3418e93258fSBjoern A. Zeeb int ret; 3428e93258fSBjoern A. Zeeb 343*6d67aabdSBjoern A. Zeeb skb_idx = rtw89_pci_get_rx_skb_idx(rtwdev, bd_ring); 344*6d67aabdSBjoern A. Zeeb skb = rx_ring->buf[skb_idx]; 3458e93258fSBjoern A. Zeeb 346*6d67aabdSBjoern A. Zeeb ret = rtw89_pci_sync_skb_for_device_and_validate_rx_info(rtwdev, rx_ring, skb); 3478e93258fSBjoern A. Zeeb if (ret) { 3488e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "failed to update %d RXBD info: %d\n", 3498e93258fSBjoern A. Zeeb bd_ring->wp, ret); 3508e93258fSBjoern A. Zeeb goto err_sync_device; 3518e93258fSBjoern A. Zeeb } 3528e93258fSBjoern A. Zeeb 3538e93258fSBjoern A. Zeeb rx_info = RTW89_PCI_RX_SKB_CB(skb); 3548e93258fSBjoern A. Zeeb fs = rx_info->fs; 3558e93258fSBjoern A. Zeeb ls = rx_info->ls; 3568e93258fSBjoern A. Zeeb 3578e93258fSBjoern A. Zeeb if (fs) { 3588e93258fSBjoern A. Zeeb if (new) { 3598e93258fSBjoern A. Zeeb rtw89_debug(rtwdev, RTW89_DBG_UNEXP, 3608e93258fSBjoern A. Zeeb "skb should not be ready before first segment start\n"); 3618e93258fSBjoern A. Zeeb goto err_sync_device; 3628e93258fSBjoern A. Zeeb } 3638e93258fSBjoern A. Zeeb if (desc_info->ready) { 3648e93258fSBjoern A. Zeeb rtw89_warn(rtwdev, "desc info should not be ready before first segment start\n"); 3658e93258fSBjoern A. Zeeb goto err_sync_device; 3668e93258fSBjoern A. Zeeb } 3678e93258fSBjoern A. Zeeb 368e2340276SBjoern A. Zeeb rtw89_chip_query_rxdesc(rtwdev, desc_info, skb->data, rxinfo_size); 3698e93258fSBjoern A. Zeeb 370e2340276SBjoern A. Zeeb new = rtw89_alloc_skb_for_rx(rtwdev, desc_info->pkt_size); 3718e93258fSBjoern A. Zeeb if (!new) 3728e93258fSBjoern A. Zeeb goto err_sync_device; 3738e93258fSBjoern A. Zeeb 3748e93258fSBjoern A. Zeeb rx_ring->diliver_skb = new; 3758e93258fSBjoern A. Zeeb 3768e93258fSBjoern A. Zeeb /* first segment has RX desc */ 377e2340276SBjoern A. Zeeb offset = desc_info->offset + desc_info->rxd_len; 3788e93258fSBjoern A. Zeeb } else { 3798e93258fSBjoern A. Zeeb offset = sizeof(struct rtw89_pci_rxbd_info); 3808e93258fSBjoern A. Zeeb if (!new) { 3818e93258fSBjoern A. Zeeb rtw89_debug(rtwdev, RTW89_DBG_UNEXP, "no last skb\n"); 3828e93258fSBjoern A. Zeeb goto err_sync_device; 3838e93258fSBjoern A. Zeeb } 3848e93258fSBjoern A. Zeeb } 3858e93258fSBjoern A. Zeeb if (!rtw89_skb_put_rx_data(rtwdev, fs, ls, new, skb, offset, rx_info, desc_info)) 3868e93258fSBjoern A. Zeeb goto err_sync_device; 3878e93258fSBjoern A. Zeeb rtw89_pci_sync_skb_for_device(rtwdev, skb); 3888e93258fSBjoern A. Zeeb rtw89_pci_rxbd_increase(rx_ring, 1); 3898e93258fSBjoern A. Zeeb 3908e93258fSBjoern A. Zeeb if (!desc_info->ready) { 3918e93258fSBjoern A. Zeeb rtw89_warn(rtwdev, "no rx desc information\n"); 3928e93258fSBjoern A. Zeeb goto err_free_resource; 3938e93258fSBjoern A. Zeeb } 3948e93258fSBjoern A. Zeeb if (ls) { 3958e93258fSBjoern A. Zeeb rtw89_core_rx(rtwdev, desc_info, new); 3968e93258fSBjoern A. Zeeb rx_ring->diliver_skb = NULL; 3978e93258fSBjoern A. Zeeb desc_info->ready = false; 3988e93258fSBjoern A. Zeeb } 3998e93258fSBjoern A. Zeeb 4008e93258fSBjoern A. Zeeb return cnt; 4018e93258fSBjoern A. Zeeb 4028e93258fSBjoern A. Zeeb err_sync_device: 4038e93258fSBjoern A. Zeeb rtw89_pci_sync_skb_for_device(rtwdev, skb); 4048e93258fSBjoern A. Zeeb rtw89_pci_rxbd_increase(rx_ring, 1); 4058e93258fSBjoern A. Zeeb err_free_resource: 4068e93258fSBjoern A. Zeeb if (new) 4078e93258fSBjoern A. Zeeb dev_kfree_skb_any(new); 4088e93258fSBjoern A. Zeeb rx_ring->diliver_skb = NULL; 4098e93258fSBjoern A. Zeeb desc_info->ready = false; 4108e93258fSBjoern A. Zeeb 4118e93258fSBjoern A. Zeeb return cnt; 4128e93258fSBjoern A. Zeeb } 4138e93258fSBjoern A. Zeeb 4148e93258fSBjoern A. Zeeb static void rtw89_pci_rxbd_deliver(struct rtw89_dev *rtwdev, 4158e93258fSBjoern A. Zeeb struct rtw89_pci_rx_ring *rx_ring, 4168e93258fSBjoern A. Zeeb u32 cnt) 4178e93258fSBjoern A. Zeeb { 4188e93258fSBjoern A. Zeeb struct rtw89_pci_dma_ring *bd_ring = &rx_ring->bd_ring; 4198e93258fSBjoern A. Zeeb u32 rx_cnt; 4208e93258fSBjoern A. Zeeb 4218e93258fSBjoern A. Zeeb while (cnt && rtwdev->napi_budget_countdown > 0) { 4228e93258fSBjoern A. Zeeb rx_cnt = rtw89_pci_rxbd_deliver_skbs(rtwdev, rx_ring); 4238e93258fSBjoern A. Zeeb if (!rx_cnt) { 4248e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "failed to deliver RXBD skb\n"); 4258e93258fSBjoern A. Zeeb 4268e93258fSBjoern A. Zeeb /* skip the rest RXBD bufs */ 4278e93258fSBjoern A. Zeeb rtw89_pci_rxbd_increase(rx_ring, cnt); 4288e93258fSBjoern A. Zeeb break; 4298e93258fSBjoern A. Zeeb } 4308e93258fSBjoern A. Zeeb 4318e93258fSBjoern A. Zeeb cnt -= rx_cnt; 4328e93258fSBjoern A. Zeeb } 4338e93258fSBjoern A. Zeeb 4348e93258fSBjoern A. Zeeb rtw89_write16(rtwdev, bd_ring->addr.idx, bd_ring->wp); 4358e93258fSBjoern A. Zeeb } 4368e93258fSBjoern A. Zeeb 4378e93258fSBjoern A. Zeeb static int rtw89_pci_poll_rxq_dma(struct rtw89_dev *rtwdev, 4388e93258fSBjoern A. Zeeb struct rtw89_pci *rtwpci, int budget) 4398e93258fSBjoern A. Zeeb { 4408e93258fSBjoern A. Zeeb struct rtw89_pci_rx_ring *rx_ring; 4418e93258fSBjoern A. Zeeb int countdown = rtwdev->napi_budget_countdown; 4428e93258fSBjoern A. Zeeb u32 cnt; 4438e93258fSBjoern A. Zeeb 4448e93258fSBjoern A. Zeeb rx_ring = &rtwpci->rx_rings[RTW89_RXCH_RXQ]; 4458e93258fSBjoern A. Zeeb 4468e93258fSBjoern A. Zeeb cnt = rtw89_pci_rxbd_recalc(rtwdev, rx_ring); 4478e93258fSBjoern A. Zeeb if (!cnt) 4488e93258fSBjoern A. Zeeb return 0; 4498e93258fSBjoern A. Zeeb 4508e93258fSBjoern A. Zeeb cnt = min_t(u32, budget, cnt); 4518e93258fSBjoern A. Zeeb 4528e93258fSBjoern A. Zeeb rtw89_pci_rxbd_deliver(rtwdev, rx_ring, cnt); 4538e93258fSBjoern A. Zeeb 4548e93258fSBjoern A. Zeeb /* In case of flushing pending SKBs, the countdown may exceed. */ 4558e93258fSBjoern A. Zeeb if (rtwdev->napi_budget_countdown <= 0) 4568e93258fSBjoern A. Zeeb return budget; 4578e93258fSBjoern A. Zeeb 4588e93258fSBjoern A. Zeeb return budget - countdown; 4598e93258fSBjoern A. Zeeb } 4608e93258fSBjoern A. Zeeb 4618e93258fSBjoern A. Zeeb static void rtw89_pci_tx_status(struct rtw89_dev *rtwdev, 4628e93258fSBjoern A. Zeeb struct rtw89_pci_tx_ring *tx_ring, 4638e93258fSBjoern A. Zeeb struct sk_buff *skb, u8 tx_status) 4648e93258fSBjoern A. Zeeb { 465e2340276SBjoern A. Zeeb struct rtw89_tx_skb_data *skb_data = RTW89_TX_SKB_CB(skb); 4668e93258fSBjoern A. Zeeb struct ieee80211_tx_info *info; 4678e93258fSBjoern A. Zeeb 468e2340276SBjoern A. Zeeb rtw89_core_tx_wait_complete(rtwdev, skb_data, tx_status == RTW89_TX_DONE); 469e2340276SBjoern A. Zeeb 4708e93258fSBjoern A. Zeeb info = IEEE80211_SKB_CB(skb); 4718e93258fSBjoern A. Zeeb ieee80211_tx_info_clear_status(info); 4728e93258fSBjoern A. Zeeb 4738e93258fSBjoern A. Zeeb if (info->flags & IEEE80211_TX_CTL_NO_ACK) 4748e93258fSBjoern A. Zeeb info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED; 4758e93258fSBjoern A. Zeeb if (tx_status == RTW89_TX_DONE) { 4768e93258fSBjoern A. Zeeb info->flags |= IEEE80211_TX_STAT_ACK; 4778e93258fSBjoern A. Zeeb tx_ring->tx_acked++; 4788e93258fSBjoern A. Zeeb } else { 4798e93258fSBjoern A. Zeeb if (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS) 4808e93258fSBjoern A. Zeeb rtw89_debug(rtwdev, RTW89_DBG_FW, 4818e93258fSBjoern A. Zeeb "failed to TX of status %x\n", tx_status); 4828e93258fSBjoern A. Zeeb switch (tx_status) { 4838e93258fSBjoern A. Zeeb case RTW89_TX_RETRY_LIMIT: 4848e93258fSBjoern A. Zeeb tx_ring->tx_retry_lmt++; 4858e93258fSBjoern A. Zeeb break; 4868e93258fSBjoern A. Zeeb case RTW89_TX_LIFE_TIME: 4878e93258fSBjoern A. Zeeb tx_ring->tx_life_time++; 4888e93258fSBjoern A. Zeeb break; 4898e93258fSBjoern A. Zeeb case RTW89_TX_MACID_DROP: 4908e93258fSBjoern A. Zeeb tx_ring->tx_mac_id_drop++; 4918e93258fSBjoern A. Zeeb break; 4928e93258fSBjoern A. Zeeb default: 4938e93258fSBjoern A. Zeeb rtw89_warn(rtwdev, "invalid TX status %x\n", tx_status); 4948e93258fSBjoern A. Zeeb break; 4958e93258fSBjoern A. Zeeb } 4968e93258fSBjoern A. Zeeb } 4978e93258fSBjoern A. Zeeb 4988e93258fSBjoern A. Zeeb ieee80211_tx_status_ni(rtwdev->hw, skb); 4998e93258fSBjoern A. Zeeb } 5008e93258fSBjoern A. Zeeb 5018e93258fSBjoern A. Zeeb static void rtw89_pci_reclaim_txbd(struct rtw89_dev *rtwdev, struct rtw89_pci_tx_ring *tx_ring) 5028e93258fSBjoern A. Zeeb { 5038e93258fSBjoern A. Zeeb struct rtw89_pci_tx_wd *txwd; 5048e93258fSBjoern A. Zeeb u32 cnt; 5058e93258fSBjoern A. Zeeb 5068e93258fSBjoern A. Zeeb cnt = rtw89_pci_txbd_recalc(rtwdev, tx_ring); 5078e93258fSBjoern A. Zeeb while (cnt--) { 5088e93258fSBjoern A. Zeeb txwd = list_first_entry_or_null(&tx_ring->busy_pages, struct rtw89_pci_tx_wd, list); 5098e93258fSBjoern A. Zeeb if (!txwd) { 5108e93258fSBjoern A. Zeeb rtw89_warn(rtwdev, "No busy txwd pages available\n"); 5118e93258fSBjoern A. Zeeb break; 5128e93258fSBjoern A. Zeeb } 5138e93258fSBjoern A. Zeeb 5148e93258fSBjoern A. Zeeb list_del_init(&txwd->list); 5158e93258fSBjoern A. Zeeb 5168e93258fSBjoern A. Zeeb /* this skb has been freed by RPP */ 5178e93258fSBjoern A. Zeeb if (skb_queue_len(&txwd->queue) == 0) 5188e93258fSBjoern A. Zeeb rtw89_pci_enqueue_txwd(tx_ring, txwd); 5198e93258fSBjoern A. Zeeb } 5208e93258fSBjoern A. Zeeb } 5218e93258fSBjoern A. Zeeb 5228e93258fSBjoern A. Zeeb static void rtw89_pci_release_busy_txwd(struct rtw89_dev *rtwdev, 5238e93258fSBjoern A. Zeeb struct rtw89_pci_tx_ring *tx_ring) 5248e93258fSBjoern A. Zeeb { 5258e93258fSBjoern A. Zeeb struct rtw89_pci_tx_wd_ring *wd_ring = &tx_ring->wd_ring; 5268e93258fSBjoern A. Zeeb struct rtw89_pci_tx_wd *txwd; 5278e93258fSBjoern A. Zeeb int i; 5288e93258fSBjoern A. Zeeb 5298e93258fSBjoern A. Zeeb for (i = 0; i < wd_ring->page_num; i++) { 5308e93258fSBjoern A. Zeeb txwd = list_first_entry_or_null(&tx_ring->busy_pages, struct rtw89_pci_tx_wd, list); 5318e93258fSBjoern A. Zeeb if (!txwd) 5328e93258fSBjoern A. Zeeb break; 5338e93258fSBjoern A. Zeeb 5348e93258fSBjoern A. Zeeb list_del_init(&txwd->list); 5358e93258fSBjoern A. Zeeb } 5368e93258fSBjoern A. Zeeb } 5378e93258fSBjoern A. Zeeb 5388e93258fSBjoern A. Zeeb static void rtw89_pci_release_txwd_skb(struct rtw89_dev *rtwdev, 5398e93258fSBjoern A. Zeeb struct rtw89_pci_tx_ring *tx_ring, 5408e93258fSBjoern A. Zeeb struct rtw89_pci_tx_wd *txwd, u16 seq, 5418e93258fSBjoern A. Zeeb u8 tx_status) 5428e93258fSBjoern A. Zeeb { 5438e93258fSBjoern A. Zeeb struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; 5448e93258fSBjoern A. Zeeb struct rtw89_pci_tx_data *tx_data; 5458e93258fSBjoern A. Zeeb struct sk_buff *skb, *tmp; 5468e93258fSBjoern A. Zeeb u8 txch = tx_ring->txch; 5478e93258fSBjoern A. Zeeb 5488e93258fSBjoern A. Zeeb if (!list_empty(&txwd->list)) { 5498e93258fSBjoern A. Zeeb rtw89_pci_reclaim_txbd(rtwdev, tx_ring); 5508e93258fSBjoern A. Zeeb /* In low power mode, RPP can receive before updating of TX BD. 5518e93258fSBjoern A. Zeeb * In normal mode, it should not happen so give it a warning. 5528e93258fSBjoern A. Zeeb */ 5538e93258fSBjoern A. Zeeb if (!rtwpci->low_power && !list_empty(&txwd->list)) 5548e93258fSBjoern A. Zeeb rtw89_warn(rtwdev, "queue %d txwd %d is not idle\n", 5558e93258fSBjoern A. Zeeb txch, seq); 5568e93258fSBjoern A. Zeeb } 5578e93258fSBjoern A. Zeeb 5588e93258fSBjoern A. Zeeb skb_queue_walk_safe(&txwd->queue, skb, tmp) { 5598e93258fSBjoern A. Zeeb skb_unlink(skb, &txwd->queue); 5608e93258fSBjoern A. Zeeb 5618e93258fSBjoern A. Zeeb tx_data = RTW89_PCI_TX_SKB_CB(skb); 5628e93258fSBjoern A. Zeeb dma_unmap_single(&rtwpci->pdev->dev, tx_data->dma, skb->len, 5638e93258fSBjoern A. Zeeb DMA_TO_DEVICE); 5648e93258fSBjoern A. Zeeb 5658e93258fSBjoern A. Zeeb rtw89_pci_tx_status(rtwdev, tx_ring, skb, tx_status); 5668e93258fSBjoern A. Zeeb } 5678e93258fSBjoern A. Zeeb 5688e93258fSBjoern A. Zeeb if (list_empty(&txwd->list)) 5698e93258fSBjoern A. Zeeb rtw89_pci_enqueue_txwd(tx_ring, txwd); 5708e93258fSBjoern A. Zeeb } 5718e93258fSBjoern A. Zeeb 5728e93258fSBjoern A. Zeeb static void rtw89_pci_release_rpp(struct rtw89_dev *rtwdev, 5738e93258fSBjoern A. Zeeb struct rtw89_pci_rpp_fmt *rpp) 5748e93258fSBjoern A. Zeeb { 5758e93258fSBjoern A. Zeeb struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; 5768e93258fSBjoern A. Zeeb struct rtw89_pci_tx_ring *tx_ring; 5778e93258fSBjoern A. Zeeb struct rtw89_pci_tx_wd_ring *wd_ring; 5788e93258fSBjoern A. Zeeb struct rtw89_pci_tx_wd *txwd; 5798e93258fSBjoern A. Zeeb u16 seq; 5808e93258fSBjoern A. Zeeb u8 qsel, tx_status, txch; 5818e93258fSBjoern A. Zeeb 5828e93258fSBjoern A. Zeeb seq = le32_get_bits(rpp->dword, RTW89_PCI_RPP_SEQ); 5838e93258fSBjoern A. Zeeb qsel = le32_get_bits(rpp->dword, RTW89_PCI_RPP_QSEL); 5848e93258fSBjoern A. Zeeb tx_status = le32_get_bits(rpp->dword, RTW89_PCI_RPP_TX_STATUS); 5858e93258fSBjoern A. Zeeb txch = rtw89_core_get_ch_dma(rtwdev, qsel); 5868e93258fSBjoern A. Zeeb 5878e93258fSBjoern A. Zeeb if (txch == RTW89_TXCH_CH12) { 5888e93258fSBjoern A. Zeeb rtw89_warn(rtwdev, "should no fwcmd release report\n"); 5898e93258fSBjoern A. Zeeb return; 5908e93258fSBjoern A. Zeeb } 5918e93258fSBjoern A. Zeeb 5928e93258fSBjoern A. Zeeb tx_ring = &rtwpci->tx_rings[txch]; 5938e93258fSBjoern A. Zeeb wd_ring = &tx_ring->wd_ring; 5948e93258fSBjoern A. Zeeb txwd = &wd_ring->pages[seq]; 5958e93258fSBjoern A. Zeeb 5968e93258fSBjoern A. Zeeb rtw89_pci_release_txwd_skb(rtwdev, tx_ring, txwd, seq, tx_status); 5978e93258fSBjoern A. Zeeb } 5988e93258fSBjoern A. Zeeb 5998e93258fSBjoern A. Zeeb static void rtw89_pci_release_pending_txwd_skb(struct rtw89_dev *rtwdev, 6008e93258fSBjoern A. Zeeb struct rtw89_pci_tx_ring *tx_ring) 6018e93258fSBjoern A. Zeeb { 6028e93258fSBjoern A. Zeeb struct rtw89_pci_tx_wd_ring *wd_ring = &tx_ring->wd_ring; 6038e93258fSBjoern A. Zeeb struct rtw89_pci_tx_wd *txwd; 6048e93258fSBjoern A. Zeeb int i; 6058e93258fSBjoern A. Zeeb 6068e93258fSBjoern A. Zeeb for (i = 0; i < wd_ring->page_num; i++) { 6078e93258fSBjoern A. Zeeb txwd = &wd_ring->pages[i]; 6088e93258fSBjoern A. Zeeb 6098e93258fSBjoern A. Zeeb if (!list_empty(&txwd->list)) 6108e93258fSBjoern A. Zeeb continue; 6118e93258fSBjoern A. Zeeb 6128e93258fSBjoern A. Zeeb rtw89_pci_release_txwd_skb(rtwdev, tx_ring, txwd, i, RTW89_TX_MACID_DROP); 6138e93258fSBjoern A. Zeeb } 6148e93258fSBjoern A. Zeeb } 6158e93258fSBjoern A. Zeeb 6168e93258fSBjoern A. Zeeb static u32 rtw89_pci_release_tx_skbs(struct rtw89_dev *rtwdev, 6178e93258fSBjoern A. Zeeb struct rtw89_pci_rx_ring *rx_ring, 6188e93258fSBjoern A. Zeeb u32 max_cnt) 6198e93258fSBjoern A. Zeeb { 6208e93258fSBjoern A. Zeeb struct rtw89_pci_dma_ring *bd_ring = &rx_ring->bd_ring; 6218e93258fSBjoern A. Zeeb struct rtw89_pci_rx_info *rx_info; 6228e93258fSBjoern A. Zeeb struct rtw89_pci_rpp_fmt *rpp; 6238e93258fSBjoern A. Zeeb struct rtw89_rx_desc_info desc_info = {}; 6248e93258fSBjoern A. Zeeb struct sk_buff *skb; 6258e93258fSBjoern A. Zeeb u32 cnt = 0; 6268e93258fSBjoern A. Zeeb u32 rpp_size = sizeof(struct rtw89_pci_rpp_fmt); 6278e93258fSBjoern A. Zeeb u32 rxinfo_size = sizeof(struct rtw89_pci_rxbd_info); 628*6d67aabdSBjoern A. Zeeb u32 skb_idx; 6298e93258fSBjoern A. Zeeb u32 offset; 6308e93258fSBjoern A. Zeeb int ret; 6318e93258fSBjoern A. Zeeb 632*6d67aabdSBjoern A. Zeeb skb_idx = rtw89_pci_get_rx_skb_idx(rtwdev, bd_ring); 633*6d67aabdSBjoern A. Zeeb skb = rx_ring->buf[skb_idx]; 6348e93258fSBjoern A. Zeeb 635*6d67aabdSBjoern A. Zeeb ret = rtw89_pci_sync_skb_for_device_and_validate_rx_info(rtwdev, rx_ring, skb); 6368e93258fSBjoern A. Zeeb if (ret) { 6378e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "failed to update %d RXBD info: %d\n", 6388e93258fSBjoern A. Zeeb bd_ring->wp, ret); 6398e93258fSBjoern A. Zeeb goto err_sync_device; 6408e93258fSBjoern A. Zeeb } 6418e93258fSBjoern A. Zeeb 6428e93258fSBjoern A. Zeeb rx_info = RTW89_PCI_RX_SKB_CB(skb); 6438e93258fSBjoern A. Zeeb if (!rx_info->fs || !rx_info->ls) { 6448e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "cannot process RP frame not set FS/LS\n"); 6458e93258fSBjoern A. Zeeb return cnt; 6468e93258fSBjoern A. Zeeb } 6478e93258fSBjoern A. Zeeb 648e2340276SBjoern A. Zeeb rtw89_chip_query_rxdesc(rtwdev, &desc_info, skb->data, rxinfo_size); 6498e93258fSBjoern A. Zeeb 6508e93258fSBjoern A. Zeeb /* first segment has RX desc */ 651e2340276SBjoern A. Zeeb offset = desc_info.offset + desc_info.rxd_len; 6528e93258fSBjoern A. Zeeb for (; offset + rpp_size <= rx_info->len; offset += rpp_size) { 6538e93258fSBjoern A. Zeeb rpp = (struct rtw89_pci_rpp_fmt *)(skb->data + offset); 6548e93258fSBjoern A. Zeeb rtw89_pci_release_rpp(rtwdev, rpp); 6558e93258fSBjoern A. Zeeb } 6568e93258fSBjoern A. Zeeb 6578e93258fSBjoern A. Zeeb rtw89_pci_sync_skb_for_device(rtwdev, skb); 6588e93258fSBjoern A. Zeeb rtw89_pci_rxbd_increase(rx_ring, 1); 6598e93258fSBjoern A. Zeeb cnt++; 6608e93258fSBjoern A. Zeeb 6618e93258fSBjoern A. Zeeb return cnt; 6628e93258fSBjoern A. Zeeb 6638e93258fSBjoern A. Zeeb err_sync_device: 6648e93258fSBjoern A. Zeeb rtw89_pci_sync_skb_for_device(rtwdev, skb); 6658e93258fSBjoern A. Zeeb return 0; 6668e93258fSBjoern A. Zeeb } 6678e93258fSBjoern A. Zeeb 6688e93258fSBjoern A. Zeeb static void rtw89_pci_release_tx(struct rtw89_dev *rtwdev, 6698e93258fSBjoern A. Zeeb struct rtw89_pci_rx_ring *rx_ring, 6708e93258fSBjoern A. Zeeb u32 cnt) 6718e93258fSBjoern A. Zeeb { 6728e93258fSBjoern A. Zeeb struct rtw89_pci_dma_ring *bd_ring = &rx_ring->bd_ring; 6738e93258fSBjoern A. Zeeb u32 release_cnt; 6748e93258fSBjoern A. Zeeb 6758e93258fSBjoern A. Zeeb while (cnt) { 6768e93258fSBjoern A. Zeeb release_cnt = rtw89_pci_release_tx_skbs(rtwdev, rx_ring, cnt); 6778e93258fSBjoern A. Zeeb if (!release_cnt) { 6788e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "failed to release TX skbs\n"); 6798e93258fSBjoern A. Zeeb 6808e93258fSBjoern A. Zeeb /* skip the rest RXBD bufs */ 6818e93258fSBjoern A. Zeeb rtw89_pci_rxbd_increase(rx_ring, cnt); 6828e93258fSBjoern A. Zeeb break; 6838e93258fSBjoern A. Zeeb } 6848e93258fSBjoern A. Zeeb 6858e93258fSBjoern A. Zeeb cnt -= release_cnt; 6868e93258fSBjoern A. Zeeb } 6878e93258fSBjoern A. Zeeb 6888e93258fSBjoern A. Zeeb rtw89_write16(rtwdev, bd_ring->addr.idx, bd_ring->wp); 6898e93258fSBjoern A. Zeeb } 6908e93258fSBjoern A. Zeeb 6918e93258fSBjoern A. Zeeb static int rtw89_pci_poll_rpq_dma(struct rtw89_dev *rtwdev, 6928e93258fSBjoern A. Zeeb struct rtw89_pci *rtwpci, int budget) 6938e93258fSBjoern A. Zeeb { 6948e93258fSBjoern A. Zeeb struct rtw89_pci_rx_ring *rx_ring; 6958e93258fSBjoern A. Zeeb u32 cnt; 6968e93258fSBjoern A. Zeeb int work_done; 6978e93258fSBjoern A. Zeeb 6988e93258fSBjoern A. Zeeb rx_ring = &rtwpci->rx_rings[RTW89_RXCH_RPQ]; 6998e93258fSBjoern A. Zeeb 7008e93258fSBjoern A. Zeeb spin_lock_bh(&rtwpci->trx_lock); 7018e93258fSBjoern A. Zeeb 7028e93258fSBjoern A. Zeeb cnt = rtw89_pci_rxbd_recalc(rtwdev, rx_ring); 7038e93258fSBjoern A. Zeeb if (cnt == 0) 7048e93258fSBjoern A. Zeeb goto out_unlock; 7058e93258fSBjoern A. Zeeb 7068e93258fSBjoern A. Zeeb rtw89_pci_release_tx(rtwdev, rx_ring, cnt); 7078e93258fSBjoern A. Zeeb 7088e93258fSBjoern A. Zeeb out_unlock: 7098e93258fSBjoern A. Zeeb spin_unlock_bh(&rtwpci->trx_lock); 7108e93258fSBjoern A. Zeeb 7118e93258fSBjoern A. Zeeb /* always release all RPQ */ 7128e93258fSBjoern A. Zeeb work_done = min_t(int, cnt, budget); 7138e93258fSBjoern A. Zeeb rtwdev->napi_budget_countdown -= work_done; 7148e93258fSBjoern A. Zeeb 7158e93258fSBjoern A. Zeeb return work_done; 7168e93258fSBjoern A. Zeeb } 7178e93258fSBjoern A. Zeeb 7188e93258fSBjoern A. Zeeb static void rtw89_pci_isr_rxd_unavail(struct rtw89_dev *rtwdev, 7198e93258fSBjoern A. Zeeb struct rtw89_pci *rtwpci) 7208e93258fSBjoern A. Zeeb { 7218e93258fSBjoern A. Zeeb struct rtw89_pci_rx_ring *rx_ring; 7228e93258fSBjoern A. Zeeb struct rtw89_pci_dma_ring *bd_ring; 7238e93258fSBjoern A. Zeeb u32 reg_idx; 7248e93258fSBjoern A. Zeeb u16 hw_idx, hw_idx_next, host_idx; 7258e93258fSBjoern A. Zeeb int i; 7268e93258fSBjoern A. Zeeb 7278e93258fSBjoern A. Zeeb for (i = 0; i < RTW89_RXCH_NUM; i++) { 7288e93258fSBjoern A. Zeeb rx_ring = &rtwpci->rx_rings[i]; 7298e93258fSBjoern A. Zeeb bd_ring = &rx_ring->bd_ring; 7308e93258fSBjoern A. Zeeb 7318e93258fSBjoern A. Zeeb reg_idx = rtw89_read32(rtwdev, bd_ring->addr.idx); 7328e93258fSBjoern A. Zeeb hw_idx = FIELD_GET(TXBD_HW_IDX_MASK, reg_idx); 7338e93258fSBjoern A. Zeeb host_idx = FIELD_GET(TXBD_HOST_IDX_MASK, reg_idx); 7348e93258fSBjoern A. Zeeb hw_idx_next = (hw_idx + 1) % bd_ring->len; 7358e93258fSBjoern A. Zeeb 7368e93258fSBjoern A. Zeeb if (hw_idx_next == host_idx) 7378e93258fSBjoern A. Zeeb rtw89_debug(rtwdev, RTW89_DBG_UNEXP, "%d RXD unavailable\n", i); 7388e93258fSBjoern A. Zeeb 7398e93258fSBjoern A. Zeeb rtw89_debug(rtwdev, RTW89_DBG_TXRX, 7408e93258fSBjoern A. Zeeb "%d RXD unavailable, idx=0x%08x, len=%d\n", 7418e93258fSBjoern A. Zeeb i, reg_idx, bd_ring->len); 7428e93258fSBjoern A. Zeeb } 7438e93258fSBjoern A. Zeeb } 7448e93258fSBjoern A. Zeeb 7458e93258fSBjoern A. Zeeb void rtw89_pci_recognize_intrs(struct rtw89_dev *rtwdev, 7468e93258fSBjoern A. Zeeb struct rtw89_pci *rtwpci, 7478e93258fSBjoern A. Zeeb struct rtw89_pci_isrs *isrs) 7488e93258fSBjoern A. Zeeb { 7498e93258fSBjoern A. Zeeb isrs->halt_c2h_isrs = rtw89_read32(rtwdev, R_AX_HISR0) & rtwpci->halt_c2h_intrs; 7508e93258fSBjoern A. Zeeb isrs->isrs[0] = rtw89_read32(rtwdev, R_AX_PCIE_HISR00) & rtwpci->intrs[0]; 7518e93258fSBjoern A. Zeeb isrs->isrs[1] = rtw89_read32(rtwdev, R_AX_PCIE_HISR10) & rtwpci->intrs[1]; 7528e93258fSBjoern A. Zeeb 7538e93258fSBjoern A. Zeeb rtw89_write32(rtwdev, R_AX_HISR0, isrs->halt_c2h_isrs); 7548e93258fSBjoern A. Zeeb rtw89_write32(rtwdev, R_AX_PCIE_HISR00, isrs->isrs[0]); 7558e93258fSBjoern A. Zeeb rtw89_write32(rtwdev, R_AX_PCIE_HISR10, isrs->isrs[1]); 7568e93258fSBjoern A. Zeeb } 7578e93258fSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_pci_recognize_intrs); 7588e93258fSBjoern A. Zeeb 7598e93258fSBjoern A. Zeeb void rtw89_pci_recognize_intrs_v1(struct rtw89_dev *rtwdev, 7608e93258fSBjoern A. Zeeb struct rtw89_pci *rtwpci, 7618e93258fSBjoern A. Zeeb struct rtw89_pci_isrs *isrs) 7628e93258fSBjoern A. Zeeb { 7638e93258fSBjoern A. Zeeb isrs->ind_isrs = rtw89_read32(rtwdev, R_AX_PCIE_HISR00_V1) & rtwpci->ind_intrs; 7648e93258fSBjoern A. Zeeb isrs->halt_c2h_isrs = isrs->ind_isrs & B_AX_HS0ISR_IND_INT_EN ? 7658e93258fSBjoern A. Zeeb rtw89_read32(rtwdev, R_AX_HISR0) & rtwpci->halt_c2h_intrs : 0; 7668e93258fSBjoern A. Zeeb isrs->isrs[0] = isrs->ind_isrs & B_AX_HCI_AXIDMA_INT_EN ? 7678e93258fSBjoern A. Zeeb rtw89_read32(rtwdev, R_AX_HAXI_HISR00) & rtwpci->intrs[0] : 0; 7688e93258fSBjoern A. Zeeb isrs->isrs[1] = isrs->ind_isrs & B_AX_HS1ISR_IND_INT_EN ? 7698e93258fSBjoern A. Zeeb rtw89_read32(rtwdev, R_AX_HISR1) & rtwpci->intrs[1] : 0; 7708e93258fSBjoern A. Zeeb 7718e93258fSBjoern A. Zeeb if (isrs->halt_c2h_isrs) 7728e93258fSBjoern A. Zeeb rtw89_write32(rtwdev, R_AX_HISR0, isrs->halt_c2h_isrs); 7738e93258fSBjoern A. Zeeb if (isrs->isrs[0]) 7748e93258fSBjoern A. Zeeb rtw89_write32(rtwdev, R_AX_HAXI_HISR00, isrs->isrs[0]); 7758e93258fSBjoern A. Zeeb if (isrs->isrs[1]) 7768e93258fSBjoern A. Zeeb rtw89_write32(rtwdev, R_AX_HISR1, isrs->isrs[1]); 7778e93258fSBjoern A. Zeeb } 7788e93258fSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_pci_recognize_intrs_v1); 7798e93258fSBjoern A. Zeeb 780*6d67aabdSBjoern A. Zeeb void rtw89_pci_recognize_intrs_v2(struct rtw89_dev *rtwdev, 781*6d67aabdSBjoern A. Zeeb struct rtw89_pci *rtwpci, 782*6d67aabdSBjoern A. Zeeb struct rtw89_pci_isrs *isrs) 7838e93258fSBjoern A. Zeeb { 784*6d67aabdSBjoern A. Zeeb isrs->ind_isrs = rtw89_read32(rtwdev, R_BE_PCIE_HISR) & rtwpci->ind_intrs; 785*6d67aabdSBjoern A. Zeeb isrs->halt_c2h_isrs = isrs->ind_isrs & B_BE_HS0ISR_IND_INT ? 786*6d67aabdSBjoern A. Zeeb rtw89_read32(rtwdev, R_BE_HISR0) & rtwpci->halt_c2h_intrs : 0; 787*6d67aabdSBjoern A. Zeeb isrs->isrs[0] = isrs->ind_isrs & B_BE_HCI_AXIDMA_INT ? 788*6d67aabdSBjoern A. Zeeb rtw89_read32(rtwdev, R_BE_HAXI_HISR00) & rtwpci->intrs[0] : 0; 789*6d67aabdSBjoern A. Zeeb isrs->isrs[1] = rtw89_read32(rtwdev, R_BE_PCIE_DMA_ISR) & rtwpci->intrs[1]; 790*6d67aabdSBjoern A. Zeeb 791*6d67aabdSBjoern A. Zeeb if (isrs->halt_c2h_isrs) 792*6d67aabdSBjoern A. Zeeb rtw89_write32(rtwdev, R_BE_HISR0, isrs->halt_c2h_isrs); 793*6d67aabdSBjoern A. Zeeb if (isrs->isrs[0]) 794*6d67aabdSBjoern A. Zeeb rtw89_write32(rtwdev, R_BE_HAXI_HISR00, isrs->isrs[0]); 795*6d67aabdSBjoern A. Zeeb if (isrs->isrs[1]) 796*6d67aabdSBjoern A. Zeeb rtw89_write32(rtwdev, R_BE_PCIE_DMA_ISR, isrs->isrs[1]); 797*6d67aabdSBjoern A. Zeeb rtw89_write32(rtwdev, R_BE_PCIE_HISR, isrs->ind_isrs); 7988e93258fSBjoern A. Zeeb } 799*6d67aabdSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_pci_recognize_intrs_v2); 8008e93258fSBjoern A. Zeeb 8018e93258fSBjoern A. Zeeb void rtw89_pci_enable_intr(struct rtw89_dev *rtwdev, struct rtw89_pci *rtwpci) 8028e93258fSBjoern A. Zeeb { 8038e93258fSBjoern A. Zeeb rtw89_write32(rtwdev, R_AX_HIMR0, rtwpci->halt_c2h_intrs); 8048e93258fSBjoern A. Zeeb rtw89_write32(rtwdev, R_AX_PCIE_HIMR00, rtwpci->intrs[0]); 8058e93258fSBjoern A. Zeeb rtw89_write32(rtwdev, R_AX_PCIE_HIMR10, rtwpci->intrs[1]); 8068e93258fSBjoern A. Zeeb } 8078e93258fSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_pci_enable_intr); 8088e93258fSBjoern A. Zeeb 8098e93258fSBjoern A. Zeeb void rtw89_pci_disable_intr(struct rtw89_dev *rtwdev, struct rtw89_pci *rtwpci) 8108e93258fSBjoern A. Zeeb { 8118e93258fSBjoern A. Zeeb rtw89_write32(rtwdev, R_AX_HIMR0, 0); 8128e93258fSBjoern A. Zeeb rtw89_write32(rtwdev, R_AX_PCIE_HIMR00, 0); 8138e93258fSBjoern A. Zeeb rtw89_write32(rtwdev, R_AX_PCIE_HIMR10, 0); 8148e93258fSBjoern A. Zeeb } 8158e93258fSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_pci_disable_intr); 8168e93258fSBjoern A. Zeeb 8178e93258fSBjoern A. Zeeb void rtw89_pci_enable_intr_v1(struct rtw89_dev *rtwdev, struct rtw89_pci *rtwpci) 8188e93258fSBjoern A. Zeeb { 8198e93258fSBjoern A. Zeeb rtw89_write32(rtwdev, R_AX_PCIE_HIMR00_V1, rtwpci->ind_intrs); 8208e93258fSBjoern A. Zeeb rtw89_write32(rtwdev, R_AX_HIMR0, rtwpci->halt_c2h_intrs); 8218e93258fSBjoern A. Zeeb rtw89_write32(rtwdev, R_AX_HAXI_HIMR00, rtwpci->intrs[0]); 8228e93258fSBjoern A. Zeeb rtw89_write32(rtwdev, R_AX_HIMR1, rtwpci->intrs[1]); 8238e93258fSBjoern A. Zeeb } 8248e93258fSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_pci_enable_intr_v1); 8258e93258fSBjoern A. Zeeb 8268e93258fSBjoern A. Zeeb void rtw89_pci_disable_intr_v1(struct rtw89_dev *rtwdev, struct rtw89_pci *rtwpci) 8278e93258fSBjoern A. Zeeb { 8288e93258fSBjoern A. Zeeb rtw89_write32(rtwdev, R_AX_PCIE_HIMR00_V1, 0); 8298e93258fSBjoern A. Zeeb } 8308e93258fSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_pci_disable_intr_v1); 8318e93258fSBjoern A. Zeeb 832*6d67aabdSBjoern A. Zeeb void rtw89_pci_enable_intr_v2(struct rtw89_dev *rtwdev, struct rtw89_pci *rtwpci) 833*6d67aabdSBjoern A. Zeeb { 834*6d67aabdSBjoern A. Zeeb rtw89_write32(rtwdev, R_BE_HIMR0, rtwpci->halt_c2h_intrs); 835*6d67aabdSBjoern A. Zeeb rtw89_write32(rtwdev, R_BE_HAXI_HIMR00, rtwpci->intrs[0]); 836*6d67aabdSBjoern A. Zeeb rtw89_write32(rtwdev, R_BE_PCIE_DMA_IMR_0_V1, rtwpci->intrs[1]); 837*6d67aabdSBjoern A. Zeeb rtw89_write32(rtwdev, R_BE_PCIE_HIMR0, rtwpci->ind_intrs); 838*6d67aabdSBjoern A. Zeeb } 839*6d67aabdSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_pci_enable_intr_v2); 840*6d67aabdSBjoern A. Zeeb 841*6d67aabdSBjoern A. Zeeb void rtw89_pci_disable_intr_v2(struct rtw89_dev *rtwdev, struct rtw89_pci *rtwpci) 842*6d67aabdSBjoern A. Zeeb { 843*6d67aabdSBjoern A. Zeeb rtw89_write32(rtwdev, R_BE_PCIE_HIMR0, 0); 844*6d67aabdSBjoern A. Zeeb rtw89_write32(rtwdev, R_BE_PCIE_DMA_IMR_0_V1, 0); 845*6d67aabdSBjoern A. Zeeb } 846*6d67aabdSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_pci_disable_intr_v2); 847*6d67aabdSBjoern A. Zeeb 8488e93258fSBjoern A. Zeeb static void rtw89_pci_ops_recovery_start(struct rtw89_dev *rtwdev) 8498e93258fSBjoern A. Zeeb { 8508e93258fSBjoern A. Zeeb struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; 8518e93258fSBjoern A. Zeeb unsigned long flags; 8528e93258fSBjoern A. Zeeb 8538e93258fSBjoern A. Zeeb spin_lock_irqsave(&rtwpci->irq_lock, flags); 8548e93258fSBjoern A. Zeeb rtw89_chip_disable_intr(rtwdev, rtwpci); 8558e93258fSBjoern A. Zeeb rtw89_chip_config_intr_mask(rtwdev, RTW89_PCI_INTR_MASK_RECOVERY_START); 8568e93258fSBjoern A. Zeeb rtw89_chip_enable_intr(rtwdev, rtwpci); 8578e93258fSBjoern A. Zeeb spin_unlock_irqrestore(&rtwpci->irq_lock, flags); 8588e93258fSBjoern A. Zeeb } 8598e93258fSBjoern A. Zeeb 8608e93258fSBjoern A. Zeeb static void rtw89_pci_ops_recovery_complete(struct rtw89_dev *rtwdev) 8618e93258fSBjoern A. Zeeb { 8628e93258fSBjoern A. Zeeb struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; 8638e93258fSBjoern A. Zeeb unsigned long flags; 8648e93258fSBjoern A. Zeeb 8658e93258fSBjoern A. Zeeb spin_lock_irqsave(&rtwpci->irq_lock, flags); 8668e93258fSBjoern A. Zeeb rtw89_chip_disable_intr(rtwdev, rtwpci); 8678e93258fSBjoern A. Zeeb rtw89_chip_config_intr_mask(rtwdev, RTW89_PCI_INTR_MASK_RECOVERY_COMPLETE); 8688e93258fSBjoern A. Zeeb rtw89_chip_enable_intr(rtwdev, rtwpci); 8698e93258fSBjoern A. Zeeb spin_unlock_irqrestore(&rtwpci->irq_lock, flags); 8708e93258fSBjoern A. Zeeb } 8718e93258fSBjoern A. Zeeb 8728e93258fSBjoern A. Zeeb static void rtw89_pci_low_power_interrupt_handler(struct rtw89_dev *rtwdev) 8738e93258fSBjoern A. Zeeb { 8748e93258fSBjoern A. Zeeb struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; 8758e93258fSBjoern A. Zeeb int budget = NAPI_POLL_WEIGHT; 8768e93258fSBjoern A. Zeeb 8778e93258fSBjoern A. Zeeb /* To prevent RXQ get stuck due to run out of budget. */ 8788e93258fSBjoern A. Zeeb rtwdev->napi_budget_countdown = budget; 8798e93258fSBjoern A. Zeeb 8808e93258fSBjoern A. Zeeb rtw89_pci_poll_rpq_dma(rtwdev, rtwpci, budget); 8818e93258fSBjoern A. Zeeb rtw89_pci_poll_rxq_dma(rtwdev, rtwpci, budget); 8828e93258fSBjoern A. Zeeb } 8838e93258fSBjoern A. Zeeb 8848e93258fSBjoern A. Zeeb static irqreturn_t rtw89_pci_interrupt_threadfn(int irq, void *dev) 8858e93258fSBjoern A. Zeeb { 8868e93258fSBjoern A. Zeeb struct rtw89_dev *rtwdev = dev; 8878e93258fSBjoern A. Zeeb struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; 888*6d67aabdSBjoern A. Zeeb const struct rtw89_pci_info *info = rtwdev->pci_info; 889*6d67aabdSBjoern A. Zeeb const struct rtw89_pci_gen_def *gen_def = info->gen_def; 8908e93258fSBjoern A. Zeeb struct rtw89_pci_isrs isrs; 8918e93258fSBjoern A. Zeeb unsigned long flags; 8928e93258fSBjoern A. Zeeb 8938e93258fSBjoern A. Zeeb spin_lock_irqsave(&rtwpci->irq_lock, flags); 8948e93258fSBjoern A. Zeeb rtw89_chip_recognize_intrs(rtwdev, rtwpci, &isrs); 8958e93258fSBjoern A. Zeeb spin_unlock_irqrestore(&rtwpci->irq_lock, flags); 8968e93258fSBjoern A. Zeeb 897*6d67aabdSBjoern A. Zeeb if (unlikely(isrs.isrs[0] & gen_def->isr_rdu)) 8988e93258fSBjoern A. Zeeb rtw89_pci_isr_rxd_unavail(rtwdev, rtwpci); 8998e93258fSBjoern A. Zeeb 900*6d67aabdSBjoern A. Zeeb if (unlikely(isrs.halt_c2h_isrs & gen_def->isr_halt_c2h)) 9018e93258fSBjoern A. Zeeb rtw89_ser_notify(rtwdev, rtw89_mac_get_err_status(rtwdev)); 9028e93258fSBjoern A. Zeeb 903*6d67aabdSBjoern A. Zeeb if (unlikely(isrs.halt_c2h_isrs & gen_def->isr_wdt_timeout)) 9048e93258fSBjoern A. Zeeb rtw89_ser_notify(rtwdev, MAC_AX_ERR_L2_ERR_WDT_TIMEOUT_INT); 9058e93258fSBjoern A. Zeeb 9068e93258fSBjoern A. Zeeb if (unlikely(rtwpci->under_recovery)) 9078e93258fSBjoern A. Zeeb goto enable_intr; 9088e93258fSBjoern A. Zeeb 9098e93258fSBjoern A. Zeeb if (unlikely(rtwpci->low_power)) { 9108e93258fSBjoern A. Zeeb rtw89_pci_low_power_interrupt_handler(rtwdev); 9118e93258fSBjoern A. Zeeb goto enable_intr; 9128e93258fSBjoern A. Zeeb } 9138e93258fSBjoern A. Zeeb 9148e93258fSBjoern A. Zeeb if (likely(rtwpci->running)) { 9158e93258fSBjoern A. Zeeb local_bh_disable(); 9168e93258fSBjoern A. Zeeb napi_schedule(&rtwdev->napi); 9178e93258fSBjoern A. Zeeb local_bh_enable(); 9188e93258fSBjoern A. Zeeb } 9198e93258fSBjoern A. Zeeb 9208e93258fSBjoern A. Zeeb return IRQ_HANDLED; 9218e93258fSBjoern A. Zeeb 9228e93258fSBjoern A. Zeeb enable_intr: 9238e93258fSBjoern A. Zeeb spin_lock_irqsave(&rtwpci->irq_lock, flags); 9248e93258fSBjoern A. Zeeb if (likely(rtwpci->running)) 9258e93258fSBjoern A. Zeeb rtw89_chip_enable_intr(rtwdev, rtwpci); 9268e93258fSBjoern A. Zeeb spin_unlock_irqrestore(&rtwpci->irq_lock, flags); 9278e93258fSBjoern A. Zeeb return IRQ_HANDLED; 9288e93258fSBjoern A. Zeeb } 9298e93258fSBjoern A. Zeeb 9308e93258fSBjoern A. Zeeb static irqreturn_t rtw89_pci_interrupt_handler(int irq, void *dev) 9318e93258fSBjoern A. Zeeb { 9328e93258fSBjoern A. Zeeb struct rtw89_dev *rtwdev = dev; 9338e93258fSBjoern A. Zeeb struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; 9348e93258fSBjoern A. Zeeb unsigned long flags; 9358e93258fSBjoern A. Zeeb irqreturn_t irqret = IRQ_WAKE_THREAD; 9368e93258fSBjoern A. Zeeb 9378e93258fSBjoern A. Zeeb spin_lock_irqsave(&rtwpci->irq_lock, flags); 9388e93258fSBjoern A. Zeeb 9398e93258fSBjoern A. Zeeb /* If interrupt event is on the road, it is still trigger interrupt 9408e93258fSBjoern A. Zeeb * even we have done pci_stop() to turn off IMR. 9418e93258fSBjoern A. Zeeb */ 9428e93258fSBjoern A. Zeeb if (unlikely(!rtwpci->running)) { 9438e93258fSBjoern A. Zeeb irqret = IRQ_HANDLED; 9448e93258fSBjoern A. Zeeb goto exit; 9458e93258fSBjoern A. Zeeb } 9468e93258fSBjoern A. Zeeb 9478e93258fSBjoern A. Zeeb rtw89_chip_disable_intr(rtwdev, rtwpci); 9488e93258fSBjoern A. Zeeb exit: 9498e93258fSBjoern A. Zeeb spin_unlock_irqrestore(&rtwpci->irq_lock, flags); 9508e93258fSBjoern A. Zeeb 9518e93258fSBjoern A. Zeeb return irqret; 9528e93258fSBjoern A. Zeeb } 9538e93258fSBjoern A. Zeeb 954*6d67aabdSBjoern A. Zeeb #define DEF_TXCHADDRS_TYPE2(gen, ch_idx, txch, v...) \ 955*6d67aabdSBjoern A. Zeeb [RTW89_TXCH_##ch_idx] = { \ 956*6d67aabdSBjoern A. Zeeb .num = R_##gen##_##txch##_TXBD_NUM ##v, \ 957*6d67aabdSBjoern A. Zeeb .idx = R_##gen##_##txch##_TXBD_IDX ##v, \ 958*6d67aabdSBjoern A. Zeeb .bdram = 0, \ 959*6d67aabdSBjoern A. Zeeb .desa_l = R_##gen##_##txch##_TXBD_DESA_L ##v, \ 960*6d67aabdSBjoern A. Zeeb .desa_h = R_##gen##_##txch##_TXBD_DESA_H ##v, \ 961*6d67aabdSBjoern A. Zeeb } 962*6d67aabdSBjoern A. Zeeb 9638e93258fSBjoern A. Zeeb #define DEF_TXCHADDRS_TYPE1(info, txch, v...) \ 9648e93258fSBjoern A. Zeeb [RTW89_TXCH_##txch] = { \ 9658e93258fSBjoern A. Zeeb .num = R_AX_##txch##_TXBD_NUM ##v, \ 9668e93258fSBjoern A. Zeeb .idx = R_AX_##txch##_TXBD_IDX ##v, \ 9678e93258fSBjoern A. Zeeb .bdram = R_AX_##txch##_BDRAM_CTRL ##v, \ 9688e93258fSBjoern A. Zeeb .desa_l = R_AX_##txch##_TXBD_DESA_L ##v, \ 9698e93258fSBjoern A. Zeeb .desa_h = R_AX_##txch##_TXBD_DESA_H ##v, \ 9708e93258fSBjoern A. Zeeb } 9718e93258fSBjoern A. Zeeb 9728e93258fSBjoern A. Zeeb #define DEF_TXCHADDRS(info, txch, v...) \ 9738e93258fSBjoern A. Zeeb [RTW89_TXCH_##txch] = { \ 9748e93258fSBjoern A. Zeeb .num = R_AX_##txch##_TXBD_NUM, \ 9758e93258fSBjoern A. Zeeb .idx = R_AX_##txch##_TXBD_IDX, \ 9768e93258fSBjoern A. Zeeb .bdram = R_AX_##txch##_BDRAM_CTRL ##v, \ 9778e93258fSBjoern A. Zeeb .desa_l = R_AX_##txch##_TXBD_DESA_L ##v, \ 9788e93258fSBjoern A. Zeeb .desa_h = R_AX_##txch##_TXBD_DESA_H ##v, \ 9798e93258fSBjoern A. Zeeb } 9808e93258fSBjoern A. Zeeb 981*6d67aabdSBjoern A. Zeeb #define DEF_RXCHADDRS(gen, ch_idx, rxch, v...) \ 982*6d67aabdSBjoern A. Zeeb [RTW89_RXCH_##ch_idx] = { \ 983*6d67aabdSBjoern A. Zeeb .num = R_##gen##_##rxch##_RXBD_NUM ##v, \ 984*6d67aabdSBjoern A. Zeeb .idx = R_##gen##_##rxch##_RXBD_IDX ##v, \ 985*6d67aabdSBjoern A. Zeeb .desa_l = R_##gen##_##rxch##_RXBD_DESA_L ##v, \ 986*6d67aabdSBjoern A. Zeeb .desa_h = R_##gen##_##rxch##_RXBD_DESA_H ##v, \ 9878e93258fSBjoern A. Zeeb } 9888e93258fSBjoern A. Zeeb 9898e93258fSBjoern A. Zeeb const struct rtw89_pci_ch_dma_addr_set rtw89_pci_ch_dma_addr_set = { 9908e93258fSBjoern A. Zeeb .tx = { 9918e93258fSBjoern A. Zeeb DEF_TXCHADDRS(info, ACH0), 9928e93258fSBjoern A. Zeeb DEF_TXCHADDRS(info, ACH1), 9938e93258fSBjoern A. Zeeb DEF_TXCHADDRS(info, ACH2), 9948e93258fSBjoern A. Zeeb DEF_TXCHADDRS(info, ACH3), 9958e93258fSBjoern A. Zeeb DEF_TXCHADDRS(info, ACH4), 9968e93258fSBjoern A. Zeeb DEF_TXCHADDRS(info, ACH5), 9978e93258fSBjoern A. Zeeb DEF_TXCHADDRS(info, ACH6), 9988e93258fSBjoern A. Zeeb DEF_TXCHADDRS(info, ACH7), 9998e93258fSBjoern A. Zeeb DEF_TXCHADDRS(info, CH8), 10008e93258fSBjoern A. Zeeb DEF_TXCHADDRS(info, CH9), 10018e93258fSBjoern A. Zeeb DEF_TXCHADDRS_TYPE1(info, CH10), 10028e93258fSBjoern A. Zeeb DEF_TXCHADDRS_TYPE1(info, CH11), 10038e93258fSBjoern A. Zeeb DEF_TXCHADDRS(info, CH12), 10048e93258fSBjoern A. Zeeb }, 10058e93258fSBjoern A. Zeeb .rx = { 1006*6d67aabdSBjoern A. Zeeb DEF_RXCHADDRS(AX, RXQ, RXQ), 1007*6d67aabdSBjoern A. Zeeb DEF_RXCHADDRS(AX, RPQ, RPQ), 10088e93258fSBjoern A. Zeeb }, 10098e93258fSBjoern A. Zeeb }; 10108e93258fSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_pci_ch_dma_addr_set); 10118e93258fSBjoern A. Zeeb 10128e93258fSBjoern A. Zeeb const struct rtw89_pci_ch_dma_addr_set rtw89_pci_ch_dma_addr_set_v1 = { 10138e93258fSBjoern A. Zeeb .tx = { 10148e93258fSBjoern A. Zeeb DEF_TXCHADDRS(info, ACH0, _V1), 10158e93258fSBjoern A. Zeeb DEF_TXCHADDRS(info, ACH1, _V1), 10168e93258fSBjoern A. Zeeb DEF_TXCHADDRS(info, ACH2, _V1), 10178e93258fSBjoern A. Zeeb DEF_TXCHADDRS(info, ACH3, _V1), 10188e93258fSBjoern A. Zeeb DEF_TXCHADDRS(info, ACH4, _V1), 10198e93258fSBjoern A. Zeeb DEF_TXCHADDRS(info, ACH5, _V1), 10208e93258fSBjoern A. Zeeb DEF_TXCHADDRS(info, ACH6, _V1), 10218e93258fSBjoern A. Zeeb DEF_TXCHADDRS(info, ACH7, _V1), 10228e93258fSBjoern A. Zeeb DEF_TXCHADDRS(info, CH8, _V1), 10238e93258fSBjoern A. Zeeb DEF_TXCHADDRS(info, CH9, _V1), 10248e93258fSBjoern A. Zeeb DEF_TXCHADDRS_TYPE1(info, CH10, _V1), 10258e93258fSBjoern A. Zeeb DEF_TXCHADDRS_TYPE1(info, CH11, _V1), 10268e93258fSBjoern A. Zeeb DEF_TXCHADDRS(info, CH12, _V1), 10278e93258fSBjoern A. Zeeb }, 10288e93258fSBjoern A. Zeeb .rx = { 1029*6d67aabdSBjoern A. Zeeb DEF_RXCHADDRS(AX, RXQ, RXQ, _V1), 1030*6d67aabdSBjoern A. Zeeb DEF_RXCHADDRS(AX, RPQ, RPQ, _V1), 10318e93258fSBjoern A. Zeeb }, 10328e93258fSBjoern A. Zeeb }; 10338e93258fSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_pci_ch_dma_addr_set_v1); 10348e93258fSBjoern A. Zeeb 1035*6d67aabdSBjoern A. Zeeb const struct rtw89_pci_ch_dma_addr_set rtw89_pci_ch_dma_addr_set_be = { 1036*6d67aabdSBjoern A. Zeeb .tx = { 1037*6d67aabdSBjoern A. Zeeb DEF_TXCHADDRS_TYPE2(BE, ACH0, CH0, _V1), 1038*6d67aabdSBjoern A. Zeeb DEF_TXCHADDRS_TYPE2(BE, ACH1, CH1, _V1), 1039*6d67aabdSBjoern A. Zeeb DEF_TXCHADDRS_TYPE2(BE, ACH2, CH2, _V1), 1040*6d67aabdSBjoern A. Zeeb DEF_TXCHADDRS_TYPE2(BE, ACH3, CH3, _V1), 1041*6d67aabdSBjoern A. Zeeb DEF_TXCHADDRS_TYPE2(BE, ACH4, CH4, _V1), 1042*6d67aabdSBjoern A. Zeeb DEF_TXCHADDRS_TYPE2(BE, ACH5, CH5, _V1), 1043*6d67aabdSBjoern A. Zeeb DEF_TXCHADDRS_TYPE2(BE, ACH6, CH6, _V1), 1044*6d67aabdSBjoern A. Zeeb DEF_TXCHADDRS_TYPE2(BE, ACH7, CH7, _V1), 1045*6d67aabdSBjoern A. Zeeb DEF_TXCHADDRS_TYPE2(BE, CH8, CH8, _V1), 1046*6d67aabdSBjoern A. Zeeb DEF_TXCHADDRS_TYPE2(BE, CH9, CH9, _V1), 1047*6d67aabdSBjoern A. Zeeb DEF_TXCHADDRS_TYPE2(BE, CH10, CH10, _V1), 1048*6d67aabdSBjoern A. Zeeb DEF_TXCHADDRS_TYPE2(BE, CH11, CH11, _V1), 1049*6d67aabdSBjoern A. Zeeb DEF_TXCHADDRS_TYPE2(BE, CH12, CH12, _V1), 1050*6d67aabdSBjoern A. Zeeb }, 1051*6d67aabdSBjoern A. Zeeb .rx = { 1052*6d67aabdSBjoern A. Zeeb DEF_RXCHADDRS(BE, RXQ, RXQ0, _V1), 1053*6d67aabdSBjoern A. Zeeb DEF_RXCHADDRS(BE, RPQ, RPQ0, _V1), 1054*6d67aabdSBjoern A. Zeeb }, 1055*6d67aabdSBjoern A. Zeeb }; 1056*6d67aabdSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_pci_ch_dma_addr_set_be); 1057*6d67aabdSBjoern A. Zeeb 10588e93258fSBjoern A. Zeeb #undef DEF_TXCHADDRS_TYPE1 10598e93258fSBjoern A. Zeeb #undef DEF_TXCHADDRS 10608e93258fSBjoern A. Zeeb #undef DEF_RXCHADDRS 10618e93258fSBjoern A. Zeeb 10628e93258fSBjoern A. Zeeb static int rtw89_pci_get_txch_addrs(struct rtw89_dev *rtwdev, 10638e93258fSBjoern A. Zeeb enum rtw89_tx_channel txch, 10648e93258fSBjoern A. Zeeb const struct rtw89_pci_ch_dma_addr **addr) 10658e93258fSBjoern A. Zeeb { 10668e93258fSBjoern A. Zeeb const struct rtw89_pci_info *info = rtwdev->pci_info; 10678e93258fSBjoern A. Zeeb 10688e93258fSBjoern A. Zeeb if (txch >= RTW89_TXCH_NUM) 10698e93258fSBjoern A. Zeeb return -EINVAL; 10708e93258fSBjoern A. Zeeb 10718e93258fSBjoern A. Zeeb *addr = &info->dma_addr_set->tx[txch]; 10728e93258fSBjoern A. Zeeb 10738e93258fSBjoern A. Zeeb return 0; 10748e93258fSBjoern A. Zeeb } 10758e93258fSBjoern A. Zeeb 10768e93258fSBjoern A. Zeeb static int rtw89_pci_get_rxch_addrs(struct rtw89_dev *rtwdev, 10778e93258fSBjoern A. Zeeb enum rtw89_rx_channel rxch, 10788e93258fSBjoern A. Zeeb const struct rtw89_pci_ch_dma_addr **addr) 10798e93258fSBjoern A. Zeeb { 10808e93258fSBjoern A. Zeeb const struct rtw89_pci_info *info = rtwdev->pci_info; 10818e93258fSBjoern A. Zeeb 10828e93258fSBjoern A. Zeeb if (rxch >= RTW89_RXCH_NUM) 10838e93258fSBjoern A. Zeeb return -EINVAL; 10848e93258fSBjoern A. Zeeb 10858e93258fSBjoern A. Zeeb *addr = &info->dma_addr_set->rx[rxch]; 10868e93258fSBjoern A. Zeeb 10878e93258fSBjoern A. Zeeb return 0; 10888e93258fSBjoern A. Zeeb } 10898e93258fSBjoern A. Zeeb 10908e93258fSBjoern A. Zeeb static u32 rtw89_pci_get_avail_txbd_num(struct rtw89_pci_tx_ring *ring) 10918e93258fSBjoern A. Zeeb { 10928e93258fSBjoern A. Zeeb struct rtw89_pci_dma_ring *bd_ring = &ring->bd_ring; 10938e93258fSBjoern A. Zeeb 10948e93258fSBjoern A. Zeeb /* reserved 1 desc check ring is full or not */ 10958e93258fSBjoern A. Zeeb if (bd_ring->rp > bd_ring->wp) 10968e93258fSBjoern A. Zeeb return bd_ring->rp - bd_ring->wp - 1; 10978e93258fSBjoern A. Zeeb 10988e93258fSBjoern A. Zeeb return bd_ring->len - (bd_ring->wp - bd_ring->rp) - 1; 10998e93258fSBjoern A. Zeeb } 11008e93258fSBjoern A. Zeeb 11018e93258fSBjoern A. Zeeb static 11028e93258fSBjoern A. Zeeb u32 __rtw89_pci_check_and_reclaim_tx_fwcmd_resource(struct rtw89_dev *rtwdev) 11038e93258fSBjoern A. Zeeb { 11048e93258fSBjoern A. Zeeb struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; 11058e93258fSBjoern A. Zeeb struct rtw89_pci_tx_ring *tx_ring = &rtwpci->tx_rings[RTW89_TXCH_CH12]; 11068e93258fSBjoern A. Zeeb u32 cnt; 11078e93258fSBjoern A. Zeeb 11088e93258fSBjoern A. Zeeb spin_lock_bh(&rtwpci->trx_lock); 11098e93258fSBjoern A. Zeeb rtw89_pci_reclaim_tx_fwcmd(rtwdev, rtwpci); 11108e93258fSBjoern A. Zeeb cnt = rtw89_pci_get_avail_txbd_num(tx_ring); 11118e93258fSBjoern A. Zeeb spin_unlock_bh(&rtwpci->trx_lock); 11128e93258fSBjoern A. Zeeb 11138e93258fSBjoern A. Zeeb return cnt; 11148e93258fSBjoern A. Zeeb } 11158e93258fSBjoern A. Zeeb 11168e93258fSBjoern A. Zeeb static 11178e93258fSBjoern A. Zeeb u32 __rtw89_pci_check_and_reclaim_tx_resource_noio(struct rtw89_dev *rtwdev, 11188e93258fSBjoern A. Zeeb u8 txch) 11198e93258fSBjoern A. Zeeb { 11208e93258fSBjoern A. Zeeb struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; 11218e93258fSBjoern A. Zeeb struct rtw89_pci_tx_ring *tx_ring = &rtwpci->tx_rings[txch]; 11228e93258fSBjoern A. Zeeb struct rtw89_pci_tx_wd_ring *wd_ring = &tx_ring->wd_ring; 11238e93258fSBjoern A. Zeeb u32 cnt; 11248e93258fSBjoern A. Zeeb 11258e93258fSBjoern A. Zeeb spin_lock_bh(&rtwpci->trx_lock); 11268e93258fSBjoern A. Zeeb cnt = rtw89_pci_get_avail_txbd_num(tx_ring); 1127*6d67aabdSBjoern A. Zeeb if (txch != RTW89_TXCH_CH12) 11288e93258fSBjoern A. Zeeb cnt = min(cnt, wd_ring->curr_num); 11298e93258fSBjoern A. Zeeb spin_unlock_bh(&rtwpci->trx_lock); 11308e93258fSBjoern A. Zeeb 11318e93258fSBjoern A. Zeeb return cnt; 11328e93258fSBjoern A. Zeeb } 11338e93258fSBjoern A. Zeeb 11348e93258fSBjoern A. Zeeb static u32 __rtw89_pci_check_and_reclaim_tx_resource(struct rtw89_dev *rtwdev, 11358e93258fSBjoern A. Zeeb u8 txch) 11368e93258fSBjoern A. Zeeb { 11378e93258fSBjoern A. Zeeb struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; 11388e93258fSBjoern A. Zeeb struct rtw89_pci_tx_ring *tx_ring = &rtwpci->tx_rings[txch]; 11398e93258fSBjoern A. Zeeb struct rtw89_pci_tx_wd_ring *wd_ring = &tx_ring->wd_ring; 1140e2340276SBjoern A. Zeeb const struct rtw89_chip_info *chip = rtwdev->chip; 11418e93258fSBjoern A. Zeeb u32 bd_cnt, wd_cnt, min_cnt = 0; 11428e93258fSBjoern A. Zeeb struct rtw89_pci_rx_ring *rx_ring; 1143e2340276SBjoern A. Zeeb enum rtw89_debug_mask debug_mask; 11448e93258fSBjoern A. Zeeb u32 cnt; 11458e93258fSBjoern A. Zeeb 11468e93258fSBjoern A. Zeeb rx_ring = &rtwpci->rx_rings[RTW89_RXCH_RPQ]; 11478e93258fSBjoern A. Zeeb 11488e93258fSBjoern A. Zeeb spin_lock_bh(&rtwpci->trx_lock); 11498e93258fSBjoern A. Zeeb bd_cnt = rtw89_pci_get_avail_txbd_num(tx_ring); 11508e93258fSBjoern A. Zeeb wd_cnt = wd_ring->curr_num; 11518e93258fSBjoern A. Zeeb 11528e93258fSBjoern A. Zeeb if (wd_cnt == 0 || bd_cnt == 0) { 11538e93258fSBjoern A. Zeeb cnt = rtw89_pci_rxbd_recalc(rtwdev, rx_ring); 11548e93258fSBjoern A. Zeeb if (cnt) 11558e93258fSBjoern A. Zeeb rtw89_pci_release_tx(rtwdev, rx_ring, cnt); 11568e93258fSBjoern A. Zeeb else if (wd_cnt == 0) 11578e93258fSBjoern A. Zeeb goto out_unlock; 11588e93258fSBjoern A. Zeeb 11598e93258fSBjoern A. Zeeb bd_cnt = rtw89_pci_get_avail_txbd_num(tx_ring); 11608e93258fSBjoern A. Zeeb if (bd_cnt == 0) 11618e93258fSBjoern A. Zeeb rtw89_pci_reclaim_txbd(rtwdev, tx_ring); 11628e93258fSBjoern A. Zeeb } 11638e93258fSBjoern A. Zeeb 11648e93258fSBjoern A. Zeeb bd_cnt = rtw89_pci_get_avail_txbd_num(tx_ring); 11658e93258fSBjoern A. Zeeb wd_cnt = wd_ring->curr_num; 11668e93258fSBjoern A. Zeeb min_cnt = min(bd_cnt, wd_cnt); 1167e2340276SBjoern A. Zeeb if (min_cnt == 0) { 1168e2340276SBjoern A. Zeeb /* This message can be frequently shown in low power mode or 1169e2340276SBjoern A. Zeeb * high traffic with small FIFO chips, and we have recognized it as normal 1170e2340276SBjoern A. Zeeb * behavior, so print with mask RTW89_DBG_TXRX in these situations. 1171e2340276SBjoern A. Zeeb */ 1172e2340276SBjoern A. Zeeb if (rtwpci->low_power || chip->small_fifo_size) 1173e2340276SBjoern A. Zeeb debug_mask = RTW89_DBG_TXRX; 1174e2340276SBjoern A. Zeeb else 1175e2340276SBjoern A. Zeeb debug_mask = RTW89_DBG_UNEXP; 1176e2340276SBjoern A. Zeeb 1177e2340276SBjoern A. Zeeb rtw89_debug(rtwdev, debug_mask, 11788e93258fSBjoern A. Zeeb "still no tx resource after reclaim: wd_cnt=%d bd_cnt=%d\n", 11798e93258fSBjoern A. Zeeb wd_cnt, bd_cnt); 1180e2340276SBjoern A. Zeeb } 11818e93258fSBjoern A. Zeeb 11828e93258fSBjoern A. Zeeb out_unlock: 11838e93258fSBjoern A. Zeeb spin_unlock_bh(&rtwpci->trx_lock); 11848e93258fSBjoern A. Zeeb 11858e93258fSBjoern A. Zeeb return min_cnt; 11868e93258fSBjoern A. Zeeb } 11878e93258fSBjoern A. Zeeb 11888e93258fSBjoern A. Zeeb static u32 rtw89_pci_check_and_reclaim_tx_resource(struct rtw89_dev *rtwdev, 11898e93258fSBjoern A. Zeeb u8 txch) 11908e93258fSBjoern A. Zeeb { 11918e93258fSBjoern A. Zeeb if (rtwdev->hci.paused) 11928e93258fSBjoern A. Zeeb return __rtw89_pci_check_and_reclaim_tx_resource_noio(rtwdev, txch); 11938e93258fSBjoern A. Zeeb 11948e93258fSBjoern A. Zeeb if (txch == RTW89_TXCH_CH12) 11958e93258fSBjoern A. Zeeb return __rtw89_pci_check_and_reclaim_tx_fwcmd_resource(rtwdev); 11968e93258fSBjoern A. Zeeb 11978e93258fSBjoern A. Zeeb return __rtw89_pci_check_and_reclaim_tx_resource(rtwdev, txch); 11988e93258fSBjoern A. Zeeb } 11998e93258fSBjoern A. Zeeb 12008e93258fSBjoern A. Zeeb static void __rtw89_pci_tx_kick_off(struct rtw89_dev *rtwdev, struct rtw89_pci_tx_ring *tx_ring) 12018e93258fSBjoern A. Zeeb { 12028e93258fSBjoern A. Zeeb struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; 12038e93258fSBjoern A. Zeeb struct rtw89_pci_dma_ring *bd_ring = &tx_ring->bd_ring; 12048e93258fSBjoern A. Zeeb u32 host_idx, addr; 12058e93258fSBjoern A. Zeeb 12068e93258fSBjoern A. Zeeb spin_lock_bh(&rtwpci->trx_lock); 12078e93258fSBjoern A. Zeeb 12088e93258fSBjoern A. Zeeb addr = bd_ring->addr.idx; 12098e93258fSBjoern A. Zeeb host_idx = bd_ring->wp; 12108e93258fSBjoern A. Zeeb rtw89_write16(rtwdev, addr, host_idx); 12118e93258fSBjoern A. Zeeb 12128e93258fSBjoern A. Zeeb spin_unlock_bh(&rtwpci->trx_lock); 12138e93258fSBjoern A. Zeeb } 12148e93258fSBjoern A. Zeeb 12158e93258fSBjoern A. Zeeb static void rtw89_pci_tx_bd_ring_update(struct rtw89_dev *rtwdev, struct rtw89_pci_tx_ring *tx_ring, 12168e93258fSBjoern A. Zeeb int n_txbd) 12178e93258fSBjoern A. Zeeb { 12188e93258fSBjoern A. Zeeb struct rtw89_pci_dma_ring *bd_ring = &tx_ring->bd_ring; 12198e93258fSBjoern A. Zeeb u32 host_idx, len; 12208e93258fSBjoern A. Zeeb 12218e93258fSBjoern A. Zeeb len = bd_ring->len; 12228e93258fSBjoern A. Zeeb host_idx = bd_ring->wp + n_txbd; 12238e93258fSBjoern A. Zeeb host_idx = host_idx < len ? host_idx : host_idx - len; 12248e93258fSBjoern A. Zeeb 12258e93258fSBjoern A. Zeeb bd_ring->wp = host_idx; 12268e93258fSBjoern A. Zeeb } 12278e93258fSBjoern A. Zeeb 12288e93258fSBjoern A. Zeeb static void rtw89_pci_ops_tx_kick_off(struct rtw89_dev *rtwdev, u8 txch) 12298e93258fSBjoern A. Zeeb { 12308e93258fSBjoern A. Zeeb struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; 12318e93258fSBjoern A. Zeeb struct rtw89_pci_tx_ring *tx_ring = &rtwpci->tx_rings[txch]; 12328e93258fSBjoern A. Zeeb 12338e93258fSBjoern A. Zeeb if (rtwdev->hci.paused) { 12348e93258fSBjoern A. Zeeb set_bit(txch, rtwpci->kick_map); 12358e93258fSBjoern A. Zeeb return; 12368e93258fSBjoern A. Zeeb } 12378e93258fSBjoern A. Zeeb 12388e93258fSBjoern A. Zeeb __rtw89_pci_tx_kick_off(rtwdev, tx_ring); 12398e93258fSBjoern A. Zeeb } 12408e93258fSBjoern A. Zeeb 12418e93258fSBjoern A. Zeeb static void rtw89_pci_tx_kick_off_pending(struct rtw89_dev *rtwdev) 12428e93258fSBjoern A. Zeeb { 12438e93258fSBjoern A. Zeeb struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; 12448e93258fSBjoern A. Zeeb struct rtw89_pci_tx_ring *tx_ring; 12458e93258fSBjoern A. Zeeb int txch; 12468e93258fSBjoern A. Zeeb 12478e93258fSBjoern A. Zeeb for (txch = 0; txch < RTW89_TXCH_NUM; txch++) { 12488e93258fSBjoern A. Zeeb if (!test_and_clear_bit(txch, rtwpci->kick_map)) 12498e93258fSBjoern A. Zeeb continue; 12508e93258fSBjoern A. Zeeb 12518e93258fSBjoern A. Zeeb tx_ring = &rtwpci->tx_rings[txch]; 12528e93258fSBjoern A. Zeeb __rtw89_pci_tx_kick_off(rtwdev, tx_ring); 12538e93258fSBjoern A. Zeeb } 12548e93258fSBjoern A. Zeeb } 12558e93258fSBjoern A. Zeeb 12568e93258fSBjoern A. Zeeb static void __pci_flush_txch(struct rtw89_dev *rtwdev, u8 txch, bool drop) 12578e93258fSBjoern A. Zeeb { 12588e93258fSBjoern A. Zeeb struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; 12598e93258fSBjoern A. Zeeb struct rtw89_pci_tx_ring *tx_ring = &rtwpci->tx_rings[txch]; 12608e93258fSBjoern A. Zeeb struct rtw89_pci_dma_ring *bd_ring = &tx_ring->bd_ring; 12618e93258fSBjoern A. Zeeb u32 cur_idx, cur_rp; 12628e93258fSBjoern A. Zeeb u8 i; 12638e93258fSBjoern A. Zeeb 12648e93258fSBjoern A. Zeeb /* Because the time taked by the I/O is a bit dynamic, it's hard to 12658e93258fSBjoern A. Zeeb * define a reasonable fixed total timeout to use read_poll_timeout* 12668e93258fSBjoern A. Zeeb * helper. Instead, we can ensure a reasonable polling times, so we 12678e93258fSBjoern A. Zeeb * just use for loop with udelay here. 12688e93258fSBjoern A. Zeeb */ 12698e93258fSBjoern A. Zeeb for (i = 0; i < 60; i++) { 12708e93258fSBjoern A. Zeeb cur_idx = rtw89_read32(rtwdev, bd_ring->addr.idx); 12718e93258fSBjoern A. Zeeb cur_rp = FIELD_GET(TXBD_HW_IDX_MASK, cur_idx); 12728e93258fSBjoern A. Zeeb if (cur_rp == bd_ring->wp) 12738e93258fSBjoern A. Zeeb return; 12748e93258fSBjoern A. Zeeb 12758e93258fSBjoern A. Zeeb udelay(1); 12768e93258fSBjoern A. Zeeb } 12778e93258fSBjoern A. Zeeb 12788e93258fSBjoern A. Zeeb if (!drop) 12798e93258fSBjoern A. Zeeb rtw89_info(rtwdev, "timed out to flush pci txch: %d\n", txch); 12808e93258fSBjoern A. Zeeb } 12818e93258fSBjoern A. Zeeb 12828e93258fSBjoern A. Zeeb static void __rtw89_pci_ops_flush_txchs(struct rtw89_dev *rtwdev, u32 txchs, 12838e93258fSBjoern A. Zeeb bool drop) 12848e93258fSBjoern A. Zeeb { 1285e2340276SBjoern A. Zeeb const struct rtw89_pci_info *info = rtwdev->pci_info; 12868e93258fSBjoern A. Zeeb u8 i; 12878e93258fSBjoern A. Zeeb 12888e93258fSBjoern A. Zeeb for (i = 0; i < RTW89_TXCH_NUM; i++) { 12898e93258fSBjoern A. Zeeb /* It may be unnecessary to flush FWCMD queue. */ 12908e93258fSBjoern A. Zeeb if (i == RTW89_TXCH_CH12) 12918e93258fSBjoern A. Zeeb continue; 1292e2340276SBjoern A. Zeeb if (info->tx_dma_ch_mask & BIT(i)) 1293e2340276SBjoern A. Zeeb continue; 12948e93258fSBjoern A. Zeeb 12958e93258fSBjoern A. Zeeb if (txchs & BIT(i)) 12968e93258fSBjoern A. Zeeb __pci_flush_txch(rtwdev, i, drop); 12978e93258fSBjoern A. Zeeb } 12988e93258fSBjoern A. Zeeb } 12998e93258fSBjoern A. Zeeb 13008e93258fSBjoern A. Zeeb static void rtw89_pci_ops_flush_queues(struct rtw89_dev *rtwdev, u32 queues, 13018e93258fSBjoern A. Zeeb bool drop) 13028e93258fSBjoern A. Zeeb { 13038e93258fSBjoern A. Zeeb __rtw89_pci_ops_flush_txchs(rtwdev, BIT(RTW89_TXCH_NUM) - 1, drop); 13048e93258fSBjoern A. Zeeb } 13058e93258fSBjoern A. Zeeb 13068e93258fSBjoern A. Zeeb u32 rtw89_pci_fill_txaddr_info(struct rtw89_dev *rtwdev, 13078e93258fSBjoern A. Zeeb void *txaddr_info_addr, u32 total_len, 13088e93258fSBjoern A. Zeeb dma_addr_t dma, u8 *add_info_nr) 13098e93258fSBjoern A. Zeeb { 13108e93258fSBjoern A. Zeeb struct rtw89_pci_tx_addr_info_32 *txaddr_info = txaddr_info_addr; 1311*6d67aabdSBjoern A. Zeeb __le16 option; 13128e93258fSBjoern A. Zeeb 13138e93258fSBjoern A. Zeeb txaddr_info->length = cpu_to_le16(total_len); 1314*6d67aabdSBjoern A. Zeeb option = cpu_to_le16(RTW89_PCI_ADDR_MSDU_LS | RTW89_PCI_ADDR_NUM(1)); 1315*6d67aabdSBjoern A. Zeeb option |= le16_encode_bits(upper_32_bits(dma), RTW89_PCI_ADDR_HIGH_MASK); 1316*6d67aabdSBjoern A. Zeeb txaddr_info->option = option; 13178e93258fSBjoern A. Zeeb txaddr_info->dma = cpu_to_le32(dma); 13188e93258fSBjoern A. Zeeb 13198e93258fSBjoern A. Zeeb *add_info_nr = 1; 13208e93258fSBjoern A. Zeeb 13218e93258fSBjoern A. Zeeb return sizeof(*txaddr_info); 13228e93258fSBjoern A. Zeeb } 13238e93258fSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_pci_fill_txaddr_info); 13248e93258fSBjoern A. Zeeb 13258e93258fSBjoern A. Zeeb u32 rtw89_pci_fill_txaddr_info_v1(struct rtw89_dev *rtwdev, 13268e93258fSBjoern A. Zeeb void *txaddr_info_addr, u32 total_len, 13278e93258fSBjoern A. Zeeb dma_addr_t dma, u8 *add_info_nr) 13288e93258fSBjoern A. Zeeb { 13298e93258fSBjoern A. Zeeb struct rtw89_pci_tx_addr_info_32_v1 *txaddr_info = txaddr_info_addr; 13308e93258fSBjoern A. Zeeb u32 remain = total_len; 13318e93258fSBjoern A. Zeeb u32 len; 13328e93258fSBjoern A. Zeeb u16 length_option; 13338e93258fSBjoern A. Zeeb int n; 13348e93258fSBjoern A. Zeeb 13358e93258fSBjoern A. Zeeb for (n = 0; n < RTW89_TXADDR_INFO_NR_V1 && remain; n++) { 13368e93258fSBjoern A. Zeeb len = remain >= TXADDR_INFO_LENTHG_V1_MAX ? 13378e93258fSBjoern A. Zeeb TXADDR_INFO_LENTHG_V1_MAX : remain; 13388e93258fSBjoern A. Zeeb remain -= len; 13398e93258fSBjoern A. Zeeb 13408e93258fSBjoern A. Zeeb length_option = FIELD_PREP(B_PCIADDR_LEN_V1_MASK, len) | 13418e93258fSBjoern A. Zeeb FIELD_PREP(B_PCIADDR_HIGH_SEL_V1_MASK, 0) | 13428e93258fSBjoern A. Zeeb FIELD_PREP(B_PCIADDR_LS_V1_MASK, remain == 0); 1343*6d67aabdSBjoern A. Zeeb length_option |= u16_encode_bits(upper_32_bits(dma), 1344*6d67aabdSBjoern A. Zeeb B_PCIADDR_HIGH_SEL_V1_MASK); 13458e93258fSBjoern A. Zeeb txaddr_info->length_opt = cpu_to_le16(length_option); 13468e93258fSBjoern A. Zeeb txaddr_info->dma_low_lsb = cpu_to_le16(FIELD_GET(GENMASK(15, 0), dma)); 13478e93258fSBjoern A. Zeeb txaddr_info->dma_low_msb = cpu_to_le16(FIELD_GET(GENMASK(31, 16), dma)); 13488e93258fSBjoern A. Zeeb 13498e93258fSBjoern A. Zeeb dma += len; 13508e93258fSBjoern A. Zeeb txaddr_info++; 13518e93258fSBjoern A. Zeeb } 13528e93258fSBjoern A. Zeeb 13538e93258fSBjoern A. Zeeb WARN_ONCE(remain, "length overflow remain=%u total_len=%u", 13548e93258fSBjoern A. Zeeb remain, total_len); 13558e93258fSBjoern A. Zeeb 13568e93258fSBjoern A. Zeeb *add_info_nr = n; 13578e93258fSBjoern A. Zeeb 13588e93258fSBjoern A. Zeeb return n * sizeof(*txaddr_info); 13598e93258fSBjoern A. Zeeb } 13608e93258fSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_pci_fill_txaddr_info_v1); 13618e93258fSBjoern A. Zeeb 13628e93258fSBjoern A. Zeeb static int rtw89_pci_txwd_submit(struct rtw89_dev *rtwdev, 13638e93258fSBjoern A. Zeeb struct rtw89_pci_tx_ring *tx_ring, 13648e93258fSBjoern A. Zeeb struct rtw89_pci_tx_wd *txwd, 13658e93258fSBjoern A. Zeeb struct rtw89_core_tx_request *tx_req) 13668e93258fSBjoern A. Zeeb { 13678e93258fSBjoern A. Zeeb struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; 13688e93258fSBjoern A. Zeeb const struct rtw89_chip_info *chip = rtwdev->chip; 13698e93258fSBjoern A. Zeeb struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info; 13708e93258fSBjoern A. Zeeb struct rtw89_pci_tx_wp_info *txwp_info; 13718e93258fSBjoern A. Zeeb void *txaddr_info_addr; 13728e93258fSBjoern A. Zeeb struct pci_dev *pdev = rtwpci->pdev; 13738e93258fSBjoern A. Zeeb struct sk_buff *skb = tx_req->skb; 13748e93258fSBjoern A. Zeeb struct rtw89_pci_tx_data *tx_data = RTW89_PCI_TX_SKB_CB(skb); 1375e2340276SBjoern A. Zeeb struct rtw89_tx_skb_data *skb_data = RTW89_TX_SKB_CB(skb); 13768e93258fSBjoern A. Zeeb bool en_wd_info = desc_info->en_wd_info; 13778e93258fSBjoern A. Zeeb u32 txwd_len; 13788e93258fSBjoern A. Zeeb u32 txwp_len; 13798e93258fSBjoern A. Zeeb u32 txaddr_info_len; 13808e93258fSBjoern A. Zeeb dma_addr_t dma; 13818e93258fSBjoern A. Zeeb int ret; 13828e93258fSBjoern A. Zeeb 13838e93258fSBjoern A. Zeeb dma = dma_map_single(&pdev->dev, skb->data, skb->len, DMA_TO_DEVICE); 13848e93258fSBjoern A. Zeeb if (dma_mapping_error(&pdev->dev, dma)) { 13858e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "failed to map skb dma data\n"); 13868e93258fSBjoern A. Zeeb ret = -EBUSY; 13878e93258fSBjoern A. Zeeb goto err; 13888e93258fSBjoern A. Zeeb } 13898e93258fSBjoern A. Zeeb 13908e93258fSBjoern A. Zeeb tx_data->dma = dma; 1391e2340276SBjoern A. Zeeb rcu_assign_pointer(skb_data->wait, NULL); 13928e93258fSBjoern A. Zeeb 13938e93258fSBjoern A. Zeeb txwp_len = sizeof(*txwp_info); 13948e93258fSBjoern A. Zeeb txwd_len = chip->txwd_body_size; 1395*6d67aabdSBjoern A. Zeeb txwd_len += en_wd_info ? chip->txwd_info_size : 0; 13968e93258fSBjoern A. Zeeb 13978e93258fSBjoern A. Zeeb #if defined(__linux__) 13988e93258fSBjoern A. Zeeb txwp_info = txwd->vaddr + txwd_len; 13998e93258fSBjoern A. Zeeb #elif defined(__FreeBSD__) 14008e93258fSBjoern A. Zeeb txwp_info = (struct rtw89_pci_tx_wp_info *)((u8 *)txwd->vaddr + txwd_len); 14018e93258fSBjoern A. Zeeb #endif 14028e93258fSBjoern A. Zeeb txwp_info->seq0 = cpu_to_le16(txwd->seq | RTW89_PCI_TXWP_VALID); 14038e93258fSBjoern A. Zeeb txwp_info->seq1 = 0; 14048e93258fSBjoern A. Zeeb txwp_info->seq2 = 0; 14058e93258fSBjoern A. Zeeb txwp_info->seq3 = 0; 14068e93258fSBjoern A. Zeeb 14078e93258fSBjoern A. Zeeb tx_ring->tx_cnt++; 14088e93258fSBjoern A. Zeeb #if defined(__linux__) 14098e93258fSBjoern A. Zeeb txaddr_info_addr = txwd->vaddr + txwd_len + txwp_len; 14108e93258fSBjoern A. Zeeb #elif defined(__FreeBSD__) 14118e93258fSBjoern A. Zeeb txaddr_info_addr = (u8 *)txwd->vaddr + txwd_len + txwp_len; 14128e93258fSBjoern A. Zeeb #endif 14138e93258fSBjoern A. Zeeb txaddr_info_len = 14148e93258fSBjoern A. Zeeb rtw89_chip_fill_txaddr_info(rtwdev, txaddr_info_addr, skb->len, 14158e93258fSBjoern A. Zeeb dma, &desc_info->addr_info_nr); 14168e93258fSBjoern A. Zeeb 14178e93258fSBjoern A. Zeeb txwd->len = txwd_len + txwp_len + txaddr_info_len; 14188e93258fSBjoern A. Zeeb 14198e93258fSBjoern A. Zeeb rtw89_chip_fill_txdesc(rtwdev, desc_info, txwd->vaddr); 14208e93258fSBjoern A. Zeeb 14218e93258fSBjoern A. Zeeb skb_queue_tail(&txwd->queue, skb); 14228e93258fSBjoern A. Zeeb 14238e93258fSBjoern A. Zeeb return 0; 14248e93258fSBjoern A. Zeeb 14258e93258fSBjoern A. Zeeb err: 14268e93258fSBjoern A. Zeeb return ret; 14278e93258fSBjoern A. Zeeb } 14288e93258fSBjoern A. Zeeb 14298e93258fSBjoern A. Zeeb static int rtw89_pci_fwcmd_submit(struct rtw89_dev *rtwdev, 14308e93258fSBjoern A. Zeeb struct rtw89_pci_tx_ring *tx_ring, 14318e93258fSBjoern A. Zeeb struct rtw89_pci_tx_bd_32 *txbd, 14328e93258fSBjoern A. Zeeb struct rtw89_core_tx_request *tx_req) 14338e93258fSBjoern A. Zeeb { 14348e93258fSBjoern A. Zeeb struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; 14358e93258fSBjoern A. Zeeb const struct rtw89_chip_info *chip = rtwdev->chip; 14368e93258fSBjoern A. Zeeb struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info; 14378e93258fSBjoern A. Zeeb void *txdesc; 14388e93258fSBjoern A. Zeeb int txdesc_size = chip->h2c_desc_size; 14398e93258fSBjoern A. Zeeb struct pci_dev *pdev = rtwpci->pdev; 14408e93258fSBjoern A. Zeeb struct sk_buff *skb = tx_req->skb; 14418e93258fSBjoern A. Zeeb struct rtw89_pci_tx_data *tx_data = RTW89_PCI_TX_SKB_CB(skb); 14428e93258fSBjoern A. Zeeb dma_addr_t dma; 1443*6d67aabdSBjoern A. Zeeb __le16 opt; 14448e93258fSBjoern A. Zeeb 14458e93258fSBjoern A. Zeeb txdesc = skb_push(skb, txdesc_size); 14468e93258fSBjoern A. Zeeb memset(txdesc, 0, txdesc_size); 14478e93258fSBjoern A. Zeeb rtw89_chip_fill_txdesc_fwcmd(rtwdev, desc_info, txdesc); 14488e93258fSBjoern A. Zeeb 14498e93258fSBjoern A. Zeeb dma = dma_map_single(&pdev->dev, skb->data, skb->len, DMA_TO_DEVICE); 14508e93258fSBjoern A. Zeeb if (dma_mapping_error(&pdev->dev, dma)) { 14518e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "failed to map fwcmd dma data\n"); 14528e93258fSBjoern A. Zeeb return -EBUSY; 14538e93258fSBjoern A. Zeeb } 14548e93258fSBjoern A. Zeeb 14558e93258fSBjoern A. Zeeb tx_data->dma = dma; 1456*6d67aabdSBjoern A. Zeeb opt = cpu_to_le16(RTW89_PCI_TXBD_OPT_LS); 1457*6d67aabdSBjoern A. Zeeb opt |= le16_encode_bits(upper_32_bits(dma), RTW89_PCI_TXBD_OPT_DMA_HI); 1458*6d67aabdSBjoern A. Zeeb txbd->opt = opt; 14598e93258fSBjoern A. Zeeb txbd->length = cpu_to_le16(skb->len); 14608e93258fSBjoern A. Zeeb txbd->dma = cpu_to_le32(tx_data->dma); 14618e93258fSBjoern A. Zeeb skb_queue_tail(&rtwpci->h2c_queue, skb); 14628e93258fSBjoern A. Zeeb 14638e93258fSBjoern A. Zeeb rtw89_pci_tx_bd_ring_update(rtwdev, tx_ring, 1); 14648e93258fSBjoern A. Zeeb 14658e93258fSBjoern A. Zeeb return 0; 14668e93258fSBjoern A. Zeeb } 14678e93258fSBjoern A. Zeeb 14688e93258fSBjoern A. Zeeb static int rtw89_pci_txbd_submit(struct rtw89_dev *rtwdev, 14698e93258fSBjoern A. Zeeb struct rtw89_pci_tx_ring *tx_ring, 14708e93258fSBjoern A. Zeeb struct rtw89_pci_tx_bd_32 *txbd, 14718e93258fSBjoern A. Zeeb struct rtw89_core_tx_request *tx_req) 14728e93258fSBjoern A. Zeeb { 14738e93258fSBjoern A. Zeeb struct rtw89_pci_tx_wd *txwd; 1474*6d67aabdSBjoern A. Zeeb __le16 opt; 14758e93258fSBjoern A. Zeeb int ret; 14768e93258fSBjoern A. Zeeb 14778e93258fSBjoern A. Zeeb /* FWCMD queue doesn't have wd pages. Instead, it submits the CMD 14788e93258fSBjoern A. Zeeb * buffer with WD BODY only. So here we don't need to check the free 14798e93258fSBjoern A. Zeeb * pages of the wd ring. 14808e93258fSBjoern A. Zeeb */ 14818e93258fSBjoern A. Zeeb if (tx_ring->txch == RTW89_TXCH_CH12) 14828e93258fSBjoern A. Zeeb return rtw89_pci_fwcmd_submit(rtwdev, tx_ring, txbd, tx_req); 14838e93258fSBjoern A. Zeeb 14848e93258fSBjoern A. Zeeb txwd = rtw89_pci_dequeue_txwd(tx_ring); 14858e93258fSBjoern A. Zeeb if (!txwd) { 14868e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "no available TXWD\n"); 14878e93258fSBjoern A. Zeeb ret = -ENOSPC; 14888e93258fSBjoern A. Zeeb goto err; 14898e93258fSBjoern A. Zeeb } 14908e93258fSBjoern A. Zeeb 14918e93258fSBjoern A. Zeeb ret = rtw89_pci_txwd_submit(rtwdev, tx_ring, txwd, tx_req); 14928e93258fSBjoern A. Zeeb if (ret) { 14938e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "failed to submit TXWD %d\n", txwd->seq); 14948e93258fSBjoern A. Zeeb goto err_enqueue_wd; 14958e93258fSBjoern A. Zeeb } 14968e93258fSBjoern A. Zeeb 14978e93258fSBjoern A. Zeeb list_add_tail(&txwd->list, &tx_ring->busy_pages); 14988e93258fSBjoern A. Zeeb 1499*6d67aabdSBjoern A. Zeeb opt = cpu_to_le16(RTW89_PCI_TXBD_OPT_LS); 1500*6d67aabdSBjoern A. Zeeb opt |= le16_encode_bits(upper_32_bits(txwd->paddr), RTW89_PCI_TXBD_OPT_DMA_HI); 1501*6d67aabdSBjoern A. Zeeb txbd->opt = opt; 15028e93258fSBjoern A. Zeeb txbd->length = cpu_to_le16(txwd->len); 15038e93258fSBjoern A. Zeeb txbd->dma = cpu_to_le32(txwd->paddr); 15048e93258fSBjoern A. Zeeb 15058e93258fSBjoern A. Zeeb rtw89_pci_tx_bd_ring_update(rtwdev, tx_ring, 1); 15068e93258fSBjoern A. Zeeb 15078e93258fSBjoern A. Zeeb return 0; 15088e93258fSBjoern A. Zeeb 15098e93258fSBjoern A. Zeeb err_enqueue_wd: 15108e93258fSBjoern A. Zeeb rtw89_pci_enqueue_txwd(tx_ring, txwd); 15118e93258fSBjoern A. Zeeb err: 15128e93258fSBjoern A. Zeeb return ret; 15138e93258fSBjoern A. Zeeb } 15148e93258fSBjoern A. Zeeb 15158e93258fSBjoern A. Zeeb static int rtw89_pci_tx_write(struct rtw89_dev *rtwdev, struct rtw89_core_tx_request *tx_req, 15168e93258fSBjoern A. Zeeb u8 txch) 15178e93258fSBjoern A. Zeeb { 15188e93258fSBjoern A. Zeeb struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; 15198e93258fSBjoern A. Zeeb struct rtw89_pci_tx_ring *tx_ring; 15208e93258fSBjoern A. Zeeb struct rtw89_pci_tx_bd_32 *txbd; 15218e93258fSBjoern A. Zeeb u32 n_avail_txbd; 15228e93258fSBjoern A. Zeeb int ret = 0; 15238e93258fSBjoern A. Zeeb 15248e93258fSBjoern A. Zeeb /* check the tx type and dma channel for fw cmd queue */ 15258e93258fSBjoern A. Zeeb if ((txch == RTW89_TXCH_CH12 || 15268e93258fSBjoern A. Zeeb tx_req->tx_type == RTW89_CORE_TX_TYPE_FWCMD) && 15278e93258fSBjoern A. Zeeb (txch != RTW89_TXCH_CH12 || 15288e93258fSBjoern A. Zeeb tx_req->tx_type != RTW89_CORE_TX_TYPE_FWCMD)) { 15298e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "only fw cmd uses dma channel 12\n"); 15308e93258fSBjoern A. Zeeb return -EINVAL; 15318e93258fSBjoern A. Zeeb } 15328e93258fSBjoern A. Zeeb 15338e93258fSBjoern A. Zeeb tx_ring = &rtwpci->tx_rings[txch]; 15348e93258fSBjoern A. Zeeb spin_lock_bh(&rtwpci->trx_lock); 15358e93258fSBjoern A. Zeeb 15368e93258fSBjoern A. Zeeb n_avail_txbd = rtw89_pci_get_avail_txbd_num(tx_ring); 15378e93258fSBjoern A. Zeeb if (n_avail_txbd == 0) { 15388e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "no available TXBD\n"); 15398e93258fSBjoern A. Zeeb ret = -ENOSPC; 15408e93258fSBjoern A. Zeeb goto err_unlock; 15418e93258fSBjoern A. Zeeb } 15428e93258fSBjoern A. Zeeb 15438e93258fSBjoern A. Zeeb txbd = rtw89_pci_get_next_txbd(tx_ring); 15448e93258fSBjoern A. Zeeb ret = rtw89_pci_txbd_submit(rtwdev, tx_ring, txbd, tx_req); 15458e93258fSBjoern A. Zeeb if (ret) { 15468e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "failed to submit TXBD\n"); 15478e93258fSBjoern A. Zeeb goto err_unlock; 15488e93258fSBjoern A. Zeeb } 15498e93258fSBjoern A. Zeeb 15508e93258fSBjoern A. Zeeb spin_unlock_bh(&rtwpci->trx_lock); 15518e93258fSBjoern A. Zeeb return 0; 15528e93258fSBjoern A. Zeeb 15538e93258fSBjoern A. Zeeb err_unlock: 15548e93258fSBjoern A. Zeeb spin_unlock_bh(&rtwpci->trx_lock); 15558e93258fSBjoern A. Zeeb return ret; 15568e93258fSBjoern A. Zeeb } 15578e93258fSBjoern A. Zeeb 15588e93258fSBjoern A. Zeeb static int rtw89_pci_ops_tx_write(struct rtw89_dev *rtwdev, struct rtw89_core_tx_request *tx_req) 15598e93258fSBjoern A. Zeeb { 15608e93258fSBjoern A. Zeeb struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info; 15618e93258fSBjoern A. Zeeb int ret; 15628e93258fSBjoern A. Zeeb 15638e93258fSBjoern A. Zeeb ret = rtw89_pci_tx_write(rtwdev, tx_req, desc_info->ch_dma); 15648e93258fSBjoern A. Zeeb if (ret) { 15658e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "failed to TX Queue %d\n", desc_info->ch_dma); 15668e93258fSBjoern A. Zeeb return ret; 15678e93258fSBjoern A. Zeeb } 15688e93258fSBjoern A. Zeeb 15698e93258fSBjoern A. Zeeb return 0; 15708e93258fSBjoern A. Zeeb } 15718e93258fSBjoern A. Zeeb 1572e2340276SBjoern A. Zeeb const struct rtw89_pci_bd_ram rtw89_bd_ram_table_dual[RTW89_TXCH_NUM] = { 15738e93258fSBjoern A. Zeeb [RTW89_TXCH_ACH0] = {.start_idx = 0, .max_num = 5, .min_num = 2}, 15748e93258fSBjoern A. Zeeb [RTW89_TXCH_ACH1] = {.start_idx = 5, .max_num = 5, .min_num = 2}, 15758e93258fSBjoern A. Zeeb [RTW89_TXCH_ACH2] = {.start_idx = 10, .max_num = 5, .min_num = 2}, 15768e93258fSBjoern A. Zeeb [RTW89_TXCH_ACH3] = {.start_idx = 15, .max_num = 5, .min_num = 2}, 15778e93258fSBjoern A. Zeeb [RTW89_TXCH_ACH4] = {.start_idx = 20, .max_num = 5, .min_num = 2}, 15788e93258fSBjoern A. Zeeb [RTW89_TXCH_ACH5] = {.start_idx = 25, .max_num = 5, .min_num = 2}, 15798e93258fSBjoern A. Zeeb [RTW89_TXCH_ACH6] = {.start_idx = 30, .max_num = 5, .min_num = 2}, 15808e93258fSBjoern A. Zeeb [RTW89_TXCH_ACH7] = {.start_idx = 35, .max_num = 5, .min_num = 2}, 15818e93258fSBjoern A. Zeeb [RTW89_TXCH_CH8] = {.start_idx = 40, .max_num = 5, .min_num = 1}, 15828e93258fSBjoern A. Zeeb [RTW89_TXCH_CH9] = {.start_idx = 45, .max_num = 5, .min_num = 1}, 15838e93258fSBjoern A. Zeeb [RTW89_TXCH_CH10] = {.start_idx = 50, .max_num = 5, .min_num = 1}, 15848e93258fSBjoern A. Zeeb [RTW89_TXCH_CH11] = {.start_idx = 55, .max_num = 5, .min_num = 1}, 15858e93258fSBjoern A. Zeeb [RTW89_TXCH_CH12] = {.start_idx = 60, .max_num = 4, .min_num = 1}, 15868e93258fSBjoern A. Zeeb }; 1587e2340276SBjoern A. Zeeb EXPORT_SYMBOL(rtw89_bd_ram_table_dual); 1588e2340276SBjoern A. Zeeb 1589e2340276SBjoern A. Zeeb const struct rtw89_pci_bd_ram rtw89_bd_ram_table_single[RTW89_TXCH_NUM] = { 1590e2340276SBjoern A. Zeeb [RTW89_TXCH_ACH0] = {.start_idx = 0, .max_num = 5, .min_num = 2}, 1591e2340276SBjoern A. Zeeb [RTW89_TXCH_ACH1] = {.start_idx = 5, .max_num = 5, .min_num = 2}, 1592e2340276SBjoern A. Zeeb [RTW89_TXCH_ACH2] = {.start_idx = 10, .max_num = 5, .min_num = 2}, 1593e2340276SBjoern A. Zeeb [RTW89_TXCH_ACH3] = {.start_idx = 15, .max_num = 5, .min_num = 2}, 1594e2340276SBjoern A. Zeeb [RTW89_TXCH_CH8] = {.start_idx = 20, .max_num = 4, .min_num = 1}, 1595e2340276SBjoern A. Zeeb [RTW89_TXCH_CH9] = {.start_idx = 24, .max_num = 4, .min_num = 1}, 1596e2340276SBjoern A. Zeeb [RTW89_TXCH_CH12] = {.start_idx = 28, .max_num = 4, .min_num = 1}, 1597e2340276SBjoern A. Zeeb }; 1598e2340276SBjoern A. Zeeb EXPORT_SYMBOL(rtw89_bd_ram_table_single); 15998e93258fSBjoern A. Zeeb 1600*6d67aabdSBjoern A. Zeeb static void rtw89_pci_init_wp_16sel(struct rtw89_dev *rtwdev) 1601*6d67aabdSBjoern A. Zeeb { 1602*6d67aabdSBjoern A. Zeeb const struct rtw89_pci_info *info = rtwdev->pci_info; 1603*6d67aabdSBjoern A. Zeeb u32 addr = info->wp_sel_addr; 1604*6d67aabdSBjoern A. Zeeb u32 val; 1605*6d67aabdSBjoern A. Zeeb int i; 1606*6d67aabdSBjoern A. Zeeb 1607*6d67aabdSBjoern A. Zeeb if (!info->wp_sel_addr) 1608*6d67aabdSBjoern A. Zeeb return; 1609*6d67aabdSBjoern A. Zeeb 1610*6d67aabdSBjoern A. Zeeb for (i = 0; i < 16; i += 4) { 1611*6d67aabdSBjoern A. Zeeb val = u32_encode_bits(i + 0, MASKBYTE0) | 1612*6d67aabdSBjoern A. Zeeb u32_encode_bits(i + 1, MASKBYTE1) | 1613*6d67aabdSBjoern A. Zeeb u32_encode_bits(i + 2, MASKBYTE2) | 1614*6d67aabdSBjoern A. Zeeb u32_encode_bits(i + 3, MASKBYTE3); 1615*6d67aabdSBjoern A. Zeeb rtw89_write32(rtwdev, addr + i, val); 1616*6d67aabdSBjoern A. Zeeb } 1617*6d67aabdSBjoern A. Zeeb } 1618*6d67aabdSBjoern A. Zeeb 16198e93258fSBjoern A. Zeeb static void rtw89_pci_reset_trx_rings(struct rtw89_dev *rtwdev) 16208e93258fSBjoern A. Zeeb { 16218e93258fSBjoern A. Zeeb struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; 1622e2340276SBjoern A. Zeeb const struct rtw89_pci_info *info = rtwdev->pci_info; 1623e2340276SBjoern A. Zeeb const struct rtw89_pci_bd_ram *bd_ram_table = *info->bd_ram_table; 16248e93258fSBjoern A. Zeeb struct rtw89_pci_tx_ring *tx_ring; 16258e93258fSBjoern A. Zeeb struct rtw89_pci_rx_ring *rx_ring; 16268e93258fSBjoern A. Zeeb struct rtw89_pci_dma_ring *bd_ring; 16278e93258fSBjoern A. Zeeb const struct rtw89_pci_bd_ram *bd_ram; 16288e93258fSBjoern A. Zeeb u32 addr_num; 1629*6d67aabdSBjoern A. Zeeb u32 addr_idx; 16308e93258fSBjoern A. Zeeb u32 addr_bdram; 16318e93258fSBjoern A. Zeeb u32 addr_desa_l; 16328e93258fSBjoern A. Zeeb u32 val32; 16338e93258fSBjoern A. Zeeb int i; 16348e93258fSBjoern A. Zeeb 16358e93258fSBjoern A. Zeeb for (i = 0; i < RTW89_TXCH_NUM; i++) { 1636e2340276SBjoern A. Zeeb if (info->tx_dma_ch_mask & BIT(i)) 1637e2340276SBjoern A. Zeeb continue; 1638e2340276SBjoern A. Zeeb 16398e93258fSBjoern A. Zeeb tx_ring = &rtwpci->tx_rings[i]; 16408e93258fSBjoern A. Zeeb bd_ring = &tx_ring->bd_ring; 1641*6d67aabdSBjoern A. Zeeb bd_ram = bd_ram_table ? &bd_ram_table[i] : NULL; 16428e93258fSBjoern A. Zeeb addr_num = bd_ring->addr.num; 16438e93258fSBjoern A. Zeeb addr_bdram = bd_ring->addr.bdram; 16448e93258fSBjoern A. Zeeb addr_desa_l = bd_ring->addr.desa_l; 16458e93258fSBjoern A. Zeeb bd_ring->wp = 0; 16468e93258fSBjoern A. Zeeb bd_ring->rp = 0; 16478e93258fSBjoern A. Zeeb 1648*6d67aabdSBjoern A. Zeeb rtw89_write16(rtwdev, addr_num, bd_ring->len); 1649*6d67aabdSBjoern A. Zeeb if (addr_bdram && bd_ram) { 16508e93258fSBjoern A. Zeeb val32 = FIELD_PREP(BDRAM_SIDX_MASK, bd_ram->start_idx) | 16518e93258fSBjoern A. Zeeb FIELD_PREP(BDRAM_MAX_MASK, bd_ram->max_num) | 16528e93258fSBjoern A. Zeeb FIELD_PREP(BDRAM_MIN_MASK, bd_ram->min_num); 16538e93258fSBjoern A. Zeeb 16548e93258fSBjoern A. Zeeb rtw89_write32(rtwdev, addr_bdram, val32); 1655*6d67aabdSBjoern A. Zeeb } 16568e93258fSBjoern A. Zeeb rtw89_write32(rtwdev, addr_desa_l, bd_ring->dma); 1657*6d67aabdSBjoern A. Zeeb rtw89_write32(rtwdev, addr_desa_l + 4, upper_32_bits(bd_ring->dma)); 16588e93258fSBjoern A. Zeeb } 16598e93258fSBjoern A. Zeeb 16608e93258fSBjoern A. Zeeb for (i = 0; i < RTW89_RXCH_NUM; i++) { 16618e93258fSBjoern A. Zeeb rx_ring = &rtwpci->rx_rings[i]; 16628e93258fSBjoern A. Zeeb bd_ring = &rx_ring->bd_ring; 16638e93258fSBjoern A. Zeeb addr_num = bd_ring->addr.num; 1664*6d67aabdSBjoern A. Zeeb addr_idx = bd_ring->addr.idx; 16658e93258fSBjoern A. Zeeb addr_desa_l = bd_ring->addr.desa_l; 1666*6d67aabdSBjoern A. Zeeb if (info->rx_ring_eq_is_full) 1667*6d67aabdSBjoern A. Zeeb bd_ring->wp = bd_ring->len - 1; 1668*6d67aabdSBjoern A. Zeeb else 16698e93258fSBjoern A. Zeeb bd_ring->wp = 0; 16708e93258fSBjoern A. Zeeb bd_ring->rp = 0; 16718e93258fSBjoern A. Zeeb rx_ring->diliver_skb = NULL; 16728e93258fSBjoern A. Zeeb rx_ring->diliver_desc.ready = false; 1673*6d67aabdSBjoern A. Zeeb rx_ring->target_rx_tag = 0; 16748e93258fSBjoern A. Zeeb 16758e93258fSBjoern A. Zeeb rtw89_write16(rtwdev, addr_num, bd_ring->len); 16768e93258fSBjoern A. Zeeb rtw89_write32(rtwdev, addr_desa_l, bd_ring->dma); 1677*6d67aabdSBjoern A. Zeeb rtw89_write32(rtwdev, addr_desa_l + 4, upper_32_bits(bd_ring->dma)); 1678*6d67aabdSBjoern A. Zeeb 1679*6d67aabdSBjoern A. Zeeb if (info->rx_ring_eq_is_full) 1680*6d67aabdSBjoern A. Zeeb rtw89_write16(rtwdev, addr_idx, bd_ring->wp); 16818e93258fSBjoern A. Zeeb } 1682*6d67aabdSBjoern A. Zeeb 1683*6d67aabdSBjoern A. Zeeb rtw89_pci_init_wp_16sel(rtwdev); 16848e93258fSBjoern A. Zeeb } 16858e93258fSBjoern A. Zeeb 16868e93258fSBjoern A. Zeeb static void rtw89_pci_release_tx_ring(struct rtw89_dev *rtwdev, 16878e93258fSBjoern A. Zeeb struct rtw89_pci_tx_ring *tx_ring) 16888e93258fSBjoern A. Zeeb { 16898e93258fSBjoern A. Zeeb rtw89_pci_release_busy_txwd(rtwdev, tx_ring); 16908e93258fSBjoern A. Zeeb rtw89_pci_release_pending_txwd_skb(rtwdev, tx_ring); 16918e93258fSBjoern A. Zeeb } 16928e93258fSBjoern A. Zeeb 1693*6d67aabdSBjoern A. Zeeb void rtw89_pci_ops_reset(struct rtw89_dev *rtwdev) 16948e93258fSBjoern A. Zeeb { 16958e93258fSBjoern A. Zeeb struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; 1696e2340276SBjoern A. Zeeb const struct rtw89_pci_info *info = rtwdev->pci_info; 16978e93258fSBjoern A. Zeeb int txch; 16988e93258fSBjoern A. Zeeb 16998e93258fSBjoern A. Zeeb rtw89_pci_reset_trx_rings(rtwdev); 17008e93258fSBjoern A. Zeeb 17018e93258fSBjoern A. Zeeb spin_lock_bh(&rtwpci->trx_lock); 17028e93258fSBjoern A. Zeeb for (txch = 0; txch < RTW89_TXCH_NUM; txch++) { 1703e2340276SBjoern A. Zeeb if (info->tx_dma_ch_mask & BIT(txch)) 1704e2340276SBjoern A. Zeeb continue; 17058e93258fSBjoern A. Zeeb if (txch == RTW89_TXCH_CH12) { 17068e93258fSBjoern A. Zeeb rtw89_pci_release_fwcmd(rtwdev, rtwpci, 17078e93258fSBjoern A. Zeeb skb_queue_len(&rtwpci->h2c_queue), true); 17088e93258fSBjoern A. Zeeb continue; 17098e93258fSBjoern A. Zeeb } 17108e93258fSBjoern A. Zeeb rtw89_pci_release_tx_ring(rtwdev, &rtwpci->tx_rings[txch]); 17118e93258fSBjoern A. Zeeb } 17128e93258fSBjoern A. Zeeb spin_unlock_bh(&rtwpci->trx_lock); 17138e93258fSBjoern A. Zeeb } 17148e93258fSBjoern A. Zeeb 17158e93258fSBjoern A. Zeeb static void rtw89_pci_enable_intr_lock(struct rtw89_dev *rtwdev) 17168e93258fSBjoern A. Zeeb { 17178e93258fSBjoern A. Zeeb struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; 17188e93258fSBjoern A. Zeeb unsigned long flags; 17198e93258fSBjoern A. Zeeb 17208e93258fSBjoern A. Zeeb spin_lock_irqsave(&rtwpci->irq_lock, flags); 17218e93258fSBjoern A. Zeeb rtwpci->running = true; 17228e93258fSBjoern A. Zeeb rtw89_chip_enable_intr(rtwdev, rtwpci); 17238e93258fSBjoern A. Zeeb spin_unlock_irqrestore(&rtwpci->irq_lock, flags); 17248e93258fSBjoern A. Zeeb } 17258e93258fSBjoern A. Zeeb 17268e93258fSBjoern A. Zeeb static void rtw89_pci_disable_intr_lock(struct rtw89_dev *rtwdev) 17278e93258fSBjoern A. Zeeb { 17288e93258fSBjoern A. Zeeb struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; 17298e93258fSBjoern A. Zeeb unsigned long flags; 17308e93258fSBjoern A. Zeeb 17318e93258fSBjoern A. Zeeb spin_lock_irqsave(&rtwpci->irq_lock, flags); 17328e93258fSBjoern A. Zeeb rtwpci->running = false; 17338e93258fSBjoern A. Zeeb rtw89_chip_disable_intr(rtwdev, rtwpci); 17348e93258fSBjoern A. Zeeb spin_unlock_irqrestore(&rtwpci->irq_lock, flags); 17358e93258fSBjoern A. Zeeb } 17368e93258fSBjoern A. Zeeb 17378e93258fSBjoern A. Zeeb static int rtw89_pci_ops_start(struct rtw89_dev *rtwdev) 17388e93258fSBjoern A. Zeeb { 17398e93258fSBjoern A. Zeeb rtw89_core_napi_start(rtwdev); 17408e93258fSBjoern A. Zeeb rtw89_pci_enable_intr_lock(rtwdev); 17418e93258fSBjoern A. Zeeb 17428e93258fSBjoern A. Zeeb return 0; 17438e93258fSBjoern A. Zeeb } 17448e93258fSBjoern A. Zeeb 17458e93258fSBjoern A. Zeeb static void rtw89_pci_ops_stop(struct rtw89_dev *rtwdev) 17468e93258fSBjoern A. Zeeb { 17478e93258fSBjoern A. Zeeb struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; 17488e93258fSBjoern A. Zeeb struct pci_dev *pdev = rtwpci->pdev; 17498e93258fSBjoern A. Zeeb 17508e93258fSBjoern A. Zeeb rtw89_pci_disable_intr_lock(rtwdev); 17518e93258fSBjoern A. Zeeb synchronize_irq(pdev->irq); 17528e93258fSBjoern A. Zeeb rtw89_core_napi_stop(rtwdev); 17538e93258fSBjoern A. Zeeb } 17548e93258fSBjoern A. Zeeb 17558e93258fSBjoern A. Zeeb static void rtw89_pci_ops_pause(struct rtw89_dev *rtwdev, bool pause) 17568e93258fSBjoern A. Zeeb { 17578e93258fSBjoern A. Zeeb struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; 17588e93258fSBjoern A. Zeeb struct pci_dev *pdev = rtwpci->pdev; 17598e93258fSBjoern A. Zeeb 17608e93258fSBjoern A. Zeeb if (pause) { 17618e93258fSBjoern A. Zeeb rtw89_pci_disable_intr_lock(rtwdev); 17628e93258fSBjoern A. Zeeb synchronize_irq(pdev->irq); 17638e93258fSBjoern A. Zeeb if (test_bit(RTW89_FLAG_NAPI_RUNNING, rtwdev->flags)) 17648e93258fSBjoern A. Zeeb napi_synchronize(&rtwdev->napi); 17658e93258fSBjoern A. Zeeb } else { 17668e93258fSBjoern A. Zeeb rtw89_pci_enable_intr_lock(rtwdev); 17678e93258fSBjoern A. Zeeb rtw89_pci_tx_kick_off_pending(rtwdev); 17688e93258fSBjoern A. Zeeb } 17698e93258fSBjoern A. Zeeb } 17708e93258fSBjoern A. Zeeb 17718e93258fSBjoern A. Zeeb static 17728e93258fSBjoern A. Zeeb void rtw89_pci_switch_bd_idx_addr(struct rtw89_dev *rtwdev, bool low_power) 17738e93258fSBjoern A. Zeeb { 17748e93258fSBjoern A. Zeeb struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; 17758e93258fSBjoern A. Zeeb const struct rtw89_pci_info *info = rtwdev->pci_info; 17768e93258fSBjoern A. Zeeb const struct rtw89_pci_bd_idx_addr *bd_idx_addr = info->bd_idx_addr_low_power; 17778e93258fSBjoern A. Zeeb const struct rtw89_pci_ch_dma_addr_set *dma_addr_set = info->dma_addr_set; 17788e93258fSBjoern A. Zeeb struct rtw89_pci_tx_ring *tx_ring; 17798e93258fSBjoern A. Zeeb struct rtw89_pci_rx_ring *rx_ring; 17808e93258fSBjoern A. Zeeb int i; 17818e93258fSBjoern A. Zeeb 17828e93258fSBjoern A. Zeeb if (WARN(!bd_idx_addr, "only HCI with low power mode needs this\n")) 17838e93258fSBjoern A. Zeeb return; 17848e93258fSBjoern A. Zeeb 17858e93258fSBjoern A. Zeeb for (i = 0; i < RTW89_TXCH_NUM; i++) { 17868e93258fSBjoern A. Zeeb tx_ring = &rtwpci->tx_rings[i]; 17878e93258fSBjoern A. Zeeb tx_ring->bd_ring.addr.idx = low_power ? 17888e93258fSBjoern A. Zeeb bd_idx_addr->tx_bd_addrs[i] : 17898e93258fSBjoern A. Zeeb dma_addr_set->tx[i].idx; 17908e93258fSBjoern A. Zeeb } 17918e93258fSBjoern A. Zeeb 17928e93258fSBjoern A. Zeeb for (i = 0; i < RTW89_RXCH_NUM; i++) { 17938e93258fSBjoern A. Zeeb rx_ring = &rtwpci->rx_rings[i]; 17948e93258fSBjoern A. Zeeb rx_ring->bd_ring.addr.idx = low_power ? 17958e93258fSBjoern A. Zeeb bd_idx_addr->rx_bd_addrs[i] : 17968e93258fSBjoern A. Zeeb dma_addr_set->rx[i].idx; 17978e93258fSBjoern A. Zeeb } 17988e93258fSBjoern A. Zeeb } 17998e93258fSBjoern A. Zeeb 18008e93258fSBjoern A. Zeeb static void rtw89_pci_ops_switch_mode(struct rtw89_dev *rtwdev, bool low_power) 18018e93258fSBjoern A. Zeeb { 18028e93258fSBjoern A. Zeeb enum rtw89_pci_intr_mask_cfg cfg; 18038e93258fSBjoern A. Zeeb 18048e93258fSBjoern A. Zeeb WARN(!rtwdev->hci.paused, "HCI isn't paused\n"); 18058e93258fSBjoern A. Zeeb 18068e93258fSBjoern A. Zeeb cfg = low_power ? RTW89_PCI_INTR_MASK_LOW_POWER : RTW89_PCI_INTR_MASK_NORMAL; 18078e93258fSBjoern A. Zeeb rtw89_chip_config_intr_mask(rtwdev, cfg); 18088e93258fSBjoern A. Zeeb rtw89_pci_switch_bd_idx_addr(rtwdev, low_power); 18098e93258fSBjoern A. Zeeb } 18108e93258fSBjoern A. Zeeb 18118e93258fSBjoern A. Zeeb static void rtw89_pci_ops_write32(struct rtw89_dev *rtwdev, u32 addr, u32 data); 18128e93258fSBjoern A. Zeeb 18138e93258fSBjoern A. Zeeb static u32 rtw89_pci_ops_read32_cmac(struct rtw89_dev *rtwdev, u32 addr) 18148e93258fSBjoern A. Zeeb { 18158e93258fSBjoern A. Zeeb struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; 18168e93258fSBjoern A. Zeeb #if defined(__linux__) 18178e93258fSBjoern A. Zeeb u32 val = readl(rtwpci->mmap + addr); 18188e93258fSBjoern A. Zeeb #elif defined(__FreeBSD__) 18198e93258fSBjoern A. Zeeb u32 val; 18208e93258fSBjoern A. Zeeb 18218e93258fSBjoern A. Zeeb val = bus_read_4((struct resource *)rtwpci->mmap, addr); 18228e93258fSBjoern A. Zeeb rtw89_debug(rtwdev, RTW89_DBG_IO_RW, "R32 (%#010x) -> %#010x\n", addr, val); 18238e93258fSBjoern A. Zeeb #endif 18248e93258fSBjoern A. Zeeb int count; 18258e93258fSBjoern A. Zeeb 18268e93258fSBjoern A. Zeeb for (count = 0; ; count++) { 18278e93258fSBjoern A. Zeeb if (val != RTW89_R32_DEAD) 18288e93258fSBjoern A. Zeeb return val; 18298e93258fSBjoern A. Zeeb if (count >= MAC_REG_POOL_COUNT) { 18308e93258fSBjoern A. Zeeb rtw89_warn(rtwdev, "addr %#x = %#x\n", addr, val); 18318e93258fSBjoern A. Zeeb return RTW89_R32_DEAD; 18328e93258fSBjoern A. Zeeb } 18338e93258fSBjoern A. Zeeb rtw89_pci_ops_write32(rtwdev, R_AX_CK_EN, B_AX_CMAC_ALLCKEN); 18348e93258fSBjoern A. Zeeb #if defined(__linux__) 18358e93258fSBjoern A. Zeeb val = readl(rtwpci->mmap + addr); 18368e93258fSBjoern A. Zeeb #elif defined(__FreeBSD__) 18378e93258fSBjoern A. Zeeb val = bus_read_4((struct resource *)rtwpci->mmap, addr); 18388e93258fSBjoern A. Zeeb rtw89_debug(rtwdev, RTW89_DBG_IO_RW, "R32 (%#010x) -> %#010x\n", addr, val); 18398e93258fSBjoern A. Zeeb #endif 18408e93258fSBjoern A. Zeeb } 18418e93258fSBjoern A. Zeeb 18428e93258fSBjoern A. Zeeb return val; 18438e93258fSBjoern A. Zeeb } 18448e93258fSBjoern A. Zeeb 18458e93258fSBjoern A. Zeeb static u8 rtw89_pci_ops_read8(struct rtw89_dev *rtwdev, u32 addr) 18468e93258fSBjoern A. Zeeb { 18478e93258fSBjoern A. Zeeb struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; 18488e93258fSBjoern A. Zeeb u32 addr32, val32, shift; 18498e93258fSBjoern A. Zeeb 18508e93258fSBjoern A. Zeeb if (!ACCESS_CMAC(addr)) 18518e93258fSBjoern A. Zeeb #if defined(__linux__) 18528e93258fSBjoern A. Zeeb return readb(rtwpci->mmap + addr); 18538e93258fSBjoern A. Zeeb #elif defined(__FreeBSD__) 18548e93258fSBjoern A. Zeeb { 18558e93258fSBjoern A. Zeeb u8 val; 18568e93258fSBjoern A. Zeeb 18578e93258fSBjoern A. Zeeb val = bus_read_1((struct resource *)rtwpci->mmap, addr); 18588e93258fSBjoern A. Zeeb rtw89_debug(rtwdev, RTW89_DBG_IO_RW, "R08 (%#010x) -> %#04x\n", addr, val); 18598e93258fSBjoern A. Zeeb return (val); 18608e93258fSBjoern A. Zeeb } 18618e93258fSBjoern A. Zeeb #endif 18628e93258fSBjoern A. Zeeb 18638e93258fSBjoern A. Zeeb addr32 = addr & ~0x3; 18648e93258fSBjoern A. Zeeb shift = (addr & 0x3) * 8; 18658e93258fSBjoern A. Zeeb val32 = rtw89_pci_ops_read32_cmac(rtwdev, addr32); 18668e93258fSBjoern A. Zeeb return val32 >> shift; 18678e93258fSBjoern A. Zeeb } 18688e93258fSBjoern A. Zeeb 18698e93258fSBjoern A. Zeeb static u16 rtw89_pci_ops_read16(struct rtw89_dev *rtwdev, u32 addr) 18708e93258fSBjoern A. Zeeb { 18718e93258fSBjoern A. Zeeb struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; 18728e93258fSBjoern A. Zeeb u32 addr32, val32, shift; 18738e93258fSBjoern A. Zeeb 18748e93258fSBjoern A. Zeeb if (!ACCESS_CMAC(addr)) 18758e93258fSBjoern A. Zeeb #if defined(__linux__) 18768e93258fSBjoern A. Zeeb return readw(rtwpci->mmap + addr); 18778e93258fSBjoern A. Zeeb #elif defined(__FreeBSD__) 18788e93258fSBjoern A. Zeeb { 18798e93258fSBjoern A. Zeeb u16 val; 18808e93258fSBjoern A. Zeeb 18818e93258fSBjoern A. Zeeb val = bus_read_2((struct resource *)rtwpci->mmap, addr); 18828e93258fSBjoern A. Zeeb rtw89_debug(rtwdev, RTW89_DBG_IO_RW, "R16 (%#010x) -> %#06x\n", addr, val); 18838e93258fSBjoern A. Zeeb return (val); 18848e93258fSBjoern A. Zeeb } 18858e93258fSBjoern A. Zeeb #endif 18868e93258fSBjoern A. Zeeb 18878e93258fSBjoern A. Zeeb addr32 = addr & ~0x3; 18888e93258fSBjoern A. Zeeb shift = (addr & 0x3) * 8; 18898e93258fSBjoern A. Zeeb val32 = rtw89_pci_ops_read32_cmac(rtwdev, addr32); 18908e93258fSBjoern A. Zeeb return val32 >> shift; 18918e93258fSBjoern A. Zeeb } 18928e93258fSBjoern A. Zeeb 18938e93258fSBjoern A. Zeeb static u32 rtw89_pci_ops_read32(struct rtw89_dev *rtwdev, u32 addr) 18948e93258fSBjoern A. Zeeb { 18958e93258fSBjoern A. Zeeb struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; 18968e93258fSBjoern A. Zeeb 18978e93258fSBjoern A. Zeeb if (!ACCESS_CMAC(addr)) 18988e93258fSBjoern A. Zeeb #if defined(__linux__) 18998e93258fSBjoern A. Zeeb return readl(rtwpci->mmap + addr); 19008e93258fSBjoern A. Zeeb #elif defined(__FreeBSD__) 19018e93258fSBjoern A. Zeeb { 19028e93258fSBjoern A. Zeeb u32 val; 19038e93258fSBjoern A. Zeeb 19048e93258fSBjoern A. Zeeb val = bus_read_4((struct resource *)rtwpci->mmap, addr); 19058e93258fSBjoern A. Zeeb rtw89_debug(rtwdev, RTW89_DBG_IO_RW, "R32 (%#010x) -> %#010x\n", addr, val); 19068e93258fSBjoern A. Zeeb return (val); 19078e93258fSBjoern A. Zeeb } 19088e93258fSBjoern A. Zeeb #endif 19098e93258fSBjoern A. Zeeb 19108e93258fSBjoern A. Zeeb return rtw89_pci_ops_read32_cmac(rtwdev, addr); 19118e93258fSBjoern A. Zeeb } 19128e93258fSBjoern A. Zeeb 19138e93258fSBjoern A. Zeeb static void rtw89_pci_ops_write8(struct rtw89_dev *rtwdev, u32 addr, u8 data) 19148e93258fSBjoern A. Zeeb { 19158e93258fSBjoern A. Zeeb struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; 19168e93258fSBjoern A. Zeeb 19178e93258fSBjoern A. Zeeb #if defined(__linux__) 19188e93258fSBjoern A. Zeeb writeb(data, rtwpci->mmap + addr); 19198e93258fSBjoern A. Zeeb #elif defined(__FreeBSD__) 19208e93258fSBjoern A. Zeeb rtw89_debug(rtwdev, RTW89_DBG_IO_RW, "W08 (%#010x) <- %#04x\n", addr, data); 19218e93258fSBjoern A. Zeeb return (bus_write_1((struct resource *)rtwpci->mmap, addr, data)); 19228e93258fSBjoern A. Zeeb #endif 19238e93258fSBjoern A. Zeeb } 19248e93258fSBjoern A. Zeeb 19258e93258fSBjoern A. Zeeb static void rtw89_pci_ops_write16(struct rtw89_dev *rtwdev, u32 addr, u16 data) 19268e93258fSBjoern A. Zeeb { 19278e93258fSBjoern A. Zeeb struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; 19288e93258fSBjoern A. Zeeb 19298e93258fSBjoern A. Zeeb #if defined(__linux__) 19308e93258fSBjoern A. Zeeb writew(data, rtwpci->mmap + addr); 19318e93258fSBjoern A. Zeeb #elif defined(__FreeBSD__) 19328e93258fSBjoern A. Zeeb rtw89_debug(rtwdev, RTW89_DBG_IO_RW, "W16 (%#010x) <- %#06x\n", addr, data); 19338e93258fSBjoern A. Zeeb return (bus_write_2((struct resource *)rtwpci->mmap, addr, data)); 19348e93258fSBjoern A. Zeeb #endif 19358e93258fSBjoern A. Zeeb } 19368e93258fSBjoern A. Zeeb 19378e93258fSBjoern A. Zeeb static void rtw89_pci_ops_write32(struct rtw89_dev *rtwdev, u32 addr, u32 data) 19388e93258fSBjoern A. Zeeb { 19398e93258fSBjoern A. Zeeb struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; 19408e93258fSBjoern A. Zeeb 19418e93258fSBjoern A. Zeeb #if defined(__linux__) 19428e93258fSBjoern A. Zeeb writel(data, rtwpci->mmap + addr); 19438e93258fSBjoern A. Zeeb #elif defined(__FreeBSD__) 19448e93258fSBjoern A. Zeeb rtw89_debug(rtwdev, RTW89_DBG_IO_RW, "W32 (%#010x) <- %#010x\n", addr, data); 19458e93258fSBjoern A. Zeeb return (bus_write_4((struct resource *)rtwpci->mmap, addr, data)); 19468e93258fSBjoern A. Zeeb #endif 19478e93258fSBjoern A. Zeeb } 19488e93258fSBjoern A. Zeeb 1949e2340276SBjoern A. Zeeb static void rtw89_pci_ctrl_dma_trx(struct rtw89_dev *rtwdev, bool enable) 1950e2340276SBjoern A. Zeeb { 1951e2340276SBjoern A. Zeeb const struct rtw89_pci_info *info = rtwdev->pci_info; 1952e2340276SBjoern A. Zeeb 1953e2340276SBjoern A. Zeeb if (enable) 1954e2340276SBjoern A. Zeeb rtw89_write32_set(rtwdev, info->init_cfg_reg, 1955e2340276SBjoern A. Zeeb info->rxhci_en_bit | info->txhci_en_bit); 1956e2340276SBjoern A. Zeeb else 1957e2340276SBjoern A. Zeeb rtw89_write32_clr(rtwdev, info->init_cfg_reg, 1958e2340276SBjoern A. Zeeb info->rxhci_en_bit | info->txhci_en_bit); 1959e2340276SBjoern A. Zeeb } 1960e2340276SBjoern A. Zeeb 1961e2340276SBjoern A. Zeeb static void rtw89_pci_ctrl_dma_io(struct rtw89_dev *rtwdev, bool enable) 19628e93258fSBjoern A. Zeeb { 1963*6d67aabdSBjoern A. Zeeb const struct rtw89_pci_info *info = rtwdev->pci_info; 1964*6d67aabdSBjoern A. Zeeb const struct rtw89_reg_def *reg = &info->dma_io_stop; 1965e2340276SBjoern A. Zeeb 1966e2340276SBjoern A. Zeeb if (enable) 1967*6d67aabdSBjoern A. Zeeb rtw89_write32_clr(rtwdev, reg->addr, reg->mask); 1968e2340276SBjoern A. Zeeb else 1969*6d67aabdSBjoern A. Zeeb rtw89_write32_set(rtwdev, reg->addr, reg->mask); 1970e2340276SBjoern A. Zeeb } 1971e2340276SBjoern A. Zeeb 1972*6d67aabdSBjoern A. Zeeb void rtw89_pci_ctrl_dma_all(struct rtw89_dev *rtwdev, bool enable) 1973e2340276SBjoern A. Zeeb { 1974e2340276SBjoern A. Zeeb rtw89_pci_ctrl_dma_io(rtwdev, enable); 1975e2340276SBjoern A. Zeeb rtw89_pci_ctrl_dma_trx(rtwdev, enable); 19768e93258fSBjoern A. Zeeb } 19778e93258fSBjoern A. Zeeb 19788e93258fSBjoern A. Zeeb static int rtw89_pci_check_mdio(struct rtw89_dev *rtwdev, u8 addr, u8 speed, u16 rw_bit) 19798e93258fSBjoern A. Zeeb { 19808e93258fSBjoern A. Zeeb u16 val; 19818e93258fSBjoern A. Zeeb 19828e93258fSBjoern A. Zeeb rtw89_write8(rtwdev, R_AX_MDIO_CFG, addr & 0x1F); 19838e93258fSBjoern A. Zeeb 19848e93258fSBjoern A. Zeeb val = rtw89_read16(rtwdev, R_AX_MDIO_CFG); 19858e93258fSBjoern A. Zeeb switch (speed) { 19868e93258fSBjoern A. Zeeb case PCIE_PHY_GEN1: 19878e93258fSBjoern A. Zeeb if (addr < 0x20) 19888e93258fSBjoern A. Zeeb val = u16_replace_bits(val, MDIO_PG0_G1, B_AX_MDIO_PHY_ADDR_MASK); 19898e93258fSBjoern A. Zeeb else 19908e93258fSBjoern A. Zeeb val = u16_replace_bits(val, MDIO_PG1_G1, B_AX_MDIO_PHY_ADDR_MASK); 19918e93258fSBjoern A. Zeeb break; 19928e93258fSBjoern A. Zeeb case PCIE_PHY_GEN2: 19938e93258fSBjoern A. Zeeb if (addr < 0x20) 19948e93258fSBjoern A. Zeeb val = u16_replace_bits(val, MDIO_PG0_G2, B_AX_MDIO_PHY_ADDR_MASK); 19958e93258fSBjoern A. Zeeb else 19968e93258fSBjoern A. Zeeb val = u16_replace_bits(val, MDIO_PG1_G2, B_AX_MDIO_PHY_ADDR_MASK); 19978e93258fSBjoern A. Zeeb break; 19988e93258fSBjoern A. Zeeb default: 19998e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "[ERR]Error Speed %d!\n", speed); 20008e93258fSBjoern A. Zeeb return -EINVAL; 20018e93258fSBjoern A. Zeeb } 20028e93258fSBjoern A. Zeeb rtw89_write16(rtwdev, R_AX_MDIO_CFG, val); 20038e93258fSBjoern A. Zeeb rtw89_write16_set(rtwdev, R_AX_MDIO_CFG, rw_bit); 20048e93258fSBjoern A. Zeeb 20058e93258fSBjoern A. Zeeb return read_poll_timeout(rtw89_read16, val, !(val & rw_bit), 10, 2000, 20068e93258fSBjoern A. Zeeb false, rtwdev, R_AX_MDIO_CFG); 20078e93258fSBjoern A. Zeeb } 20088e93258fSBjoern A. Zeeb 20098e93258fSBjoern A. Zeeb static int 20108e93258fSBjoern A. Zeeb rtw89_read16_mdio(struct rtw89_dev *rtwdev, u8 addr, u8 speed, u16 *val) 20118e93258fSBjoern A. Zeeb { 20128e93258fSBjoern A. Zeeb int ret; 20138e93258fSBjoern A. Zeeb 20148e93258fSBjoern A. Zeeb ret = rtw89_pci_check_mdio(rtwdev, addr, speed, B_AX_MDIO_RFLAG); 20158e93258fSBjoern A. Zeeb if (ret) { 20168e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "[ERR]MDIO R16 0x%X fail ret=%d!\n", addr, ret); 20178e93258fSBjoern A. Zeeb return ret; 20188e93258fSBjoern A. Zeeb } 20198e93258fSBjoern A. Zeeb *val = rtw89_read16(rtwdev, R_AX_MDIO_RDATA); 20208e93258fSBjoern A. Zeeb 20218e93258fSBjoern A. Zeeb return 0; 20228e93258fSBjoern A. Zeeb } 20238e93258fSBjoern A. Zeeb 20248e93258fSBjoern A. Zeeb static int 20258e93258fSBjoern A. Zeeb rtw89_write16_mdio(struct rtw89_dev *rtwdev, u8 addr, u16 data, u8 speed) 20268e93258fSBjoern A. Zeeb { 20278e93258fSBjoern A. Zeeb int ret; 20288e93258fSBjoern A. Zeeb 20298e93258fSBjoern A. Zeeb rtw89_write16(rtwdev, R_AX_MDIO_WDATA, data); 20308e93258fSBjoern A. Zeeb ret = rtw89_pci_check_mdio(rtwdev, addr, speed, B_AX_MDIO_WFLAG); 20318e93258fSBjoern A. Zeeb if (ret) { 20328e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "[ERR]MDIO W16 0x%X = %x fail ret=%d!\n", addr, data, ret); 20338e93258fSBjoern A. Zeeb return ret; 20348e93258fSBjoern A. Zeeb } 20358e93258fSBjoern A. Zeeb 20368e93258fSBjoern A. Zeeb return 0; 20378e93258fSBjoern A. Zeeb } 20388e93258fSBjoern A. Zeeb 20398e93258fSBjoern A. Zeeb static int 20408e93258fSBjoern A. Zeeb rtw89_write16_mdio_mask(struct rtw89_dev *rtwdev, u8 addr, u16 mask, u16 data, u8 speed) 20418e93258fSBjoern A. Zeeb { 20428e93258fSBjoern A. Zeeb u32 shift; 20438e93258fSBjoern A. Zeeb int ret; 20448e93258fSBjoern A. Zeeb u16 val; 20458e93258fSBjoern A. Zeeb 20468e93258fSBjoern A. Zeeb ret = rtw89_read16_mdio(rtwdev, addr, speed, &val); 20478e93258fSBjoern A. Zeeb if (ret) 20488e93258fSBjoern A. Zeeb return ret; 20498e93258fSBjoern A. Zeeb 20508e93258fSBjoern A. Zeeb shift = __ffs(mask); 20518e93258fSBjoern A. Zeeb val &= ~mask; 20528e93258fSBjoern A. Zeeb val |= ((data << shift) & mask); 20538e93258fSBjoern A. Zeeb 20548e93258fSBjoern A. Zeeb ret = rtw89_write16_mdio(rtwdev, addr, val, speed); 20558e93258fSBjoern A. Zeeb if (ret) 20568e93258fSBjoern A. Zeeb return ret; 20578e93258fSBjoern A. Zeeb 20588e93258fSBjoern A. Zeeb return 0; 20598e93258fSBjoern A. Zeeb } 20608e93258fSBjoern A. Zeeb 20618e93258fSBjoern A. Zeeb static int rtw89_write16_mdio_set(struct rtw89_dev *rtwdev, u8 addr, u16 mask, u8 speed) 20628e93258fSBjoern A. Zeeb { 20638e93258fSBjoern A. Zeeb int ret; 20648e93258fSBjoern A. Zeeb u16 val; 20658e93258fSBjoern A. Zeeb 20668e93258fSBjoern A. Zeeb ret = rtw89_read16_mdio(rtwdev, addr, speed, &val); 20678e93258fSBjoern A. Zeeb if (ret) 20688e93258fSBjoern A. Zeeb return ret; 20698e93258fSBjoern A. Zeeb ret = rtw89_write16_mdio(rtwdev, addr, val | mask, speed); 20708e93258fSBjoern A. Zeeb if (ret) 20718e93258fSBjoern A. Zeeb return ret; 20728e93258fSBjoern A. Zeeb 20738e93258fSBjoern A. Zeeb return 0; 20748e93258fSBjoern A. Zeeb } 20758e93258fSBjoern A. Zeeb 20768e93258fSBjoern A. Zeeb static int rtw89_write16_mdio_clr(struct rtw89_dev *rtwdev, u8 addr, u16 mask, u8 speed) 20778e93258fSBjoern A. Zeeb { 20788e93258fSBjoern A. Zeeb int ret; 20798e93258fSBjoern A. Zeeb u16 val; 20808e93258fSBjoern A. Zeeb 20818e93258fSBjoern A. Zeeb ret = rtw89_read16_mdio(rtwdev, addr, speed, &val); 20828e93258fSBjoern A. Zeeb if (ret) 20838e93258fSBjoern A. Zeeb return ret; 20848e93258fSBjoern A. Zeeb ret = rtw89_write16_mdio(rtwdev, addr, val & ~mask, speed); 20858e93258fSBjoern A. Zeeb if (ret) 20868e93258fSBjoern A. Zeeb return ret; 20878e93258fSBjoern A. Zeeb 20888e93258fSBjoern A. Zeeb return 0; 20898e93258fSBjoern A. Zeeb } 20908e93258fSBjoern A. Zeeb 2091*6d67aabdSBjoern A. Zeeb static int rtw89_dbi_write8(struct rtw89_dev *rtwdev, u16 addr, u8 data) 2092*6d67aabdSBjoern A. Zeeb { 2093*6d67aabdSBjoern A. Zeeb u16 addr_2lsb = addr & B_AX_DBI_2LSB; 2094*6d67aabdSBjoern A. Zeeb u16 write_addr; 2095*6d67aabdSBjoern A. Zeeb u8 flag; 2096*6d67aabdSBjoern A. Zeeb int ret; 2097*6d67aabdSBjoern A. Zeeb 2098*6d67aabdSBjoern A. Zeeb write_addr = addr & B_AX_DBI_ADDR_MSK; 2099*6d67aabdSBjoern A. Zeeb write_addr |= u16_encode_bits(BIT(addr_2lsb), B_AX_DBI_WREN_MSK); 2100*6d67aabdSBjoern A. Zeeb rtw89_write8(rtwdev, R_AX_DBI_WDATA + addr_2lsb, data); 2101*6d67aabdSBjoern A. Zeeb rtw89_write16(rtwdev, R_AX_DBI_FLAG, write_addr); 2102*6d67aabdSBjoern A. Zeeb rtw89_write8(rtwdev, R_AX_DBI_FLAG + 2, B_AX_DBI_WFLAG >> 16); 2103*6d67aabdSBjoern A. Zeeb 2104*6d67aabdSBjoern A. Zeeb ret = read_poll_timeout_atomic(rtw89_read8, flag, !flag, 10, 2105*6d67aabdSBjoern A. Zeeb 10 * RTW89_PCI_WR_RETRY_CNT, false, 2106*6d67aabdSBjoern A. Zeeb rtwdev, R_AX_DBI_FLAG + 2); 2107*6d67aabdSBjoern A. Zeeb if (ret) 2108*6d67aabdSBjoern A. Zeeb rtw89_err(rtwdev, "failed to write DBI register, addr=0x%X\n", 2109*6d67aabdSBjoern A. Zeeb addr); 2110*6d67aabdSBjoern A. Zeeb 2111*6d67aabdSBjoern A. Zeeb return ret; 2112*6d67aabdSBjoern A. Zeeb } 2113*6d67aabdSBjoern A. Zeeb 2114*6d67aabdSBjoern A. Zeeb static int rtw89_dbi_read8(struct rtw89_dev *rtwdev, u16 addr, u8 *value) 2115*6d67aabdSBjoern A. Zeeb { 2116*6d67aabdSBjoern A. Zeeb u16 read_addr = addr & B_AX_DBI_ADDR_MSK; 2117*6d67aabdSBjoern A. Zeeb u8 flag; 2118*6d67aabdSBjoern A. Zeeb int ret; 2119*6d67aabdSBjoern A. Zeeb 2120*6d67aabdSBjoern A. Zeeb rtw89_write16(rtwdev, R_AX_DBI_FLAG, read_addr); 2121*6d67aabdSBjoern A. Zeeb rtw89_write8(rtwdev, R_AX_DBI_FLAG + 2, B_AX_DBI_RFLAG >> 16); 2122*6d67aabdSBjoern A. Zeeb 2123*6d67aabdSBjoern A. Zeeb ret = read_poll_timeout_atomic(rtw89_read8, flag, !flag, 10, 2124*6d67aabdSBjoern A. Zeeb 10 * RTW89_PCI_WR_RETRY_CNT, false, 2125*6d67aabdSBjoern A. Zeeb rtwdev, R_AX_DBI_FLAG + 2); 2126*6d67aabdSBjoern A. Zeeb if (ret) { 2127*6d67aabdSBjoern A. Zeeb rtw89_err(rtwdev, "failed to read DBI register, addr=0x%X\n", 2128*6d67aabdSBjoern A. Zeeb addr); 2129*6d67aabdSBjoern A. Zeeb return ret; 2130*6d67aabdSBjoern A. Zeeb } 2131*6d67aabdSBjoern A. Zeeb 2132*6d67aabdSBjoern A. Zeeb read_addr = R_AX_DBI_RDATA + (addr & 3); 2133*6d67aabdSBjoern A. Zeeb *value = rtw89_read8(rtwdev, read_addr); 2134*6d67aabdSBjoern A. Zeeb 2135*6d67aabdSBjoern A. Zeeb return 0; 2136*6d67aabdSBjoern A. Zeeb } 2137*6d67aabdSBjoern A. Zeeb 21388e93258fSBjoern A. Zeeb static int rtw89_pci_write_config_byte(struct rtw89_dev *rtwdev, u16 addr, 21398e93258fSBjoern A. Zeeb u8 data) 21408e93258fSBjoern A. Zeeb { 21418e93258fSBjoern A. Zeeb struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; 2142*6d67aabdSBjoern A. Zeeb enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id; 21438e93258fSBjoern A. Zeeb struct pci_dev *pdev = rtwpci->pdev; 2144*6d67aabdSBjoern A. Zeeb int ret; 21458e93258fSBjoern A. Zeeb 2146*6d67aabdSBjoern A. Zeeb ret = pci_write_config_byte(pdev, addr, data); 2147*6d67aabdSBjoern A. Zeeb if (!ret) 2148*6d67aabdSBjoern A. Zeeb return 0; 2149*6d67aabdSBjoern A. Zeeb 2150*6d67aabdSBjoern A. Zeeb if (chip_id == RTL8852A || rtw89_is_rtl885xb(rtwdev)) 2151*6d67aabdSBjoern A. Zeeb ret = rtw89_dbi_write8(rtwdev, addr, data); 2152*6d67aabdSBjoern A. Zeeb 2153*6d67aabdSBjoern A. Zeeb return ret; 21548e93258fSBjoern A. Zeeb } 21558e93258fSBjoern A. Zeeb 21568e93258fSBjoern A. Zeeb static int rtw89_pci_read_config_byte(struct rtw89_dev *rtwdev, u16 addr, 21578e93258fSBjoern A. Zeeb u8 *value) 21588e93258fSBjoern A. Zeeb { 21598e93258fSBjoern A. Zeeb struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; 2160*6d67aabdSBjoern A. Zeeb enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id; 21618e93258fSBjoern A. Zeeb struct pci_dev *pdev = rtwpci->pdev; 2162*6d67aabdSBjoern A. Zeeb int ret; 21638e93258fSBjoern A. Zeeb 2164*6d67aabdSBjoern A. Zeeb ret = pci_read_config_byte(pdev, addr, value); 2165*6d67aabdSBjoern A. Zeeb if (!ret) 2166*6d67aabdSBjoern A. Zeeb return 0; 2167*6d67aabdSBjoern A. Zeeb 2168*6d67aabdSBjoern A. Zeeb if (chip_id == RTL8852A || rtw89_is_rtl885xb(rtwdev)) 2169*6d67aabdSBjoern A. Zeeb ret = rtw89_dbi_read8(rtwdev, addr, value); 2170*6d67aabdSBjoern A. Zeeb 2171*6d67aabdSBjoern A. Zeeb return ret; 21728e93258fSBjoern A. Zeeb } 21738e93258fSBjoern A. Zeeb 21748e93258fSBjoern A. Zeeb static int rtw89_pci_config_byte_set(struct rtw89_dev *rtwdev, u16 addr, 21758e93258fSBjoern A. Zeeb u8 bit) 21768e93258fSBjoern A. Zeeb { 21778e93258fSBjoern A. Zeeb u8 value; 21788e93258fSBjoern A. Zeeb int ret; 21798e93258fSBjoern A. Zeeb 21808e93258fSBjoern A. Zeeb ret = rtw89_pci_read_config_byte(rtwdev, addr, &value); 21818e93258fSBjoern A. Zeeb if (ret) 21828e93258fSBjoern A. Zeeb return ret; 21838e93258fSBjoern A. Zeeb 21848e93258fSBjoern A. Zeeb value |= bit; 21858e93258fSBjoern A. Zeeb ret = rtw89_pci_write_config_byte(rtwdev, addr, value); 21868e93258fSBjoern A. Zeeb 21878e93258fSBjoern A. Zeeb return ret; 21888e93258fSBjoern A. Zeeb } 21898e93258fSBjoern A. Zeeb 21908e93258fSBjoern A. Zeeb static int rtw89_pci_config_byte_clr(struct rtw89_dev *rtwdev, u16 addr, 21918e93258fSBjoern A. Zeeb u8 bit) 21928e93258fSBjoern A. Zeeb { 21938e93258fSBjoern A. Zeeb u8 value; 21948e93258fSBjoern A. Zeeb int ret; 21958e93258fSBjoern A. Zeeb 21968e93258fSBjoern A. Zeeb ret = rtw89_pci_read_config_byte(rtwdev, addr, &value); 21978e93258fSBjoern A. Zeeb if (ret) 21988e93258fSBjoern A. Zeeb return ret; 21998e93258fSBjoern A. Zeeb 22008e93258fSBjoern A. Zeeb value &= ~bit; 22018e93258fSBjoern A. Zeeb ret = rtw89_pci_write_config_byte(rtwdev, addr, value); 22028e93258fSBjoern A. Zeeb 22038e93258fSBjoern A. Zeeb return ret; 22048e93258fSBjoern A. Zeeb } 22058e93258fSBjoern A. Zeeb 22068e93258fSBjoern A. Zeeb static int 22078e93258fSBjoern A. Zeeb __get_target(struct rtw89_dev *rtwdev, u16 *target, enum rtw89_pcie_phy phy_rate) 22088e93258fSBjoern A. Zeeb { 22098e93258fSBjoern A. Zeeb u16 val, tar; 22108e93258fSBjoern A. Zeeb int ret; 22118e93258fSBjoern A. Zeeb 22128e93258fSBjoern A. Zeeb /* Enable counter */ 22138e93258fSBjoern A. Zeeb ret = rtw89_read16_mdio(rtwdev, RAC_CTRL_PPR_V1, phy_rate, &val); 22148e93258fSBjoern A. Zeeb if (ret) 22158e93258fSBjoern A. Zeeb return ret; 22168e93258fSBjoern A. Zeeb ret = rtw89_write16_mdio(rtwdev, RAC_CTRL_PPR_V1, val & ~B_AX_CLK_CALIB_EN, 22178e93258fSBjoern A. Zeeb phy_rate); 22188e93258fSBjoern A. Zeeb if (ret) 22198e93258fSBjoern A. Zeeb return ret; 22208e93258fSBjoern A. Zeeb ret = rtw89_write16_mdio(rtwdev, RAC_CTRL_PPR_V1, val | B_AX_CLK_CALIB_EN, 22218e93258fSBjoern A. Zeeb phy_rate); 22228e93258fSBjoern A. Zeeb if (ret) 22238e93258fSBjoern A. Zeeb return ret; 22248e93258fSBjoern A. Zeeb 22258e93258fSBjoern A. Zeeb fsleep(300); 22268e93258fSBjoern A. Zeeb 22278e93258fSBjoern A. Zeeb ret = rtw89_read16_mdio(rtwdev, RAC_CTRL_PPR_V1, phy_rate, &tar); 22288e93258fSBjoern A. Zeeb if (ret) 22298e93258fSBjoern A. Zeeb return ret; 22308e93258fSBjoern A. Zeeb ret = rtw89_write16_mdio(rtwdev, RAC_CTRL_PPR_V1, val & ~B_AX_CLK_CALIB_EN, 22318e93258fSBjoern A. Zeeb phy_rate); 22328e93258fSBjoern A. Zeeb if (ret) 22338e93258fSBjoern A. Zeeb return ret; 22348e93258fSBjoern A. Zeeb 22358e93258fSBjoern A. Zeeb tar = tar & 0x0FFF; 22368e93258fSBjoern A. Zeeb if (tar == 0 || tar == 0x0FFF) { 22378e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "[ERR]Get target failed.\n"); 22388e93258fSBjoern A. Zeeb return -EINVAL; 22398e93258fSBjoern A. Zeeb } 22408e93258fSBjoern A. Zeeb 22418e93258fSBjoern A. Zeeb *target = tar; 22428e93258fSBjoern A. Zeeb 22438e93258fSBjoern A. Zeeb return 0; 22448e93258fSBjoern A. Zeeb } 22458e93258fSBjoern A. Zeeb 2246e2340276SBjoern A. Zeeb static int rtw89_pci_autok_x(struct rtw89_dev *rtwdev) 2247e2340276SBjoern A. Zeeb { 2248e2340276SBjoern A. Zeeb int ret; 2249e2340276SBjoern A. Zeeb 2250*6d67aabdSBjoern A. Zeeb if (!rtw89_is_rtl885xb(rtwdev)) 2251e2340276SBjoern A. Zeeb return 0; 2252e2340276SBjoern A. Zeeb 2253e2340276SBjoern A. Zeeb ret = rtw89_write16_mdio_mask(rtwdev, RAC_REG_FLD_0, BAC_AUTOK_N_MASK, 2254e2340276SBjoern A. Zeeb PCIE_AUTOK_4, PCIE_PHY_GEN1); 2255e2340276SBjoern A. Zeeb return ret; 2256e2340276SBjoern A. Zeeb } 2257e2340276SBjoern A. Zeeb 22588e93258fSBjoern A. Zeeb static int rtw89_pci_auto_refclk_cal(struct rtw89_dev *rtwdev, bool autook_en) 22598e93258fSBjoern A. Zeeb { 22608e93258fSBjoern A. Zeeb enum rtw89_pcie_phy phy_rate; 22618e93258fSBjoern A. Zeeb u16 val16, mgn_set, div_set, tar; 22628e93258fSBjoern A. Zeeb u8 val8, bdr_ori; 22638e93258fSBjoern A. Zeeb bool l1_flag = false; 22648e93258fSBjoern A. Zeeb int ret = 0; 22658e93258fSBjoern A. Zeeb 2266*6d67aabdSBjoern A. Zeeb if (!rtw89_is_rtl885xb(rtwdev)) 22678e93258fSBjoern A. Zeeb return 0; 22688e93258fSBjoern A. Zeeb 22698e93258fSBjoern A. Zeeb ret = rtw89_pci_read_config_byte(rtwdev, RTW89_PCIE_PHY_RATE, &val8); 22708e93258fSBjoern A. Zeeb if (ret) { 22718e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "[ERR]pci config read %X\n", 22728e93258fSBjoern A. Zeeb RTW89_PCIE_PHY_RATE); 22738e93258fSBjoern A. Zeeb return ret; 22748e93258fSBjoern A. Zeeb } 22758e93258fSBjoern A. Zeeb 22768e93258fSBjoern A. Zeeb if (FIELD_GET(RTW89_PCIE_PHY_RATE_MASK, val8) == 0x1) { 22778e93258fSBjoern A. Zeeb phy_rate = PCIE_PHY_GEN1; 22788e93258fSBjoern A. Zeeb } else if (FIELD_GET(RTW89_PCIE_PHY_RATE_MASK, val8) == 0x2) { 22798e93258fSBjoern A. Zeeb phy_rate = PCIE_PHY_GEN2; 22808e93258fSBjoern A. Zeeb } else { 22818e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "[ERR]PCIe PHY rate %#x not support\n", val8); 22828e93258fSBjoern A. Zeeb return -EOPNOTSUPP; 22838e93258fSBjoern A. Zeeb } 22848e93258fSBjoern A. Zeeb /* Disable L1BD */ 22858e93258fSBjoern A. Zeeb ret = rtw89_pci_read_config_byte(rtwdev, RTW89_PCIE_L1_CTRL, &bdr_ori); 22868e93258fSBjoern A. Zeeb if (ret) { 22878e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "[ERR]pci config read %X\n", RTW89_PCIE_L1_CTRL); 22888e93258fSBjoern A. Zeeb return ret; 22898e93258fSBjoern A. Zeeb } 22908e93258fSBjoern A. Zeeb 22918e93258fSBjoern A. Zeeb if (bdr_ori & RTW89_PCIE_BIT_L1) { 22928e93258fSBjoern A. Zeeb ret = rtw89_pci_write_config_byte(rtwdev, RTW89_PCIE_L1_CTRL, 22938e93258fSBjoern A. Zeeb bdr_ori & ~RTW89_PCIE_BIT_L1); 22948e93258fSBjoern A. Zeeb if (ret) { 22958e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "[ERR]pci config write %X\n", 22968e93258fSBjoern A. Zeeb RTW89_PCIE_L1_CTRL); 22978e93258fSBjoern A. Zeeb return ret; 22988e93258fSBjoern A. Zeeb } 22998e93258fSBjoern A. Zeeb l1_flag = true; 23008e93258fSBjoern A. Zeeb } 23018e93258fSBjoern A. Zeeb 23028e93258fSBjoern A. Zeeb ret = rtw89_read16_mdio(rtwdev, RAC_CTRL_PPR_V1, phy_rate, &val16); 23038e93258fSBjoern A. Zeeb if (ret) { 23048e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "[ERR]mdio_r16_pcie %X\n", RAC_CTRL_PPR_V1); 23058e93258fSBjoern A. Zeeb goto end; 23068e93258fSBjoern A. Zeeb } 23078e93258fSBjoern A. Zeeb 23088e93258fSBjoern A. Zeeb if (val16 & B_AX_CALIB_EN) { 23098e93258fSBjoern A. Zeeb ret = rtw89_write16_mdio(rtwdev, RAC_CTRL_PPR_V1, 23108e93258fSBjoern A. Zeeb val16 & ~B_AX_CALIB_EN, phy_rate); 23118e93258fSBjoern A. Zeeb if (ret) { 23128e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "[ERR]mdio_w16_pcie %X\n", RAC_CTRL_PPR_V1); 23138e93258fSBjoern A. Zeeb goto end; 23148e93258fSBjoern A. Zeeb } 23158e93258fSBjoern A. Zeeb } 23168e93258fSBjoern A. Zeeb 23178e93258fSBjoern A. Zeeb if (!autook_en) 23188e93258fSBjoern A. Zeeb goto end; 23198e93258fSBjoern A. Zeeb /* Set div */ 23208e93258fSBjoern A. Zeeb ret = rtw89_write16_mdio_clr(rtwdev, RAC_CTRL_PPR_V1, B_AX_DIV, phy_rate); 23218e93258fSBjoern A. Zeeb if (ret) { 23228e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "[ERR]mdio_w16_pcie %X\n", RAC_CTRL_PPR_V1); 23238e93258fSBjoern A. Zeeb goto end; 23248e93258fSBjoern A. Zeeb } 23258e93258fSBjoern A. Zeeb 23268e93258fSBjoern A. Zeeb /* Obtain div and margin */ 23278e93258fSBjoern A. Zeeb ret = __get_target(rtwdev, &tar, phy_rate); 23288e93258fSBjoern A. Zeeb if (ret) { 23298e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "[ERR]1st get target fail %d\n", ret); 23308e93258fSBjoern A. Zeeb goto end; 23318e93258fSBjoern A. Zeeb } 23328e93258fSBjoern A. Zeeb 23338e93258fSBjoern A. Zeeb mgn_set = tar * INTF_INTGRA_HOSTREF_V1 / INTF_INTGRA_MINREF_V1 - tar; 23348e93258fSBjoern A. Zeeb 23358e93258fSBjoern A. Zeeb if (mgn_set >= 128) { 23368e93258fSBjoern A. Zeeb div_set = 0x0003; 23378e93258fSBjoern A. Zeeb mgn_set = 0x000F; 23388e93258fSBjoern A. Zeeb } else if (mgn_set >= 64) { 23398e93258fSBjoern A. Zeeb div_set = 0x0003; 23408e93258fSBjoern A. Zeeb mgn_set >>= 3; 23418e93258fSBjoern A. Zeeb } else if (mgn_set >= 32) { 23428e93258fSBjoern A. Zeeb div_set = 0x0002; 23438e93258fSBjoern A. Zeeb mgn_set >>= 2; 23448e93258fSBjoern A. Zeeb } else if (mgn_set >= 16) { 23458e93258fSBjoern A. Zeeb div_set = 0x0001; 23468e93258fSBjoern A. Zeeb mgn_set >>= 1; 23478e93258fSBjoern A. Zeeb } else if (mgn_set == 0) { 23488e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "[ERR]cal mgn is 0,tar = %d\n", tar); 23498e93258fSBjoern A. Zeeb goto end; 23508e93258fSBjoern A. Zeeb } else { 23518e93258fSBjoern A. Zeeb div_set = 0x0000; 23528e93258fSBjoern A. Zeeb } 23538e93258fSBjoern A. Zeeb 23548e93258fSBjoern A. Zeeb ret = rtw89_read16_mdio(rtwdev, RAC_CTRL_PPR_V1, phy_rate, &val16); 23558e93258fSBjoern A. Zeeb if (ret) { 23568e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "[ERR]mdio_r16_pcie %X\n", RAC_CTRL_PPR_V1); 23578e93258fSBjoern A. Zeeb goto end; 23588e93258fSBjoern A. Zeeb } 23598e93258fSBjoern A. Zeeb 23608e93258fSBjoern A. Zeeb val16 |= u16_encode_bits(div_set, B_AX_DIV); 23618e93258fSBjoern A. Zeeb 23628e93258fSBjoern A. Zeeb ret = rtw89_write16_mdio(rtwdev, RAC_CTRL_PPR_V1, val16, phy_rate); 23638e93258fSBjoern A. Zeeb if (ret) { 23648e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "[ERR]mdio_w16_pcie %X\n", RAC_CTRL_PPR_V1); 23658e93258fSBjoern A. Zeeb goto end; 23668e93258fSBjoern A. Zeeb } 23678e93258fSBjoern A. Zeeb 23688e93258fSBjoern A. Zeeb ret = __get_target(rtwdev, &tar, phy_rate); 23698e93258fSBjoern A. Zeeb if (ret) { 23708e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "[ERR]2nd get target fail %d\n", ret); 23718e93258fSBjoern A. Zeeb goto end; 23728e93258fSBjoern A. Zeeb } 23738e93258fSBjoern A. Zeeb 23748e93258fSBjoern A. Zeeb rtw89_debug(rtwdev, RTW89_DBG_HCI, "[TRACE]target = 0x%X, div = 0x%X, margin = 0x%X\n", 23758e93258fSBjoern A. Zeeb tar, div_set, mgn_set); 23768e93258fSBjoern A. Zeeb ret = rtw89_write16_mdio(rtwdev, RAC_SET_PPR_V1, 23778e93258fSBjoern A. Zeeb (tar & 0x0FFF) | (mgn_set << 12), phy_rate); 23788e93258fSBjoern A. Zeeb if (ret) { 23798e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "[ERR]mdio_w16_pcie %X\n", RAC_SET_PPR_V1); 23808e93258fSBjoern A. Zeeb goto end; 23818e93258fSBjoern A. Zeeb } 23828e93258fSBjoern A. Zeeb 23838e93258fSBjoern A. Zeeb /* Enable function */ 23848e93258fSBjoern A. Zeeb ret = rtw89_write16_mdio_set(rtwdev, RAC_CTRL_PPR_V1, B_AX_CALIB_EN, phy_rate); 23858e93258fSBjoern A. Zeeb if (ret) { 23868e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "[ERR]mdio_w16_pcie %X\n", RAC_CTRL_PPR_V1); 23878e93258fSBjoern A. Zeeb goto end; 23888e93258fSBjoern A. Zeeb } 23898e93258fSBjoern A. Zeeb 23908e93258fSBjoern A. Zeeb /* CLK delay = 0 */ 23918e93258fSBjoern A. Zeeb ret = rtw89_pci_write_config_byte(rtwdev, RTW89_PCIE_CLK_CTRL, 23928e93258fSBjoern A. Zeeb PCIE_CLKDLY_HW_0); 23938e93258fSBjoern A. Zeeb 23948e93258fSBjoern A. Zeeb end: 23958e93258fSBjoern A. Zeeb /* Set L1BD to ori */ 23968e93258fSBjoern A. Zeeb if (l1_flag) { 23978e93258fSBjoern A. Zeeb ret = rtw89_pci_write_config_byte(rtwdev, RTW89_PCIE_L1_CTRL, 23988e93258fSBjoern A. Zeeb bdr_ori); 23998e93258fSBjoern A. Zeeb if (ret) { 24008e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "[ERR]pci config write %X\n", 24018e93258fSBjoern A. Zeeb RTW89_PCIE_L1_CTRL); 24028e93258fSBjoern A. Zeeb return ret; 24038e93258fSBjoern A. Zeeb } 24048e93258fSBjoern A. Zeeb } 24058e93258fSBjoern A. Zeeb 24068e93258fSBjoern A. Zeeb return ret; 24078e93258fSBjoern A. Zeeb } 24088e93258fSBjoern A. Zeeb 24098e93258fSBjoern A. Zeeb static int rtw89_pci_deglitch_setting(struct rtw89_dev *rtwdev) 24108e93258fSBjoern A. Zeeb { 24118e93258fSBjoern A. Zeeb enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id; 24128e93258fSBjoern A. Zeeb int ret; 24138e93258fSBjoern A. Zeeb 24148e93258fSBjoern A. Zeeb if (chip_id == RTL8852A) { 24158e93258fSBjoern A. Zeeb ret = rtw89_write16_mdio_clr(rtwdev, RAC_ANA24, B_AX_DEGLITCH, 24168e93258fSBjoern A. Zeeb PCIE_PHY_GEN1); 24178e93258fSBjoern A. Zeeb if (ret) 24188e93258fSBjoern A. Zeeb return ret; 24198e93258fSBjoern A. Zeeb ret = rtw89_write16_mdio_clr(rtwdev, RAC_ANA24, B_AX_DEGLITCH, 24208e93258fSBjoern A. Zeeb PCIE_PHY_GEN2); 24218e93258fSBjoern A. Zeeb if (ret) 24228e93258fSBjoern A. Zeeb return ret; 24238e93258fSBjoern A. Zeeb } else if (chip_id == RTL8852C) { 24248e93258fSBjoern A. Zeeb rtw89_write16_clr(rtwdev, R_RAC_DIRECT_OFFSET_G1 + RAC_ANA24 * 2, 24258e93258fSBjoern A. Zeeb B_AX_DEGLITCH); 24268e93258fSBjoern A. Zeeb rtw89_write16_clr(rtwdev, R_RAC_DIRECT_OFFSET_G2 + RAC_ANA24 * 2, 24278e93258fSBjoern A. Zeeb B_AX_DEGLITCH); 24288e93258fSBjoern A. Zeeb } 24298e93258fSBjoern A. Zeeb 24308e93258fSBjoern A. Zeeb return 0; 24318e93258fSBjoern A. Zeeb } 24328e93258fSBjoern A. Zeeb 2433*6d67aabdSBjoern A. Zeeb static void rtw89_pci_disable_eq(struct rtw89_dev *rtwdev) 2434*6d67aabdSBjoern A. Zeeb { 2435*6d67aabdSBjoern A. Zeeb u16 g1_oobs, g2_oobs; 2436*6d67aabdSBjoern A. Zeeb u32 backup_aspm; 2437*6d67aabdSBjoern A. Zeeb u32 phy_offset; 2438*6d67aabdSBjoern A. Zeeb u16 oobs_val; 2439*6d67aabdSBjoern A. Zeeb int ret; 2440*6d67aabdSBjoern A. Zeeb 2441*6d67aabdSBjoern A. Zeeb if (rtwdev->chip->chip_id != RTL8852C) 2442*6d67aabdSBjoern A. Zeeb return; 2443*6d67aabdSBjoern A. Zeeb 2444*6d67aabdSBjoern A. Zeeb g1_oobs = rtw89_read16_mask(rtwdev, R_RAC_DIRECT_OFFSET_G1 + 2445*6d67aabdSBjoern A. Zeeb RAC_ANA09 * RAC_MULT, BAC_OOBS_SEL); 2446*6d67aabdSBjoern A. Zeeb g2_oobs = rtw89_read16_mask(rtwdev, R_RAC_DIRECT_OFFSET_G2 + 2447*6d67aabdSBjoern A. Zeeb RAC_ANA09 * RAC_MULT, BAC_OOBS_SEL); 2448*6d67aabdSBjoern A. Zeeb if (g1_oobs && g2_oobs) 2449*6d67aabdSBjoern A. Zeeb return; 2450*6d67aabdSBjoern A. Zeeb 2451*6d67aabdSBjoern A. Zeeb backup_aspm = rtw89_read32(rtwdev, R_AX_PCIE_MIX_CFG_V1); 2452*6d67aabdSBjoern A. Zeeb rtw89_write32_clr(rtwdev, R_AX_PCIE_MIX_CFG_V1, B_AX_ASPM_CTRL_MASK); 2453*6d67aabdSBjoern A. Zeeb 2454*6d67aabdSBjoern A. Zeeb ret = rtw89_pci_get_phy_offset_by_link_speed(rtwdev, &phy_offset); 2455*6d67aabdSBjoern A. Zeeb if (ret) 2456*6d67aabdSBjoern A. Zeeb goto out; 2457*6d67aabdSBjoern A. Zeeb 2458*6d67aabdSBjoern A. Zeeb rtw89_write16_set(rtwdev, phy_offset + RAC_ANA0D * RAC_MULT, BAC_RX_TEST_EN); 2459*6d67aabdSBjoern A. Zeeb rtw89_write16(rtwdev, phy_offset + RAC_ANA10 * RAC_MULT, ADDR_SEL_PINOUT_DIS_VAL); 2460*6d67aabdSBjoern A. Zeeb rtw89_write16_set(rtwdev, phy_offset + RAC_ANA19 * RAC_MULT, B_PCIE_BIT_RD_SEL); 2461*6d67aabdSBjoern A. Zeeb 2462*6d67aabdSBjoern A. Zeeb oobs_val = rtw89_read16_mask(rtwdev, phy_offset + RAC_ANA1F * RAC_MULT, 2463*6d67aabdSBjoern A. Zeeb OOBS_LEVEL_MASK); 2464*6d67aabdSBjoern A. Zeeb 2465*6d67aabdSBjoern A. Zeeb rtw89_write16_mask(rtwdev, R_RAC_DIRECT_OFFSET_G1 + RAC_ANA03 * RAC_MULT, 2466*6d67aabdSBjoern A. Zeeb OOBS_SEN_MASK, oobs_val); 2467*6d67aabdSBjoern A. Zeeb rtw89_write16_set(rtwdev, R_RAC_DIRECT_OFFSET_G1 + RAC_ANA09 * RAC_MULT, 2468*6d67aabdSBjoern A. Zeeb BAC_OOBS_SEL); 2469*6d67aabdSBjoern A. Zeeb 2470*6d67aabdSBjoern A. Zeeb rtw89_write16_mask(rtwdev, R_RAC_DIRECT_OFFSET_G2 + RAC_ANA03 * RAC_MULT, 2471*6d67aabdSBjoern A. Zeeb OOBS_SEN_MASK, oobs_val); 2472*6d67aabdSBjoern A. Zeeb rtw89_write16_set(rtwdev, R_RAC_DIRECT_OFFSET_G2 + RAC_ANA09 * RAC_MULT, 2473*6d67aabdSBjoern A. Zeeb BAC_OOBS_SEL); 2474*6d67aabdSBjoern A. Zeeb 2475*6d67aabdSBjoern A. Zeeb out: 2476*6d67aabdSBjoern A. Zeeb rtw89_write32(rtwdev, R_AX_PCIE_MIX_CFG_V1, backup_aspm); 2477*6d67aabdSBjoern A. Zeeb } 2478*6d67aabdSBjoern A. Zeeb 2479*6d67aabdSBjoern A. Zeeb static void rtw89_pci_ber(struct rtw89_dev *rtwdev) 2480*6d67aabdSBjoern A. Zeeb { 2481*6d67aabdSBjoern A. Zeeb u32 phy_offset; 2482*6d67aabdSBjoern A. Zeeb 2483*6d67aabdSBjoern A. Zeeb if (!test_bit(RTW89_QUIRK_PCI_BER, rtwdev->quirks)) 2484*6d67aabdSBjoern A. Zeeb return; 2485*6d67aabdSBjoern A. Zeeb 2486*6d67aabdSBjoern A. Zeeb phy_offset = R_RAC_DIRECT_OFFSET_G1; 2487*6d67aabdSBjoern A. Zeeb rtw89_write16(rtwdev, phy_offset + RAC_ANA1E * RAC_MULT, RAC_ANA1E_G1_VAL); 2488*6d67aabdSBjoern A. Zeeb rtw89_write16(rtwdev, phy_offset + RAC_ANA2E * RAC_MULT, RAC_ANA2E_VAL); 2489*6d67aabdSBjoern A. Zeeb 2490*6d67aabdSBjoern A. Zeeb phy_offset = R_RAC_DIRECT_OFFSET_G2; 2491*6d67aabdSBjoern A. Zeeb rtw89_write16(rtwdev, phy_offset + RAC_ANA1E * RAC_MULT, RAC_ANA1E_G2_VAL); 2492*6d67aabdSBjoern A. Zeeb rtw89_write16(rtwdev, phy_offset + RAC_ANA2E * RAC_MULT, RAC_ANA2E_VAL); 2493*6d67aabdSBjoern A. Zeeb } 2494*6d67aabdSBjoern A. Zeeb 24958e93258fSBjoern A. Zeeb static void rtw89_pci_rxdma_prefth(struct rtw89_dev *rtwdev) 24968e93258fSBjoern A. Zeeb { 24978e93258fSBjoern A. Zeeb if (rtwdev->chip->chip_id != RTL8852A) 24988e93258fSBjoern A. Zeeb return; 24998e93258fSBjoern A. Zeeb 25008e93258fSBjoern A. Zeeb rtw89_write32_set(rtwdev, R_AX_PCIE_INIT_CFG1, B_AX_DIS_RXDMA_PRE); 25018e93258fSBjoern A. Zeeb } 25028e93258fSBjoern A. Zeeb 25038e93258fSBjoern A. Zeeb static void rtw89_pci_l1off_pwroff(struct rtw89_dev *rtwdev) 25048e93258fSBjoern A. Zeeb { 2505e2340276SBjoern A. Zeeb enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id; 2506e2340276SBjoern A. Zeeb 2507*6d67aabdSBjoern A. Zeeb if (chip_id != RTL8852A && !rtw89_is_rtl885xb(rtwdev)) 25088e93258fSBjoern A. Zeeb return; 25098e93258fSBjoern A. Zeeb 25108e93258fSBjoern A. Zeeb rtw89_write32_clr(rtwdev, R_AX_PCIE_PS_CTRL, B_AX_L1OFF_PWR_OFF_EN); 25118e93258fSBjoern A. Zeeb } 25128e93258fSBjoern A. Zeeb 25138e93258fSBjoern A. Zeeb static u32 rtw89_pci_l2_rxen_lat(struct rtw89_dev *rtwdev) 25148e93258fSBjoern A. Zeeb { 25158e93258fSBjoern A. Zeeb int ret; 25168e93258fSBjoern A. Zeeb 25178e93258fSBjoern A. Zeeb if (rtwdev->chip->chip_id != RTL8852A) 25188e93258fSBjoern A. Zeeb return 0; 25198e93258fSBjoern A. Zeeb 25208e93258fSBjoern A. Zeeb ret = rtw89_write16_mdio_clr(rtwdev, RAC_ANA26, B_AX_RXEN, 25218e93258fSBjoern A. Zeeb PCIE_PHY_GEN1); 25228e93258fSBjoern A. Zeeb if (ret) 25238e93258fSBjoern A. Zeeb return ret; 25248e93258fSBjoern A. Zeeb 25258e93258fSBjoern A. Zeeb ret = rtw89_write16_mdio_clr(rtwdev, RAC_ANA26, B_AX_RXEN, 25268e93258fSBjoern A. Zeeb PCIE_PHY_GEN2); 25278e93258fSBjoern A. Zeeb if (ret) 25288e93258fSBjoern A. Zeeb return ret; 25298e93258fSBjoern A. Zeeb 25308e93258fSBjoern A. Zeeb return 0; 25318e93258fSBjoern A. Zeeb } 25328e93258fSBjoern A. Zeeb 25338e93258fSBjoern A. Zeeb static void rtw89_pci_aphy_pwrcut(struct rtw89_dev *rtwdev) 25348e93258fSBjoern A. Zeeb { 2535e2340276SBjoern A. Zeeb enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id; 2536e2340276SBjoern A. Zeeb 2537*6d67aabdSBjoern A. Zeeb if (chip_id != RTL8852A && !rtw89_is_rtl885xb(rtwdev)) 25388e93258fSBjoern A. Zeeb return; 25398e93258fSBjoern A. Zeeb 25408e93258fSBjoern A. Zeeb rtw89_write32_clr(rtwdev, R_AX_SYS_PW_CTRL, B_AX_PSUS_OFF_CAPC_EN); 25418e93258fSBjoern A. Zeeb } 25428e93258fSBjoern A. Zeeb 25438e93258fSBjoern A. Zeeb static void rtw89_pci_hci_ldo(struct rtw89_dev *rtwdev) 25448e93258fSBjoern A. Zeeb { 2545e2340276SBjoern A. Zeeb enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id; 2546e2340276SBjoern A. Zeeb 2547*6d67aabdSBjoern A. Zeeb if (chip_id == RTL8852A || rtw89_is_rtl885xb(rtwdev)) { 25488e93258fSBjoern A. Zeeb rtw89_write32_set(rtwdev, R_AX_SYS_SDIO_CTRL, 25498e93258fSBjoern A. Zeeb B_AX_PCIE_DIS_L2_CTRL_LDO_HCI); 25508e93258fSBjoern A. Zeeb rtw89_write32_clr(rtwdev, R_AX_SYS_SDIO_CTRL, 25518e93258fSBjoern A. Zeeb B_AX_PCIE_DIS_WLSUS_AFT_PDN); 25528e93258fSBjoern A. Zeeb } else if (rtwdev->chip->chip_id == RTL8852C) { 25538e93258fSBjoern A. Zeeb rtw89_write32_clr(rtwdev, R_AX_SYS_SDIO_CTRL, 25548e93258fSBjoern A. Zeeb B_AX_PCIE_DIS_L2_CTRL_LDO_HCI); 25558e93258fSBjoern A. Zeeb } 25568e93258fSBjoern A. Zeeb } 25578e93258fSBjoern A. Zeeb 25588e93258fSBjoern A. Zeeb static int rtw89_pci_dphy_delay(struct rtw89_dev *rtwdev) 25598e93258fSBjoern A. Zeeb { 2560*6d67aabdSBjoern A. Zeeb if (!rtw89_is_rtl885xb(rtwdev)) 25618e93258fSBjoern A. Zeeb return 0; 25628e93258fSBjoern A. Zeeb 25638e93258fSBjoern A. Zeeb return rtw89_write16_mdio_mask(rtwdev, RAC_REG_REV2, BAC_CMU_EN_DLY_MASK, 25648e93258fSBjoern A. Zeeb PCIE_DPHY_DLY_25US, PCIE_PHY_GEN1); 25658e93258fSBjoern A. Zeeb } 25668e93258fSBjoern A. Zeeb 25678e93258fSBjoern A. Zeeb static void rtw89_pci_power_wake(struct rtw89_dev *rtwdev, bool pwr_up) 25688e93258fSBjoern A. Zeeb { 25698e93258fSBjoern A. Zeeb if (pwr_up) 25708e93258fSBjoern A. Zeeb rtw89_write32_set(rtwdev, R_AX_HCI_OPT_CTRL, BIT_WAKE_CTRL); 25718e93258fSBjoern A. Zeeb else 25728e93258fSBjoern A. Zeeb rtw89_write32_clr(rtwdev, R_AX_HCI_OPT_CTRL, BIT_WAKE_CTRL); 25738e93258fSBjoern A. Zeeb } 25748e93258fSBjoern A. Zeeb 25758e93258fSBjoern A. Zeeb static void rtw89_pci_autoload_hang(struct rtw89_dev *rtwdev) 25768e93258fSBjoern A. Zeeb { 25778e93258fSBjoern A. Zeeb if (rtwdev->chip->chip_id != RTL8852C) 25788e93258fSBjoern A. Zeeb return; 25798e93258fSBjoern A. Zeeb 25808e93258fSBjoern A. Zeeb rtw89_write32_set(rtwdev, R_AX_PCIE_BG_CLR, B_AX_BG_CLR_ASYNC_M3); 25818e93258fSBjoern A. Zeeb rtw89_write32_clr(rtwdev, R_AX_PCIE_BG_CLR, B_AX_BG_CLR_ASYNC_M3); 25828e93258fSBjoern A. Zeeb } 25838e93258fSBjoern A. Zeeb 25848e93258fSBjoern A. Zeeb static void rtw89_pci_l12_vmain(struct rtw89_dev *rtwdev) 25858e93258fSBjoern A. Zeeb { 25868e93258fSBjoern A. Zeeb if (!(rtwdev->chip->chip_id == RTL8852C && rtwdev->hal.cv == CHIP_CAV)) 25878e93258fSBjoern A. Zeeb return; 25888e93258fSBjoern A. Zeeb 25898e93258fSBjoern A. Zeeb rtw89_write32_set(rtwdev, R_AX_SYS_SDIO_CTRL, B_AX_PCIE_FORCE_PWR_NGAT); 25908e93258fSBjoern A. Zeeb } 25918e93258fSBjoern A. Zeeb 25928e93258fSBjoern A. Zeeb static void rtw89_pci_gen2_force_ib(struct rtw89_dev *rtwdev) 25938e93258fSBjoern A. Zeeb { 25948e93258fSBjoern A. Zeeb if (!(rtwdev->chip->chip_id == RTL8852C && rtwdev->hal.cv == CHIP_CAV)) 25958e93258fSBjoern A. Zeeb return; 25968e93258fSBjoern A. Zeeb 25978e93258fSBjoern A. Zeeb rtw89_write32_set(rtwdev, R_AX_PMC_DBG_CTRL2, 25988e93258fSBjoern A. Zeeb B_AX_SYSON_DIS_PMCR_AX_WRMSK); 25998e93258fSBjoern A. Zeeb rtw89_write32_set(rtwdev, R_AX_HCI_BG_CTRL, B_AX_BG_CLR_ASYNC_M3); 26008e93258fSBjoern A. Zeeb rtw89_write32_clr(rtwdev, R_AX_PMC_DBG_CTRL2, 26018e93258fSBjoern A. Zeeb B_AX_SYSON_DIS_PMCR_AX_WRMSK); 26028e93258fSBjoern A. Zeeb } 26038e93258fSBjoern A. Zeeb 26048e93258fSBjoern A. Zeeb static void rtw89_pci_l1_ent_lat(struct rtw89_dev *rtwdev) 26058e93258fSBjoern A. Zeeb { 26068e93258fSBjoern A. Zeeb if (rtwdev->chip->chip_id != RTL8852C) 26078e93258fSBjoern A. Zeeb return; 26088e93258fSBjoern A. Zeeb 26098e93258fSBjoern A. Zeeb rtw89_write32_clr(rtwdev, R_AX_PCIE_PS_CTRL_V1, B_AX_SEL_REQ_ENTR_L1); 26108e93258fSBjoern A. Zeeb } 26118e93258fSBjoern A. Zeeb 26128e93258fSBjoern A. Zeeb static void rtw89_pci_wd_exit_l1(struct rtw89_dev *rtwdev) 26138e93258fSBjoern A. Zeeb { 26148e93258fSBjoern A. Zeeb if (rtwdev->chip->chip_id != RTL8852C) 26158e93258fSBjoern A. Zeeb return; 26168e93258fSBjoern A. Zeeb 26178e93258fSBjoern A. Zeeb rtw89_write32_set(rtwdev, R_AX_PCIE_PS_CTRL_V1, B_AX_DMAC0_EXIT_L1_EN); 26188e93258fSBjoern A. Zeeb } 26198e93258fSBjoern A. Zeeb 26208e93258fSBjoern A. Zeeb static void rtw89_pci_set_sic(struct rtw89_dev *rtwdev) 26218e93258fSBjoern A. Zeeb { 26228e93258fSBjoern A. Zeeb if (rtwdev->chip->chip_id == RTL8852C) 26238e93258fSBjoern A. Zeeb return; 26248e93258fSBjoern A. Zeeb 26258e93258fSBjoern A. Zeeb rtw89_write32_clr(rtwdev, R_AX_PCIE_EXP_CTRL, 26268e93258fSBjoern A. Zeeb B_AX_SIC_EN_FORCE_CLKREQ); 26278e93258fSBjoern A. Zeeb } 26288e93258fSBjoern A. Zeeb 26298e93258fSBjoern A. Zeeb static void rtw89_pci_set_lbc(struct rtw89_dev *rtwdev) 26308e93258fSBjoern A. Zeeb { 26318e93258fSBjoern A. Zeeb const struct rtw89_pci_info *info = rtwdev->pci_info; 26328e93258fSBjoern A. Zeeb u32 lbc; 26338e93258fSBjoern A. Zeeb 26348e93258fSBjoern A. Zeeb if (rtwdev->chip->chip_id == RTL8852C) 26358e93258fSBjoern A. Zeeb return; 26368e93258fSBjoern A. Zeeb 26378e93258fSBjoern A. Zeeb lbc = rtw89_read32(rtwdev, R_AX_LBC_WATCHDOG); 26388e93258fSBjoern A. Zeeb if (info->lbc_en == MAC_AX_PCIE_ENABLE) { 26398e93258fSBjoern A. Zeeb lbc = u32_replace_bits(lbc, info->lbc_tmr, B_AX_LBC_TIMER); 26408e93258fSBjoern A. Zeeb lbc |= B_AX_LBC_FLAG | B_AX_LBC_EN; 26418e93258fSBjoern A. Zeeb rtw89_write32(rtwdev, R_AX_LBC_WATCHDOG, lbc); 26428e93258fSBjoern A. Zeeb } else { 26438e93258fSBjoern A. Zeeb lbc &= ~B_AX_LBC_EN; 26448e93258fSBjoern A. Zeeb } 26458e93258fSBjoern A. Zeeb rtw89_write32_set(rtwdev, R_AX_LBC_WATCHDOG, lbc); 26468e93258fSBjoern A. Zeeb } 26478e93258fSBjoern A. Zeeb 26488e93258fSBjoern A. Zeeb static void rtw89_pci_set_io_rcy(struct rtw89_dev *rtwdev) 26498e93258fSBjoern A. Zeeb { 26508e93258fSBjoern A. Zeeb const struct rtw89_pci_info *info = rtwdev->pci_info; 26518e93258fSBjoern A. Zeeb u32 val32; 26528e93258fSBjoern A. Zeeb 26538e93258fSBjoern A. Zeeb if (rtwdev->chip->chip_id != RTL8852C) 26548e93258fSBjoern A. Zeeb return; 26558e93258fSBjoern A. Zeeb 26568e93258fSBjoern A. Zeeb if (info->io_rcy_en == MAC_AX_PCIE_ENABLE) { 26578e93258fSBjoern A. Zeeb val32 = FIELD_PREP(B_AX_PCIE_WDT_TIMER_M1_MASK, 26588e93258fSBjoern A. Zeeb info->io_rcy_tmr); 26598e93258fSBjoern A. Zeeb rtw89_write32(rtwdev, R_AX_PCIE_WDT_TIMER_M1, val32); 26608e93258fSBjoern A. Zeeb rtw89_write32(rtwdev, R_AX_PCIE_WDT_TIMER_M2, val32); 26618e93258fSBjoern A. Zeeb rtw89_write32(rtwdev, R_AX_PCIE_WDT_TIMER_E0, val32); 26628e93258fSBjoern A. Zeeb 26638e93258fSBjoern A. Zeeb rtw89_write32_set(rtwdev, R_AX_PCIE_IO_RCY_M1, B_AX_PCIE_IO_RCY_WDT_MODE_M1); 26648e93258fSBjoern A. Zeeb rtw89_write32_set(rtwdev, R_AX_PCIE_IO_RCY_M2, B_AX_PCIE_IO_RCY_WDT_MODE_M2); 26658e93258fSBjoern A. Zeeb rtw89_write32_set(rtwdev, R_AX_PCIE_IO_RCY_E0, B_AX_PCIE_IO_RCY_WDT_MODE_E0); 26668e93258fSBjoern A. Zeeb } else { 26678e93258fSBjoern A. Zeeb rtw89_write32_clr(rtwdev, R_AX_PCIE_IO_RCY_M1, B_AX_PCIE_IO_RCY_WDT_MODE_M1); 26688e93258fSBjoern A. Zeeb rtw89_write32_clr(rtwdev, R_AX_PCIE_IO_RCY_M2, B_AX_PCIE_IO_RCY_WDT_MODE_M2); 26698e93258fSBjoern A. Zeeb rtw89_write32_clr(rtwdev, R_AX_PCIE_IO_RCY_E0, B_AX_PCIE_IO_RCY_WDT_MODE_E0); 26708e93258fSBjoern A. Zeeb } 26718e93258fSBjoern A. Zeeb 26728e93258fSBjoern A. Zeeb rtw89_write32_clr(rtwdev, R_AX_PCIE_IO_RCY_S1, B_AX_PCIE_IO_RCY_WDT_MODE_S1); 26738e93258fSBjoern A. Zeeb } 26748e93258fSBjoern A. Zeeb 26758e93258fSBjoern A. Zeeb static void rtw89_pci_set_dbg(struct rtw89_dev *rtwdev) 26768e93258fSBjoern A. Zeeb { 26778e93258fSBjoern A. Zeeb if (rtwdev->chip->chip_id == RTL8852C) 26788e93258fSBjoern A. Zeeb return; 26798e93258fSBjoern A. Zeeb 26808e93258fSBjoern A. Zeeb rtw89_write32_set(rtwdev, R_AX_PCIE_DBG_CTRL, 26818e93258fSBjoern A. Zeeb B_AX_ASFF_FULL_NO_STK | B_AX_EN_STUCK_DBG); 26828e93258fSBjoern A. Zeeb 26838e93258fSBjoern A. Zeeb if (rtwdev->chip->chip_id == RTL8852A) 26848e93258fSBjoern A. Zeeb rtw89_write32_set(rtwdev, R_AX_PCIE_EXP_CTRL, 26858e93258fSBjoern A. Zeeb B_AX_EN_CHKDSC_NO_RX_STUCK); 26868e93258fSBjoern A. Zeeb } 26878e93258fSBjoern A. Zeeb 26888e93258fSBjoern A. Zeeb static void rtw89_pci_set_keep_reg(struct rtw89_dev *rtwdev) 26898e93258fSBjoern A. Zeeb { 26908e93258fSBjoern A. Zeeb if (rtwdev->chip->chip_id == RTL8852C) 26918e93258fSBjoern A. Zeeb return; 26928e93258fSBjoern A. Zeeb 26938e93258fSBjoern A. Zeeb rtw89_write32_set(rtwdev, R_AX_PCIE_INIT_CFG1, 26948e93258fSBjoern A. Zeeb B_AX_PCIE_TXRST_KEEP_REG | B_AX_PCIE_RXRST_KEEP_REG); 26958e93258fSBjoern A. Zeeb } 26968e93258fSBjoern A. Zeeb 2697*6d67aabdSBjoern A. Zeeb static void rtw89_pci_clr_idx_all_ax(struct rtw89_dev *rtwdev) 26988e93258fSBjoern A. Zeeb { 26998e93258fSBjoern A. Zeeb const struct rtw89_pci_info *info = rtwdev->pci_info; 27008e93258fSBjoern A. Zeeb enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id; 27018e93258fSBjoern A. Zeeb u32 val = B_AX_CLR_ACH0_IDX | B_AX_CLR_ACH1_IDX | B_AX_CLR_ACH2_IDX | 27028e93258fSBjoern A. Zeeb B_AX_CLR_ACH3_IDX | B_AX_CLR_CH8_IDX | B_AX_CLR_CH9_IDX | 27038e93258fSBjoern A. Zeeb B_AX_CLR_CH12_IDX; 27048e93258fSBjoern A. Zeeb u32 rxbd_rwptr_clr = info->rxbd_rwptr_clr_reg; 27058e93258fSBjoern A. Zeeb u32 txbd_rwptr_clr2 = info->txbd_rwptr_clr2_reg; 27068e93258fSBjoern A. Zeeb 27078e93258fSBjoern A. Zeeb if (chip_id == RTL8852A || chip_id == RTL8852C) 27088e93258fSBjoern A. Zeeb val |= B_AX_CLR_ACH4_IDX | B_AX_CLR_ACH5_IDX | 27098e93258fSBjoern A. Zeeb B_AX_CLR_ACH6_IDX | B_AX_CLR_ACH7_IDX; 27108e93258fSBjoern A. Zeeb /* clear DMA indexes */ 27118e93258fSBjoern A. Zeeb rtw89_write32_set(rtwdev, R_AX_TXBD_RWPTR_CLR1, val); 27128e93258fSBjoern A. Zeeb if (chip_id == RTL8852A || chip_id == RTL8852C) 27138e93258fSBjoern A. Zeeb rtw89_write32_set(rtwdev, txbd_rwptr_clr2, 27148e93258fSBjoern A. Zeeb B_AX_CLR_CH10_IDX | B_AX_CLR_CH11_IDX); 27158e93258fSBjoern A. Zeeb rtw89_write32_set(rtwdev, rxbd_rwptr_clr, 27168e93258fSBjoern A. Zeeb B_AX_CLR_RXQ_IDX | B_AX_CLR_RPQ_IDX); 27178e93258fSBjoern A. Zeeb } 27188e93258fSBjoern A. Zeeb 2719*6d67aabdSBjoern A. Zeeb static int rtw89_pci_poll_txdma_ch_idle_ax(struct rtw89_dev *rtwdev) 27208e93258fSBjoern A. Zeeb { 27218e93258fSBjoern A. Zeeb const struct rtw89_pci_info *info = rtwdev->pci_info; 27228e93258fSBjoern A. Zeeb u32 ret, check, dma_busy; 2723e2340276SBjoern A. Zeeb u32 dma_busy1 = info->dma_busy1.addr; 27248e93258fSBjoern A. Zeeb u32 dma_busy2 = info->dma_busy2_reg; 27258e93258fSBjoern A. Zeeb 2726e2340276SBjoern A. Zeeb check = info->dma_busy1.mask; 27278e93258fSBjoern A. Zeeb 27288e93258fSBjoern A. Zeeb ret = read_poll_timeout(rtw89_read32, dma_busy, (dma_busy & check) == 0, 27298e93258fSBjoern A. Zeeb 10, 100, false, rtwdev, dma_busy1); 27308e93258fSBjoern A. Zeeb if (ret) 27318e93258fSBjoern A. Zeeb return ret; 27328e93258fSBjoern A. Zeeb 2733e2340276SBjoern A. Zeeb if (!dma_busy2) 2734e2340276SBjoern A. Zeeb return 0; 2735e2340276SBjoern A. Zeeb 27368e93258fSBjoern A. Zeeb check = B_AX_CH10_BUSY | B_AX_CH11_BUSY; 27378e93258fSBjoern A. Zeeb 27388e93258fSBjoern A. Zeeb ret = read_poll_timeout(rtw89_read32, dma_busy, (dma_busy & check) == 0, 27398e93258fSBjoern A. Zeeb 10, 100, false, rtwdev, dma_busy2); 27408e93258fSBjoern A. Zeeb if (ret) 27418e93258fSBjoern A. Zeeb return ret; 27428e93258fSBjoern A. Zeeb 27438e93258fSBjoern A. Zeeb return 0; 27448e93258fSBjoern A. Zeeb } 27458e93258fSBjoern A. Zeeb 2746*6d67aabdSBjoern A. Zeeb static int rtw89_pci_poll_rxdma_ch_idle_ax(struct rtw89_dev *rtwdev) 27478e93258fSBjoern A. Zeeb { 27488e93258fSBjoern A. Zeeb const struct rtw89_pci_info *info = rtwdev->pci_info; 27498e93258fSBjoern A. Zeeb u32 ret, check, dma_busy; 27508e93258fSBjoern A. Zeeb u32 dma_busy3 = info->dma_busy3_reg; 27518e93258fSBjoern A. Zeeb 27528e93258fSBjoern A. Zeeb check = B_AX_RXQ_BUSY | B_AX_RPQ_BUSY; 27538e93258fSBjoern A. Zeeb 27548e93258fSBjoern A. Zeeb ret = read_poll_timeout(rtw89_read32, dma_busy, (dma_busy & check) == 0, 27558e93258fSBjoern A. Zeeb 10, 100, false, rtwdev, dma_busy3); 27568e93258fSBjoern A. Zeeb if (ret) 27578e93258fSBjoern A. Zeeb return ret; 27588e93258fSBjoern A. Zeeb 27598e93258fSBjoern A. Zeeb return 0; 27608e93258fSBjoern A. Zeeb } 27618e93258fSBjoern A. Zeeb 27628e93258fSBjoern A. Zeeb static int rtw89_pci_poll_dma_all_idle(struct rtw89_dev *rtwdev) 27638e93258fSBjoern A. Zeeb { 27648e93258fSBjoern A. Zeeb u32 ret; 27658e93258fSBjoern A. Zeeb 2766*6d67aabdSBjoern A. Zeeb ret = rtw89_pci_poll_txdma_ch_idle_ax(rtwdev); 27678e93258fSBjoern A. Zeeb if (ret) { 27688e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "txdma ch busy\n"); 27698e93258fSBjoern A. Zeeb return ret; 27708e93258fSBjoern A. Zeeb } 27718e93258fSBjoern A. Zeeb 2772*6d67aabdSBjoern A. Zeeb ret = rtw89_pci_poll_rxdma_ch_idle_ax(rtwdev); 27738e93258fSBjoern A. Zeeb if (ret) { 27748e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "rxdma ch busy\n"); 27758e93258fSBjoern A. Zeeb return ret; 27768e93258fSBjoern A. Zeeb } 27778e93258fSBjoern A. Zeeb 27788e93258fSBjoern A. Zeeb return 0; 27798e93258fSBjoern A. Zeeb } 27808e93258fSBjoern A. Zeeb 27818e93258fSBjoern A. Zeeb static int rtw89_pci_mode_op(struct rtw89_dev *rtwdev) 27828e93258fSBjoern A. Zeeb { 27838e93258fSBjoern A. Zeeb const struct rtw89_pci_info *info = rtwdev->pci_info; 27848e93258fSBjoern A. Zeeb enum mac_ax_bd_trunc_mode txbd_trunc_mode = info->txbd_trunc_mode; 27858e93258fSBjoern A. Zeeb enum mac_ax_bd_trunc_mode rxbd_trunc_mode = info->rxbd_trunc_mode; 27868e93258fSBjoern A. Zeeb enum mac_ax_rxbd_mode rxbd_mode = info->rxbd_mode; 27878e93258fSBjoern A. Zeeb enum mac_ax_tag_mode tag_mode = info->tag_mode; 27888e93258fSBjoern A. Zeeb enum mac_ax_wd_dma_intvl wd_dma_idle_intvl = info->wd_dma_idle_intvl; 27898e93258fSBjoern A. Zeeb enum mac_ax_wd_dma_intvl wd_dma_act_intvl = info->wd_dma_act_intvl; 27908e93258fSBjoern A. Zeeb enum mac_ax_tx_burst tx_burst = info->tx_burst; 27918e93258fSBjoern A. Zeeb enum mac_ax_rx_burst rx_burst = info->rx_burst; 27928e93258fSBjoern A. Zeeb enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id; 27938e93258fSBjoern A. Zeeb u8 cv = rtwdev->hal.cv; 27948e93258fSBjoern A. Zeeb u32 val32; 27958e93258fSBjoern A. Zeeb 27968e93258fSBjoern A. Zeeb if (txbd_trunc_mode == MAC_AX_BD_TRUNC) { 27978e93258fSBjoern A. Zeeb if (chip_id == RTL8852A && cv == CHIP_CBV) 27988e93258fSBjoern A. Zeeb rtw89_write32_set(rtwdev, R_AX_PCIE_INIT_CFG1, B_AX_TX_TRUNC_MODE); 27998e93258fSBjoern A. Zeeb } else if (txbd_trunc_mode == MAC_AX_BD_NORM) { 28008e93258fSBjoern A. Zeeb if (chip_id == RTL8852A || chip_id == RTL8852B) 28018e93258fSBjoern A. Zeeb rtw89_write32_clr(rtwdev, R_AX_PCIE_INIT_CFG1, B_AX_TX_TRUNC_MODE); 28028e93258fSBjoern A. Zeeb } 28038e93258fSBjoern A. Zeeb 28048e93258fSBjoern A. Zeeb if (rxbd_trunc_mode == MAC_AX_BD_TRUNC) { 28058e93258fSBjoern A. Zeeb if (chip_id == RTL8852A && cv == CHIP_CBV) 28068e93258fSBjoern A. Zeeb rtw89_write32_set(rtwdev, R_AX_PCIE_INIT_CFG1, B_AX_RX_TRUNC_MODE); 28078e93258fSBjoern A. Zeeb } else if (rxbd_trunc_mode == MAC_AX_BD_NORM) { 28088e93258fSBjoern A. Zeeb if (chip_id == RTL8852A || chip_id == RTL8852B) 28098e93258fSBjoern A. Zeeb rtw89_write32_clr(rtwdev, R_AX_PCIE_INIT_CFG1, B_AX_RX_TRUNC_MODE); 28108e93258fSBjoern A. Zeeb } 28118e93258fSBjoern A. Zeeb 28128e93258fSBjoern A. Zeeb if (rxbd_mode == MAC_AX_RXBD_PKT) { 28138e93258fSBjoern A. Zeeb rtw89_write32_clr(rtwdev, info->init_cfg_reg, info->rxbd_mode_bit); 28148e93258fSBjoern A. Zeeb } else if (rxbd_mode == MAC_AX_RXBD_SEP) { 28158e93258fSBjoern A. Zeeb rtw89_write32_set(rtwdev, info->init_cfg_reg, info->rxbd_mode_bit); 28168e93258fSBjoern A. Zeeb 28178e93258fSBjoern A. Zeeb if (chip_id == RTL8852A || chip_id == RTL8852B) 28188e93258fSBjoern A. Zeeb rtw89_write32_mask(rtwdev, R_AX_PCIE_INIT_CFG2, 28198e93258fSBjoern A. Zeeb B_AX_PCIE_RX_APPLEN_MASK, 0); 28208e93258fSBjoern A. Zeeb } 28218e93258fSBjoern A. Zeeb 2822*6d67aabdSBjoern A. Zeeb if (chip_id == RTL8852A || rtw89_is_rtl885xb(rtwdev)) { 28238e93258fSBjoern A. Zeeb rtw89_write32_mask(rtwdev, R_AX_PCIE_INIT_CFG1, B_AX_PCIE_MAX_TXDMA_MASK, tx_burst); 28248e93258fSBjoern A. Zeeb rtw89_write32_mask(rtwdev, R_AX_PCIE_INIT_CFG1, B_AX_PCIE_MAX_RXDMA_MASK, rx_burst); 28258e93258fSBjoern A. Zeeb } else if (chip_id == RTL8852C) { 28268e93258fSBjoern A. Zeeb rtw89_write32_mask(rtwdev, R_AX_HAXI_INIT_CFG1, B_AX_HAXI_MAX_TXDMA_MASK, tx_burst); 28278e93258fSBjoern A. Zeeb rtw89_write32_mask(rtwdev, R_AX_HAXI_INIT_CFG1, B_AX_HAXI_MAX_RXDMA_MASK, rx_burst); 28288e93258fSBjoern A. Zeeb } 28298e93258fSBjoern A. Zeeb 2830*6d67aabdSBjoern A. Zeeb if (chip_id == RTL8852A || rtw89_is_rtl885xb(rtwdev)) { 28318e93258fSBjoern A. Zeeb if (tag_mode == MAC_AX_TAG_SGL) { 28328e93258fSBjoern A. Zeeb val32 = rtw89_read32(rtwdev, R_AX_PCIE_INIT_CFG1) & 28338e93258fSBjoern A. Zeeb ~B_AX_LATENCY_CONTROL; 28348e93258fSBjoern A. Zeeb rtw89_write32(rtwdev, R_AX_PCIE_INIT_CFG1, val32); 28358e93258fSBjoern A. Zeeb } else if (tag_mode == MAC_AX_TAG_MULTI) { 28368e93258fSBjoern A. Zeeb val32 = rtw89_read32(rtwdev, R_AX_PCIE_INIT_CFG1) | 28378e93258fSBjoern A. Zeeb B_AX_LATENCY_CONTROL; 28388e93258fSBjoern A. Zeeb rtw89_write32(rtwdev, R_AX_PCIE_INIT_CFG1, val32); 28398e93258fSBjoern A. Zeeb } 28408e93258fSBjoern A. Zeeb } 28418e93258fSBjoern A. Zeeb 28428e93258fSBjoern A. Zeeb rtw89_write32_mask(rtwdev, info->exp_ctrl_reg, info->max_tag_num_mask, 28438e93258fSBjoern A. Zeeb info->multi_tag_num); 28448e93258fSBjoern A. Zeeb 2845*6d67aabdSBjoern A. Zeeb if (chip_id == RTL8852A || rtw89_is_rtl885xb(rtwdev)) { 28468e93258fSBjoern A. Zeeb rtw89_write32_mask(rtwdev, R_AX_PCIE_INIT_CFG2, B_AX_WD_ITVL_IDLE, 28478e93258fSBjoern A. Zeeb wd_dma_idle_intvl); 28488e93258fSBjoern A. Zeeb rtw89_write32_mask(rtwdev, R_AX_PCIE_INIT_CFG2, B_AX_WD_ITVL_ACT, 28498e93258fSBjoern A. Zeeb wd_dma_act_intvl); 28508e93258fSBjoern A. Zeeb } else if (chip_id == RTL8852C) { 28518e93258fSBjoern A. Zeeb rtw89_write32_mask(rtwdev, R_AX_HAXI_INIT_CFG1, B_AX_WD_ITVL_IDLE_V1_MASK, 28528e93258fSBjoern A. Zeeb wd_dma_idle_intvl); 28538e93258fSBjoern A. Zeeb rtw89_write32_mask(rtwdev, R_AX_HAXI_INIT_CFG1, B_AX_WD_ITVL_ACT_V1_MASK, 28548e93258fSBjoern A. Zeeb wd_dma_act_intvl); 28558e93258fSBjoern A. Zeeb } 28568e93258fSBjoern A. Zeeb 28578e93258fSBjoern A. Zeeb if (txbd_trunc_mode == MAC_AX_BD_TRUNC) { 28588e93258fSBjoern A. Zeeb rtw89_write32_set(rtwdev, R_AX_TX_ADDRESS_INFO_MODE_SETTING, 28598e93258fSBjoern A. Zeeb B_AX_HOST_ADDR_INFO_8B_SEL); 28608e93258fSBjoern A. Zeeb rtw89_write32_clr(rtwdev, R_AX_PKTIN_SETTING, B_AX_WD_ADDR_INFO_LENGTH); 28618e93258fSBjoern A. Zeeb } else if (txbd_trunc_mode == MAC_AX_BD_NORM) { 28628e93258fSBjoern A. Zeeb rtw89_write32_clr(rtwdev, R_AX_TX_ADDRESS_INFO_MODE_SETTING, 28638e93258fSBjoern A. Zeeb B_AX_HOST_ADDR_INFO_8B_SEL); 28648e93258fSBjoern A. Zeeb rtw89_write32_set(rtwdev, R_AX_PKTIN_SETTING, B_AX_WD_ADDR_INFO_LENGTH); 28658e93258fSBjoern A. Zeeb } 28668e93258fSBjoern A. Zeeb 28678e93258fSBjoern A. Zeeb return 0; 28688e93258fSBjoern A. Zeeb } 28698e93258fSBjoern A. Zeeb 28708e93258fSBjoern A. Zeeb static int rtw89_pci_ops_deinit(struct rtw89_dev *rtwdev) 28718e93258fSBjoern A. Zeeb { 28728e93258fSBjoern A. Zeeb const struct rtw89_pci_info *info = rtwdev->pci_info; 28738e93258fSBjoern A. Zeeb 28748e93258fSBjoern A. Zeeb if (rtwdev->chip->chip_id == RTL8852A) { 28758e93258fSBjoern A. Zeeb /* ltr sw trigger */ 28768e93258fSBjoern A. Zeeb rtw89_write32_set(rtwdev, R_AX_LTR_CTRL_0, B_AX_APP_LTR_IDLE); 28778e93258fSBjoern A. Zeeb } 28788e93258fSBjoern A. Zeeb info->ltr_set(rtwdev, false); 28798e93258fSBjoern A. Zeeb rtw89_pci_ctrl_dma_all(rtwdev, false); 28808e93258fSBjoern A. Zeeb rtw89_pci_clr_idx_all(rtwdev); 28818e93258fSBjoern A. Zeeb 28828e93258fSBjoern A. Zeeb return 0; 28838e93258fSBjoern A. Zeeb } 28848e93258fSBjoern A. Zeeb 2885*6d67aabdSBjoern A. Zeeb static int rtw89_pci_ops_mac_pre_init_ax(struct rtw89_dev *rtwdev) 28868e93258fSBjoern A. Zeeb { 28878e93258fSBjoern A. Zeeb const struct rtw89_pci_info *info = rtwdev->pci_info; 28888e93258fSBjoern A. Zeeb int ret; 28898e93258fSBjoern A. Zeeb 2890*6d67aabdSBjoern A. Zeeb rtw89_pci_ber(rtwdev); 28918e93258fSBjoern A. Zeeb rtw89_pci_rxdma_prefth(rtwdev); 28928e93258fSBjoern A. Zeeb rtw89_pci_l1off_pwroff(rtwdev); 28938e93258fSBjoern A. Zeeb rtw89_pci_deglitch_setting(rtwdev); 28948e93258fSBjoern A. Zeeb ret = rtw89_pci_l2_rxen_lat(rtwdev); 28958e93258fSBjoern A. Zeeb if (ret) { 28968e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "[ERR] pcie l2 rxen lat %d\n", ret); 28978e93258fSBjoern A. Zeeb return ret; 28988e93258fSBjoern A. Zeeb } 28998e93258fSBjoern A. Zeeb 29008e93258fSBjoern A. Zeeb rtw89_pci_aphy_pwrcut(rtwdev); 29018e93258fSBjoern A. Zeeb rtw89_pci_hci_ldo(rtwdev); 29028e93258fSBjoern A. Zeeb rtw89_pci_dphy_delay(rtwdev); 29038e93258fSBjoern A. Zeeb 2904e2340276SBjoern A. Zeeb ret = rtw89_pci_autok_x(rtwdev); 2905e2340276SBjoern A. Zeeb if (ret) { 2906e2340276SBjoern A. Zeeb rtw89_err(rtwdev, "[ERR] pcie autok_x fail %d\n", ret); 2907e2340276SBjoern A. Zeeb return ret; 2908e2340276SBjoern A. Zeeb } 2909e2340276SBjoern A. Zeeb 29108e93258fSBjoern A. Zeeb ret = rtw89_pci_auto_refclk_cal(rtwdev, false); 29118e93258fSBjoern A. Zeeb if (ret) { 29128e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "[ERR] pcie autok fail %d\n", ret); 29138e93258fSBjoern A. Zeeb return ret; 29148e93258fSBjoern A. Zeeb } 29158e93258fSBjoern A. Zeeb 29168e93258fSBjoern A. Zeeb rtw89_pci_power_wake(rtwdev, true); 29178e93258fSBjoern A. Zeeb rtw89_pci_autoload_hang(rtwdev); 29188e93258fSBjoern A. Zeeb rtw89_pci_l12_vmain(rtwdev); 29198e93258fSBjoern A. Zeeb rtw89_pci_gen2_force_ib(rtwdev); 29208e93258fSBjoern A. Zeeb rtw89_pci_l1_ent_lat(rtwdev); 29218e93258fSBjoern A. Zeeb rtw89_pci_wd_exit_l1(rtwdev); 29228e93258fSBjoern A. Zeeb rtw89_pci_set_sic(rtwdev); 29238e93258fSBjoern A. Zeeb rtw89_pci_set_lbc(rtwdev); 29248e93258fSBjoern A. Zeeb rtw89_pci_set_io_rcy(rtwdev); 29258e93258fSBjoern A. Zeeb rtw89_pci_set_dbg(rtwdev); 29268e93258fSBjoern A. Zeeb rtw89_pci_set_keep_reg(rtwdev); 29278e93258fSBjoern A. Zeeb 2928e2340276SBjoern A. Zeeb rtw89_write32_set(rtwdev, info->dma_stop1.addr, B_AX_STOP_WPDMA); 29298e93258fSBjoern A. Zeeb 29308e93258fSBjoern A. Zeeb /* stop DMA activities */ 29318e93258fSBjoern A. Zeeb rtw89_pci_ctrl_dma_all(rtwdev, false); 29328e93258fSBjoern A. Zeeb 29338e93258fSBjoern A. Zeeb ret = rtw89_pci_poll_dma_all_idle(rtwdev); 29348e93258fSBjoern A. Zeeb if (ret) { 29358e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "[ERR] poll pcie dma all idle\n"); 29368e93258fSBjoern A. Zeeb return ret; 29378e93258fSBjoern A. Zeeb } 29388e93258fSBjoern A. Zeeb 29398e93258fSBjoern A. Zeeb rtw89_pci_clr_idx_all(rtwdev); 29408e93258fSBjoern A. Zeeb rtw89_pci_mode_op(rtwdev); 29418e93258fSBjoern A. Zeeb 29428e93258fSBjoern A. Zeeb /* fill TRX BD indexes */ 29438e93258fSBjoern A. Zeeb rtw89_pci_ops_reset(rtwdev); 29448e93258fSBjoern A. Zeeb 2945*6d67aabdSBjoern A. Zeeb ret = rtw89_pci_rst_bdram_ax(rtwdev); 29468e93258fSBjoern A. Zeeb if (ret) { 29478e93258fSBjoern A. Zeeb rtw89_warn(rtwdev, "reset bdram busy\n"); 29488e93258fSBjoern A. Zeeb return ret; 29498e93258fSBjoern A. Zeeb } 29508e93258fSBjoern A. Zeeb 2951e2340276SBjoern A. Zeeb /* disable all channels except to FW CMD channel to download firmware */ 2952*6d67aabdSBjoern A. Zeeb rtw89_pci_ctrl_txdma_ch_ax(rtwdev, false); 2953*6d67aabdSBjoern A. Zeeb rtw89_pci_ctrl_txdma_fw_ch_ax(rtwdev, true); 29548e93258fSBjoern A. Zeeb 29558e93258fSBjoern A. Zeeb /* start DMA activities */ 29568e93258fSBjoern A. Zeeb rtw89_pci_ctrl_dma_all(rtwdev, true); 29578e93258fSBjoern A. Zeeb 29588e93258fSBjoern A. Zeeb return 0; 29598e93258fSBjoern A. Zeeb } 29608e93258fSBjoern A. Zeeb 29618e93258fSBjoern A. Zeeb int rtw89_pci_ltr_set(struct rtw89_dev *rtwdev, bool en) 29628e93258fSBjoern A. Zeeb { 29638e93258fSBjoern A. Zeeb u32 val; 29648e93258fSBjoern A. Zeeb 29658e93258fSBjoern A. Zeeb if (!en) 29668e93258fSBjoern A. Zeeb return 0; 29678e93258fSBjoern A. Zeeb 29688e93258fSBjoern A. Zeeb val = rtw89_read32(rtwdev, R_AX_LTR_CTRL_0); 29698e93258fSBjoern A. Zeeb if (rtw89_pci_ltr_is_err_reg_val(val)) 29708e93258fSBjoern A. Zeeb return -EINVAL; 29718e93258fSBjoern A. Zeeb val = rtw89_read32(rtwdev, R_AX_LTR_CTRL_1); 29728e93258fSBjoern A. Zeeb if (rtw89_pci_ltr_is_err_reg_val(val)) 29738e93258fSBjoern A. Zeeb return -EINVAL; 29748e93258fSBjoern A. Zeeb val = rtw89_read32(rtwdev, R_AX_LTR_IDLE_LATENCY); 29758e93258fSBjoern A. Zeeb if (rtw89_pci_ltr_is_err_reg_val(val)) 29768e93258fSBjoern A. Zeeb return -EINVAL; 29778e93258fSBjoern A. Zeeb val = rtw89_read32(rtwdev, R_AX_LTR_ACTIVE_LATENCY); 29788e93258fSBjoern A. Zeeb if (rtw89_pci_ltr_is_err_reg_val(val)) 29798e93258fSBjoern A. Zeeb return -EINVAL; 29808e93258fSBjoern A. Zeeb 2981e2340276SBjoern A. Zeeb rtw89_write32_set(rtwdev, R_AX_LTR_CTRL_0, B_AX_LTR_HW_EN | B_AX_LTR_EN | 2982e2340276SBjoern A. Zeeb B_AX_LTR_WD_NOEMP_CHK); 29838e93258fSBjoern A. Zeeb rtw89_write32_mask(rtwdev, R_AX_LTR_CTRL_0, B_AX_LTR_SPACE_IDX_MASK, 29848e93258fSBjoern A. Zeeb PCI_LTR_SPC_500US); 29858e93258fSBjoern A. Zeeb rtw89_write32_mask(rtwdev, R_AX_LTR_CTRL_0, B_AX_LTR_IDLE_TIMER_IDX_MASK, 2986e2340276SBjoern A. Zeeb PCI_LTR_IDLE_TIMER_3_2MS); 29878e93258fSBjoern A. Zeeb rtw89_write32_mask(rtwdev, R_AX_LTR_CTRL_1, B_AX_LTR_RX0_TH_MASK, 0x28); 29888e93258fSBjoern A. Zeeb rtw89_write32_mask(rtwdev, R_AX_LTR_CTRL_1, B_AX_LTR_RX1_TH_MASK, 0x28); 2989e2340276SBjoern A. Zeeb rtw89_write32(rtwdev, R_AX_LTR_IDLE_LATENCY, 0x90039003); 29908e93258fSBjoern A. Zeeb rtw89_write32(rtwdev, R_AX_LTR_ACTIVE_LATENCY, 0x880b880b); 29918e93258fSBjoern A. Zeeb 29928e93258fSBjoern A. Zeeb return 0; 29938e93258fSBjoern A. Zeeb } 29948e93258fSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_pci_ltr_set); 29958e93258fSBjoern A. Zeeb 29968e93258fSBjoern A. Zeeb int rtw89_pci_ltr_set_v1(struct rtw89_dev *rtwdev, bool en) 29978e93258fSBjoern A. Zeeb { 29988e93258fSBjoern A. Zeeb u32 dec_ctrl; 29998e93258fSBjoern A. Zeeb u32 val32; 30008e93258fSBjoern A. Zeeb 30018e93258fSBjoern A. Zeeb val32 = rtw89_read32(rtwdev, R_AX_LTR_CTRL_0); 30028e93258fSBjoern A. Zeeb if (rtw89_pci_ltr_is_err_reg_val(val32)) 30038e93258fSBjoern A. Zeeb return -EINVAL; 30048e93258fSBjoern A. Zeeb val32 = rtw89_read32(rtwdev, R_AX_LTR_CTRL_1); 30058e93258fSBjoern A. Zeeb if (rtw89_pci_ltr_is_err_reg_val(val32)) 30068e93258fSBjoern A. Zeeb return -EINVAL; 30078e93258fSBjoern A. Zeeb dec_ctrl = rtw89_read32(rtwdev, R_AX_LTR_DEC_CTRL); 30088e93258fSBjoern A. Zeeb if (rtw89_pci_ltr_is_err_reg_val(dec_ctrl)) 30098e93258fSBjoern A. Zeeb return -EINVAL; 30108e93258fSBjoern A. Zeeb val32 = rtw89_read32(rtwdev, R_AX_LTR_LATENCY_IDX3); 30118e93258fSBjoern A. Zeeb if (rtw89_pci_ltr_is_err_reg_val(val32)) 30128e93258fSBjoern A. Zeeb return -EINVAL; 30138e93258fSBjoern A. Zeeb val32 = rtw89_read32(rtwdev, R_AX_LTR_LATENCY_IDX0); 30148e93258fSBjoern A. Zeeb if (rtw89_pci_ltr_is_err_reg_val(val32)) 30158e93258fSBjoern A. Zeeb return -EINVAL; 30168e93258fSBjoern A. Zeeb 30178e93258fSBjoern A. Zeeb if (!en) { 30188e93258fSBjoern A. Zeeb dec_ctrl &= ~(LTR_EN_BITS | B_AX_LTR_IDX_DRV_MASK | B_AX_LTR_HW_DEC_EN); 30198e93258fSBjoern A. Zeeb dec_ctrl |= FIELD_PREP(B_AX_LTR_IDX_DRV_MASK, PCIE_LTR_IDX_IDLE) | 30208e93258fSBjoern A. Zeeb B_AX_LTR_REQ_DRV; 30218e93258fSBjoern A. Zeeb } else { 30228e93258fSBjoern A. Zeeb dec_ctrl |= B_AX_LTR_HW_DEC_EN; 30238e93258fSBjoern A. Zeeb } 30248e93258fSBjoern A. Zeeb 30258e93258fSBjoern A. Zeeb dec_ctrl &= ~B_AX_LTR_SPACE_IDX_V1_MASK; 30268e93258fSBjoern A. Zeeb dec_ctrl |= FIELD_PREP(B_AX_LTR_SPACE_IDX_V1_MASK, PCI_LTR_SPC_500US); 30278e93258fSBjoern A. Zeeb 30288e93258fSBjoern A. Zeeb if (en) 30298e93258fSBjoern A. Zeeb rtw89_write32_set(rtwdev, R_AX_LTR_CTRL_0, 30308e93258fSBjoern A. Zeeb B_AX_LTR_WD_NOEMP_CHK_V1 | B_AX_LTR_HW_EN); 30318e93258fSBjoern A. Zeeb rtw89_write32_mask(rtwdev, R_AX_LTR_CTRL_0, B_AX_LTR_IDLE_TIMER_IDX_MASK, 30328e93258fSBjoern A. Zeeb PCI_LTR_IDLE_TIMER_3_2MS); 30338e93258fSBjoern A. Zeeb rtw89_write32_mask(rtwdev, R_AX_LTR_CTRL_1, B_AX_LTR_RX0_TH_MASK, 0x28); 30348e93258fSBjoern A. Zeeb rtw89_write32_mask(rtwdev, R_AX_LTR_CTRL_1, B_AX_LTR_RX1_TH_MASK, 0x28); 30358e93258fSBjoern A. Zeeb rtw89_write32(rtwdev, R_AX_LTR_DEC_CTRL, dec_ctrl); 30368e93258fSBjoern A. Zeeb rtw89_write32(rtwdev, R_AX_LTR_LATENCY_IDX3, 0x90039003); 30378e93258fSBjoern A. Zeeb rtw89_write32(rtwdev, R_AX_LTR_LATENCY_IDX0, 0x880b880b); 30388e93258fSBjoern A. Zeeb 30398e93258fSBjoern A. Zeeb return 0; 30408e93258fSBjoern A. Zeeb } 30418e93258fSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_pci_ltr_set_v1); 30428e93258fSBjoern A. Zeeb 3043*6d67aabdSBjoern A. Zeeb static int rtw89_pci_ops_mac_post_init_ax(struct rtw89_dev *rtwdev) 30448e93258fSBjoern A. Zeeb { 30458e93258fSBjoern A. Zeeb const struct rtw89_pci_info *info = rtwdev->pci_info; 30468e93258fSBjoern A. Zeeb enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id; 30478e93258fSBjoern A. Zeeb int ret; 30488e93258fSBjoern A. Zeeb 30498e93258fSBjoern A. Zeeb ret = info->ltr_set(rtwdev, true); 30508e93258fSBjoern A. Zeeb if (ret) { 30518e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "pci ltr set fail\n"); 30528e93258fSBjoern A. Zeeb return ret; 30538e93258fSBjoern A. Zeeb } 30548e93258fSBjoern A. Zeeb if (chip_id == RTL8852A) { 30558e93258fSBjoern A. Zeeb /* ltr sw trigger */ 30568e93258fSBjoern A. Zeeb rtw89_write32_set(rtwdev, R_AX_LTR_CTRL_0, B_AX_APP_LTR_ACT); 30578e93258fSBjoern A. Zeeb } 3058*6d67aabdSBjoern A. Zeeb if (chip_id == RTL8852A || rtw89_is_rtl885xb(rtwdev)) { 30598e93258fSBjoern A. Zeeb /* ADDR info 8-byte mode */ 30608e93258fSBjoern A. Zeeb rtw89_write32_set(rtwdev, R_AX_TX_ADDRESS_INFO_MODE_SETTING, 30618e93258fSBjoern A. Zeeb B_AX_HOST_ADDR_INFO_8B_SEL); 30628e93258fSBjoern A. Zeeb rtw89_write32_clr(rtwdev, R_AX_PKTIN_SETTING, B_AX_WD_ADDR_INFO_LENGTH); 30638e93258fSBjoern A. Zeeb } 30648e93258fSBjoern A. Zeeb 30658e93258fSBjoern A. Zeeb /* enable DMA for all queues */ 3066*6d67aabdSBjoern A. Zeeb rtw89_pci_ctrl_txdma_ch_ax(rtwdev, true); 30678e93258fSBjoern A. Zeeb 30688e93258fSBjoern A. Zeeb /* Release PCI IO */ 3069e2340276SBjoern A. Zeeb rtw89_write32_clr(rtwdev, info->dma_stop1.addr, 30708e93258fSBjoern A. Zeeb B_AX_STOP_WPDMA | B_AX_STOP_PCIEIO); 30718e93258fSBjoern A. Zeeb 30728e93258fSBjoern A. Zeeb return 0; 30738e93258fSBjoern A. Zeeb } 30748e93258fSBjoern A. Zeeb 30758e93258fSBjoern A. Zeeb static int rtw89_pci_claim_device(struct rtw89_dev *rtwdev, 30768e93258fSBjoern A. Zeeb struct pci_dev *pdev) 30778e93258fSBjoern A. Zeeb { 30788e93258fSBjoern A. Zeeb struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; 30798e93258fSBjoern A. Zeeb int ret; 30808e93258fSBjoern A. Zeeb 30818e93258fSBjoern A. Zeeb ret = pci_enable_device(pdev); 30828e93258fSBjoern A. Zeeb if (ret) { 30838e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "failed to enable pci device\n"); 30848e93258fSBjoern A. Zeeb return ret; 30858e93258fSBjoern A. Zeeb } 30868e93258fSBjoern A. Zeeb 30878e93258fSBjoern A. Zeeb pci_set_master(pdev); 30888e93258fSBjoern A. Zeeb pci_set_drvdata(pdev, rtwdev->hw); 30898e93258fSBjoern A. Zeeb 30908e93258fSBjoern A. Zeeb rtwpci->pdev = pdev; 30918e93258fSBjoern A. Zeeb 30928e93258fSBjoern A. Zeeb return 0; 30938e93258fSBjoern A. Zeeb } 30948e93258fSBjoern A. Zeeb 30958e93258fSBjoern A. Zeeb static void rtw89_pci_declaim_device(struct rtw89_dev *rtwdev, 30968e93258fSBjoern A. Zeeb struct pci_dev *pdev) 30978e93258fSBjoern A. Zeeb { 30988e93258fSBjoern A. Zeeb pci_disable_device(pdev); 30998e93258fSBjoern A. Zeeb } 31008e93258fSBjoern A. Zeeb 3101*6d67aabdSBjoern A. Zeeb static void rtw89_pci_cfg_dac(struct rtw89_dev *rtwdev) 3102*6d67aabdSBjoern A. Zeeb { 3103*6d67aabdSBjoern A. Zeeb struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; 3104*6d67aabdSBjoern A. Zeeb const struct rtw89_chip_info *chip = rtwdev->chip; 3105*6d67aabdSBjoern A. Zeeb 3106*6d67aabdSBjoern A. Zeeb if (!rtwpci->enable_dac) 3107*6d67aabdSBjoern A. Zeeb return; 3108*6d67aabdSBjoern A. Zeeb 3109*6d67aabdSBjoern A. Zeeb switch (chip->chip_id) { 3110*6d67aabdSBjoern A. Zeeb case RTL8852A: 3111*6d67aabdSBjoern A. Zeeb case RTL8852B: 3112*6d67aabdSBjoern A. Zeeb case RTL8851B: 3113*6d67aabdSBjoern A. Zeeb case RTL8852BT: 3114*6d67aabdSBjoern A. Zeeb break; 3115*6d67aabdSBjoern A. Zeeb default: 3116*6d67aabdSBjoern A. Zeeb return; 3117*6d67aabdSBjoern A. Zeeb } 3118*6d67aabdSBjoern A. Zeeb 3119*6d67aabdSBjoern A. Zeeb rtw89_pci_config_byte_set(rtwdev, RTW89_PCIE_L1_CTRL, RTW89_PCIE_BIT_EN_64BITS); 3120*6d67aabdSBjoern A. Zeeb } 3121*6d67aabdSBjoern A. Zeeb 31228e93258fSBjoern A. Zeeb static int rtw89_pci_setup_mapping(struct rtw89_dev *rtwdev, 31238e93258fSBjoern A. Zeeb struct pci_dev *pdev) 31248e93258fSBjoern A. Zeeb { 31258e93258fSBjoern A. Zeeb struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; 31268e93258fSBjoern A. Zeeb unsigned long resource_len; 31278e93258fSBjoern A. Zeeb u8 bar_id = 2; 31288e93258fSBjoern A. Zeeb int ret; 31298e93258fSBjoern A. Zeeb 31308e93258fSBjoern A. Zeeb ret = pci_request_regions(pdev, KBUILD_MODNAME); 31318e93258fSBjoern A. Zeeb if (ret) { 31328e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "failed to request pci regions\n"); 31338e93258fSBjoern A. Zeeb goto err; 31348e93258fSBjoern A. Zeeb } 31358e93258fSBjoern A. Zeeb 3136*6d67aabdSBjoern A. Zeeb ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(36)); 3137*6d67aabdSBjoern A. Zeeb if (!ret) { 3138*6d67aabdSBjoern A. Zeeb rtwpci->enable_dac = true; 3139*6d67aabdSBjoern A. Zeeb rtw89_pci_cfg_dac(rtwdev); 3140*6d67aabdSBjoern A. Zeeb } else { 3141*6d67aabdSBjoern A. Zeeb ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); 31428e93258fSBjoern A. Zeeb if (ret) { 3143*6d67aabdSBjoern A. Zeeb rtw89_err(rtwdev, 3144*6d67aabdSBjoern A. Zeeb "failed to set dma and consistent mask to 32/36-bit\n"); 31458e93258fSBjoern A. Zeeb goto err_release_regions; 31468e93258fSBjoern A. Zeeb } 31478e93258fSBjoern A. Zeeb } 31488e93258fSBjoern A. Zeeb 31498e93258fSBjoern A. Zeeb #if defined(__FreeBSD__) 31508e93258fSBjoern A. Zeeb linuxkpi_pcim_want_to_use_bus_functions(pdev); 31518e93258fSBjoern A. Zeeb #endif 31528e93258fSBjoern A. Zeeb resource_len = pci_resource_len(pdev, bar_id); 31538e93258fSBjoern A. Zeeb rtwpci->mmap = pci_iomap(pdev, bar_id, resource_len); 31548e93258fSBjoern A. Zeeb if (!rtwpci->mmap) { 31558e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "failed to map pci io\n"); 31568e93258fSBjoern A. Zeeb ret = -EIO; 31578e93258fSBjoern A. Zeeb goto err_release_regions; 31588e93258fSBjoern A. Zeeb } 31598e93258fSBjoern A. Zeeb 31608e93258fSBjoern A. Zeeb return 0; 31618e93258fSBjoern A. Zeeb 31628e93258fSBjoern A. Zeeb err_release_regions: 31638e93258fSBjoern A. Zeeb pci_release_regions(pdev); 31648e93258fSBjoern A. Zeeb err: 31658e93258fSBjoern A. Zeeb return ret; 31668e93258fSBjoern A. Zeeb } 31678e93258fSBjoern A. Zeeb 31688e93258fSBjoern A. Zeeb static void rtw89_pci_clear_mapping(struct rtw89_dev *rtwdev, 31698e93258fSBjoern A. Zeeb struct pci_dev *pdev) 31708e93258fSBjoern A. Zeeb { 31718e93258fSBjoern A. Zeeb struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; 31728e93258fSBjoern A. Zeeb 31738e93258fSBjoern A. Zeeb if (rtwpci->mmap) { 31748e93258fSBjoern A. Zeeb pci_iounmap(pdev, rtwpci->mmap); 31758e93258fSBjoern A. Zeeb pci_release_regions(pdev); 31768e93258fSBjoern A. Zeeb } 31778e93258fSBjoern A. Zeeb } 31788e93258fSBjoern A. Zeeb 31798e93258fSBjoern A. Zeeb static void rtw89_pci_free_tx_wd_ring(struct rtw89_dev *rtwdev, 31808e93258fSBjoern A. Zeeb struct pci_dev *pdev, 31818e93258fSBjoern A. Zeeb struct rtw89_pci_tx_ring *tx_ring) 31828e93258fSBjoern A. Zeeb { 31838e93258fSBjoern A. Zeeb struct rtw89_pci_tx_wd_ring *wd_ring = &tx_ring->wd_ring; 31848e93258fSBjoern A. Zeeb u8 *head = wd_ring->head; 31858e93258fSBjoern A. Zeeb dma_addr_t dma = wd_ring->dma; 31868e93258fSBjoern A. Zeeb u32 page_size = wd_ring->page_size; 31878e93258fSBjoern A. Zeeb u32 page_num = wd_ring->page_num; 31888e93258fSBjoern A. Zeeb u32 ring_sz = page_size * page_num; 31898e93258fSBjoern A. Zeeb 31908e93258fSBjoern A. Zeeb dma_free_coherent(&pdev->dev, ring_sz, head, dma); 31918e93258fSBjoern A. Zeeb wd_ring->head = NULL; 31928e93258fSBjoern A. Zeeb } 31938e93258fSBjoern A. Zeeb 31948e93258fSBjoern A. Zeeb static void rtw89_pci_free_tx_ring(struct rtw89_dev *rtwdev, 31958e93258fSBjoern A. Zeeb struct pci_dev *pdev, 31968e93258fSBjoern A. Zeeb struct rtw89_pci_tx_ring *tx_ring) 31978e93258fSBjoern A. Zeeb { 31988e93258fSBjoern A. Zeeb int ring_sz; 31998e93258fSBjoern A. Zeeb u8 *head; 32008e93258fSBjoern A. Zeeb dma_addr_t dma; 32018e93258fSBjoern A. Zeeb 32028e93258fSBjoern A. Zeeb head = tx_ring->bd_ring.head; 32038e93258fSBjoern A. Zeeb dma = tx_ring->bd_ring.dma; 32048e93258fSBjoern A. Zeeb ring_sz = tx_ring->bd_ring.desc_size * tx_ring->bd_ring.len; 32058e93258fSBjoern A. Zeeb dma_free_coherent(&pdev->dev, ring_sz, head, dma); 32068e93258fSBjoern A. Zeeb 32078e93258fSBjoern A. Zeeb tx_ring->bd_ring.head = NULL; 32088e93258fSBjoern A. Zeeb } 32098e93258fSBjoern A. Zeeb 32108e93258fSBjoern A. Zeeb static void rtw89_pci_free_tx_rings(struct rtw89_dev *rtwdev, 32118e93258fSBjoern A. Zeeb struct pci_dev *pdev) 32128e93258fSBjoern A. Zeeb { 32138e93258fSBjoern A. Zeeb struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; 3214e2340276SBjoern A. Zeeb const struct rtw89_pci_info *info = rtwdev->pci_info; 32158e93258fSBjoern A. Zeeb struct rtw89_pci_tx_ring *tx_ring; 32168e93258fSBjoern A. Zeeb int i; 32178e93258fSBjoern A. Zeeb 32188e93258fSBjoern A. Zeeb for (i = 0; i < RTW89_TXCH_NUM; i++) { 3219e2340276SBjoern A. Zeeb if (info->tx_dma_ch_mask & BIT(i)) 3220e2340276SBjoern A. Zeeb continue; 32218e93258fSBjoern A. Zeeb tx_ring = &rtwpci->tx_rings[i]; 32228e93258fSBjoern A. Zeeb rtw89_pci_free_tx_wd_ring(rtwdev, pdev, tx_ring); 32238e93258fSBjoern A. Zeeb rtw89_pci_free_tx_ring(rtwdev, pdev, tx_ring); 32248e93258fSBjoern A. Zeeb } 32258e93258fSBjoern A. Zeeb } 32268e93258fSBjoern A. Zeeb 32278e93258fSBjoern A. Zeeb static void rtw89_pci_free_rx_ring(struct rtw89_dev *rtwdev, 32288e93258fSBjoern A. Zeeb struct pci_dev *pdev, 32298e93258fSBjoern A. Zeeb struct rtw89_pci_rx_ring *rx_ring) 32308e93258fSBjoern A. Zeeb { 32318e93258fSBjoern A. Zeeb struct rtw89_pci_rx_info *rx_info; 32328e93258fSBjoern A. Zeeb struct sk_buff *skb; 32338e93258fSBjoern A. Zeeb dma_addr_t dma; 32348e93258fSBjoern A. Zeeb u32 buf_sz; 32358e93258fSBjoern A. Zeeb u8 *head; 32368e93258fSBjoern A. Zeeb int ring_sz = rx_ring->bd_ring.desc_size * rx_ring->bd_ring.len; 32378e93258fSBjoern A. Zeeb int i; 32388e93258fSBjoern A. Zeeb 32398e93258fSBjoern A. Zeeb buf_sz = rx_ring->buf_sz; 32408e93258fSBjoern A. Zeeb for (i = 0; i < rx_ring->bd_ring.len; i++) { 32418e93258fSBjoern A. Zeeb skb = rx_ring->buf[i]; 32428e93258fSBjoern A. Zeeb if (!skb) 32438e93258fSBjoern A. Zeeb continue; 32448e93258fSBjoern A. Zeeb 32458e93258fSBjoern A. Zeeb rx_info = RTW89_PCI_RX_SKB_CB(skb); 32468e93258fSBjoern A. Zeeb dma = rx_info->dma; 32478e93258fSBjoern A. Zeeb dma_unmap_single(&pdev->dev, dma, buf_sz, DMA_FROM_DEVICE); 32488e93258fSBjoern A. Zeeb dev_kfree_skb(skb); 32498e93258fSBjoern A. Zeeb rx_ring->buf[i] = NULL; 32508e93258fSBjoern A. Zeeb } 32518e93258fSBjoern A. Zeeb 32528e93258fSBjoern A. Zeeb head = rx_ring->bd_ring.head; 32538e93258fSBjoern A. Zeeb dma = rx_ring->bd_ring.dma; 32548e93258fSBjoern A. Zeeb dma_free_coherent(&pdev->dev, ring_sz, head, dma); 32558e93258fSBjoern A. Zeeb 32568e93258fSBjoern A. Zeeb rx_ring->bd_ring.head = NULL; 32578e93258fSBjoern A. Zeeb } 32588e93258fSBjoern A. Zeeb 32598e93258fSBjoern A. Zeeb static void rtw89_pci_free_rx_rings(struct rtw89_dev *rtwdev, 32608e93258fSBjoern A. Zeeb struct pci_dev *pdev) 32618e93258fSBjoern A. Zeeb { 32628e93258fSBjoern A. Zeeb struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; 32638e93258fSBjoern A. Zeeb struct rtw89_pci_rx_ring *rx_ring; 32648e93258fSBjoern A. Zeeb int i; 32658e93258fSBjoern A. Zeeb 32668e93258fSBjoern A. Zeeb for (i = 0; i < RTW89_RXCH_NUM; i++) { 32678e93258fSBjoern A. Zeeb rx_ring = &rtwpci->rx_rings[i]; 32688e93258fSBjoern A. Zeeb rtw89_pci_free_rx_ring(rtwdev, pdev, rx_ring); 32698e93258fSBjoern A. Zeeb } 32708e93258fSBjoern A. Zeeb } 32718e93258fSBjoern A. Zeeb 32728e93258fSBjoern A. Zeeb static void rtw89_pci_free_trx_rings(struct rtw89_dev *rtwdev, 32738e93258fSBjoern A. Zeeb struct pci_dev *pdev) 32748e93258fSBjoern A. Zeeb { 32758e93258fSBjoern A. Zeeb rtw89_pci_free_rx_rings(rtwdev, pdev); 32768e93258fSBjoern A. Zeeb rtw89_pci_free_tx_rings(rtwdev, pdev); 32778e93258fSBjoern A. Zeeb } 32788e93258fSBjoern A. Zeeb 32798e93258fSBjoern A. Zeeb static int rtw89_pci_init_rx_bd(struct rtw89_dev *rtwdev, struct pci_dev *pdev, 32808e93258fSBjoern A. Zeeb struct rtw89_pci_rx_ring *rx_ring, 32818e93258fSBjoern A. Zeeb struct sk_buff *skb, int buf_sz, u32 idx) 32828e93258fSBjoern A. Zeeb { 32838e93258fSBjoern A. Zeeb struct rtw89_pci_rx_info *rx_info; 32848e93258fSBjoern A. Zeeb struct rtw89_pci_rx_bd_32 *rx_bd; 32858e93258fSBjoern A. Zeeb dma_addr_t dma; 32868e93258fSBjoern A. Zeeb 32878e93258fSBjoern A. Zeeb if (!skb) 32888e93258fSBjoern A. Zeeb return -EINVAL; 32898e93258fSBjoern A. Zeeb 32908e93258fSBjoern A. Zeeb dma = dma_map_single(&pdev->dev, skb->data, buf_sz, DMA_FROM_DEVICE); 32918e93258fSBjoern A. Zeeb if (dma_mapping_error(&pdev->dev, dma)) 32928e93258fSBjoern A. Zeeb return -EBUSY; 32938e93258fSBjoern A. Zeeb 32948e93258fSBjoern A. Zeeb rx_info = RTW89_PCI_RX_SKB_CB(skb); 32958e93258fSBjoern A. Zeeb rx_bd = RTW89_PCI_RX_BD(rx_ring, idx); 32968e93258fSBjoern A. Zeeb 32978e93258fSBjoern A. Zeeb memset(rx_bd, 0, sizeof(*rx_bd)); 32988e93258fSBjoern A. Zeeb rx_bd->buf_size = cpu_to_le16(buf_sz); 32998e93258fSBjoern A. Zeeb rx_bd->dma = cpu_to_le32(dma); 3300*6d67aabdSBjoern A. Zeeb rx_bd->opt = le16_encode_bits(upper_32_bits(dma), RTW89_PCI_RXBD_OPT_DMA_HI); 33018e93258fSBjoern A. Zeeb rx_info->dma = dma; 33028e93258fSBjoern A. Zeeb 33038e93258fSBjoern A. Zeeb return 0; 33048e93258fSBjoern A. Zeeb } 33058e93258fSBjoern A. Zeeb 33068e93258fSBjoern A. Zeeb static int rtw89_pci_alloc_tx_wd_ring(struct rtw89_dev *rtwdev, 33078e93258fSBjoern A. Zeeb struct pci_dev *pdev, 33088e93258fSBjoern A. Zeeb struct rtw89_pci_tx_ring *tx_ring, 33098e93258fSBjoern A. Zeeb enum rtw89_tx_channel txch) 33108e93258fSBjoern A. Zeeb { 33118e93258fSBjoern A. Zeeb struct rtw89_pci_tx_wd_ring *wd_ring = &tx_ring->wd_ring; 33128e93258fSBjoern A. Zeeb struct rtw89_pci_tx_wd *txwd; 33138e93258fSBjoern A. Zeeb dma_addr_t dma; 33148e93258fSBjoern A. Zeeb dma_addr_t cur_paddr; 33158e93258fSBjoern A. Zeeb u8 *head; 33168e93258fSBjoern A. Zeeb u8 *cur_vaddr; 33178e93258fSBjoern A. Zeeb u32 page_size = RTW89_PCI_TXWD_PAGE_SIZE; 33188e93258fSBjoern A. Zeeb u32 page_num = RTW89_PCI_TXWD_NUM_MAX; 33198e93258fSBjoern A. Zeeb u32 ring_sz = page_size * page_num; 33208e93258fSBjoern A. Zeeb u32 page_offset; 33218e93258fSBjoern A. Zeeb int i; 33228e93258fSBjoern A. Zeeb 33238e93258fSBjoern A. Zeeb /* FWCMD queue doesn't use txwd as pages */ 33248e93258fSBjoern A. Zeeb if (txch == RTW89_TXCH_CH12) 33258e93258fSBjoern A. Zeeb return 0; 33268e93258fSBjoern A. Zeeb 33278e93258fSBjoern A. Zeeb head = dma_alloc_coherent(&pdev->dev, ring_sz, &dma, GFP_KERNEL); 33288e93258fSBjoern A. Zeeb if (!head) 33298e93258fSBjoern A. Zeeb return -ENOMEM; 33308e93258fSBjoern A. Zeeb 33318e93258fSBjoern A. Zeeb INIT_LIST_HEAD(&wd_ring->free_pages); 33328e93258fSBjoern A. Zeeb wd_ring->head = head; 33338e93258fSBjoern A. Zeeb wd_ring->dma = dma; 33348e93258fSBjoern A. Zeeb wd_ring->page_size = page_size; 33358e93258fSBjoern A. Zeeb wd_ring->page_num = page_num; 33368e93258fSBjoern A. Zeeb 33378e93258fSBjoern A. Zeeb page_offset = 0; 33388e93258fSBjoern A. Zeeb for (i = 0; i < page_num; i++) { 33398e93258fSBjoern A. Zeeb txwd = &wd_ring->pages[i]; 33408e93258fSBjoern A. Zeeb cur_paddr = dma + page_offset; 33418e93258fSBjoern A. Zeeb cur_vaddr = head + page_offset; 33428e93258fSBjoern A. Zeeb 33438e93258fSBjoern A. Zeeb skb_queue_head_init(&txwd->queue); 33448e93258fSBjoern A. Zeeb INIT_LIST_HEAD(&txwd->list); 33458e93258fSBjoern A. Zeeb txwd->paddr = cur_paddr; 33468e93258fSBjoern A. Zeeb txwd->vaddr = cur_vaddr; 33478e93258fSBjoern A. Zeeb txwd->len = page_size; 33488e93258fSBjoern A. Zeeb txwd->seq = i; 33498e93258fSBjoern A. Zeeb rtw89_pci_enqueue_txwd(tx_ring, txwd); 33508e93258fSBjoern A. Zeeb 33518e93258fSBjoern A. Zeeb page_offset += page_size; 33528e93258fSBjoern A. Zeeb } 33538e93258fSBjoern A. Zeeb 33548e93258fSBjoern A. Zeeb return 0; 33558e93258fSBjoern A. Zeeb } 33568e93258fSBjoern A. Zeeb 33578e93258fSBjoern A. Zeeb static int rtw89_pci_alloc_tx_ring(struct rtw89_dev *rtwdev, 33588e93258fSBjoern A. Zeeb struct pci_dev *pdev, 33598e93258fSBjoern A. Zeeb struct rtw89_pci_tx_ring *tx_ring, 33608e93258fSBjoern A. Zeeb u32 desc_size, u32 len, 33618e93258fSBjoern A. Zeeb enum rtw89_tx_channel txch) 33628e93258fSBjoern A. Zeeb { 33638e93258fSBjoern A. Zeeb const struct rtw89_pci_ch_dma_addr *txch_addr; 33648e93258fSBjoern A. Zeeb int ring_sz = desc_size * len; 33658e93258fSBjoern A. Zeeb u8 *head; 33668e93258fSBjoern A. Zeeb dma_addr_t dma; 33678e93258fSBjoern A. Zeeb int ret; 33688e93258fSBjoern A. Zeeb 33698e93258fSBjoern A. Zeeb ret = rtw89_pci_alloc_tx_wd_ring(rtwdev, pdev, tx_ring, txch); 33708e93258fSBjoern A. Zeeb if (ret) { 33718e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "failed to alloc txwd ring of txch %d\n", txch); 33728e93258fSBjoern A. Zeeb goto err; 33738e93258fSBjoern A. Zeeb } 33748e93258fSBjoern A. Zeeb 33758e93258fSBjoern A. Zeeb ret = rtw89_pci_get_txch_addrs(rtwdev, txch, &txch_addr); 33768e93258fSBjoern A. Zeeb if (ret) { 33778e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "failed to get address of txch %d", txch); 33788e93258fSBjoern A. Zeeb goto err_free_wd_ring; 33798e93258fSBjoern A. Zeeb } 33808e93258fSBjoern A. Zeeb 33818e93258fSBjoern A. Zeeb head = dma_alloc_coherent(&pdev->dev, ring_sz, &dma, GFP_KERNEL); 33828e93258fSBjoern A. Zeeb if (!head) { 33838e93258fSBjoern A. Zeeb ret = -ENOMEM; 33848e93258fSBjoern A. Zeeb goto err_free_wd_ring; 33858e93258fSBjoern A. Zeeb } 33868e93258fSBjoern A. Zeeb 33878e93258fSBjoern A. Zeeb INIT_LIST_HEAD(&tx_ring->busy_pages); 33888e93258fSBjoern A. Zeeb tx_ring->bd_ring.head = head; 33898e93258fSBjoern A. Zeeb tx_ring->bd_ring.dma = dma; 33908e93258fSBjoern A. Zeeb tx_ring->bd_ring.len = len; 33918e93258fSBjoern A. Zeeb tx_ring->bd_ring.desc_size = desc_size; 33928e93258fSBjoern A. Zeeb tx_ring->bd_ring.addr = *txch_addr; 33938e93258fSBjoern A. Zeeb tx_ring->bd_ring.wp = 0; 33948e93258fSBjoern A. Zeeb tx_ring->bd_ring.rp = 0; 33958e93258fSBjoern A. Zeeb tx_ring->txch = txch; 33968e93258fSBjoern A. Zeeb 33978e93258fSBjoern A. Zeeb return 0; 33988e93258fSBjoern A. Zeeb 33998e93258fSBjoern A. Zeeb err_free_wd_ring: 34008e93258fSBjoern A. Zeeb rtw89_pci_free_tx_wd_ring(rtwdev, pdev, tx_ring); 34018e93258fSBjoern A. Zeeb err: 34028e93258fSBjoern A. Zeeb return ret; 34038e93258fSBjoern A. Zeeb } 34048e93258fSBjoern A. Zeeb 34058e93258fSBjoern A. Zeeb static int rtw89_pci_alloc_tx_rings(struct rtw89_dev *rtwdev, 34068e93258fSBjoern A. Zeeb struct pci_dev *pdev) 34078e93258fSBjoern A. Zeeb { 34088e93258fSBjoern A. Zeeb struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; 3409e2340276SBjoern A. Zeeb const struct rtw89_pci_info *info = rtwdev->pci_info; 34108e93258fSBjoern A. Zeeb struct rtw89_pci_tx_ring *tx_ring; 34118e93258fSBjoern A. Zeeb u32 desc_size; 34128e93258fSBjoern A. Zeeb u32 len; 34138e93258fSBjoern A. Zeeb u32 i, tx_allocated; 34148e93258fSBjoern A. Zeeb int ret; 34158e93258fSBjoern A. Zeeb 34168e93258fSBjoern A. Zeeb for (i = 0; i < RTW89_TXCH_NUM; i++) { 3417e2340276SBjoern A. Zeeb if (info->tx_dma_ch_mask & BIT(i)) 3418e2340276SBjoern A. Zeeb continue; 34198e93258fSBjoern A. Zeeb tx_ring = &rtwpci->tx_rings[i]; 34208e93258fSBjoern A. Zeeb desc_size = sizeof(struct rtw89_pci_tx_bd_32); 34218e93258fSBjoern A. Zeeb len = RTW89_PCI_TXBD_NUM_MAX; 34228e93258fSBjoern A. Zeeb ret = rtw89_pci_alloc_tx_ring(rtwdev, pdev, tx_ring, 34238e93258fSBjoern A. Zeeb desc_size, len, i); 34248e93258fSBjoern A. Zeeb if (ret) { 34258e93258fSBjoern A. Zeeb #if defined(__linux__) 34268e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "failed to alloc tx ring %d\n", i); 34278e93258fSBjoern A. Zeeb #elif defined(__FreeBSD__) 34288e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "failed to alloc tx ring %d: ret=%d\n", i, ret); 34298e93258fSBjoern A. Zeeb #endif 34308e93258fSBjoern A. Zeeb goto err_free; 34318e93258fSBjoern A. Zeeb } 34328e93258fSBjoern A. Zeeb } 34338e93258fSBjoern A. Zeeb 34348e93258fSBjoern A. Zeeb return 0; 34358e93258fSBjoern A. Zeeb 34368e93258fSBjoern A. Zeeb err_free: 34378e93258fSBjoern A. Zeeb tx_allocated = i; 34388e93258fSBjoern A. Zeeb for (i = 0; i < tx_allocated; i++) { 34398e93258fSBjoern A. Zeeb tx_ring = &rtwpci->tx_rings[i]; 34408e93258fSBjoern A. Zeeb rtw89_pci_free_tx_ring(rtwdev, pdev, tx_ring); 34418e93258fSBjoern A. Zeeb } 34428e93258fSBjoern A. Zeeb 34438e93258fSBjoern A. Zeeb return ret; 34448e93258fSBjoern A. Zeeb } 34458e93258fSBjoern A. Zeeb 34468e93258fSBjoern A. Zeeb static int rtw89_pci_alloc_rx_ring(struct rtw89_dev *rtwdev, 34478e93258fSBjoern A. Zeeb struct pci_dev *pdev, 34488e93258fSBjoern A. Zeeb struct rtw89_pci_rx_ring *rx_ring, 34498e93258fSBjoern A. Zeeb u32 desc_size, u32 len, u32 rxch) 34508e93258fSBjoern A. Zeeb { 3451*6d67aabdSBjoern A. Zeeb const struct rtw89_pci_info *info = rtwdev->pci_info; 34528e93258fSBjoern A. Zeeb const struct rtw89_pci_ch_dma_addr *rxch_addr; 34538e93258fSBjoern A. Zeeb struct sk_buff *skb; 34548e93258fSBjoern A. Zeeb u8 *head; 34558e93258fSBjoern A. Zeeb dma_addr_t dma; 34568e93258fSBjoern A. Zeeb int ring_sz = desc_size * len; 34578e93258fSBjoern A. Zeeb int buf_sz = RTW89_PCI_RX_BUF_SIZE; 34588e93258fSBjoern A. Zeeb int i, allocated; 34598e93258fSBjoern A. Zeeb int ret; 34608e93258fSBjoern A. Zeeb 34618e93258fSBjoern A. Zeeb ret = rtw89_pci_get_rxch_addrs(rtwdev, rxch, &rxch_addr); 34628e93258fSBjoern A. Zeeb if (ret) { 34638e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "failed to get address of rxch %d", rxch); 34648e93258fSBjoern A. Zeeb return ret; 34658e93258fSBjoern A. Zeeb } 34668e93258fSBjoern A. Zeeb 34678e93258fSBjoern A. Zeeb head = dma_alloc_coherent(&pdev->dev, ring_sz, &dma, GFP_KERNEL); 34688e93258fSBjoern A. Zeeb if (!head) { 34698e93258fSBjoern A. Zeeb ret = -ENOMEM; 34708e93258fSBjoern A. Zeeb goto err; 34718e93258fSBjoern A. Zeeb } 34728e93258fSBjoern A. Zeeb 34738e93258fSBjoern A. Zeeb rx_ring->bd_ring.head = head; 34748e93258fSBjoern A. Zeeb rx_ring->bd_ring.dma = dma; 34758e93258fSBjoern A. Zeeb rx_ring->bd_ring.len = len; 34768e93258fSBjoern A. Zeeb rx_ring->bd_ring.desc_size = desc_size; 34778e93258fSBjoern A. Zeeb rx_ring->bd_ring.addr = *rxch_addr; 3478*6d67aabdSBjoern A. Zeeb if (info->rx_ring_eq_is_full) 3479*6d67aabdSBjoern A. Zeeb rx_ring->bd_ring.wp = len - 1; 3480*6d67aabdSBjoern A. Zeeb else 34818e93258fSBjoern A. Zeeb rx_ring->bd_ring.wp = 0; 34828e93258fSBjoern A. Zeeb rx_ring->bd_ring.rp = 0; 34838e93258fSBjoern A. Zeeb rx_ring->buf_sz = buf_sz; 34848e93258fSBjoern A. Zeeb rx_ring->diliver_skb = NULL; 34858e93258fSBjoern A. Zeeb rx_ring->diliver_desc.ready = false; 3486*6d67aabdSBjoern A. Zeeb rx_ring->target_rx_tag = 0; 34878e93258fSBjoern A. Zeeb 34888e93258fSBjoern A. Zeeb for (i = 0; i < len; i++) { 34898e93258fSBjoern A. Zeeb skb = dev_alloc_skb(buf_sz); 34908e93258fSBjoern A. Zeeb if (!skb) { 34918e93258fSBjoern A. Zeeb ret = -ENOMEM; 34928e93258fSBjoern A. Zeeb goto err_free; 34938e93258fSBjoern A. Zeeb } 34948e93258fSBjoern A. Zeeb 34958e93258fSBjoern A. Zeeb memset(skb->data, 0, buf_sz); 34968e93258fSBjoern A. Zeeb rx_ring->buf[i] = skb; 34978e93258fSBjoern A. Zeeb ret = rtw89_pci_init_rx_bd(rtwdev, pdev, rx_ring, skb, 34988e93258fSBjoern A. Zeeb buf_sz, i); 34998e93258fSBjoern A. Zeeb if (ret) { 35008e93258fSBjoern A. Zeeb #if defined(__linux__) 35018e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "failed to init rx buf %d\n", i); 35028e93258fSBjoern A. Zeeb #elif defined(__FreeBSD__) 35038e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "failed to init rx buf %d ret=%d\n", i, ret); 35048e93258fSBjoern A. Zeeb #endif 35058e93258fSBjoern A. Zeeb dev_kfree_skb_any(skb); 35068e93258fSBjoern A. Zeeb rx_ring->buf[i] = NULL; 35078e93258fSBjoern A. Zeeb goto err_free; 35088e93258fSBjoern A. Zeeb } 35098e93258fSBjoern A. Zeeb } 35108e93258fSBjoern A. Zeeb 35118e93258fSBjoern A. Zeeb return 0; 35128e93258fSBjoern A. Zeeb 35138e93258fSBjoern A. Zeeb err_free: 35148e93258fSBjoern A. Zeeb allocated = i; 35158e93258fSBjoern A. Zeeb for (i = 0; i < allocated; i++) { 35168e93258fSBjoern A. Zeeb skb = rx_ring->buf[i]; 35178e93258fSBjoern A. Zeeb if (!skb) 35188e93258fSBjoern A. Zeeb continue; 35198e93258fSBjoern A. Zeeb dma = *((dma_addr_t *)skb->cb); 35208e93258fSBjoern A. Zeeb dma_unmap_single(&pdev->dev, dma, buf_sz, DMA_FROM_DEVICE); 35218e93258fSBjoern A. Zeeb dev_kfree_skb(skb); 35228e93258fSBjoern A. Zeeb rx_ring->buf[i] = NULL; 35238e93258fSBjoern A. Zeeb } 35248e93258fSBjoern A. Zeeb 35258e93258fSBjoern A. Zeeb head = rx_ring->bd_ring.head; 35268e93258fSBjoern A. Zeeb dma = rx_ring->bd_ring.dma; 35278e93258fSBjoern A. Zeeb dma_free_coherent(&pdev->dev, ring_sz, head, dma); 35288e93258fSBjoern A. Zeeb 35298e93258fSBjoern A. Zeeb rx_ring->bd_ring.head = NULL; 35308e93258fSBjoern A. Zeeb err: 35318e93258fSBjoern A. Zeeb return ret; 35328e93258fSBjoern A. Zeeb } 35338e93258fSBjoern A. Zeeb 35348e93258fSBjoern A. Zeeb static int rtw89_pci_alloc_rx_rings(struct rtw89_dev *rtwdev, 35358e93258fSBjoern A. Zeeb struct pci_dev *pdev) 35368e93258fSBjoern A. Zeeb { 35378e93258fSBjoern A. Zeeb struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; 35388e93258fSBjoern A. Zeeb struct rtw89_pci_rx_ring *rx_ring; 35398e93258fSBjoern A. Zeeb u32 desc_size; 35408e93258fSBjoern A. Zeeb u32 len; 35418e93258fSBjoern A. Zeeb int i, rx_allocated; 35428e93258fSBjoern A. Zeeb int ret; 35438e93258fSBjoern A. Zeeb 35448e93258fSBjoern A. Zeeb for (i = 0; i < RTW89_RXCH_NUM; i++) { 35458e93258fSBjoern A. Zeeb rx_ring = &rtwpci->rx_rings[i]; 35468e93258fSBjoern A. Zeeb desc_size = sizeof(struct rtw89_pci_rx_bd_32); 35478e93258fSBjoern A. Zeeb len = RTW89_PCI_RXBD_NUM_MAX; 35488e93258fSBjoern A. Zeeb ret = rtw89_pci_alloc_rx_ring(rtwdev, pdev, rx_ring, 35498e93258fSBjoern A. Zeeb desc_size, len, i); 35508e93258fSBjoern A. Zeeb if (ret) { 35518e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "failed to alloc rx ring %d\n", i); 35528e93258fSBjoern A. Zeeb goto err_free; 35538e93258fSBjoern A. Zeeb } 35548e93258fSBjoern A. Zeeb } 35558e93258fSBjoern A. Zeeb 35568e93258fSBjoern A. Zeeb return 0; 35578e93258fSBjoern A. Zeeb 35588e93258fSBjoern A. Zeeb err_free: 35598e93258fSBjoern A. Zeeb rx_allocated = i; 35608e93258fSBjoern A. Zeeb for (i = 0; i < rx_allocated; i++) { 35618e93258fSBjoern A. Zeeb rx_ring = &rtwpci->rx_rings[i]; 35628e93258fSBjoern A. Zeeb rtw89_pci_free_rx_ring(rtwdev, pdev, rx_ring); 35638e93258fSBjoern A. Zeeb } 35648e93258fSBjoern A. Zeeb 35658e93258fSBjoern A. Zeeb return ret; 35668e93258fSBjoern A. Zeeb } 35678e93258fSBjoern A. Zeeb 35688e93258fSBjoern A. Zeeb static int rtw89_pci_alloc_trx_rings(struct rtw89_dev *rtwdev, 35698e93258fSBjoern A. Zeeb struct pci_dev *pdev) 35708e93258fSBjoern A. Zeeb { 35718e93258fSBjoern A. Zeeb int ret; 35728e93258fSBjoern A. Zeeb 35738e93258fSBjoern A. Zeeb ret = rtw89_pci_alloc_tx_rings(rtwdev, pdev); 35748e93258fSBjoern A. Zeeb if (ret) { 35758e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "failed to alloc dma tx rings\n"); 35768e93258fSBjoern A. Zeeb goto err; 35778e93258fSBjoern A. Zeeb } 35788e93258fSBjoern A. Zeeb 35798e93258fSBjoern A. Zeeb ret = rtw89_pci_alloc_rx_rings(rtwdev, pdev); 35808e93258fSBjoern A. Zeeb if (ret) { 35818e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "failed to alloc dma rx rings\n"); 35828e93258fSBjoern A. Zeeb goto err_free_tx_rings; 35838e93258fSBjoern A. Zeeb } 35848e93258fSBjoern A. Zeeb 35858e93258fSBjoern A. Zeeb return 0; 35868e93258fSBjoern A. Zeeb 35878e93258fSBjoern A. Zeeb err_free_tx_rings: 35888e93258fSBjoern A. Zeeb rtw89_pci_free_tx_rings(rtwdev, pdev); 35898e93258fSBjoern A. Zeeb err: 35908e93258fSBjoern A. Zeeb return ret; 35918e93258fSBjoern A. Zeeb } 35928e93258fSBjoern A. Zeeb 35938e93258fSBjoern A. Zeeb static void rtw89_pci_h2c_init(struct rtw89_dev *rtwdev, 35948e93258fSBjoern A. Zeeb struct rtw89_pci *rtwpci) 35958e93258fSBjoern A. Zeeb { 35968e93258fSBjoern A. Zeeb skb_queue_head_init(&rtwpci->h2c_queue); 35978e93258fSBjoern A. Zeeb skb_queue_head_init(&rtwpci->h2c_release_queue); 35988e93258fSBjoern A. Zeeb } 35998e93258fSBjoern A. Zeeb 36008e93258fSBjoern A. Zeeb static int rtw89_pci_setup_resource(struct rtw89_dev *rtwdev, 36018e93258fSBjoern A. Zeeb struct pci_dev *pdev) 36028e93258fSBjoern A. Zeeb { 36038e93258fSBjoern A. Zeeb struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; 36048e93258fSBjoern A. Zeeb int ret; 36058e93258fSBjoern A. Zeeb 36068e93258fSBjoern A. Zeeb ret = rtw89_pci_setup_mapping(rtwdev, pdev); 36078e93258fSBjoern A. Zeeb if (ret) { 36088e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "failed to setup pci mapping\n"); 36098e93258fSBjoern A. Zeeb goto err; 36108e93258fSBjoern A. Zeeb } 36118e93258fSBjoern A. Zeeb 36128e93258fSBjoern A. Zeeb ret = rtw89_pci_alloc_trx_rings(rtwdev, pdev); 36138e93258fSBjoern A. Zeeb if (ret) { 36148e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "failed to alloc pci trx rings\n"); 36158e93258fSBjoern A. Zeeb goto err_pci_unmap; 36168e93258fSBjoern A. Zeeb } 36178e93258fSBjoern A. Zeeb 36188e93258fSBjoern A. Zeeb rtw89_pci_h2c_init(rtwdev, rtwpci); 36198e93258fSBjoern A. Zeeb 36208e93258fSBjoern A. Zeeb spin_lock_init(&rtwpci->irq_lock); 36218e93258fSBjoern A. Zeeb spin_lock_init(&rtwpci->trx_lock); 36228e93258fSBjoern A. Zeeb 36238e93258fSBjoern A. Zeeb return 0; 36248e93258fSBjoern A. Zeeb 36258e93258fSBjoern A. Zeeb err_pci_unmap: 36268e93258fSBjoern A. Zeeb rtw89_pci_clear_mapping(rtwdev, pdev); 36278e93258fSBjoern A. Zeeb err: 36288e93258fSBjoern A. Zeeb return ret; 36298e93258fSBjoern A. Zeeb } 36308e93258fSBjoern A. Zeeb 36318e93258fSBjoern A. Zeeb static void rtw89_pci_clear_resource(struct rtw89_dev *rtwdev, 36328e93258fSBjoern A. Zeeb struct pci_dev *pdev) 36338e93258fSBjoern A. Zeeb { 36348e93258fSBjoern A. Zeeb struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; 36358e93258fSBjoern A. Zeeb 36368e93258fSBjoern A. Zeeb rtw89_pci_free_trx_rings(rtwdev, pdev); 36378e93258fSBjoern A. Zeeb rtw89_pci_clear_mapping(rtwdev, pdev); 36388e93258fSBjoern A. Zeeb rtw89_pci_release_fwcmd(rtwdev, rtwpci, 36398e93258fSBjoern A. Zeeb skb_queue_len(&rtwpci->h2c_queue), true); 36408e93258fSBjoern A. Zeeb } 36418e93258fSBjoern A. Zeeb 36428e93258fSBjoern A. Zeeb void rtw89_pci_config_intr_mask(struct rtw89_dev *rtwdev) 36438e93258fSBjoern A. Zeeb { 36448e93258fSBjoern A. Zeeb struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; 3645e2340276SBjoern A. Zeeb const struct rtw89_chip_info *chip = rtwdev->chip; 3646e2340276SBjoern A. Zeeb u32 hs0isr_ind_int_en = B_AX_HS0ISR_IND_INT_EN; 3647e2340276SBjoern A. Zeeb 3648e2340276SBjoern A. Zeeb if (chip->chip_id == RTL8851B) 3649e2340276SBjoern A. Zeeb hs0isr_ind_int_en = B_AX_HS0ISR_IND_INT_EN_WKARND; 36508e93258fSBjoern A. Zeeb 36518e93258fSBjoern A. Zeeb rtwpci->halt_c2h_intrs = B_AX_HALT_C2H_INT_EN | 0; 36528e93258fSBjoern A. Zeeb 36538e93258fSBjoern A. Zeeb if (rtwpci->under_recovery) { 3654e2340276SBjoern A. Zeeb rtwpci->intrs[0] = hs0isr_ind_int_en; 36558e93258fSBjoern A. Zeeb rtwpci->intrs[1] = 0; 36568e93258fSBjoern A. Zeeb } else { 36578e93258fSBjoern A. Zeeb rtwpci->intrs[0] = B_AX_TXDMA_STUCK_INT_EN | 36588e93258fSBjoern A. Zeeb B_AX_RXDMA_INT_EN | 36598e93258fSBjoern A. Zeeb B_AX_RXP1DMA_INT_EN | 36608e93258fSBjoern A. Zeeb B_AX_RPQDMA_INT_EN | 36618e93258fSBjoern A. Zeeb B_AX_RXDMA_STUCK_INT_EN | 36628e93258fSBjoern A. Zeeb B_AX_RDU_INT_EN | 36638e93258fSBjoern A. Zeeb B_AX_RPQBD_FULL_INT_EN | 3664e2340276SBjoern A. Zeeb hs0isr_ind_int_en; 36658e93258fSBjoern A. Zeeb 36668e93258fSBjoern A. Zeeb rtwpci->intrs[1] = B_AX_HC10ISR_IND_INT_EN; 36678e93258fSBjoern A. Zeeb } 36688e93258fSBjoern A. Zeeb } 36698e93258fSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_pci_config_intr_mask); 36708e93258fSBjoern A. Zeeb 36718e93258fSBjoern A. Zeeb static void rtw89_pci_recovery_intr_mask_v1(struct rtw89_dev *rtwdev) 36728e93258fSBjoern A. Zeeb { 36738e93258fSBjoern A. Zeeb struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; 36748e93258fSBjoern A. Zeeb 36758e93258fSBjoern A. Zeeb rtwpci->ind_intrs = B_AX_HS0ISR_IND_INT_EN; 36768e93258fSBjoern A. Zeeb rtwpci->halt_c2h_intrs = B_AX_HALT_C2H_INT_EN | B_AX_WDT_TIMEOUT_INT_EN; 36778e93258fSBjoern A. Zeeb rtwpci->intrs[0] = 0; 36788e93258fSBjoern A. Zeeb rtwpci->intrs[1] = 0; 36798e93258fSBjoern A. Zeeb } 36808e93258fSBjoern A. Zeeb 36818e93258fSBjoern A. Zeeb static void rtw89_pci_default_intr_mask_v1(struct rtw89_dev *rtwdev) 36828e93258fSBjoern A. Zeeb { 36838e93258fSBjoern A. Zeeb struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; 36848e93258fSBjoern A. Zeeb 36858e93258fSBjoern A. Zeeb rtwpci->ind_intrs = B_AX_HCI_AXIDMA_INT_EN | 36868e93258fSBjoern A. Zeeb B_AX_HS1ISR_IND_INT_EN | 36878e93258fSBjoern A. Zeeb B_AX_HS0ISR_IND_INT_EN; 36888e93258fSBjoern A. Zeeb rtwpci->halt_c2h_intrs = B_AX_HALT_C2H_INT_EN | B_AX_WDT_TIMEOUT_INT_EN; 36898e93258fSBjoern A. Zeeb rtwpci->intrs[0] = B_AX_TXDMA_STUCK_INT_EN | 36908e93258fSBjoern A. Zeeb B_AX_RXDMA_INT_EN | 36918e93258fSBjoern A. Zeeb B_AX_RXP1DMA_INT_EN | 36928e93258fSBjoern A. Zeeb B_AX_RPQDMA_INT_EN | 36938e93258fSBjoern A. Zeeb B_AX_RXDMA_STUCK_INT_EN | 36948e93258fSBjoern A. Zeeb B_AX_RDU_INT_EN | 36958e93258fSBjoern A. Zeeb B_AX_RPQBD_FULL_INT_EN; 36968e93258fSBjoern A. Zeeb rtwpci->intrs[1] = B_AX_GPIO18_INT_EN; 36978e93258fSBjoern A. Zeeb } 36988e93258fSBjoern A. Zeeb 36998e93258fSBjoern A. Zeeb static void rtw89_pci_low_power_intr_mask_v1(struct rtw89_dev *rtwdev) 37008e93258fSBjoern A. Zeeb { 37018e93258fSBjoern A. Zeeb struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; 37028e93258fSBjoern A. Zeeb 37038e93258fSBjoern A. Zeeb rtwpci->ind_intrs = B_AX_HS1ISR_IND_INT_EN | 37048e93258fSBjoern A. Zeeb B_AX_HS0ISR_IND_INT_EN; 37058e93258fSBjoern A. Zeeb rtwpci->halt_c2h_intrs = B_AX_HALT_C2H_INT_EN | B_AX_WDT_TIMEOUT_INT_EN; 37068e93258fSBjoern A. Zeeb rtwpci->intrs[0] = 0; 37078e93258fSBjoern A. Zeeb rtwpci->intrs[1] = B_AX_GPIO18_INT_EN; 37088e93258fSBjoern A. Zeeb } 37098e93258fSBjoern A. Zeeb 37108e93258fSBjoern A. Zeeb void rtw89_pci_config_intr_mask_v1(struct rtw89_dev *rtwdev) 37118e93258fSBjoern A. Zeeb { 37128e93258fSBjoern A. Zeeb struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; 37138e93258fSBjoern A. Zeeb 37148e93258fSBjoern A. Zeeb if (rtwpci->under_recovery) 37158e93258fSBjoern A. Zeeb rtw89_pci_recovery_intr_mask_v1(rtwdev); 37168e93258fSBjoern A. Zeeb else if (rtwpci->low_power) 37178e93258fSBjoern A. Zeeb rtw89_pci_low_power_intr_mask_v1(rtwdev); 37188e93258fSBjoern A. Zeeb else 37198e93258fSBjoern A. Zeeb rtw89_pci_default_intr_mask_v1(rtwdev); 37208e93258fSBjoern A. Zeeb } 37218e93258fSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_pci_config_intr_mask_v1); 37228e93258fSBjoern A. Zeeb 3723*6d67aabdSBjoern A. Zeeb static void rtw89_pci_recovery_intr_mask_v2(struct rtw89_dev *rtwdev) 3724*6d67aabdSBjoern A. Zeeb { 3725*6d67aabdSBjoern A. Zeeb struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; 3726*6d67aabdSBjoern A. Zeeb 3727*6d67aabdSBjoern A. Zeeb rtwpci->ind_intrs = B_BE_HS0_IND_INT_EN0; 3728*6d67aabdSBjoern A. Zeeb rtwpci->halt_c2h_intrs = B_BE_HALT_C2H_INT_EN | B_BE_WDT_TIMEOUT_INT_EN; 3729*6d67aabdSBjoern A. Zeeb rtwpci->intrs[0] = 0; 3730*6d67aabdSBjoern A. Zeeb rtwpci->intrs[1] = 0; 3731*6d67aabdSBjoern A. Zeeb } 3732*6d67aabdSBjoern A. Zeeb 3733*6d67aabdSBjoern A. Zeeb static void rtw89_pci_default_intr_mask_v2(struct rtw89_dev *rtwdev) 3734*6d67aabdSBjoern A. Zeeb { 3735*6d67aabdSBjoern A. Zeeb struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; 3736*6d67aabdSBjoern A. Zeeb 3737*6d67aabdSBjoern A. Zeeb rtwpci->ind_intrs = B_BE_HCI_AXIDMA_INT_EN0 | 3738*6d67aabdSBjoern A. Zeeb B_BE_HS0_IND_INT_EN0; 3739*6d67aabdSBjoern A. Zeeb rtwpci->halt_c2h_intrs = B_BE_HALT_C2H_INT_EN | B_BE_WDT_TIMEOUT_INT_EN; 3740*6d67aabdSBjoern A. Zeeb rtwpci->intrs[0] = B_BE_RDU_CH1_INT_IMR_V1 | 3741*6d67aabdSBjoern A. Zeeb B_BE_RDU_CH0_INT_IMR_V1; 3742*6d67aabdSBjoern A. Zeeb rtwpci->intrs[1] = B_BE_PCIE_RX_RX0P2_IMR0_V1 | 3743*6d67aabdSBjoern A. Zeeb B_BE_PCIE_RX_RPQ0_IMR0_V1; 3744*6d67aabdSBjoern A. Zeeb } 3745*6d67aabdSBjoern A. Zeeb 3746*6d67aabdSBjoern A. Zeeb static void rtw89_pci_low_power_intr_mask_v2(struct rtw89_dev *rtwdev) 3747*6d67aabdSBjoern A. Zeeb { 3748*6d67aabdSBjoern A. Zeeb struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; 3749*6d67aabdSBjoern A. Zeeb 3750*6d67aabdSBjoern A. Zeeb rtwpci->ind_intrs = B_BE_HS0_IND_INT_EN0 | 3751*6d67aabdSBjoern A. Zeeb B_BE_HS1_IND_INT_EN0; 3752*6d67aabdSBjoern A. Zeeb rtwpci->halt_c2h_intrs = B_BE_HALT_C2H_INT_EN | B_BE_WDT_TIMEOUT_INT_EN; 3753*6d67aabdSBjoern A. Zeeb rtwpci->intrs[0] = 0; 3754*6d67aabdSBjoern A. Zeeb rtwpci->intrs[1] = B_BE_PCIE_RX_RX0P2_IMR0_V1 | 3755*6d67aabdSBjoern A. Zeeb B_BE_PCIE_RX_RPQ0_IMR0_V1; 3756*6d67aabdSBjoern A. Zeeb } 3757*6d67aabdSBjoern A. Zeeb 3758*6d67aabdSBjoern A. Zeeb void rtw89_pci_config_intr_mask_v2(struct rtw89_dev *rtwdev) 3759*6d67aabdSBjoern A. Zeeb { 3760*6d67aabdSBjoern A. Zeeb struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; 3761*6d67aabdSBjoern A. Zeeb 3762*6d67aabdSBjoern A. Zeeb if (rtwpci->under_recovery) 3763*6d67aabdSBjoern A. Zeeb rtw89_pci_recovery_intr_mask_v2(rtwdev); 3764*6d67aabdSBjoern A. Zeeb else if (rtwpci->low_power) 3765*6d67aabdSBjoern A. Zeeb rtw89_pci_low_power_intr_mask_v2(rtwdev); 3766*6d67aabdSBjoern A. Zeeb else 3767*6d67aabdSBjoern A. Zeeb rtw89_pci_default_intr_mask_v2(rtwdev); 3768*6d67aabdSBjoern A. Zeeb } 3769*6d67aabdSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_pci_config_intr_mask_v2); 3770*6d67aabdSBjoern A. Zeeb 37718e93258fSBjoern A. Zeeb static int rtw89_pci_request_irq(struct rtw89_dev *rtwdev, 37728e93258fSBjoern A. Zeeb struct pci_dev *pdev) 37738e93258fSBjoern A. Zeeb { 37748e93258fSBjoern A. Zeeb unsigned long flags = 0; 37758e93258fSBjoern A. Zeeb int ret; 37768e93258fSBjoern A. Zeeb 3777*6d67aabdSBjoern A. Zeeb flags |= PCI_IRQ_INTX | PCI_IRQ_MSI; 37788e93258fSBjoern A. Zeeb ret = pci_alloc_irq_vectors(pdev, 1, 1, flags); 37798e93258fSBjoern A. Zeeb if (ret < 0) { 37808e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "failed to alloc irq vectors, ret %d\n", ret); 37818e93258fSBjoern A. Zeeb goto err; 37828e93258fSBjoern A. Zeeb } 37838e93258fSBjoern A. Zeeb 37848e93258fSBjoern A. Zeeb ret = devm_request_threaded_irq(rtwdev->dev, pdev->irq, 37858e93258fSBjoern A. Zeeb rtw89_pci_interrupt_handler, 37868e93258fSBjoern A. Zeeb rtw89_pci_interrupt_threadfn, 37878e93258fSBjoern A. Zeeb IRQF_SHARED, KBUILD_MODNAME, rtwdev); 37888e93258fSBjoern A. Zeeb if (ret) { 37898e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "failed to request threaded irq\n"); 37908e93258fSBjoern A. Zeeb goto err_free_vector; 37918e93258fSBjoern A. Zeeb } 37928e93258fSBjoern A. Zeeb 37938e93258fSBjoern A. Zeeb rtw89_chip_config_intr_mask(rtwdev, RTW89_PCI_INTR_MASK_RESET); 37948e93258fSBjoern A. Zeeb 37958e93258fSBjoern A. Zeeb return 0; 37968e93258fSBjoern A. Zeeb 37978e93258fSBjoern A. Zeeb err_free_vector: 37988e93258fSBjoern A. Zeeb pci_free_irq_vectors(pdev); 37998e93258fSBjoern A. Zeeb err: 38008e93258fSBjoern A. Zeeb return ret; 38018e93258fSBjoern A. Zeeb } 38028e93258fSBjoern A. Zeeb 38038e93258fSBjoern A. Zeeb static void rtw89_pci_free_irq(struct rtw89_dev *rtwdev, 38048e93258fSBjoern A. Zeeb struct pci_dev *pdev) 38058e93258fSBjoern A. Zeeb { 38068e93258fSBjoern A. Zeeb devm_free_irq(rtwdev->dev, pdev->irq, rtwdev); 38078e93258fSBjoern A. Zeeb pci_free_irq_vectors(pdev); 38088e93258fSBjoern A. Zeeb } 38098e93258fSBjoern A. Zeeb 38108e93258fSBjoern A. Zeeb static u16 gray_code_to_bin(u16 gray_code, u32 bit_num) 38118e93258fSBjoern A. Zeeb { 38128e93258fSBjoern A. Zeeb u16 bin = 0, gray_bit; 38138e93258fSBjoern A. Zeeb u32 bit_idx; 38148e93258fSBjoern A. Zeeb 38158e93258fSBjoern A. Zeeb for (bit_idx = 0; bit_idx < bit_num; bit_idx++) { 38168e93258fSBjoern A. Zeeb gray_bit = (gray_code >> bit_idx) & 0x1; 38178e93258fSBjoern A. Zeeb if (bit_num - bit_idx > 1) 38188e93258fSBjoern A. Zeeb gray_bit ^= (gray_code >> (bit_idx + 1)) & 0x1; 38198e93258fSBjoern A. Zeeb bin |= (gray_bit << bit_idx); 38208e93258fSBjoern A. Zeeb } 38218e93258fSBjoern A. Zeeb 38228e93258fSBjoern A. Zeeb return bin; 38238e93258fSBjoern A. Zeeb } 38248e93258fSBjoern A. Zeeb 38258e93258fSBjoern A. Zeeb static int rtw89_pci_filter_out(struct rtw89_dev *rtwdev) 38268e93258fSBjoern A. Zeeb { 38278e93258fSBjoern A. Zeeb struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; 38288e93258fSBjoern A. Zeeb struct pci_dev *pdev = rtwpci->pdev; 38298e93258fSBjoern A. Zeeb u16 val16, filter_out_val; 38308e93258fSBjoern A. Zeeb u32 val, phy_offset; 38318e93258fSBjoern A. Zeeb int ret; 38328e93258fSBjoern A. Zeeb 38338e93258fSBjoern A. Zeeb if (rtwdev->chip->chip_id != RTL8852C) 38348e93258fSBjoern A. Zeeb return 0; 38358e93258fSBjoern A. Zeeb 38368e93258fSBjoern A. Zeeb val = rtw89_read32_mask(rtwdev, R_AX_PCIE_MIX_CFG_V1, B_AX_ASPM_CTRL_MASK); 38378e93258fSBjoern A. Zeeb if (val == B_AX_ASPM_CTRL_L1) 38388e93258fSBjoern A. Zeeb return 0; 38398e93258fSBjoern A. Zeeb 38408e93258fSBjoern A. Zeeb ret = pci_read_config_dword(pdev, RTW89_PCIE_L1_STS_V1, &val); 38418e93258fSBjoern A. Zeeb if (ret) 38428e93258fSBjoern A. Zeeb return ret; 38438e93258fSBjoern A. Zeeb 38448e93258fSBjoern A. Zeeb val = FIELD_GET(RTW89_BCFG_LINK_SPEED_MASK, val); 38458e93258fSBjoern A. Zeeb if (val == RTW89_PCIE_GEN1_SPEED) { 38468e93258fSBjoern A. Zeeb phy_offset = R_RAC_DIRECT_OFFSET_G1; 38478e93258fSBjoern A. Zeeb } else if (val == RTW89_PCIE_GEN2_SPEED) { 38488e93258fSBjoern A. Zeeb phy_offset = R_RAC_DIRECT_OFFSET_G2; 38498e93258fSBjoern A. Zeeb val16 = rtw89_read16(rtwdev, phy_offset + RAC_ANA10 * RAC_MULT); 38508e93258fSBjoern A. Zeeb rtw89_write16_set(rtwdev, phy_offset + RAC_ANA10 * RAC_MULT, 38518e93258fSBjoern A. Zeeb val16 | B_PCIE_BIT_PINOUT_DIS); 38528e93258fSBjoern A. Zeeb rtw89_write16_set(rtwdev, phy_offset + RAC_ANA19 * RAC_MULT, 38538e93258fSBjoern A. Zeeb val16 & ~B_PCIE_BIT_RD_SEL); 38548e93258fSBjoern A. Zeeb 38558e93258fSBjoern A. Zeeb val16 = rtw89_read16_mask(rtwdev, 38568e93258fSBjoern A. Zeeb phy_offset + RAC_ANA1F * RAC_MULT, 38578e93258fSBjoern A. Zeeb FILTER_OUT_EQ_MASK); 38588e93258fSBjoern A. Zeeb val16 = gray_code_to_bin(val16, hweight16(val16)); 38598e93258fSBjoern A. Zeeb filter_out_val = rtw89_read16(rtwdev, phy_offset + RAC_ANA24 * 38608e93258fSBjoern A. Zeeb RAC_MULT); 38618e93258fSBjoern A. Zeeb filter_out_val &= ~REG_FILTER_OUT_MASK; 38628e93258fSBjoern A. Zeeb filter_out_val |= FIELD_PREP(REG_FILTER_OUT_MASK, val16); 38638e93258fSBjoern A. Zeeb 38648e93258fSBjoern A. Zeeb rtw89_write16(rtwdev, phy_offset + RAC_ANA24 * RAC_MULT, 38658e93258fSBjoern A. Zeeb filter_out_val); 38668e93258fSBjoern A. Zeeb rtw89_write16_set(rtwdev, phy_offset + RAC_ANA0A * RAC_MULT, 38678e93258fSBjoern A. Zeeb B_BAC_EQ_SEL); 38688e93258fSBjoern A. Zeeb rtw89_write16_set(rtwdev, 38698e93258fSBjoern A. Zeeb R_RAC_DIRECT_OFFSET_G1 + RAC_ANA0C * RAC_MULT, 38708e93258fSBjoern A. Zeeb B_PCIE_BIT_PSAVE); 38718e93258fSBjoern A. Zeeb } else { 38728e93258fSBjoern A. Zeeb return -EOPNOTSUPP; 38738e93258fSBjoern A. Zeeb } 38748e93258fSBjoern A. Zeeb rtw89_write16_set(rtwdev, phy_offset + RAC_ANA0C * RAC_MULT, 38758e93258fSBjoern A. Zeeb B_PCIE_BIT_PSAVE); 38768e93258fSBjoern A. Zeeb 38778e93258fSBjoern A. Zeeb return 0; 38788e93258fSBjoern A. Zeeb } 38798e93258fSBjoern A. Zeeb 38808e93258fSBjoern A. Zeeb static void rtw89_pci_clkreq_set(struct rtw89_dev *rtwdev, bool enable) 38818e93258fSBjoern A. Zeeb { 3882*6d67aabdSBjoern A. Zeeb const struct rtw89_pci_info *info = rtwdev->pci_info; 3883*6d67aabdSBjoern A. Zeeb const struct rtw89_pci_gen_def *gen_def = info->gen_def; 38848e93258fSBjoern A. Zeeb 38858e93258fSBjoern A. Zeeb if (rtw89_pci_disable_clkreq) 38868e93258fSBjoern A. Zeeb return; 38878e93258fSBjoern A. Zeeb 3888*6d67aabdSBjoern A. Zeeb gen_def->clkreq_set(rtwdev, enable); 3889*6d67aabdSBjoern A. Zeeb } 3890*6d67aabdSBjoern A. Zeeb 3891*6d67aabdSBjoern A. Zeeb static void rtw89_pci_clkreq_set_ax(struct rtw89_dev *rtwdev, bool enable) 3892*6d67aabdSBjoern A. Zeeb { 3893*6d67aabdSBjoern A. Zeeb enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id; 3894*6d67aabdSBjoern A. Zeeb int ret; 3895*6d67aabdSBjoern A. Zeeb 38968e93258fSBjoern A. Zeeb ret = rtw89_pci_write_config_byte(rtwdev, RTW89_PCIE_CLK_CTRL, 38978e93258fSBjoern A. Zeeb PCIE_CLKDLY_HW_30US); 38988e93258fSBjoern A. Zeeb if (ret) 38998e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "failed to set CLKREQ Delay\n"); 39008e93258fSBjoern A. Zeeb 3901*6d67aabdSBjoern A. Zeeb if (chip_id == RTL8852A || rtw89_is_rtl885xb(rtwdev)) { 39028e93258fSBjoern A. Zeeb if (enable) 39038e93258fSBjoern A. Zeeb ret = rtw89_pci_config_byte_set(rtwdev, 39048e93258fSBjoern A. Zeeb RTW89_PCIE_L1_CTRL, 39058e93258fSBjoern A. Zeeb RTW89_PCIE_BIT_CLK); 39068e93258fSBjoern A. Zeeb else 39078e93258fSBjoern A. Zeeb ret = rtw89_pci_config_byte_clr(rtwdev, 39088e93258fSBjoern A. Zeeb RTW89_PCIE_L1_CTRL, 39098e93258fSBjoern A. Zeeb RTW89_PCIE_BIT_CLK); 39108e93258fSBjoern A. Zeeb if (ret) 39118e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "failed to %s CLKREQ_L1, ret=%d", 39128e93258fSBjoern A. Zeeb enable ? "set" : "unset", ret); 39138e93258fSBjoern A. Zeeb } else if (chip_id == RTL8852C) { 39148e93258fSBjoern A. Zeeb rtw89_write32_set(rtwdev, R_AX_PCIE_LAT_CTRL, 39158e93258fSBjoern A. Zeeb B_AX_CLK_REQ_SEL_OPT | B_AX_CLK_REQ_SEL); 39168e93258fSBjoern A. Zeeb if (enable) 39178e93258fSBjoern A. Zeeb rtw89_write32_set(rtwdev, R_AX_L1_CLK_CTRL, 39188e93258fSBjoern A. Zeeb B_AX_CLK_REQ_N); 39198e93258fSBjoern A. Zeeb else 39208e93258fSBjoern A. Zeeb rtw89_write32_clr(rtwdev, R_AX_L1_CLK_CTRL, 39218e93258fSBjoern A. Zeeb B_AX_CLK_REQ_N); 39228e93258fSBjoern A. Zeeb } 39238e93258fSBjoern A. Zeeb } 39248e93258fSBjoern A. Zeeb 39258e93258fSBjoern A. Zeeb static void rtw89_pci_aspm_set(struct rtw89_dev *rtwdev, bool enable) 39268e93258fSBjoern A. Zeeb { 3927*6d67aabdSBjoern A. Zeeb const struct rtw89_pci_info *info = rtwdev->pci_info; 3928*6d67aabdSBjoern A. Zeeb const struct rtw89_pci_gen_def *gen_def = info->gen_def; 39298e93258fSBjoern A. Zeeb 39308e93258fSBjoern A. Zeeb if (rtw89_pci_disable_aspm_l1) 39318e93258fSBjoern A. Zeeb return; 39328e93258fSBjoern A. Zeeb 3933*6d67aabdSBjoern A. Zeeb gen_def->aspm_set(rtwdev, enable); 3934*6d67aabdSBjoern A. Zeeb } 3935*6d67aabdSBjoern A. Zeeb 3936*6d67aabdSBjoern A. Zeeb static void rtw89_pci_aspm_set_ax(struct rtw89_dev *rtwdev, bool enable) 3937*6d67aabdSBjoern A. Zeeb { 3938*6d67aabdSBjoern A. Zeeb enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id; 3939*6d67aabdSBjoern A. Zeeb u8 value = 0; 3940*6d67aabdSBjoern A. Zeeb int ret; 3941*6d67aabdSBjoern A. Zeeb 39428e93258fSBjoern A. Zeeb ret = rtw89_pci_read_config_byte(rtwdev, RTW89_PCIE_ASPM_CTRL, &value); 39438e93258fSBjoern A. Zeeb if (ret) 3944*6d67aabdSBjoern A. Zeeb rtw89_warn(rtwdev, "failed to read ASPM Delay\n"); 39458e93258fSBjoern A. Zeeb 3946*6d67aabdSBjoern A. Zeeb u8p_replace_bits(&value, PCIE_L1DLY_16US, RTW89_L1DLY_MASK); 3947*6d67aabdSBjoern A. Zeeb u8p_replace_bits(&value, PCIE_L0SDLY_4US, RTW89_L0DLY_MASK); 39488e93258fSBjoern A. Zeeb 39498e93258fSBjoern A. Zeeb ret = rtw89_pci_write_config_byte(rtwdev, RTW89_PCIE_ASPM_CTRL, value); 39508e93258fSBjoern A. Zeeb if (ret) 3951*6d67aabdSBjoern A. Zeeb rtw89_warn(rtwdev, "failed to read ASPM Delay\n"); 39528e93258fSBjoern A. Zeeb 3953*6d67aabdSBjoern A. Zeeb if (chip_id == RTL8852A || rtw89_is_rtl885xb(rtwdev)) { 39548e93258fSBjoern A. Zeeb if (enable) 39558e93258fSBjoern A. Zeeb ret = rtw89_pci_config_byte_set(rtwdev, 39568e93258fSBjoern A. Zeeb RTW89_PCIE_L1_CTRL, 39578e93258fSBjoern A. Zeeb RTW89_PCIE_BIT_L1); 39588e93258fSBjoern A. Zeeb else 39598e93258fSBjoern A. Zeeb ret = rtw89_pci_config_byte_clr(rtwdev, 39608e93258fSBjoern A. Zeeb RTW89_PCIE_L1_CTRL, 39618e93258fSBjoern A. Zeeb RTW89_PCIE_BIT_L1); 39628e93258fSBjoern A. Zeeb } else if (chip_id == RTL8852C) { 39638e93258fSBjoern A. Zeeb if (enable) 39648e93258fSBjoern A. Zeeb rtw89_write32_set(rtwdev, R_AX_PCIE_MIX_CFG_V1, 39658e93258fSBjoern A. Zeeb B_AX_ASPM_CTRL_L1); 39668e93258fSBjoern A. Zeeb else 39678e93258fSBjoern A. Zeeb rtw89_write32_clr(rtwdev, R_AX_PCIE_MIX_CFG_V1, 39688e93258fSBjoern A. Zeeb B_AX_ASPM_CTRL_L1); 39698e93258fSBjoern A. Zeeb } 39708e93258fSBjoern A. Zeeb if (ret) 39718e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "failed to %s ASPM L1, ret=%d", 39728e93258fSBjoern A. Zeeb enable ? "set" : "unset", ret); 39738e93258fSBjoern A. Zeeb } 39748e93258fSBjoern A. Zeeb 39758e93258fSBjoern A. Zeeb static void rtw89_pci_recalc_int_mit(struct rtw89_dev *rtwdev) 39768e93258fSBjoern A. Zeeb { 3977*6d67aabdSBjoern A. Zeeb enum rtw89_chip_gen chip_gen = rtwdev->chip->chip_gen; 3978*6d67aabdSBjoern A. Zeeb const struct rtw89_pci_info *info = rtwdev->pci_info; 39798e93258fSBjoern A. Zeeb struct rtw89_traffic_stats *stats = &rtwdev->stats; 39808e93258fSBjoern A. Zeeb enum rtw89_tfc_lv tx_tfc_lv = stats->tx_tfc_lv; 39818e93258fSBjoern A. Zeeb enum rtw89_tfc_lv rx_tfc_lv = stats->rx_tfc_lv; 39828e93258fSBjoern A. Zeeb u32 val = 0; 39838e93258fSBjoern A. Zeeb 3984*6d67aabdSBjoern A. Zeeb if (rtwdev->scanning || 3985*6d67aabdSBjoern A. Zeeb (tx_tfc_lv < RTW89_TFC_HIGH && rx_tfc_lv < RTW89_TFC_HIGH)) 3986*6d67aabdSBjoern A. Zeeb goto out; 3987*6d67aabdSBjoern A. Zeeb 3988*6d67aabdSBjoern A. Zeeb if (chip_gen == RTW89_CHIP_BE) 3989*6d67aabdSBjoern A. Zeeb val = B_BE_PCIE_MIT_RX0P2_EN | B_BE_PCIE_MIT_RX0P1_EN; 3990*6d67aabdSBjoern A. Zeeb else 39918e93258fSBjoern A. Zeeb val = B_AX_RXMIT_RXP2_SEL | B_AX_RXMIT_RXP1_SEL | 39928e93258fSBjoern A. Zeeb FIELD_PREP(B_AX_RXCOUNTER_MATCH_MASK, RTW89_PCI_RXBD_NUM_MAX / 2) | 39938e93258fSBjoern A. Zeeb FIELD_PREP(B_AX_RXTIMER_UNIT_MASK, AX_RXTIMER_UNIT_64US) | 39948e93258fSBjoern A. Zeeb FIELD_PREP(B_AX_RXTIMER_MATCH_MASK, 2048 / 64); 39958e93258fSBjoern A. Zeeb 3996*6d67aabdSBjoern A. Zeeb out: 3997*6d67aabdSBjoern A. Zeeb rtw89_write32(rtwdev, info->mit_addr, val); 39988e93258fSBjoern A. Zeeb } 39998e93258fSBjoern A. Zeeb 40008e93258fSBjoern A. Zeeb static void rtw89_pci_link_cfg(struct rtw89_dev *rtwdev) 40018e93258fSBjoern A. Zeeb { 40028e93258fSBjoern A. Zeeb struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; 40038e93258fSBjoern A. Zeeb struct pci_dev *pdev = rtwpci->pdev; 40048e93258fSBjoern A. Zeeb u16 link_ctrl; 40058e93258fSBjoern A. Zeeb int ret; 40068e93258fSBjoern A. Zeeb 40078e93258fSBjoern A. Zeeb /* Though there is standard PCIE configuration space to set the 40088e93258fSBjoern A. Zeeb * link control register, but by Realtek's design, driver should 40098e93258fSBjoern A. Zeeb * check if host supports CLKREQ/ASPM to enable the HW module. 40108e93258fSBjoern A. Zeeb * 40118e93258fSBjoern A. Zeeb * These functions are implemented by two HW modules associated, 40128e93258fSBjoern A. Zeeb * one is responsible to access PCIE configuration space to 40138e93258fSBjoern A. Zeeb * follow the host settings, and another is in charge of doing 40148e93258fSBjoern A. Zeeb * CLKREQ/ASPM mechanisms, it is default disabled. Because sometimes 40158e93258fSBjoern A. Zeeb * the host does not support it, and due to some reasons or wrong 40168e93258fSBjoern A. Zeeb * settings (ex. CLKREQ# not Bi-Direction), it could lead to device 40178e93258fSBjoern A. Zeeb * loss if HW misbehaves on the link. 40188e93258fSBjoern A. Zeeb * 40198e93258fSBjoern A. Zeeb * Hence it's designed that driver should first check the PCIE 40208e93258fSBjoern A. Zeeb * configuration space is sync'ed and enabled, then driver can turn 40218e93258fSBjoern A. Zeeb * on the other module that is actually working on the mechanism. 40228e93258fSBjoern A. Zeeb */ 40238e93258fSBjoern A. Zeeb ret = pcie_capability_read_word(pdev, PCI_EXP_LNKCTL, &link_ctrl); 40248e93258fSBjoern A. Zeeb if (ret) { 40258e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "failed to read PCI cap, ret=%d\n", ret); 40268e93258fSBjoern A. Zeeb return; 40278e93258fSBjoern A. Zeeb } 40288e93258fSBjoern A. Zeeb 40298e93258fSBjoern A. Zeeb if (link_ctrl & PCI_EXP_LNKCTL_CLKREQ_EN) 40308e93258fSBjoern A. Zeeb rtw89_pci_clkreq_set(rtwdev, true); 40318e93258fSBjoern A. Zeeb 40328e93258fSBjoern A. Zeeb if (link_ctrl & PCI_EXP_LNKCTL_ASPM_L1) 40338e93258fSBjoern A. Zeeb rtw89_pci_aspm_set(rtwdev, true); 40348e93258fSBjoern A. Zeeb } 40358e93258fSBjoern A. Zeeb 40368e93258fSBjoern A. Zeeb static void rtw89_pci_l1ss_set(struct rtw89_dev *rtwdev, bool enable) 40378e93258fSBjoern A. Zeeb { 4038*6d67aabdSBjoern A. Zeeb const struct rtw89_pci_info *info = rtwdev->pci_info; 4039*6d67aabdSBjoern A. Zeeb const struct rtw89_pci_gen_def *gen_def = info->gen_def; 4040*6d67aabdSBjoern A. Zeeb 4041*6d67aabdSBjoern A. Zeeb if (rtw89_pci_disable_l1ss) 4042*6d67aabdSBjoern A. Zeeb return; 4043*6d67aabdSBjoern A. Zeeb 4044*6d67aabdSBjoern A. Zeeb gen_def->l1ss_set(rtwdev, enable); 4045*6d67aabdSBjoern A. Zeeb } 4046*6d67aabdSBjoern A. Zeeb 4047*6d67aabdSBjoern A. Zeeb static void rtw89_pci_l1ss_set_ax(struct rtw89_dev *rtwdev, bool enable) 4048*6d67aabdSBjoern A. Zeeb { 40498e93258fSBjoern A. Zeeb enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id; 40508e93258fSBjoern A. Zeeb int ret; 40518e93258fSBjoern A. Zeeb 4052*6d67aabdSBjoern A. Zeeb if (chip_id == RTL8852A || rtw89_is_rtl885xb(rtwdev)) { 40538e93258fSBjoern A. Zeeb if (enable) 40548e93258fSBjoern A. Zeeb ret = rtw89_pci_config_byte_set(rtwdev, 40558e93258fSBjoern A. Zeeb RTW89_PCIE_TIMER_CTRL, 40568e93258fSBjoern A. Zeeb RTW89_PCIE_BIT_L1SUB); 40578e93258fSBjoern A. Zeeb else 40588e93258fSBjoern A. Zeeb ret = rtw89_pci_config_byte_clr(rtwdev, 40598e93258fSBjoern A. Zeeb RTW89_PCIE_TIMER_CTRL, 40608e93258fSBjoern A. Zeeb RTW89_PCIE_BIT_L1SUB); 40618e93258fSBjoern A. Zeeb if (ret) 40628e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "failed to %s L1SS, ret=%d", 40638e93258fSBjoern A. Zeeb enable ? "set" : "unset", ret); 40648e93258fSBjoern A. Zeeb } else if (chip_id == RTL8852C) { 40658e93258fSBjoern A. Zeeb ret = rtw89_pci_config_byte_clr(rtwdev, RTW89_PCIE_L1SS_STS_V1, 40668e93258fSBjoern A. Zeeb RTW89_PCIE_BIT_ASPM_L11 | 40678e93258fSBjoern A. Zeeb RTW89_PCIE_BIT_PCI_L11); 40688e93258fSBjoern A. Zeeb if (ret) 40698e93258fSBjoern A. Zeeb rtw89_warn(rtwdev, "failed to unset ASPM L1.1, ret=%d", ret); 40708e93258fSBjoern A. Zeeb if (enable) 40718e93258fSBjoern A. Zeeb rtw89_write32_clr(rtwdev, R_AX_PCIE_MIX_CFG_V1, 40728e93258fSBjoern A. Zeeb B_AX_L1SUB_DISABLE); 40738e93258fSBjoern A. Zeeb else 40748e93258fSBjoern A. Zeeb rtw89_write32_set(rtwdev, R_AX_PCIE_MIX_CFG_V1, 40758e93258fSBjoern A. Zeeb B_AX_L1SUB_DISABLE); 40768e93258fSBjoern A. Zeeb } 40778e93258fSBjoern A. Zeeb } 40788e93258fSBjoern A. Zeeb 40798e93258fSBjoern A. Zeeb static void rtw89_pci_l1ss_cfg(struct rtw89_dev *rtwdev) 40808e93258fSBjoern A. Zeeb { 40818e93258fSBjoern A. Zeeb struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; 40828e93258fSBjoern A. Zeeb struct pci_dev *pdev = rtwpci->pdev; 40838e93258fSBjoern A. Zeeb u32 l1ss_cap_ptr, l1ss_ctrl; 40848e93258fSBjoern A. Zeeb 40858e93258fSBjoern A. Zeeb if (rtw89_pci_disable_l1ss) 40868e93258fSBjoern A. Zeeb return; 40878e93258fSBjoern A. Zeeb 40888e93258fSBjoern A. Zeeb l1ss_cap_ptr = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_L1SS); 40898e93258fSBjoern A. Zeeb if (!l1ss_cap_ptr) 40908e93258fSBjoern A. Zeeb return; 40918e93258fSBjoern A. Zeeb 40928e93258fSBjoern A. Zeeb pci_read_config_dword(pdev, l1ss_cap_ptr + PCI_L1SS_CTL1, &l1ss_ctrl); 40938e93258fSBjoern A. Zeeb 40948e93258fSBjoern A. Zeeb if (l1ss_ctrl & PCI_L1SS_CTL1_L1SS_MASK) 40958e93258fSBjoern A. Zeeb rtw89_pci_l1ss_set(rtwdev, true); 40968e93258fSBjoern A. Zeeb } 40978e93258fSBjoern A. Zeeb 4098*6d67aabdSBjoern A. Zeeb static int rtw89_pci_poll_io_idle_ax(struct rtw89_dev *rtwdev) 40998e93258fSBjoern A. Zeeb { 41008e93258fSBjoern A. Zeeb int ret = 0; 41018e93258fSBjoern A. Zeeb u32 sts; 41028e93258fSBjoern A. Zeeb u32 busy = B_AX_PCIEIO_BUSY | B_AX_PCIEIO_TX_BUSY | B_AX_PCIEIO_RX_BUSY; 41038e93258fSBjoern A. Zeeb 41048e93258fSBjoern A. Zeeb ret = read_poll_timeout_atomic(rtw89_read32, sts, (sts & busy) == 0x0, 41058e93258fSBjoern A. Zeeb 10, 1000, false, rtwdev, 41068e93258fSBjoern A. Zeeb R_AX_PCIE_DMA_BUSY1); 41078e93258fSBjoern A. Zeeb if (ret) { 41088e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "pci dmach busy1 0x%X\n", 41098e93258fSBjoern A. Zeeb rtw89_read32(rtwdev, R_AX_PCIE_DMA_BUSY1)); 41108e93258fSBjoern A. Zeeb return -EINVAL; 41118e93258fSBjoern A. Zeeb } 41128e93258fSBjoern A. Zeeb return ret; 41138e93258fSBjoern A. Zeeb } 41148e93258fSBjoern A. Zeeb 4115*6d67aabdSBjoern A. Zeeb static int rtw89_pci_lv1rst_stop_dma_ax(struct rtw89_dev *rtwdev) 41168e93258fSBjoern A. Zeeb { 4117e2340276SBjoern A. Zeeb u32 val; 41188e93258fSBjoern A. Zeeb int ret; 41198e93258fSBjoern A. Zeeb 4120e2340276SBjoern A. Zeeb if (rtwdev->chip->chip_id == RTL8852C) 4121e2340276SBjoern A. Zeeb return 0; 4122e2340276SBjoern A. Zeeb 4123e2340276SBjoern A. Zeeb rtw89_pci_ctrl_dma_all(rtwdev, false); 4124*6d67aabdSBjoern A. Zeeb ret = rtw89_pci_poll_io_idle_ax(rtwdev); 41258e93258fSBjoern A. Zeeb if (ret) { 41268e93258fSBjoern A. Zeeb val = rtw89_read32(rtwdev, R_AX_DBG_ERR_FLAG); 41278e93258fSBjoern A. Zeeb rtw89_debug(rtwdev, RTW89_DBG_HCI, 41288e93258fSBjoern A. Zeeb "[PCIe] poll_io_idle fail, before 0x%08x: 0x%08x\n", 41298e93258fSBjoern A. Zeeb R_AX_DBG_ERR_FLAG, val); 41308e93258fSBjoern A. Zeeb if (val & B_AX_TX_STUCK || val & B_AX_PCIE_TXBD_LEN0) 4131e2340276SBjoern A. Zeeb rtw89_mac_ctrl_hci_dma_tx(rtwdev, false); 41328e93258fSBjoern A. Zeeb if (val & B_AX_RX_STUCK) 4133e2340276SBjoern A. Zeeb rtw89_mac_ctrl_hci_dma_rx(rtwdev, false); 4134e2340276SBjoern A. Zeeb rtw89_mac_ctrl_hci_dma_trx(rtwdev, true); 4135*6d67aabdSBjoern A. Zeeb ret = rtw89_pci_poll_io_idle_ax(rtwdev); 41368e93258fSBjoern A. Zeeb val = rtw89_read32(rtwdev, R_AX_DBG_ERR_FLAG); 41378e93258fSBjoern A. Zeeb rtw89_debug(rtwdev, RTW89_DBG_HCI, 41388e93258fSBjoern A. Zeeb "[PCIe] poll_io_idle fail, after 0x%08x: 0x%08x\n", 41398e93258fSBjoern A. Zeeb R_AX_DBG_ERR_FLAG, val); 41408e93258fSBjoern A. Zeeb } 41418e93258fSBjoern A. Zeeb 41428e93258fSBjoern A. Zeeb return ret; 41438e93258fSBjoern A. Zeeb } 41448e93258fSBjoern A. Zeeb 4145*6d67aabdSBjoern A. Zeeb static int rtw89_pci_lv1rst_start_dma_ax(struct rtw89_dev *rtwdev) 41468e93258fSBjoern A. Zeeb { 41478e93258fSBjoern A. Zeeb u32 ret; 41488e93258fSBjoern A. Zeeb 4149e2340276SBjoern A. Zeeb if (rtwdev->chip->chip_id == RTL8852C) 4150e2340276SBjoern A. Zeeb return 0; 4151e2340276SBjoern A. Zeeb 4152e2340276SBjoern A. Zeeb rtw89_mac_ctrl_hci_dma_trx(rtwdev, false); 4153e2340276SBjoern A. Zeeb rtw89_mac_ctrl_hci_dma_trx(rtwdev, true); 41548e93258fSBjoern A. Zeeb rtw89_pci_clr_idx_all(rtwdev); 41558e93258fSBjoern A. Zeeb 4156*6d67aabdSBjoern A. Zeeb ret = rtw89_pci_rst_bdram_ax(rtwdev); 41578e93258fSBjoern A. Zeeb if (ret) 41588e93258fSBjoern A. Zeeb return ret; 41598e93258fSBjoern A. Zeeb 4160e2340276SBjoern A. Zeeb rtw89_pci_ctrl_dma_all(rtwdev, true); 41618e93258fSBjoern A. Zeeb return ret; 41628e93258fSBjoern A. Zeeb } 41638e93258fSBjoern A. Zeeb 41648e93258fSBjoern A. Zeeb static int rtw89_pci_ops_mac_lv1_recovery(struct rtw89_dev *rtwdev, 41658e93258fSBjoern A. Zeeb enum rtw89_lv1_rcvy_step step) 41668e93258fSBjoern A. Zeeb { 4167*6d67aabdSBjoern A. Zeeb const struct rtw89_pci_info *info = rtwdev->pci_info; 4168*6d67aabdSBjoern A. Zeeb const struct rtw89_pci_gen_def *gen_def = info->gen_def; 41698e93258fSBjoern A. Zeeb int ret; 41708e93258fSBjoern A. Zeeb 41718e93258fSBjoern A. Zeeb switch (step) { 41728e93258fSBjoern A. Zeeb case RTW89_LV1_RCVY_STEP_1: 4173*6d67aabdSBjoern A. Zeeb ret = gen_def->lv1rst_stop_dma(rtwdev); 41748e93258fSBjoern A. Zeeb if (ret) 41758e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "lv1 rcvy pci stop dma fail\n"); 41768e93258fSBjoern A. Zeeb 41778e93258fSBjoern A. Zeeb break; 41788e93258fSBjoern A. Zeeb 41798e93258fSBjoern A. Zeeb case RTW89_LV1_RCVY_STEP_2: 4180*6d67aabdSBjoern A. Zeeb ret = gen_def->lv1rst_start_dma(rtwdev); 41818e93258fSBjoern A. Zeeb if (ret) 41828e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "lv1 rcvy pci start dma fail\n"); 41838e93258fSBjoern A. Zeeb break; 41848e93258fSBjoern A. Zeeb 41858e93258fSBjoern A. Zeeb default: 41868e93258fSBjoern A. Zeeb return -EINVAL; 41878e93258fSBjoern A. Zeeb } 41888e93258fSBjoern A. Zeeb 41898e93258fSBjoern A. Zeeb return ret; 41908e93258fSBjoern A. Zeeb } 41918e93258fSBjoern A. Zeeb 41928e93258fSBjoern A. Zeeb static void rtw89_pci_ops_dump_err_status(struct rtw89_dev *rtwdev) 41938e93258fSBjoern A. Zeeb { 4194*6d67aabdSBjoern A. Zeeb if (rtwdev->chip->chip_gen == RTW89_CHIP_BE) 4195*6d67aabdSBjoern A. Zeeb return; 4196*6d67aabdSBjoern A. Zeeb 4197*6d67aabdSBjoern A. Zeeb if (rtwdev->chip->chip_id == RTL8852C) { 4198*6d67aabdSBjoern A. Zeeb rtw89_info(rtwdev, "R_AX_DBG_ERR_FLAG=0x%08x\n", 4199*6d67aabdSBjoern A. Zeeb rtw89_read32(rtwdev, R_AX_DBG_ERR_FLAG_V1)); 4200*6d67aabdSBjoern A. Zeeb rtw89_info(rtwdev, "R_AX_LBC_WATCHDOG=0x%08x\n", 4201*6d67aabdSBjoern A. Zeeb rtw89_read32(rtwdev, R_AX_LBC_WATCHDOG_V1)); 4202*6d67aabdSBjoern A. Zeeb } else { 42038e93258fSBjoern A. Zeeb rtw89_info(rtwdev, "R_AX_RPQ_RXBD_IDX =0x%08x\n", 42048e93258fSBjoern A. Zeeb rtw89_read32(rtwdev, R_AX_RPQ_RXBD_IDX)); 42058e93258fSBjoern A. Zeeb rtw89_info(rtwdev, "R_AX_DBG_ERR_FLAG=0x%08x\n", 42068e93258fSBjoern A. Zeeb rtw89_read32(rtwdev, R_AX_DBG_ERR_FLAG)); 42078e93258fSBjoern A. Zeeb rtw89_info(rtwdev, "R_AX_LBC_WATCHDOG=0x%08x\n", 42088e93258fSBjoern A. Zeeb rtw89_read32(rtwdev, R_AX_LBC_WATCHDOG)); 42098e93258fSBjoern A. Zeeb } 4210*6d67aabdSBjoern A. Zeeb } 42118e93258fSBjoern A. Zeeb 42128e93258fSBjoern A. Zeeb static int rtw89_pci_napi_poll(struct napi_struct *napi, int budget) 42138e93258fSBjoern A. Zeeb { 42148e93258fSBjoern A. Zeeb struct rtw89_dev *rtwdev = container_of(napi, struct rtw89_dev, napi); 42158e93258fSBjoern A. Zeeb struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; 4216*6d67aabdSBjoern A. Zeeb const struct rtw89_pci_info *info = rtwdev->pci_info; 4217*6d67aabdSBjoern A. Zeeb const struct rtw89_pci_gen_def *gen_def = info->gen_def; 42188e93258fSBjoern A. Zeeb unsigned long flags; 42198e93258fSBjoern A. Zeeb int work_done; 42208e93258fSBjoern A. Zeeb 42218e93258fSBjoern A. Zeeb rtwdev->napi_budget_countdown = budget; 42228e93258fSBjoern A. Zeeb 4223*6d67aabdSBjoern A. Zeeb rtw89_write32(rtwdev, gen_def->isr_clear_rpq.addr, gen_def->isr_clear_rpq.data); 42248e93258fSBjoern A. Zeeb work_done = rtw89_pci_poll_rpq_dma(rtwdev, rtwpci, rtwdev->napi_budget_countdown); 42258e93258fSBjoern A. Zeeb if (work_done == budget) 42268e93258fSBjoern A. Zeeb return budget; 42278e93258fSBjoern A. Zeeb 4228*6d67aabdSBjoern A. Zeeb rtw89_write32(rtwdev, gen_def->isr_clear_rxq.addr, gen_def->isr_clear_rxq.data); 42298e93258fSBjoern A. Zeeb work_done += rtw89_pci_poll_rxq_dma(rtwdev, rtwpci, rtwdev->napi_budget_countdown); 42308e93258fSBjoern A. Zeeb if (work_done < budget && napi_complete_done(napi, work_done)) { 42318e93258fSBjoern A. Zeeb spin_lock_irqsave(&rtwpci->irq_lock, flags); 42328e93258fSBjoern A. Zeeb if (likely(rtwpci->running)) 42338e93258fSBjoern A. Zeeb rtw89_chip_enable_intr(rtwdev, rtwpci); 42348e93258fSBjoern A. Zeeb spin_unlock_irqrestore(&rtwpci->irq_lock, flags); 42358e93258fSBjoern A. Zeeb } 42368e93258fSBjoern A. Zeeb 42378e93258fSBjoern A. Zeeb return work_done; 42388e93258fSBjoern A. Zeeb } 42398e93258fSBjoern A. Zeeb 42408e93258fSBjoern A. Zeeb static int __maybe_unused rtw89_pci_suspend(struct device *dev) 42418e93258fSBjoern A. Zeeb { 42428e93258fSBjoern A. Zeeb struct ieee80211_hw *hw = dev_get_drvdata(dev); 42438e93258fSBjoern A. Zeeb struct rtw89_dev *rtwdev = hw->priv; 42448e93258fSBjoern A. Zeeb enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id; 42458e93258fSBjoern A. Zeeb 42468e93258fSBjoern A. Zeeb rtw89_write32_set(rtwdev, R_AX_RSV_CTRL, B_AX_WLOCK_1C_BIT6); 42478e93258fSBjoern A. Zeeb rtw89_write32_set(rtwdev, R_AX_RSV_CTRL, B_AX_R_DIS_PRST); 42488e93258fSBjoern A. Zeeb rtw89_write32_clr(rtwdev, R_AX_RSV_CTRL, B_AX_WLOCK_1C_BIT6); 4249*6d67aabdSBjoern A. Zeeb if (chip_id == RTL8852A || rtw89_is_rtl885xb(rtwdev)) { 42508e93258fSBjoern A. Zeeb rtw89_write32_clr(rtwdev, R_AX_SYS_SDIO_CTRL, 42518e93258fSBjoern A. Zeeb B_AX_PCIE_DIS_L2_CTRL_LDO_HCI); 42528e93258fSBjoern A. Zeeb rtw89_write32_set(rtwdev, R_AX_PCIE_INIT_CFG1, 42538e93258fSBjoern A. Zeeb B_AX_PCIE_PERST_KEEP_REG | B_AX_PCIE_TRAIN_KEEP_REG); 42548e93258fSBjoern A. Zeeb } else { 42558e93258fSBjoern A. Zeeb rtw89_write32_clr(rtwdev, R_AX_PCIE_PS_CTRL_V1, 42568e93258fSBjoern A. Zeeb B_AX_CMAC_EXIT_L1_EN | B_AX_DMAC0_EXIT_L1_EN); 42578e93258fSBjoern A. Zeeb } 42588e93258fSBjoern A. Zeeb 42598e93258fSBjoern A. Zeeb return 0; 42608e93258fSBjoern A. Zeeb } 42618e93258fSBjoern A. Zeeb 42628e93258fSBjoern A. Zeeb static void rtw89_pci_l2_hci_ldo(struct rtw89_dev *rtwdev) 42638e93258fSBjoern A. Zeeb { 42648e93258fSBjoern A. Zeeb if (rtwdev->chip->chip_id == RTL8852C) 42658e93258fSBjoern A. Zeeb return; 42668e93258fSBjoern A. Zeeb 42678e93258fSBjoern A. Zeeb /* Hardware need write the reg twice to ensure the setting work */ 42688e93258fSBjoern A. Zeeb rtw89_pci_write_config_byte(rtwdev, RTW89_PCIE_RST_MSTATE, 42698e93258fSBjoern A. Zeeb RTW89_PCIE_BIT_CFG_RST_MSTATE); 42708e93258fSBjoern A. Zeeb rtw89_pci_write_config_byte(rtwdev, RTW89_PCIE_RST_MSTATE, 42718e93258fSBjoern A. Zeeb RTW89_PCIE_BIT_CFG_RST_MSTATE); 42728e93258fSBjoern A. Zeeb } 42738e93258fSBjoern A. Zeeb 42748e93258fSBjoern A. Zeeb static int __maybe_unused rtw89_pci_resume(struct device *dev) 42758e93258fSBjoern A. Zeeb { 42768e93258fSBjoern A. Zeeb struct ieee80211_hw *hw = dev_get_drvdata(dev); 42778e93258fSBjoern A. Zeeb struct rtw89_dev *rtwdev = hw->priv; 42788e93258fSBjoern A. Zeeb enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id; 42798e93258fSBjoern A. Zeeb 42808e93258fSBjoern A. Zeeb rtw89_write32_set(rtwdev, R_AX_RSV_CTRL, B_AX_WLOCK_1C_BIT6); 42818e93258fSBjoern A. Zeeb rtw89_write32_clr(rtwdev, R_AX_RSV_CTRL, B_AX_R_DIS_PRST); 42828e93258fSBjoern A. Zeeb rtw89_write32_clr(rtwdev, R_AX_RSV_CTRL, B_AX_WLOCK_1C_BIT6); 4283*6d67aabdSBjoern A. Zeeb if (chip_id == RTL8852A || rtw89_is_rtl885xb(rtwdev)) { 42848e93258fSBjoern A. Zeeb rtw89_write32_set(rtwdev, R_AX_SYS_SDIO_CTRL, 42858e93258fSBjoern A. Zeeb B_AX_PCIE_DIS_L2_CTRL_LDO_HCI); 42868e93258fSBjoern A. Zeeb rtw89_write32_clr(rtwdev, R_AX_PCIE_INIT_CFG1, 42878e93258fSBjoern A. Zeeb B_AX_PCIE_PERST_KEEP_REG | B_AX_PCIE_TRAIN_KEEP_REG); 42888e93258fSBjoern A. Zeeb } else { 42898e93258fSBjoern A. Zeeb rtw89_write32_set(rtwdev, R_AX_PCIE_PS_CTRL_V1, 42908e93258fSBjoern A. Zeeb B_AX_CMAC_EXIT_L1_EN | B_AX_DMAC0_EXIT_L1_EN); 42918e93258fSBjoern A. Zeeb rtw89_write32_clr(rtwdev, R_AX_PCIE_PS_CTRL_V1, 42928e93258fSBjoern A. Zeeb B_AX_SEL_REQ_ENTR_L1); 42938e93258fSBjoern A. Zeeb } 42948e93258fSBjoern A. Zeeb rtw89_pci_l2_hci_ldo(rtwdev); 4295*6d67aabdSBjoern A. Zeeb rtw89_pci_disable_eq(rtwdev); 4296*6d67aabdSBjoern A. Zeeb rtw89_pci_cfg_dac(rtwdev); 42978e93258fSBjoern A. Zeeb rtw89_pci_filter_out(rtwdev); 42988e93258fSBjoern A. Zeeb rtw89_pci_link_cfg(rtwdev); 42998e93258fSBjoern A. Zeeb rtw89_pci_l1ss_cfg(rtwdev); 43008e93258fSBjoern A. Zeeb 43018e93258fSBjoern A. Zeeb return 0; 43028e93258fSBjoern A. Zeeb } 43038e93258fSBjoern A. Zeeb 43048e93258fSBjoern A. Zeeb SIMPLE_DEV_PM_OPS(rtw89_pm_ops, rtw89_pci_suspend, rtw89_pci_resume); 43058e93258fSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_pm_ops); 43068e93258fSBjoern A. Zeeb 4307*6d67aabdSBjoern A. Zeeb const struct rtw89_pci_gen_def rtw89_pci_gen_ax = { 4308*6d67aabdSBjoern A. Zeeb .isr_rdu = B_AX_RDU_INT, 4309*6d67aabdSBjoern A. Zeeb .isr_halt_c2h = B_AX_HALT_C2H_INT_EN, 4310*6d67aabdSBjoern A. Zeeb .isr_wdt_timeout = B_AX_WDT_TIMEOUT_INT_EN, 4311*6d67aabdSBjoern A. Zeeb .isr_clear_rpq = {R_AX_PCIE_HISR00, B_AX_RPQDMA_INT | B_AX_RPQBD_FULL_INT}, 4312*6d67aabdSBjoern A. Zeeb .isr_clear_rxq = {R_AX_PCIE_HISR00, B_AX_RXP1DMA_INT | B_AX_RXDMA_INT | 4313*6d67aabdSBjoern A. Zeeb B_AX_RDU_INT}, 4314*6d67aabdSBjoern A. Zeeb 4315*6d67aabdSBjoern A. Zeeb .mac_pre_init = rtw89_pci_ops_mac_pre_init_ax, 4316*6d67aabdSBjoern A. Zeeb .mac_pre_deinit = NULL, 4317*6d67aabdSBjoern A. Zeeb .mac_post_init = rtw89_pci_ops_mac_post_init_ax, 4318*6d67aabdSBjoern A. Zeeb 4319*6d67aabdSBjoern A. Zeeb .clr_idx_all = rtw89_pci_clr_idx_all_ax, 4320*6d67aabdSBjoern A. Zeeb .rst_bdram = rtw89_pci_rst_bdram_ax, 4321*6d67aabdSBjoern A. Zeeb 4322*6d67aabdSBjoern A. Zeeb .lv1rst_stop_dma = rtw89_pci_lv1rst_stop_dma_ax, 4323*6d67aabdSBjoern A. Zeeb .lv1rst_start_dma = rtw89_pci_lv1rst_start_dma_ax, 4324*6d67aabdSBjoern A. Zeeb 4325*6d67aabdSBjoern A. Zeeb .ctrl_txdma_ch = rtw89_pci_ctrl_txdma_ch_ax, 4326*6d67aabdSBjoern A. Zeeb .ctrl_txdma_fw_ch = rtw89_pci_ctrl_txdma_fw_ch_ax, 4327*6d67aabdSBjoern A. Zeeb .poll_txdma_ch_idle = rtw89_pci_poll_txdma_ch_idle_ax, 4328*6d67aabdSBjoern A. Zeeb 4329*6d67aabdSBjoern A. Zeeb .aspm_set = rtw89_pci_aspm_set_ax, 4330*6d67aabdSBjoern A. Zeeb .clkreq_set = rtw89_pci_clkreq_set_ax, 4331*6d67aabdSBjoern A. Zeeb .l1ss_set = rtw89_pci_l1ss_set_ax, 4332*6d67aabdSBjoern A. Zeeb }; 4333*6d67aabdSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_pci_gen_ax); 4334*6d67aabdSBjoern A. Zeeb 43358e93258fSBjoern A. Zeeb static const struct rtw89_hci_ops rtw89_pci_ops = { 43368e93258fSBjoern A. Zeeb .tx_write = rtw89_pci_ops_tx_write, 43378e93258fSBjoern A. Zeeb .tx_kick_off = rtw89_pci_ops_tx_kick_off, 43388e93258fSBjoern A. Zeeb .flush_queues = rtw89_pci_ops_flush_queues, 43398e93258fSBjoern A. Zeeb .reset = rtw89_pci_ops_reset, 43408e93258fSBjoern A. Zeeb .start = rtw89_pci_ops_start, 43418e93258fSBjoern A. Zeeb .stop = rtw89_pci_ops_stop, 43428e93258fSBjoern A. Zeeb .pause = rtw89_pci_ops_pause, 43438e93258fSBjoern A. Zeeb .switch_mode = rtw89_pci_ops_switch_mode, 43448e93258fSBjoern A. Zeeb .recalc_int_mit = rtw89_pci_recalc_int_mit, 43458e93258fSBjoern A. Zeeb 43468e93258fSBjoern A. Zeeb .read8 = rtw89_pci_ops_read8, 43478e93258fSBjoern A. Zeeb .read16 = rtw89_pci_ops_read16, 43488e93258fSBjoern A. Zeeb .read32 = rtw89_pci_ops_read32, 43498e93258fSBjoern A. Zeeb .write8 = rtw89_pci_ops_write8, 43508e93258fSBjoern A. Zeeb .write16 = rtw89_pci_ops_write16, 43518e93258fSBjoern A. Zeeb .write32 = rtw89_pci_ops_write32, 43528e93258fSBjoern A. Zeeb 43538e93258fSBjoern A. Zeeb .mac_pre_init = rtw89_pci_ops_mac_pre_init, 4354*6d67aabdSBjoern A. Zeeb .mac_pre_deinit = rtw89_pci_ops_mac_pre_deinit, 43558e93258fSBjoern A. Zeeb .mac_post_init = rtw89_pci_ops_mac_post_init, 43568e93258fSBjoern A. Zeeb .deinit = rtw89_pci_ops_deinit, 43578e93258fSBjoern A. Zeeb 43588e93258fSBjoern A. Zeeb .check_and_reclaim_tx_resource = rtw89_pci_check_and_reclaim_tx_resource, 43598e93258fSBjoern A. Zeeb .mac_lv1_rcvy = rtw89_pci_ops_mac_lv1_recovery, 43608e93258fSBjoern A. Zeeb .dump_err_status = rtw89_pci_ops_dump_err_status, 43618e93258fSBjoern A. Zeeb .napi_poll = rtw89_pci_napi_poll, 43628e93258fSBjoern A. Zeeb 43638e93258fSBjoern A. Zeeb .recovery_start = rtw89_pci_ops_recovery_start, 43648e93258fSBjoern A. Zeeb .recovery_complete = rtw89_pci_ops_recovery_complete, 4365e2340276SBjoern A. Zeeb 4366*6d67aabdSBjoern A. Zeeb .ctrl_txdma_ch = rtw89_pci_ctrl_txdma_ch, 4367*6d67aabdSBjoern A. Zeeb .ctrl_txdma_fw_ch = rtw89_pci_ctrl_txdma_fw_ch, 4368e2340276SBjoern A. Zeeb .ctrl_trxhci = rtw89_pci_ctrl_dma_trx, 4369*6d67aabdSBjoern A. Zeeb .poll_txdma_ch_idle = rtw89_pci_poll_txdma_ch_idle, 4370*6d67aabdSBjoern A. Zeeb 4371e2340276SBjoern A. Zeeb .clr_idx_all = rtw89_pci_clr_idx_all, 4372e2340276SBjoern A. Zeeb .clear = rtw89_pci_clear_resource, 4373e2340276SBjoern A. Zeeb .disable_intr = rtw89_pci_disable_intr_lock, 4374e2340276SBjoern A. Zeeb .enable_intr = rtw89_pci_enable_intr_lock, 4375*6d67aabdSBjoern A. Zeeb .rst_bdram = rtw89_pci_reset_bdram, 43768e93258fSBjoern A. Zeeb }; 43778e93258fSBjoern A. Zeeb 43788e93258fSBjoern A. Zeeb int rtw89_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) 43798e93258fSBjoern A. Zeeb { 43808e93258fSBjoern A. Zeeb struct rtw89_dev *rtwdev; 43818e93258fSBjoern A. Zeeb const struct rtw89_driver_info *info; 43828e93258fSBjoern A. Zeeb const struct rtw89_pci_info *pci_info; 43838e93258fSBjoern A. Zeeb int ret; 43848e93258fSBjoern A. Zeeb 43858e93258fSBjoern A. Zeeb info = (const struct rtw89_driver_info *)id->driver_data; 43868e93258fSBjoern A. Zeeb 43878e93258fSBjoern A. Zeeb rtwdev = rtw89_alloc_ieee80211_hw(&pdev->dev, 43888e93258fSBjoern A. Zeeb sizeof(struct rtw89_pci), 43898e93258fSBjoern A. Zeeb info->chip); 43908e93258fSBjoern A. Zeeb if (!rtwdev) { 43918e93258fSBjoern A. Zeeb dev_err(&pdev->dev, "failed to allocate hw\n"); 43928e93258fSBjoern A. Zeeb return -ENOMEM; 43938e93258fSBjoern A. Zeeb } 43948e93258fSBjoern A. Zeeb 43958e93258fSBjoern A. Zeeb pci_info = info->bus.pci; 43968e93258fSBjoern A. Zeeb 43978e93258fSBjoern A. Zeeb rtwdev->pci_info = info->bus.pci; 43988e93258fSBjoern A. Zeeb rtwdev->hci.ops = &rtw89_pci_ops; 43998e93258fSBjoern A. Zeeb rtwdev->hci.type = RTW89_HCI_TYPE_PCIE; 44008e93258fSBjoern A. Zeeb rtwdev->hci.rpwm_addr = pci_info->rpwm_addr; 44018e93258fSBjoern A. Zeeb rtwdev->hci.cpwm_addr = pci_info->cpwm_addr; 44028e93258fSBjoern A. Zeeb 4403*6d67aabdSBjoern A. Zeeb rtw89_check_quirks(rtwdev, info->quirks); 4404*6d67aabdSBjoern A. Zeeb 44058e93258fSBjoern A. Zeeb SET_IEEE80211_DEV(rtwdev->hw, &pdev->dev); 44068e93258fSBjoern A. Zeeb 44078e93258fSBjoern A. Zeeb ret = rtw89_core_init(rtwdev); 44088e93258fSBjoern A. Zeeb if (ret) { 44098e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "failed to initialise core\n"); 44108e93258fSBjoern A. Zeeb goto err_release_hw; 44118e93258fSBjoern A. Zeeb } 44128e93258fSBjoern A. Zeeb 44138e93258fSBjoern A. Zeeb ret = rtw89_pci_claim_device(rtwdev, pdev); 44148e93258fSBjoern A. Zeeb if (ret) { 44158e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "failed to claim pci device\n"); 44168e93258fSBjoern A. Zeeb goto err_core_deinit; 44178e93258fSBjoern A. Zeeb } 44188e93258fSBjoern A. Zeeb 44198e93258fSBjoern A. Zeeb ret = rtw89_pci_setup_resource(rtwdev, pdev); 44208e93258fSBjoern A. Zeeb if (ret) { 44218e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "failed to setup pci resource\n"); 44228e93258fSBjoern A. Zeeb goto err_declaim_pci; 44238e93258fSBjoern A. Zeeb } 44248e93258fSBjoern A. Zeeb 44258e93258fSBjoern A. Zeeb ret = rtw89_chip_info_setup(rtwdev); 44268e93258fSBjoern A. Zeeb if (ret) { 44278e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "failed to setup chip information\n"); 44288e93258fSBjoern A. Zeeb goto err_clear_resource; 44298e93258fSBjoern A. Zeeb } 44308e93258fSBjoern A. Zeeb 4431*6d67aabdSBjoern A. Zeeb rtw89_pci_disable_eq(rtwdev); 44328e93258fSBjoern A. Zeeb rtw89_pci_filter_out(rtwdev); 44338e93258fSBjoern A. Zeeb rtw89_pci_link_cfg(rtwdev); 44348e93258fSBjoern A. Zeeb rtw89_pci_l1ss_cfg(rtwdev); 44358e93258fSBjoern A. Zeeb 4436*6d67aabdSBjoern A. Zeeb ret = rtw89_core_napi_init(rtwdev); 4437*6d67aabdSBjoern A. Zeeb if (ret) { 4438*6d67aabdSBjoern A. Zeeb rtw89_err(rtwdev, "failed to init napi\n"); 4439*6d67aabdSBjoern A. Zeeb goto err_clear_resource; 4440*6d67aabdSBjoern A. Zeeb } 44418e93258fSBjoern A. Zeeb 44428e93258fSBjoern A. Zeeb ret = rtw89_pci_request_irq(rtwdev, pdev); 44438e93258fSBjoern A. Zeeb if (ret) { 44448e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "failed to request pci irq\n"); 4445e2340276SBjoern A. Zeeb goto err_deinit_napi; 4446e2340276SBjoern A. Zeeb } 4447e2340276SBjoern A. Zeeb 4448e2340276SBjoern A. Zeeb ret = rtw89_core_register(rtwdev); 4449e2340276SBjoern A. Zeeb if (ret) { 4450e2340276SBjoern A. Zeeb rtw89_err(rtwdev, "failed to register core\n"); 4451e2340276SBjoern A. Zeeb goto err_free_irq; 44528e93258fSBjoern A. Zeeb } 44538e93258fSBjoern A. Zeeb 4454*6d67aabdSBjoern A. Zeeb set_bit(RTW89_FLAG_PROBE_DONE, rtwdev->flags); 4455*6d67aabdSBjoern A. Zeeb 44568e93258fSBjoern A. Zeeb return 0; 44578e93258fSBjoern A. Zeeb 4458e2340276SBjoern A. Zeeb err_free_irq: 4459e2340276SBjoern A. Zeeb rtw89_pci_free_irq(rtwdev, pdev); 4460e2340276SBjoern A. Zeeb err_deinit_napi: 44618e93258fSBjoern A. Zeeb rtw89_core_napi_deinit(rtwdev); 44628e93258fSBjoern A. Zeeb err_clear_resource: 44638e93258fSBjoern A. Zeeb rtw89_pci_clear_resource(rtwdev, pdev); 44648e93258fSBjoern A. Zeeb err_declaim_pci: 44658e93258fSBjoern A. Zeeb rtw89_pci_declaim_device(rtwdev, pdev); 44668e93258fSBjoern A. Zeeb err_core_deinit: 44678e93258fSBjoern A. Zeeb rtw89_core_deinit(rtwdev); 44688e93258fSBjoern A. Zeeb err_release_hw: 44698e93258fSBjoern A. Zeeb rtw89_free_ieee80211_hw(rtwdev); 44708e93258fSBjoern A. Zeeb 44718e93258fSBjoern A. Zeeb return ret; 44728e93258fSBjoern A. Zeeb } 44738e93258fSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_pci_probe); 44748e93258fSBjoern A. Zeeb 44758e93258fSBjoern A. Zeeb void rtw89_pci_remove(struct pci_dev *pdev) 44768e93258fSBjoern A. Zeeb { 44778e93258fSBjoern A. Zeeb struct ieee80211_hw *hw = pci_get_drvdata(pdev); 44788e93258fSBjoern A. Zeeb struct rtw89_dev *rtwdev; 44798e93258fSBjoern A. Zeeb 44808e93258fSBjoern A. Zeeb rtwdev = hw->priv; 44818e93258fSBjoern A. Zeeb 44828e93258fSBjoern A. Zeeb rtw89_pci_free_irq(rtwdev, pdev); 44838e93258fSBjoern A. Zeeb rtw89_core_napi_deinit(rtwdev); 44848e93258fSBjoern A. Zeeb rtw89_core_unregister(rtwdev); 44858e93258fSBjoern A. Zeeb rtw89_pci_clear_resource(rtwdev, pdev); 44868e93258fSBjoern A. Zeeb rtw89_pci_declaim_device(rtwdev, pdev); 44878e93258fSBjoern A. Zeeb rtw89_core_deinit(rtwdev); 44888e93258fSBjoern A. Zeeb rtw89_free_ieee80211_hw(rtwdev); 44898e93258fSBjoern A. Zeeb } 44908e93258fSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_pci_remove); 44918e93258fSBjoern A. Zeeb 44928e93258fSBjoern A. Zeeb MODULE_AUTHOR("Realtek Corporation"); 4493*6d67aabdSBjoern A. Zeeb MODULE_DESCRIPTION("Realtek PCI 802.11ax wireless driver"); 44948e93258fSBjoern A. Zeeb MODULE_LICENSE("Dual BSD/GPL"); 44958e93258fSBjoern A. Zeeb #if defined(__FreeBSD__) 44968e93258fSBjoern A. Zeeb MODULE_VERSION(rtw89_pci, 1); 44978e93258fSBjoern A. Zeeb MODULE_DEPEND(rtw89_pci, linuxkpi, 1, 1, 1); 44988e93258fSBjoern A. Zeeb MODULE_DEPEND(rtw89_pci, linuxkpi_wlan, 1, 1, 1); 44998e93258fSBjoern A. Zeeb #ifdef CONFIG_RTW89_DEBUGFS 45001a2b5573SBjoern A. Zeeb MODULE_DEPEND(rtw89_pci, lindebugfs, 1, 1, 1); 45018e93258fSBjoern A. Zeeb #endif 45028e93258fSBjoern A. Zeeb #endif 4503