162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 262306a36Sopenharmony_ci/* Copyright(c) 2018-2019 Realtek Corporation 362306a36Sopenharmony_ci */ 462306a36Sopenharmony_ci 562306a36Sopenharmony_ci#include <linux/module.h> 662306a36Sopenharmony_ci#include <linux/pci.h> 762306a36Sopenharmony_ci#include "main.h" 862306a36Sopenharmony_ci#include "pci.h" 962306a36Sopenharmony_ci#include "reg.h" 1062306a36Sopenharmony_ci#include "tx.h" 1162306a36Sopenharmony_ci#include "rx.h" 1262306a36Sopenharmony_ci#include "fw.h" 1362306a36Sopenharmony_ci#include "ps.h" 1462306a36Sopenharmony_ci#include "debug.h" 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_cistatic bool rtw_disable_msi; 1762306a36Sopenharmony_cistatic bool rtw_pci_disable_aspm; 1862306a36Sopenharmony_cimodule_param_named(disable_msi, rtw_disable_msi, bool, 0644); 1962306a36Sopenharmony_cimodule_param_named(disable_aspm, rtw_pci_disable_aspm, bool, 0644); 2062306a36Sopenharmony_ciMODULE_PARM_DESC(disable_msi, "Set Y to disable MSI interrupt support"); 2162306a36Sopenharmony_ciMODULE_PARM_DESC(disable_aspm, "Set Y to disable PCI ASPM support"); 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_cistatic u32 rtw_pci_tx_queue_idx_addr[] = { 2462306a36Sopenharmony_ci [RTW_TX_QUEUE_BK] = RTK_PCI_TXBD_IDX_BKQ, 2562306a36Sopenharmony_ci [RTW_TX_QUEUE_BE] = RTK_PCI_TXBD_IDX_BEQ, 2662306a36Sopenharmony_ci [RTW_TX_QUEUE_VI] = RTK_PCI_TXBD_IDX_VIQ, 2762306a36Sopenharmony_ci [RTW_TX_QUEUE_VO] = RTK_PCI_TXBD_IDX_VOQ, 2862306a36Sopenharmony_ci [RTW_TX_QUEUE_MGMT] = RTK_PCI_TXBD_IDX_MGMTQ, 2962306a36Sopenharmony_ci [RTW_TX_QUEUE_HI0] = RTK_PCI_TXBD_IDX_HI0Q, 3062306a36Sopenharmony_ci [RTW_TX_QUEUE_H2C] = RTK_PCI_TXBD_IDX_H2CQ, 3162306a36Sopenharmony_ci}; 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_cistatic u8 rtw_pci_get_tx_qsel(struct sk_buff *skb, 3462306a36Sopenharmony_ci enum rtw_tx_queue_type queue) 3562306a36Sopenharmony_ci{ 3662306a36Sopenharmony_ci switch (queue) { 3762306a36Sopenharmony_ci case RTW_TX_QUEUE_BCN: 3862306a36Sopenharmony_ci return TX_DESC_QSEL_BEACON; 3962306a36Sopenharmony_ci case RTW_TX_QUEUE_H2C: 4062306a36Sopenharmony_ci return TX_DESC_QSEL_H2C; 4162306a36Sopenharmony_ci case RTW_TX_QUEUE_MGMT: 4262306a36Sopenharmony_ci return TX_DESC_QSEL_MGMT; 4362306a36Sopenharmony_ci case RTW_TX_QUEUE_HI0: 4462306a36Sopenharmony_ci return TX_DESC_QSEL_HIGH; 4562306a36Sopenharmony_ci default: 4662306a36Sopenharmony_ci return skb->priority; 4762306a36Sopenharmony_ci } 4862306a36Sopenharmony_ci}; 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_cistatic u8 rtw_pci_read8(struct rtw_dev *rtwdev, u32 addr) 5162306a36Sopenharmony_ci{ 5262306a36Sopenharmony_ci struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci return readb(rtwpci->mmap + addr); 5562306a36Sopenharmony_ci} 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_cistatic u16 rtw_pci_read16(struct rtw_dev *rtwdev, u32 addr) 5862306a36Sopenharmony_ci{ 5962306a36Sopenharmony_ci struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci return readw(rtwpci->mmap + addr); 6262306a36Sopenharmony_ci} 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_cistatic u32 rtw_pci_read32(struct rtw_dev *rtwdev, u32 addr) 6562306a36Sopenharmony_ci{ 6662306a36Sopenharmony_ci struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci return readl(rtwpci->mmap + addr); 6962306a36Sopenharmony_ci} 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_cistatic void rtw_pci_write8(struct rtw_dev *rtwdev, u32 addr, u8 val) 7262306a36Sopenharmony_ci{ 7362306a36Sopenharmony_ci struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci writeb(val, rtwpci->mmap + addr); 7662306a36Sopenharmony_ci} 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_cistatic void rtw_pci_write16(struct rtw_dev *rtwdev, u32 addr, u16 val) 7962306a36Sopenharmony_ci{ 8062306a36Sopenharmony_ci struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci writew(val, rtwpci->mmap + addr); 8362306a36Sopenharmony_ci} 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_cistatic void rtw_pci_write32(struct rtw_dev *rtwdev, u32 addr, u32 val) 8662306a36Sopenharmony_ci{ 8762306a36Sopenharmony_ci struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci writel(val, rtwpci->mmap + addr); 9062306a36Sopenharmony_ci} 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_cistatic void rtw_pci_free_tx_ring_skbs(struct rtw_dev *rtwdev, 9362306a36Sopenharmony_ci struct rtw_pci_tx_ring *tx_ring) 9462306a36Sopenharmony_ci{ 9562306a36Sopenharmony_ci struct pci_dev *pdev = to_pci_dev(rtwdev->dev); 9662306a36Sopenharmony_ci struct rtw_pci_tx_data *tx_data; 9762306a36Sopenharmony_ci struct sk_buff *skb, *tmp; 9862306a36Sopenharmony_ci dma_addr_t dma; 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci /* free every skb remained in tx list */ 10162306a36Sopenharmony_ci skb_queue_walk_safe(&tx_ring->queue, skb, tmp) { 10262306a36Sopenharmony_ci __skb_unlink(skb, &tx_ring->queue); 10362306a36Sopenharmony_ci tx_data = rtw_pci_get_tx_data(skb); 10462306a36Sopenharmony_ci dma = tx_data->dma; 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci dma_unmap_single(&pdev->dev, dma, skb->len, DMA_TO_DEVICE); 10762306a36Sopenharmony_ci dev_kfree_skb_any(skb); 10862306a36Sopenharmony_ci } 10962306a36Sopenharmony_ci} 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_cistatic void rtw_pci_free_tx_ring(struct rtw_dev *rtwdev, 11262306a36Sopenharmony_ci struct rtw_pci_tx_ring *tx_ring) 11362306a36Sopenharmony_ci{ 11462306a36Sopenharmony_ci struct pci_dev *pdev = to_pci_dev(rtwdev->dev); 11562306a36Sopenharmony_ci u8 *head = tx_ring->r.head; 11662306a36Sopenharmony_ci u32 len = tx_ring->r.len; 11762306a36Sopenharmony_ci int ring_sz = len * tx_ring->r.desc_size; 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci rtw_pci_free_tx_ring_skbs(rtwdev, tx_ring); 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci /* free the ring itself */ 12262306a36Sopenharmony_ci dma_free_coherent(&pdev->dev, ring_sz, head, tx_ring->r.dma); 12362306a36Sopenharmony_ci tx_ring->r.head = NULL; 12462306a36Sopenharmony_ci} 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_cistatic void rtw_pci_free_rx_ring_skbs(struct rtw_dev *rtwdev, 12762306a36Sopenharmony_ci struct rtw_pci_rx_ring *rx_ring) 12862306a36Sopenharmony_ci{ 12962306a36Sopenharmony_ci struct pci_dev *pdev = to_pci_dev(rtwdev->dev); 13062306a36Sopenharmony_ci struct sk_buff *skb; 13162306a36Sopenharmony_ci int buf_sz = RTK_PCI_RX_BUF_SIZE; 13262306a36Sopenharmony_ci dma_addr_t dma; 13362306a36Sopenharmony_ci int i; 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci for (i = 0; i < rx_ring->r.len; i++) { 13662306a36Sopenharmony_ci skb = rx_ring->buf[i]; 13762306a36Sopenharmony_ci if (!skb) 13862306a36Sopenharmony_ci continue; 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci dma = *((dma_addr_t *)skb->cb); 14162306a36Sopenharmony_ci dma_unmap_single(&pdev->dev, dma, buf_sz, DMA_FROM_DEVICE); 14262306a36Sopenharmony_ci dev_kfree_skb(skb); 14362306a36Sopenharmony_ci rx_ring->buf[i] = NULL; 14462306a36Sopenharmony_ci } 14562306a36Sopenharmony_ci} 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_cistatic void rtw_pci_free_rx_ring(struct rtw_dev *rtwdev, 14862306a36Sopenharmony_ci struct rtw_pci_rx_ring *rx_ring) 14962306a36Sopenharmony_ci{ 15062306a36Sopenharmony_ci struct pci_dev *pdev = to_pci_dev(rtwdev->dev); 15162306a36Sopenharmony_ci u8 *head = rx_ring->r.head; 15262306a36Sopenharmony_ci int ring_sz = rx_ring->r.desc_size * rx_ring->r.len; 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci rtw_pci_free_rx_ring_skbs(rtwdev, rx_ring); 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci dma_free_coherent(&pdev->dev, ring_sz, head, rx_ring->r.dma); 15762306a36Sopenharmony_ci} 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_cistatic void rtw_pci_free_trx_ring(struct rtw_dev *rtwdev) 16062306a36Sopenharmony_ci{ 16162306a36Sopenharmony_ci struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; 16262306a36Sopenharmony_ci struct rtw_pci_tx_ring *tx_ring; 16362306a36Sopenharmony_ci struct rtw_pci_rx_ring *rx_ring; 16462306a36Sopenharmony_ci int i; 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci for (i = 0; i < RTK_MAX_TX_QUEUE_NUM; i++) { 16762306a36Sopenharmony_ci tx_ring = &rtwpci->tx_rings[i]; 16862306a36Sopenharmony_ci rtw_pci_free_tx_ring(rtwdev, tx_ring); 16962306a36Sopenharmony_ci } 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci for (i = 0; i < RTK_MAX_RX_QUEUE_NUM; i++) { 17262306a36Sopenharmony_ci rx_ring = &rtwpci->rx_rings[i]; 17362306a36Sopenharmony_ci rtw_pci_free_rx_ring(rtwdev, rx_ring); 17462306a36Sopenharmony_ci } 17562306a36Sopenharmony_ci} 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_cistatic int rtw_pci_init_tx_ring(struct rtw_dev *rtwdev, 17862306a36Sopenharmony_ci struct rtw_pci_tx_ring *tx_ring, 17962306a36Sopenharmony_ci u8 desc_size, u32 len) 18062306a36Sopenharmony_ci{ 18162306a36Sopenharmony_ci struct pci_dev *pdev = to_pci_dev(rtwdev->dev); 18262306a36Sopenharmony_ci int ring_sz = desc_size * len; 18362306a36Sopenharmony_ci dma_addr_t dma; 18462306a36Sopenharmony_ci u8 *head; 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci if (len > TRX_BD_IDX_MASK) { 18762306a36Sopenharmony_ci rtw_err(rtwdev, "len %d exceeds maximum TX entries\n", len); 18862306a36Sopenharmony_ci return -EINVAL; 18962306a36Sopenharmony_ci } 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci head = dma_alloc_coherent(&pdev->dev, ring_sz, &dma, GFP_KERNEL); 19262306a36Sopenharmony_ci if (!head) { 19362306a36Sopenharmony_ci rtw_err(rtwdev, "failed to allocate tx ring\n"); 19462306a36Sopenharmony_ci return -ENOMEM; 19562306a36Sopenharmony_ci } 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci skb_queue_head_init(&tx_ring->queue); 19862306a36Sopenharmony_ci tx_ring->r.head = head; 19962306a36Sopenharmony_ci tx_ring->r.dma = dma; 20062306a36Sopenharmony_ci tx_ring->r.len = len; 20162306a36Sopenharmony_ci tx_ring->r.desc_size = desc_size; 20262306a36Sopenharmony_ci tx_ring->r.wp = 0; 20362306a36Sopenharmony_ci tx_ring->r.rp = 0; 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci return 0; 20662306a36Sopenharmony_ci} 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_cistatic int rtw_pci_reset_rx_desc(struct rtw_dev *rtwdev, struct sk_buff *skb, 20962306a36Sopenharmony_ci struct rtw_pci_rx_ring *rx_ring, 21062306a36Sopenharmony_ci u32 idx, u32 desc_sz) 21162306a36Sopenharmony_ci{ 21262306a36Sopenharmony_ci struct pci_dev *pdev = to_pci_dev(rtwdev->dev); 21362306a36Sopenharmony_ci struct rtw_pci_rx_buffer_desc *buf_desc; 21462306a36Sopenharmony_ci int buf_sz = RTK_PCI_RX_BUF_SIZE; 21562306a36Sopenharmony_ci dma_addr_t dma; 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci if (!skb) 21862306a36Sopenharmony_ci return -EINVAL; 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci dma = dma_map_single(&pdev->dev, skb->data, buf_sz, DMA_FROM_DEVICE); 22162306a36Sopenharmony_ci if (dma_mapping_error(&pdev->dev, dma)) 22262306a36Sopenharmony_ci return -EBUSY; 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci *((dma_addr_t *)skb->cb) = dma; 22562306a36Sopenharmony_ci buf_desc = (struct rtw_pci_rx_buffer_desc *)(rx_ring->r.head + 22662306a36Sopenharmony_ci idx * desc_sz); 22762306a36Sopenharmony_ci memset(buf_desc, 0, sizeof(*buf_desc)); 22862306a36Sopenharmony_ci buf_desc->buf_size = cpu_to_le16(RTK_PCI_RX_BUF_SIZE); 22962306a36Sopenharmony_ci buf_desc->dma = cpu_to_le32(dma); 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci return 0; 23262306a36Sopenharmony_ci} 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_cistatic void rtw_pci_sync_rx_desc_device(struct rtw_dev *rtwdev, dma_addr_t dma, 23562306a36Sopenharmony_ci struct rtw_pci_rx_ring *rx_ring, 23662306a36Sopenharmony_ci u32 idx, u32 desc_sz) 23762306a36Sopenharmony_ci{ 23862306a36Sopenharmony_ci struct device *dev = rtwdev->dev; 23962306a36Sopenharmony_ci struct rtw_pci_rx_buffer_desc *buf_desc; 24062306a36Sopenharmony_ci int buf_sz = RTK_PCI_RX_BUF_SIZE; 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ci dma_sync_single_for_device(dev, dma, buf_sz, DMA_FROM_DEVICE); 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci buf_desc = (struct rtw_pci_rx_buffer_desc *)(rx_ring->r.head + 24562306a36Sopenharmony_ci idx * desc_sz); 24662306a36Sopenharmony_ci memset(buf_desc, 0, sizeof(*buf_desc)); 24762306a36Sopenharmony_ci buf_desc->buf_size = cpu_to_le16(RTK_PCI_RX_BUF_SIZE); 24862306a36Sopenharmony_ci buf_desc->dma = cpu_to_le32(dma); 24962306a36Sopenharmony_ci} 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_cistatic int rtw_pci_init_rx_ring(struct rtw_dev *rtwdev, 25262306a36Sopenharmony_ci struct rtw_pci_rx_ring *rx_ring, 25362306a36Sopenharmony_ci u8 desc_size, u32 len) 25462306a36Sopenharmony_ci{ 25562306a36Sopenharmony_ci struct pci_dev *pdev = to_pci_dev(rtwdev->dev); 25662306a36Sopenharmony_ci struct sk_buff *skb = NULL; 25762306a36Sopenharmony_ci dma_addr_t dma; 25862306a36Sopenharmony_ci u8 *head; 25962306a36Sopenharmony_ci int ring_sz = desc_size * len; 26062306a36Sopenharmony_ci int buf_sz = RTK_PCI_RX_BUF_SIZE; 26162306a36Sopenharmony_ci int i, allocated; 26262306a36Sopenharmony_ci int ret = 0; 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ci head = dma_alloc_coherent(&pdev->dev, ring_sz, &dma, GFP_KERNEL); 26562306a36Sopenharmony_ci if (!head) { 26662306a36Sopenharmony_ci rtw_err(rtwdev, "failed to allocate rx ring\n"); 26762306a36Sopenharmony_ci return -ENOMEM; 26862306a36Sopenharmony_ci } 26962306a36Sopenharmony_ci rx_ring->r.head = head; 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci for (i = 0; i < len; i++) { 27262306a36Sopenharmony_ci skb = dev_alloc_skb(buf_sz); 27362306a36Sopenharmony_ci if (!skb) { 27462306a36Sopenharmony_ci allocated = i; 27562306a36Sopenharmony_ci ret = -ENOMEM; 27662306a36Sopenharmony_ci goto err_out; 27762306a36Sopenharmony_ci } 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci memset(skb->data, 0, buf_sz); 28062306a36Sopenharmony_ci rx_ring->buf[i] = skb; 28162306a36Sopenharmony_ci ret = rtw_pci_reset_rx_desc(rtwdev, skb, rx_ring, i, desc_size); 28262306a36Sopenharmony_ci if (ret) { 28362306a36Sopenharmony_ci allocated = i; 28462306a36Sopenharmony_ci dev_kfree_skb_any(skb); 28562306a36Sopenharmony_ci goto err_out; 28662306a36Sopenharmony_ci } 28762306a36Sopenharmony_ci } 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ci rx_ring->r.dma = dma; 29062306a36Sopenharmony_ci rx_ring->r.len = len; 29162306a36Sopenharmony_ci rx_ring->r.desc_size = desc_size; 29262306a36Sopenharmony_ci rx_ring->r.wp = 0; 29362306a36Sopenharmony_ci rx_ring->r.rp = 0; 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci return 0; 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_cierr_out: 29862306a36Sopenharmony_ci for (i = 0; i < allocated; i++) { 29962306a36Sopenharmony_ci skb = rx_ring->buf[i]; 30062306a36Sopenharmony_ci if (!skb) 30162306a36Sopenharmony_ci continue; 30262306a36Sopenharmony_ci dma = *((dma_addr_t *)skb->cb); 30362306a36Sopenharmony_ci dma_unmap_single(&pdev->dev, dma, buf_sz, DMA_FROM_DEVICE); 30462306a36Sopenharmony_ci dev_kfree_skb_any(skb); 30562306a36Sopenharmony_ci rx_ring->buf[i] = NULL; 30662306a36Sopenharmony_ci } 30762306a36Sopenharmony_ci dma_free_coherent(&pdev->dev, ring_sz, head, dma); 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ci rtw_err(rtwdev, "failed to init rx buffer\n"); 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci return ret; 31262306a36Sopenharmony_ci} 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_cistatic int rtw_pci_init_trx_ring(struct rtw_dev *rtwdev) 31562306a36Sopenharmony_ci{ 31662306a36Sopenharmony_ci struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; 31762306a36Sopenharmony_ci struct rtw_pci_tx_ring *tx_ring; 31862306a36Sopenharmony_ci struct rtw_pci_rx_ring *rx_ring; 31962306a36Sopenharmony_ci const struct rtw_chip_info *chip = rtwdev->chip; 32062306a36Sopenharmony_ci int i = 0, j = 0, tx_alloced = 0, rx_alloced = 0; 32162306a36Sopenharmony_ci int tx_desc_size, rx_desc_size; 32262306a36Sopenharmony_ci u32 len; 32362306a36Sopenharmony_ci int ret; 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci tx_desc_size = chip->tx_buf_desc_sz; 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci for (i = 0; i < RTK_MAX_TX_QUEUE_NUM; i++) { 32862306a36Sopenharmony_ci tx_ring = &rtwpci->tx_rings[i]; 32962306a36Sopenharmony_ci len = max_num_of_tx_queue(i); 33062306a36Sopenharmony_ci ret = rtw_pci_init_tx_ring(rtwdev, tx_ring, tx_desc_size, len); 33162306a36Sopenharmony_ci if (ret) 33262306a36Sopenharmony_ci goto out; 33362306a36Sopenharmony_ci } 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci rx_desc_size = chip->rx_buf_desc_sz; 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci for (j = 0; j < RTK_MAX_RX_QUEUE_NUM; j++) { 33862306a36Sopenharmony_ci rx_ring = &rtwpci->rx_rings[j]; 33962306a36Sopenharmony_ci ret = rtw_pci_init_rx_ring(rtwdev, rx_ring, rx_desc_size, 34062306a36Sopenharmony_ci RTK_MAX_RX_DESC_NUM); 34162306a36Sopenharmony_ci if (ret) 34262306a36Sopenharmony_ci goto out; 34362306a36Sopenharmony_ci } 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci return 0; 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ciout: 34862306a36Sopenharmony_ci tx_alloced = i; 34962306a36Sopenharmony_ci for (i = 0; i < tx_alloced; i++) { 35062306a36Sopenharmony_ci tx_ring = &rtwpci->tx_rings[i]; 35162306a36Sopenharmony_ci rtw_pci_free_tx_ring(rtwdev, tx_ring); 35262306a36Sopenharmony_ci } 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci rx_alloced = j; 35562306a36Sopenharmony_ci for (j = 0; j < rx_alloced; j++) { 35662306a36Sopenharmony_ci rx_ring = &rtwpci->rx_rings[j]; 35762306a36Sopenharmony_ci rtw_pci_free_rx_ring(rtwdev, rx_ring); 35862306a36Sopenharmony_ci } 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_ci return ret; 36162306a36Sopenharmony_ci} 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_cistatic void rtw_pci_deinit(struct rtw_dev *rtwdev) 36462306a36Sopenharmony_ci{ 36562306a36Sopenharmony_ci rtw_pci_free_trx_ring(rtwdev); 36662306a36Sopenharmony_ci} 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_cistatic int rtw_pci_init(struct rtw_dev *rtwdev) 36962306a36Sopenharmony_ci{ 37062306a36Sopenharmony_ci struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; 37162306a36Sopenharmony_ci int ret = 0; 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci rtwpci->irq_mask[0] = IMR_HIGHDOK | 37462306a36Sopenharmony_ci IMR_MGNTDOK | 37562306a36Sopenharmony_ci IMR_BKDOK | 37662306a36Sopenharmony_ci IMR_BEDOK | 37762306a36Sopenharmony_ci IMR_VIDOK | 37862306a36Sopenharmony_ci IMR_VODOK | 37962306a36Sopenharmony_ci IMR_ROK | 38062306a36Sopenharmony_ci IMR_BCNDMAINT_E | 38162306a36Sopenharmony_ci IMR_C2HCMD | 38262306a36Sopenharmony_ci 0; 38362306a36Sopenharmony_ci rtwpci->irq_mask[1] = IMR_TXFOVW | 38462306a36Sopenharmony_ci 0; 38562306a36Sopenharmony_ci rtwpci->irq_mask[3] = IMR_H2CDOK | 38662306a36Sopenharmony_ci 0; 38762306a36Sopenharmony_ci spin_lock_init(&rtwpci->irq_lock); 38862306a36Sopenharmony_ci spin_lock_init(&rtwpci->hwirq_lock); 38962306a36Sopenharmony_ci ret = rtw_pci_init_trx_ring(rtwdev); 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_ci return ret; 39262306a36Sopenharmony_ci} 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_cistatic void rtw_pci_reset_buf_desc(struct rtw_dev *rtwdev) 39562306a36Sopenharmony_ci{ 39662306a36Sopenharmony_ci struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; 39762306a36Sopenharmony_ci u32 len; 39862306a36Sopenharmony_ci u8 tmp; 39962306a36Sopenharmony_ci dma_addr_t dma; 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci tmp = rtw_read8(rtwdev, RTK_PCI_CTRL + 3); 40262306a36Sopenharmony_ci rtw_write8(rtwdev, RTK_PCI_CTRL + 3, tmp | 0xf7); 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ci dma = rtwpci->tx_rings[RTW_TX_QUEUE_BCN].r.dma; 40562306a36Sopenharmony_ci rtw_write32(rtwdev, RTK_PCI_TXBD_DESA_BCNQ, dma); 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ci if (!rtw_chip_wcpu_11n(rtwdev)) { 40862306a36Sopenharmony_ci len = rtwpci->tx_rings[RTW_TX_QUEUE_H2C].r.len; 40962306a36Sopenharmony_ci dma = rtwpci->tx_rings[RTW_TX_QUEUE_H2C].r.dma; 41062306a36Sopenharmony_ci rtwpci->tx_rings[RTW_TX_QUEUE_H2C].r.rp = 0; 41162306a36Sopenharmony_ci rtwpci->tx_rings[RTW_TX_QUEUE_H2C].r.wp = 0; 41262306a36Sopenharmony_ci rtw_write16(rtwdev, RTK_PCI_TXBD_NUM_H2CQ, len & TRX_BD_IDX_MASK); 41362306a36Sopenharmony_ci rtw_write32(rtwdev, RTK_PCI_TXBD_DESA_H2CQ, dma); 41462306a36Sopenharmony_ci } 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_ci len = rtwpci->tx_rings[RTW_TX_QUEUE_BK].r.len; 41762306a36Sopenharmony_ci dma = rtwpci->tx_rings[RTW_TX_QUEUE_BK].r.dma; 41862306a36Sopenharmony_ci rtwpci->tx_rings[RTW_TX_QUEUE_BK].r.rp = 0; 41962306a36Sopenharmony_ci rtwpci->tx_rings[RTW_TX_QUEUE_BK].r.wp = 0; 42062306a36Sopenharmony_ci rtw_write16(rtwdev, RTK_PCI_TXBD_NUM_BKQ, len & TRX_BD_IDX_MASK); 42162306a36Sopenharmony_ci rtw_write32(rtwdev, RTK_PCI_TXBD_DESA_BKQ, dma); 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_ci len = rtwpci->tx_rings[RTW_TX_QUEUE_BE].r.len; 42462306a36Sopenharmony_ci dma = rtwpci->tx_rings[RTW_TX_QUEUE_BE].r.dma; 42562306a36Sopenharmony_ci rtwpci->tx_rings[RTW_TX_QUEUE_BE].r.rp = 0; 42662306a36Sopenharmony_ci rtwpci->tx_rings[RTW_TX_QUEUE_BE].r.wp = 0; 42762306a36Sopenharmony_ci rtw_write16(rtwdev, RTK_PCI_TXBD_NUM_BEQ, len & TRX_BD_IDX_MASK); 42862306a36Sopenharmony_ci rtw_write32(rtwdev, RTK_PCI_TXBD_DESA_BEQ, dma); 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_ci len = rtwpci->tx_rings[RTW_TX_QUEUE_VO].r.len; 43162306a36Sopenharmony_ci dma = rtwpci->tx_rings[RTW_TX_QUEUE_VO].r.dma; 43262306a36Sopenharmony_ci rtwpci->tx_rings[RTW_TX_QUEUE_VO].r.rp = 0; 43362306a36Sopenharmony_ci rtwpci->tx_rings[RTW_TX_QUEUE_VO].r.wp = 0; 43462306a36Sopenharmony_ci rtw_write16(rtwdev, RTK_PCI_TXBD_NUM_VOQ, len & TRX_BD_IDX_MASK); 43562306a36Sopenharmony_ci rtw_write32(rtwdev, RTK_PCI_TXBD_DESA_VOQ, dma); 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_ci len = rtwpci->tx_rings[RTW_TX_QUEUE_VI].r.len; 43862306a36Sopenharmony_ci dma = rtwpci->tx_rings[RTW_TX_QUEUE_VI].r.dma; 43962306a36Sopenharmony_ci rtwpci->tx_rings[RTW_TX_QUEUE_VI].r.rp = 0; 44062306a36Sopenharmony_ci rtwpci->tx_rings[RTW_TX_QUEUE_VI].r.wp = 0; 44162306a36Sopenharmony_ci rtw_write16(rtwdev, RTK_PCI_TXBD_NUM_VIQ, len & TRX_BD_IDX_MASK); 44262306a36Sopenharmony_ci rtw_write32(rtwdev, RTK_PCI_TXBD_DESA_VIQ, dma); 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_ci len = rtwpci->tx_rings[RTW_TX_QUEUE_MGMT].r.len; 44562306a36Sopenharmony_ci dma = rtwpci->tx_rings[RTW_TX_QUEUE_MGMT].r.dma; 44662306a36Sopenharmony_ci rtwpci->tx_rings[RTW_TX_QUEUE_MGMT].r.rp = 0; 44762306a36Sopenharmony_ci rtwpci->tx_rings[RTW_TX_QUEUE_MGMT].r.wp = 0; 44862306a36Sopenharmony_ci rtw_write16(rtwdev, RTK_PCI_TXBD_NUM_MGMTQ, len & TRX_BD_IDX_MASK); 44962306a36Sopenharmony_ci rtw_write32(rtwdev, RTK_PCI_TXBD_DESA_MGMTQ, dma); 45062306a36Sopenharmony_ci 45162306a36Sopenharmony_ci len = rtwpci->tx_rings[RTW_TX_QUEUE_HI0].r.len; 45262306a36Sopenharmony_ci dma = rtwpci->tx_rings[RTW_TX_QUEUE_HI0].r.dma; 45362306a36Sopenharmony_ci rtwpci->tx_rings[RTW_TX_QUEUE_HI0].r.rp = 0; 45462306a36Sopenharmony_ci rtwpci->tx_rings[RTW_TX_QUEUE_HI0].r.wp = 0; 45562306a36Sopenharmony_ci rtw_write16(rtwdev, RTK_PCI_TXBD_NUM_HI0Q, len & TRX_BD_IDX_MASK); 45662306a36Sopenharmony_ci rtw_write32(rtwdev, RTK_PCI_TXBD_DESA_HI0Q, dma); 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_ci len = rtwpci->rx_rings[RTW_RX_QUEUE_MPDU].r.len; 45962306a36Sopenharmony_ci dma = rtwpci->rx_rings[RTW_RX_QUEUE_MPDU].r.dma; 46062306a36Sopenharmony_ci rtwpci->rx_rings[RTW_RX_QUEUE_MPDU].r.rp = 0; 46162306a36Sopenharmony_ci rtwpci->rx_rings[RTW_RX_QUEUE_MPDU].r.wp = 0; 46262306a36Sopenharmony_ci rtw_write16(rtwdev, RTK_PCI_RXBD_NUM_MPDUQ, len & TRX_BD_IDX_MASK); 46362306a36Sopenharmony_ci rtw_write32(rtwdev, RTK_PCI_RXBD_DESA_MPDUQ, dma); 46462306a36Sopenharmony_ci 46562306a36Sopenharmony_ci /* reset read/write point */ 46662306a36Sopenharmony_ci rtw_write32(rtwdev, RTK_PCI_TXBD_RWPTR_CLR, 0xffffffff); 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_ci /* reset H2C Queue index in a single write */ 46962306a36Sopenharmony_ci if (rtw_chip_wcpu_11ac(rtwdev)) 47062306a36Sopenharmony_ci rtw_write32_set(rtwdev, RTK_PCI_TXBD_H2CQ_CSR, 47162306a36Sopenharmony_ci BIT_CLR_H2CQ_HOST_IDX | BIT_CLR_H2CQ_HW_IDX); 47262306a36Sopenharmony_ci} 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_cistatic void rtw_pci_reset_trx_ring(struct rtw_dev *rtwdev) 47562306a36Sopenharmony_ci{ 47662306a36Sopenharmony_ci rtw_pci_reset_buf_desc(rtwdev); 47762306a36Sopenharmony_ci} 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_cistatic void rtw_pci_enable_interrupt(struct rtw_dev *rtwdev, 48062306a36Sopenharmony_ci struct rtw_pci *rtwpci, bool exclude_rx) 48162306a36Sopenharmony_ci{ 48262306a36Sopenharmony_ci unsigned long flags; 48362306a36Sopenharmony_ci u32 imr0_unmask = exclude_rx ? IMR_ROK : 0; 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_ci spin_lock_irqsave(&rtwpci->hwirq_lock, flags); 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_ci rtw_write32(rtwdev, RTK_PCI_HIMR0, rtwpci->irq_mask[0] & ~imr0_unmask); 48862306a36Sopenharmony_ci rtw_write32(rtwdev, RTK_PCI_HIMR1, rtwpci->irq_mask[1]); 48962306a36Sopenharmony_ci if (rtw_chip_wcpu_11ac(rtwdev)) 49062306a36Sopenharmony_ci rtw_write32(rtwdev, RTK_PCI_HIMR3, rtwpci->irq_mask[3]); 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci rtwpci->irq_enabled = true; 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_ci spin_unlock_irqrestore(&rtwpci->hwirq_lock, flags); 49562306a36Sopenharmony_ci} 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_cistatic void rtw_pci_disable_interrupt(struct rtw_dev *rtwdev, 49862306a36Sopenharmony_ci struct rtw_pci *rtwpci) 49962306a36Sopenharmony_ci{ 50062306a36Sopenharmony_ci unsigned long flags; 50162306a36Sopenharmony_ci 50262306a36Sopenharmony_ci spin_lock_irqsave(&rtwpci->hwirq_lock, flags); 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci if (!rtwpci->irq_enabled) 50562306a36Sopenharmony_ci goto out; 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_ci rtw_write32(rtwdev, RTK_PCI_HIMR0, 0); 50862306a36Sopenharmony_ci rtw_write32(rtwdev, RTK_PCI_HIMR1, 0); 50962306a36Sopenharmony_ci if (rtw_chip_wcpu_11ac(rtwdev)) 51062306a36Sopenharmony_ci rtw_write32(rtwdev, RTK_PCI_HIMR3, 0); 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_ci rtwpci->irq_enabled = false; 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_ciout: 51562306a36Sopenharmony_ci spin_unlock_irqrestore(&rtwpci->hwirq_lock, flags); 51662306a36Sopenharmony_ci} 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_cistatic void rtw_pci_dma_reset(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci) 51962306a36Sopenharmony_ci{ 52062306a36Sopenharmony_ci /* reset dma and rx tag */ 52162306a36Sopenharmony_ci rtw_write32_set(rtwdev, RTK_PCI_CTRL, 52262306a36Sopenharmony_ci BIT_RST_TRXDMA_INTF | BIT_RX_TAG_EN); 52362306a36Sopenharmony_ci rtwpci->rx_tag = 0; 52462306a36Sopenharmony_ci} 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_cistatic int rtw_pci_setup(struct rtw_dev *rtwdev) 52762306a36Sopenharmony_ci{ 52862306a36Sopenharmony_ci struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_ci rtw_pci_reset_trx_ring(rtwdev); 53162306a36Sopenharmony_ci rtw_pci_dma_reset(rtwdev, rtwpci); 53262306a36Sopenharmony_ci 53362306a36Sopenharmony_ci return 0; 53462306a36Sopenharmony_ci} 53562306a36Sopenharmony_ci 53662306a36Sopenharmony_cistatic void rtw_pci_dma_release(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci) 53762306a36Sopenharmony_ci{ 53862306a36Sopenharmony_ci struct rtw_pci_tx_ring *tx_ring; 53962306a36Sopenharmony_ci enum rtw_tx_queue_type queue; 54062306a36Sopenharmony_ci 54162306a36Sopenharmony_ci rtw_pci_reset_trx_ring(rtwdev); 54262306a36Sopenharmony_ci for (queue = 0; queue < RTK_MAX_TX_QUEUE_NUM; queue++) { 54362306a36Sopenharmony_ci tx_ring = &rtwpci->tx_rings[queue]; 54462306a36Sopenharmony_ci rtw_pci_free_tx_ring_skbs(rtwdev, tx_ring); 54562306a36Sopenharmony_ci } 54662306a36Sopenharmony_ci} 54762306a36Sopenharmony_ci 54862306a36Sopenharmony_cistatic void rtw_pci_napi_start(struct rtw_dev *rtwdev) 54962306a36Sopenharmony_ci{ 55062306a36Sopenharmony_ci struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; 55162306a36Sopenharmony_ci 55262306a36Sopenharmony_ci if (test_and_set_bit(RTW_PCI_FLAG_NAPI_RUNNING, rtwpci->flags)) 55362306a36Sopenharmony_ci return; 55462306a36Sopenharmony_ci 55562306a36Sopenharmony_ci napi_enable(&rtwpci->napi); 55662306a36Sopenharmony_ci} 55762306a36Sopenharmony_ci 55862306a36Sopenharmony_cistatic void rtw_pci_napi_stop(struct rtw_dev *rtwdev) 55962306a36Sopenharmony_ci{ 56062306a36Sopenharmony_ci struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_ci if (!test_and_clear_bit(RTW_PCI_FLAG_NAPI_RUNNING, rtwpci->flags)) 56362306a36Sopenharmony_ci return; 56462306a36Sopenharmony_ci 56562306a36Sopenharmony_ci napi_synchronize(&rtwpci->napi); 56662306a36Sopenharmony_ci napi_disable(&rtwpci->napi); 56762306a36Sopenharmony_ci} 56862306a36Sopenharmony_ci 56962306a36Sopenharmony_cistatic int rtw_pci_start(struct rtw_dev *rtwdev) 57062306a36Sopenharmony_ci{ 57162306a36Sopenharmony_ci struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; 57262306a36Sopenharmony_ci 57362306a36Sopenharmony_ci rtw_pci_napi_start(rtwdev); 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_ci spin_lock_bh(&rtwpci->irq_lock); 57662306a36Sopenharmony_ci rtwpci->running = true; 57762306a36Sopenharmony_ci rtw_pci_enable_interrupt(rtwdev, rtwpci, false); 57862306a36Sopenharmony_ci spin_unlock_bh(&rtwpci->irq_lock); 57962306a36Sopenharmony_ci 58062306a36Sopenharmony_ci return 0; 58162306a36Sopenharmony_ci} 58262306a36Sopenharmony_ci 58362306a36Sopenharmony_cistatic void rtw_pci_stop(struct rtw_dev *rtwdev) 58462306a36Sopenharmony_ci{ 58562306a36Sopenharmony_ci struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; 58662306a36Sopenharmony_ci struct pci_dev *pdev = rtwpci->pdev; 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_ci spin_lock_bh(&rtwpci->irq_lock); 58962306a36Sopenharmony_ci rtwpci->running = false; 59062306a36Sopenharmony_ci rtw_pci_disable_interrupt(rtwdev, rtwpci); 59162306a36Sopenharmony_ci spin_unlock_bh(&rtwpci->irq_lock); 59262306a36Sopenharmony_ci 59362306a36Sopenharmony_ci synchronize_irq(pdev->irq); 59462306a36Sopenharmony_ci rtw_pci_napi_stop(rtwdev); 59562306a36Sopenharmony_ci 59662306a36Sopenharmony_ci spin_lock_bh(&rtwpci->irq_lock); 59762306a36Sopenharmony_ci rtw_pci_dma_release(rtwdev, rtwpci); 59862306a36Sopenharmony_ci spin_unlock_bh(&rtwpci->irq_lock); 59962306a36Sopenharmony_ci} 60062306a36Sopenharmony_ci 60162306a36Sopenharmony_cistatic void rtw_pci_deep_ps_enter(struct rtw_dev *rtwdev) 60262306a36Sopenharmony_ci{ 60362306a36Sopenharmony_ci struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; 60462306a36Sopenharmony_ci struct rtw_pci_tx_ring *tx_ring; 60562306a36Sopenharmony_ci enum rtw_tx_queue_type queue; 60662306a36Sopenharmony_ci bool tx_empty = true; 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_ci if (rtw_fw_feature_check(&rtwdev->fw, FW_FEATURE_TX_WAKE)) 60962306a36Sopenharmony_ci goto enter_deep_ps; 61062306a36Sopenharmony_ci 61162306a36Sopenharmony_ci lockdep_assert_held(&rtwpci->irq_lock); 61262306a36Sopenharmony_ci 61362306a36Sopenharmony_ci /* Deep PS state is not allowed to TX-DMA */ 61462306a36Sopenharmony_ci for (queue = 0; queue < RTK_MAX_TX_QUEUE_NUM; queue++) { 61562306a36Sopenharmony_ci /* BCN queue is rsvd page, does not have DMA interrupt 61662306a36Sopenharmony_ci * H2C queue is managed by firmware 61762306a36Sopenharmony_ci */ 61862306a36Sopenharmony_ci if (queue == RTW_TX_QUEUE_BCN || 61962306a36Sopenharmony_ci queue == RTW_TX_QUEUE_H2C) 62062306a36Sopenharmony_ci continue; 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_ci tx_ring = &rtwpci->tx_rings[queue]; 62362306a36Sopenharmony_ci 62462306a36Sopenharmony_ci /* check if there is any skb DMAing */ 62562306a36Sopenharmony_ci if (skb_queue_len(&tx_ring->queue)) { 62662306a36Sopenharmony_ci tx_empty = false; 62762306a36Sopenharmony_ci break; 62862306a36Sopenharmony_ci } 62962306a36Sopenharmony_ci } 63062306a36Sopenharmony_ci 63162306a36Sopenharmony_ci if (!tx_empty) { 63262306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_PS, 63362306a36Sopenharmony_ci "TX path not empty, cannot enter deep power save state\n"); 63462306a36Sopenharmony_ci return; 63562306a36Sopenharmony_ci } 63662306a36Sopenharmony_cienter_deep_ps: 63762306a36Sopenharmony_ci set_bit(RTW_FLAG_LEISURE_PS_DEEP, rtwdev->flags); 63862306a36Sopenharmony_ci rtw_power_mode_change(rtwdev, true); 63962306a36Sopenharmony_ci} 64062306a36Sopenharmony_ci 64162306a36Sopenharmony_cistatic void rtw_pci_deep_ps_leave(struct rtw_dev *rtwdev) 64262306a36Sopenharmony_ci{ 64362306a36Sopenharmony_ci struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; 64462306a36Sopenharmony_ci 64562306a36Sopenharmony_ci lockdep_assert_held(&rtwpci->irq_lock); 64662306a36Sopenharmony_ci 64762306a36Sopenharmony_ci if (test_and_clear_bit(RTW_FLAG_LEISURE_PS_DEEP, rtwdev->flags)) 64862306a36Sopenharmony_ci rtw_power_mode_change(rtwdev, false); 64962306a36Sopenharmony_ci} 65062306a36Sopenharmony_ci 65162306a36Sopenharmony_cistatic void rtw_pci_deep_ps(struct rtw_dev *rtwdev, bool enter) 65262306a36Sopenharmony_ci{ 65362306a36Sopenharmony_ci struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; 65462306a36Sopenharmony_ci 65562306a36Sopenharmony_ci spin_lock_bh(&rtwpci->irq_lock); 65662306a36Sopenharmony_ci 65762306a36Sopenharmony_ci if (enter && !test_bit(RTW_FLAG_LEISURE_PS_DEEP, rtwdev->flags)) 65862306a36Sopenharmony_ci rtw_pci_deep_ps_enter(rtwdev); 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_ci if (!enter && test_bit(RTW_FLAG_LEISURE_PS_DEEP, rtwdev->flags)) 66162306a36Sopenharmony_ci rtw_pci_deep_ps_leave(rtwdev); 66262306a36Sopenharmony_ci 66362306a36Sopenharmony_ci spin_unlock_bh(&rtwpci->irq_lock); 66462306a36Sopenharmony_ci} 66562306a36Sopenharmony_ci 66662306a36Sopenharmony_cistatic void rtw_pci_release_rsvd_page(struct rtw_pci *rtwpci, 66762306a36Sopenharmony_ci struct rtw_pci_tx_ring *ring) 66862306a36Sopenharmony_ci{ 66962306a36Sopenharmony_ci struct sk_buff *prev = skb_dequeue(&ring->queue); 67062306a36Sopenharmony_ci struct rtw_pci_tx_data *tx_data; 67162306a36Sopenharmony_ci dma_addr_t dma; 67262306a36Sopenharmony_ci 67362306a36Sopenharmony_ci if (!prev) 67462306a36Sopenharmony_ci return; 67562306a36Sopenharmony_ci 67662306a36Sopenharmony_ci tx_data = rtw_pci_get_tx_data(prev); 67762306a36Sopenharmony_ci dma = tx_data->dma; 67862306a36Sopenharmony_ci dma_unmap_single(&rtwpci->pdev->dev, dma, prev->len, DMA_TO_DEVICE); 67962306a36Sopenharmony_ci dev_kfree_skb_any(prev); 68062306a36Sopenharmony_ci} 68162306a36Sopenharmony_ci 68262306a36Sopenharmony_cistatic void rtw_pci_dma_check(struct rtw_dev *rtwdev, 68362306a36Sopenharmony_ci struct rtw_pci_rx_ring *rx_ring, 68462306a36Sopenharmony_ci u32 idx) 68562306a36Sopenharmony_ci{ 68662306a36Sopenharmony_ci struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; 68762306a36Sopenharmony_ci const struct rtw_chip_info *chip = rtwdev->chip; 68862306a36Sopenharmony_ci struct rtw_pci_rx_buffer_desc *buf_desc; 68962306a36Sopenharmony_ci u32 desc_sz = chip->rx_buf_desc_sz; 69062306a36Sopenharmony_ci u16 total_pkt_size; 69162306a36Sopenharmony_ci 69262306a36Sopenharmony_ci buf_desc = (struct rtw_pci_rx_buffer_desc *)(rx_ring->r.head + 69362306a36Sopenharmony_ci idx * desc_sz); 69462306a36Sopenharmony_ci total_pkt_size = le16_to_cpu(buf_desc->total_pkt_size); 69562306a36Sopenharmony_ci 69662306a36Sopenharmony_ci /* rx tag mismatch, throw a warning */ 69762306a36Sopenharmony_ci if (total_pkt_size != rtwpci->rx_tag) 69862306a36Sopenharmony_ci rtw_warn(rtwdev, "pci bus timeout, check dma status\n"); 69962306a36Sopenharmony_ci 70062306a36Sopenharmony_ci rtwpci->rx_tag = (rtwpci->rx_tag + 1) % RX_TAG_MAX; 70162306a36Sopenharmony_ci} 70262306a36Sopenharmony_ci 70362306a36Sopenharmony_cistatic u32 __pci_get_hw_tx_ring_rp(struct rtw_dev *rtwdev, u8 pci_q) 70462306a36Sopenharmony_ci{ 70562306a36Sopenharmony_ci u32 bd_idx_addr = rtw_pci_tx_queue_idx_addr[pci_q]; 70662306a36Sopenharmony_ci u32 bd_idx = rtw_read16(rtwdev, bd_idx_addr + 2); 70762306a36Sopenharmony_ci 70862306a36Sopenharmony_ci return FIELD_GET(TRX_BD_IDX_MASK, bd_idx); 70962306a36Sopenharmony_ci} 71062306a36Sopenharmony_ci 71162306a36Sopenharmony_cistatic void __pci_flush_queue(struct rtw_dev *rtwdev, u8 pci_q, bool drop) 71262306a36Sopenharmony_ci{ 71362306a36Sopenharmony_ci struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; 71462306a36Sopenharmony_ci struct rtw_pci_tx_ring *ring = &rtwpci->tx_rings[pci_q]; 71562306a36Sopenharmony_ci u32 cur_rp; 71662306a36Sopenharmony_ci u8 i; 71762306a36Sopenharmony_ci 71862306a36Sopenharmony_ci /* Because the time taked by the I/O in __pci_get_hw_tx_ring_rp is a 71962306a36Sopenharmony_ci * bit dynamic, it's hard to define a reasonable fixed total timeout to 72062306a36Sopenharmony_ci * use read_poll_timeout* helper. Instead, we can ensure a reasonable 72162306a36Sopenharmony_ci * polling times, so we just use for loop with udelay here. 72262306a36Sopenharmony_ci */ 72362306a36Sopenharmony_ci for (i = 0; i < 30; i++) { 72462306a36Sopenharmony_ci cur_rp = __pci_get_hw_tx_ring_rp(rtwdev, pci_q); 72562306a36Sopenharmony_ci if (cur_rp == ring->r.wp) 72662306a36Sopenharmony_ci return; 72762306a36Sopenharmony_ci 72862306a36Sopenharmony_ci udelay(1); 72962306a36Sopenharmony_ci } 73062306a36Sopenharmony_ci 73162306a36Sopenharmony_ci if (!drop) 73262306a36Sopenharmony_ci rtw_warn(rtwdev, "timed out to flush pci tx ring[%d]\n", pci_q); 73362306a36Sopenharmony_ci} 73462306a36Sopenharmony_ci 73562306a36Sopenharmony_cistatic void __rtw_pci_flush_queues(struct rtw_dev *rtwdev, u32 pci_queues, 73662306a36Sopenharmony_ci bool drop) 73762306a36Sopenharmony_ci{ 73862306a36Sopenharmony_ci u8 q; 73962306a36Sopenharmony_ci 74062306a36Sopenharmony_ci for (q = 0; q < RTK_MAX_TX_QUEUE_NUM; q++) { 74162306a36Sopenharmony_ci /* Unnecessary to flush BCN, H2C and HI tx queues. */ 74262306a36Sopenharmony_ci if (q == RTW_TX_QUEUE_BCN || q == RTW_TX_QUEUE_H2C || 74362306a36Sopenharmony_ci q == RTW_TX_QUEUE_HI0) 74462306a36Sopenharmony_ci continue; 74562306a36Sopenharmony_ci 74662306a36Sopenharmony_ci if (pci_queues & BIT(q)) 74762306a36Sopenharmony_ci __pci_flush_queue(rtwdev, q, drop); 74862306a36Sopenharmony_ci } 74962306a36Sopenharmony_ci} 75062306a36Sopenharmony_ci 75162306a36Sopenharmony_cistatic void rtw_pci_flush_queues(struct rtw_dev *rtwdev, u32 queues, bool drop) 75262306a36Sopenharmony_ci{ 75362306a36Sopenharmony_ci u32 pci_queues = 0; 75462306a36Sopenharmony_ci u8 i; 75562306a36Sopenharmony_ci 75662306a36Sopenharmony_ci /* If all of the hardware queues are requested to flush, 75762306a36Sopenharmony_ci * flush all of the pci queues. 75862306a36Sopenharmony_ci */ 75962306a36Sopenharmony_ci if (queues == BIT(rtwdev->hw->queues) - 1) { 76062306a36Sopenharmony_ci pci_queues = BIT(RTK_MAX_TX_QUEUE_NUM) - 1; 76162306a36Sopenharmony_ci } else { 76262306a36Sopenharmony_ci for (i = 0; i < rtwdev->hw->queues; i++) 76362306a36Sopenharmony_ci if (queues & BIT(i)) 76462306a36Sopenharmony_ci pci_queues |= BIT(rtw_tx_ac_to_hwq(i)); 76562306a36Sopenharmony_ci } 76662306a36Sopenharmony_ci 76762306a36Sopenharmony_ci __rtw_pci_flush_queues(rtwdev, pci_queues, drop); 76862306a36Sopenharmony_ci} 76962306a36Sopenharmony_ci 77062306a36Sopenharmony_cistatic void rtw_pci_tx_kick_off_queue(struct rtw_dev *rtwdev, 77162306a36Sopenharmony_ci enum rtw_tx_queue_type queue) 77262306a36Sopenharmony_ci{ 77362306a36Sopenharmony_ci struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; 77462306a36Sopenharmony_ci struct rtw_pci_tx_ring *ring; 77562306a36Sopenharmony_ci u32 bd_idx; 77662306a36Sopenharmony_ci 77762306a36Sopenharmony_ci ring = &rtwpci->tx_rings[queue]; 77862306a36Sopenharmony_ci bd_idx = rtw_pci_tx_queue_idx_addr[queue]; 77962306a36Sopenharmony_ci 78062306a36Sopenharmony_ci spin_lock_bh(&rtwpci->irq_lock); 78162306a36Sopenharmony_ci if (!rtw_fw_feature_check(&rtwdev->fw, FW_FEATURE_TX_WAKE)) 78262306a36Sopenharmony_ci rtw_pci_deep_ps_leave(rtwdev); 78362306a36Sopenharmony_ci rtw_write16(rtwdev, bd_idx, ring->r.wp & TRX_BD_IDX_MASK); 78462306a36Sopenharmony_ci spin_unlock_bh(&rtwpci->irq_lock); 78562306a36Sopenharmony_ci} 78662306a36Sopenharmony_ci 78762306a36Sopenharmony_cistatic void rtw_pci_tx_kick_off(struct rtw_dev *rtwdev) 78862306a36Sopenharmony_ci{ 78962306a36Sopenharmony_ci struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; 79062306a36Sopenharmony_ci enum rtw_tx_queue_type queue; 79162306a36Sopenharmony_ci 79262306a36Sopenharmony_ci for (queue = 0; queue < RTK_MAX_TX_QUEUE_NUM; queue++) 79362306a36Sopenharmony_ci if (test_and_clear_bit(queue, rtwpci->tx_queued)) 79462306a36Sopenharmony_ci rtw_pci_tx_kick_off_queue(rtwdev, queue); 79562306a36Sopenharmony_ci} 79662306a36Sopenharmony_ci 79762306a36Sopenharmony_cistatic int rtw_pci_tx_write_data(struct rtw_dev *rtwdev, 79862306a36Sopenharmony_ci struct rtw_tx_pkt_info *pkt_info, 79962306a36Sopenharmony_ci struct sk_buff *skb, 80062306a36Sopenharmony_ci enum rtw_tx_queue_type queue) 80162306a36Sopenharmony_ci{ 80262306a36Sopenharmony_ci struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; 80362306a36Sopenharmony_ci const struct rtw_chip_info *chip = rtwdev->chip; 80462306a36Sopenharmony_ci struct rtw_pci_tx_ring *ring; 80562306a36Sopenharmony_ci struct rtw_pci_tx_data *tx_data; 80662306a36Sopenharmony_ci dma_addr_t dma; 80762306a36Sopenharmony_ci u32 tx_pkt_desc_sz = chip->tx_pkt_desc_sz; 80862306a36Sopenharmony_ci u32 tx_buf_desc_sz = chip->tx_buf_desc_sz; 80962306a36Sopenharmony_ci u32 size; 81062306a36Sopenharmony_ci u32 psb_len; 81162306a36Sopenharmony_ci u8 *pkt_desc; 81262306a36Sopenharmony_ci struct rtw_pci_tx_buffer_desc *buf_desc; 81362306a36Sopenharmony_ci 81462306a36Sopenharmony_ci ring = &rtwpci->tx_rings[queue]; 81562306a36Sopenharmony_ci 81662306a36Sopenharmony_ci size = skb->len; 81762306a36Sopenharmony_ci 81862306a36Sopenharmony_ci if (queue == RTW_TX_QUEUE_BCN) 81962306a36Sopenharmony_ci rtw_pci_release_rsvd_page(rtwpci, ring); 82062306a36Sopenharmony_ci else if (!avail_desc(ring->r.wp, ring->r.rp, ring->r.len)) 82162306a36Sopenharmony_ci return -ENOSPC; 82262306a36Sopenharmony_ci 82362306a36Sopenharmony_ci pkt_desc = skb_push(skb, chip->tx_pkt_desc_sz); 82462306a36Sopenharmony_ci memset(pkt_desc, 0, tx_pkt_desc_sz); 82562306a36Sopenharmony_ci pkt_info->qsel = rtw_pci_get_tx_qsel(skb, queue); 82662306a36Sopenharmony_ci rtw_tx_fill_tx_desc(pkt_info, skb); 82762306a36Sopenharmony_ci dma = dma_map_single(&rtwpci->pdev->dev, skb->data, skb->len, 82862306a36Sopenharmony_ci DMA_TO_DEVICE); 82962306a36Sopenharmony_ci if (dma_mapping_error(&rtwpci->pdev->dev, dma)) 83062306a36Sopenharmony_ci return -EBUSY; 83162306a36Sopenharmony_ci 83262306a36Sopenharmony_ci /* after this we got dma mapped, there is no way back */ 83362306a36Sopenharmony_ci buf_desc = get_tx_buffer_desc(ring, tx_buf_desc_sz); 83462306a36Sopenharmony_ci memset(buf_desc, 0, tx_buf_desc_sz); 83562306a36Sopenharmony_ci psb_len = (skb->len - 1) / 128 + 1; 83662306a36Sopenharmony_ci if (queue == RTW_TX_QUEUE_BCN) 83762306a36Sopenharmony_ci psb_len |= 1 << RTK_PCI_TXBD_OWN_OFFSET; 83862306a36Sopenharmony_ci 83962306a36Sopenharmony_ci buf_desc[0].psb_len = cpu_to_le16(psb_len); 84062306a36Sopenharmony_ci buf_desc[0].buf_size = cpu_to_le16(tx_pkt_desc_sz); 84162306a36Sopenharmony_ci buf_desc[0].dma = cpu_to_le32(dma); 84262306a36Sopenharmony_ci buf_desc[1].buf_size = cpu_to_le16(size); 84362306a36Sopenharmony_ci buf_desc[1].dma = cpu_to_le32(dma + tx_pkt_desc_sz); 84462306a36Sopenharmony_ci 84562306a36Sopenharmony_ci tx_data = rtw_pci_get_tx_data(skb); 84662306a36Sopenharmony_ci tx_data->dma = dma; 84762306a36Sopenharmony_ci tx_data->sn = pkt_info->sn; 84862306a36Sopenharmony_ci 84962306a36Sopenharmony_ci spin_lock_bh(&rtwpci->irq_lock); 85062306a36Sopenharmony_ci 85162306a36Sopenharmony_ci skb_queue_tail(&ring->queue, skb); 85262306a36Sopenharmony_ci 85362306a36Sopenharmony_ci if (queue == RTW_TX_QUEUE_BCN) 85462306a36Sopenharmony_ci goto out_unlock; 85562306a36Sopenharmony_ci 85662306a36Sopenharmony_ci /* update write-index, and kick it off later */ 85762306a36Sopenharmony_ci set_bit(queue, rtwpci->tx_queued); 85862306a36Sopenharmony_ci if (++ring->r.wp >= ring->r.len) 85962306a36Sopenharmony_ci ring->r.wp = 0; 86062306a36Sopenharmony_ci 86162306a36Sopenharmony_ciout_unlock: 86262306a36Sopenharmony_ci spin_unlock_bh(&rtwpci->irq_lock); 86362306a36Sopenharmony_ci 86462306a36Sopenharmony_ci return 0; 86562306a36Sopenharmony_ci} 86662306a36Sopenharmony_ci 86762306a36Sopenharmony_cistatic int rtw_pci_write_data_rsvd_page(struct rtw_dev *rtwdev, u8 *buf, 86862306a36Sopenharmony_ci u32 size) 86962306a36Sopenharmony_ci{ 87062306a36Sopenharmony_ci struct sk_buff *skb; 87162306a36Sopenharmony_ci struct rtw_tx_pkt_info pkt_info = {0}; 87262306a36Sopenharmony_ci u8 reg_bcn_work; 87362306a36Sopenharmony_ci int ret; 87462306a36Sopenharmony_ci 87562306a36Sopenharmony_ci skb = rtw_tx_write_data_rsvd_page_get(rtwdev, &pkt_info, buf, size); 87662306a36Sopenharmony_ci if (!skb) 87762306a36Sopenharmony_ci return -ENOMEM; 87862306a36Sopenharmony_ci 87962306a36Sopenharmony_ci ret = rtw_pci_tx_write_data(rtwdev, &pkt_info, skb, RTW_TX_QUEUE_BCN); 88062306a36Sopenharmony_ci if (ret) { 88162306a36Sopenharmony_ci rtw_err(rtwdev, "failed to write rsvd page data\n"); 88262306a36Sopenharmony_ci return ret; 88362306a36Sopenharmony_ci } 88462306a36Sopenharmony_ci 88562306a36Sopenharmony_ci /* reserved pages go through beacon queue */ 88662306a36Sopenharmony_ci reg_bcn_work = rtw_read8(rtwdev, RTK_PCI_TXBD_BCN_WORK); 88762306a36Sopenharmony_ci reg_bcn_work |= BIT_PCI_BCNQ_FLAG; 88862306a36Sopenharmony_ci rtw_write8(rtwdev, RTK_PCI_TXBD_BCN_WORK, reg_bcn_work); 88962306a36Sopenharmony_ci 89062306a36Sopenharmony_ci return 0; 89162306a36Sopenharmony_ci} 89262306a36Sopenharmony_ci 89362306a36Sopenharmony_cistatic int rtw_pci_write_data_h2c(struct rtw_dev *rtwdev, u8 *buf, u32 size) 89462306a36Sopenharmony_ci{ 89562306a36Sopenharmony_ci struct sk_buff *skb; 89662306a36Sopenharmony_ci struct rtw_tx_pkt_info pkt_info = {0}; 89762306a36Sopenharmony_ci int ret; 89862306a36Sopenharmony_ci 89962306a36Sopenharmony_ci skb = rtw_tx_write_data_h2c_get(rtwdev, &pkt_info, buf, size); 90062306a36Sopenharmony_ci if (!skb) 90162306a36Sopenharmony_ci return -ENOMEM; 90262306a36Sopenharmony_ci 90362306a36Sopenharmony_ci ret = rtw_pci_tx_write_data(rtwdev, &pkt_info, skb, RTW_TX_QUEUE_H2C); 90462306a36Sopenharmony_ci if (ret) { 90562306a36Sopenharmony_ci rtw_err(rtwdev, "failed to write h2c data\n"); 90662306a36Sopenharmony_ci return ret; 90762306a36Sopenharmony_ci } 90862306a36Sopenharmony_ci 90962306a36Sopenharmony_ci rtw_pci_tx_kick_off_queue(rtwdev, RTW_TX_QUEUE_H2C); 91062306a36Sopenharmony_ci 91162306a36Sopenharmony_ci return 0; 91262306a36Sopenharmony_ci} 91362306a36Sopenharmony_ci 91462306a36Sopenharmony_cistatic int rtw_pci_tx_write(struct rtw_dev *rtwdev, 91562306a36Sopenharmony_ci struct rtw_tx_pkt_info *pkt_info, 91662306a36Sopenharmony_ci struct sk_buff *skb) 91762306a36Sopenharmony_ci{ 91862306a36Sopenharmony_ci enum rtw_tx_queue_type queue = rtw_tx_queue_mapping(skb); 91962306a36Sopenharmony_ci struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; 92062306a36Sopenharmony_ci struct rtw_pci_tx_ring *ring; 92162306a36Sopenharmony_ci int ret; 92262306a36Sopenharmony_ci 92362306a36Sopenharmony_ci ret = rtw_pci_tx_write_data(rtwdev, pkt_info, skb, queue); 92462306a36Sopenharmony_ci if (ret) 92562306a36Sopenharmony_ci return ret; 92662306a36Sopenharmony_ci 92762306a36Sopenharmony_ci ring = &rtwpci->tx_rings[queue]; 92862306a36Sopenharmony_ci spin_lock_bh(&rtwpci->irq_lock); 92962306a36Sopenharmony_ci if (avail_desc(ring->r.wp, ring->r.rp, ring->r.len) < 2) { 93062306a36Sopenharmony_ci ieee80211_stop_queue(rtwdev->hw, skb_get_queue_mapping(skb)); 93162306a36Sopenharmony_ci ring->queue_stopped = true; 93262306a36Sopenharmony_ci } 93362306a36Sopenharmony_ci spin_unlock_bh(&rtwpci->irq_lock); 93462306a36Sopenharmony_ci 93562306a36Sopenharmony_ci return 0; 93662306a36Sopenharmony_ci} 93762306a36Sopenharmony_ci 93862306a36Sopenharmony_cistatic void rtw_pci_tx_isr(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci, 93962306a36Sopenharmony_ci u8 hw_queue) 94062306a36Sopenharmony_ci{ 94162306a36Sopenharmony_ci struct ieee80211_hw *hw = rtwdev->hw; 94262306a36Sopenharmony_ci struct ieee80211_tx_info *info; 94362306a36Sopenharmony_ci struct rtw_pci_tx_ring *ring; 94462306a36Sopenharmony_ci struct rtw_pci_tx_data *tx_data; 94562306a36Sopenharmony_ci struct sk_buff *skb; 94662306a36Sopenharmony_ci u32 count; 94762306a36Sopenharmony_ci u32 bd_idx_addr; 94862306a36Sopenharmony_ci u32 bd_idx, cur_rp, rp_idx; 94962306a36Sopenharmony_ci u16 q_map; 95062306a36Sopenharmony_ci 95162306a36Sopenharmony_ci ring = &rtwpci->tx_rings[hw_queue]; 95262306a36Sopenharmony_ci 95362306a36Sopenharmony_ci bd_idx_addr = rtw_pci_tx_queue_idx_addr[hw_queue]; 95462306a36Sopenharmony_ci bd_idx = rtw_read32(rtwdev, bd_idx_addr); 95562306a36Sopenharmony_ci cur_rp = bd_idx >> 16; 95662306a36Sopenharmony_ci cur_rp &= TRX_BD_IDX_MASK; 95762306a36Sopenharmony_ci rp_idx = ring->r.rp; 95862306a36Sopenharmony_ci if (cur_rp >= ring->r.rp) 95962306a36Sopenharmony_ci count = cur_rp - ring->r.rp; 96062306a36Sopenharmony_ci else 96162306a36Sopenharmony_ci count = ring->r.len - (ring->r.rp - cur_rp); 96262306a36Sopenharmony_ci 96362306a36Sopenharmony_ci while (count--) { 96462306a36Sopenharmony_ci skb = skb_dequeue(&ring->queue); 96562306a36Sopenharmony_ci if (!skb) { 96662306a36Sopenharmony_ci rtw_err(rtwdev, "failed to dequeue %d skb TX queue %d, BD=0x%08x, rp %d -> %d\n", 96762306a36Sopenharmony_ci count, hw_queue, bd_idx, ring->r.rp, cur_rp); 96862306a36Sopenharmony_ci break; 96962306a36Sopenharmony_ci } 97062306a36Sopenharmony_ci tx_data = rtw_pci_get_tx_data(skb); 97162306a36Sopenharmony_ci dma_unmap_single(&rtwpci->pdev->dev, tx_data->dma, skb->len, 97262306a36Sopenharmony_ci DMA_TO_DEVICE); 97362306a36Sopenharmony_ci 97462306a36Sopenharmony_ci /* just free command packets from host to card */ 97562306a36Sopenharmony_ci if (hw_queue == RTW_TX_QUEUE_H2C) { 97662306a36Sopenharmony_ci dev_kfree_skb_irq(skb); 97762306a36Sopenharmony_ci continue; 97862306a36Sopenharmony_ci } 97962306a36Sopenharmony_ci 98062306a36Sopenharmony_ci if (ring->queue_stopped && 98162306a36Sopenharmony_ci avail_desc(ring->r.wp, rp_idx, ring->r.len) > 4) { 98262306a36Sopenharmony_ci q_map = skb_get_queue_mapping(skb); 98362306a36Sopenharmony_ci ieee80211_wake_queue(hw, q_map); 98462306a36Sopenharmony_ci ring->queue_stopped = false; 98562306a36Sopenharmony_ci } 98662306a36Sopenharmony_ci 98762306a36Sopenharmony_ci if (++rp_idx >= ring->r.len) 98862306a36Sopenharmony_ci rp_idx = 0; 98962306a36Sopenharmony_ci 99062306a36Sopenharmony_ci skb_pull(skb, rtwdev->chip->tx_pkt_desc_sz); 99162306a36Sopenharmony_ci 99262306a36Sopenharmony_ci info = IEEE80211_SKB_CB(skb); 99362306a36Sopenharmony_ci 99462306a36Sopenharmony_ci /* enqueue to wait for tx report */ 99562306a36Sopenharmony_ci if (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS) { 99662306a36Sopenharmony_ci rtw_tx_report_enqueue(rtwdev, skb, tx_data->sn); 99762306a36Sopenharmony_ci continue; 99862306a36Sopenharmony_ci } 99962306a36Sopenharmony_ci 100062306a36Sopenharmony_ci /* always ACK for others, then they won't be marked as drop */ 100162306a36Sopenharmony_ci if (info->flags & IEEE80211_TX_CTL_NO_ACK) 100262306a36Sopenharmony_ci info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED; 100362306a36Sopenharmony_ci else 100462306a36Sopenharmony_ci info->flags |= IEEE80211_TX_STAT_ACK; 100562306a36Sopenharmony_ci 100662306a36Sopenharmony_ci ieee80211_tx_info_clear_status(info); 100762306a36Sopenharmony_ci ieee80211_tx_status_irqsafe(hw, skb); 100862306a36Sopenharmony_ci } 100962306a36Sopenharmony_ci 101062306a36Sopenharmony_ci ring->r.rp = cur_rp; 101162306a36Sopenharmony_ci} 101262306a36Sopenharmony_ci 101362306a36Sopenharmony_cistatic void rtw_pci_rx_isr(struct rtw_dev *rtwdev) 101462306a36Sopenharmony_ci{ 101562306a36Sopenharmony_ci struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; 101662306a36Sopenharmony_ci struct napi_struct *napi = &rtwpci->napi; 101762306a36Sopenharmony_ci 101862306a36Sopenharmony_ci napi_schedule(napi); 101962306a36Sopenharmony_ci} 102062306a36Sopenharmony_ci 102162306a36Sopenharmony_cistatic int rtw_pci_get_hw_rx_ring_nr(struct rtw_dev *rtwdev, 102262306a36Sopenharmony_ci struct rtw_pci *rtwpci) 102362306a36Sopenharmony_ci{ 102462306a36Sopenharmony_ci struct rtw_pci_rx_ring *ring; 102562306a36Sopenharmony_ci int count = 0; 102662306a36Sopenharmony_ci u32 tmp, cur_wp; 102762306a36Sopenharmony_ci 102862306a36Sopenharmony_ci ring = &rtwpci->rx_rings[RTW_RX_QUEUE_MPDU]; 102962306a36Sopenharmony_ci tmp = rtw_read32(rtwdev, RTK_PCI_RXBD_IDX_MPDUQ); 103062306a36Sopenharmony_ci cur_wp = u32_get_bits(tmp, TRX_BD_HW_IDX_MASK); 103162306a36Sopenharmony_ci if (cur_wp >= ring->r.wp) 103262306a36Sopenharmony_ci count = cur_wp - ring->r.wp; 103362306a36Sopenharmony_ci else 103462306a36Sopenharmony_ci count = ring->r.len - (ring->r.wp - cur_wp); 103562306a36Sopenharmony_ci 103662306a36Sopenharmony_ci return count; 103762306a36Sopenharmony_ci} 103862306a36Sopenharmony_ci 103962306a36Sopenharmony_cistatic u32 rtw_pci_rx_napi(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci, 104062306a36Sopenharmony_ci u8 hw_queue, u32 limit) 104162306a36Sopenharmony_ci{ 104262306a36Sopenharmony_ci const struct rtw_chip_info *chip = rtwdev->chip; 104362306a36Sopenharmony_ci struct napi_struct *napi = &rtwpci->napi; 104462306a36Sopenharmony_ci struct rtw_pci_rx_ring *ring = &rtwpci->rx_rings[RTW_RX_QUEUE_MPDU]; 104562306a36Sopenharmony_ci struct rtw_rx_pkt_stat pkt_stat; 104662306a36Sopenharmony_ci struct ieee80211_rx_status rx_status; 104762306a36Sopenharmony_ci struct sk_buff *skb, *new; 104862306a36Sopenharmony_ci u32 cur_rp = ring->r.rp; 104962306a36Sopenharmony_ci u32 count, rx_done = 0; 105062306a36Sopenharmony_ci u32 pkt_offset; 105162306a36Sopenharmony_ci u32 pkt_desc_sz = chip->rx_pkt_desc_sz; 105262306a36Sopenharmony_ci u32 buf_desc_sz = chip->rx_buf_desc_sz; 105362306a36Sopenharmony_ci u32 new_len; 105462306a36Sopenharmony_ci u8 *rx_desc; 105562306a36Sopenharmony_ci dma_addr_t dma; 105662306a36Sopenharmony_ci 105762306a36Sopenharmony_ci count = rtw_pci_get_hw_rx_ring_nr(rtwdev, rtwpci); 105862306a36Sopenharmony_ci count = min(count, limit); 105962306a36Sopenharmony_ci 106062306a36Sopenharmony_ci while (count--) { 106162306a36Sopenharmony_ci rtw_pci_dma_check(rtwdev, ring, cur_rp); 106262306a36Sopenharmony_ci skb = ring->buf[cur_rp]; 106362306a36Sopenharmony_ci dma = *((dma_addr_t *)skb->cb); 106462306a36Sopenharmony_ci dma_sync_single_for_cpu(rtwdev->dev, dma, RTK_PCI_RX_BUF_SIZE, 106562306a36Sopenharmony_ci DMA_FROM_DEVICE); 106662306a36Sopenharmony_ci rx_desc = skb->data; 106762306a36Sopenharmony_ci chip->ops->query_rx_desc(rtwdev, rx_desc, &pkt_stat, &rx_status); 106862306a36Sopenharmony_ci 106962306a36Sopenharmony_ci /* offset from rx_desc to payload */ 107062306a36Sopenharmony_ci pkt_offset = pkt_desc_sz + pkt_stat.drv_info_sz + 107162306a36Sopenharmony_ci pkt_stat.shift; 107262306a36Sopenharmony_ci 107362306a36Sopenharmony_ci /* allocate a new skb for this frame, 107462306a36Sopenharmony_ci * discard the frame if none available 107562306a36Sopenharmony_ci */ 107662306a36Sopenharmony_ci new_len = pkt_stat.pkt_len + pkt_offset; 107762306a36Sopenharmony_ci new = dev_alloc_skb(new_len); 107862306a36Sopenharmony_ci if (WARN_ONCE(!new, "rx routine starvation\n")) 107962306a36Sopenharmony_ci goto next_rp; 108062306a36Sopenharmony_ci 108162306a36Sopenharmony_ci /* put the DMA data including rx_desc from phy to new skb */ 108262306a36Sopenharmony_ci skb_put_data(new, skb->data, new_len); 108362306a36Sopenharmony_ci 108462306a36Sopenharmony_ci if (pkt_stat.is_c2h) { 108562306a36Sopenharmony_ci rtw_fw_c2h_cmd_rx_irqsafe(rtwdev, pkt_offset, new); 108662306a36Sopenharmony_ci } else { 108762306a36Sopenharmony_ci /* remove rx_desc */ 108862306a36Sopenharmony_ci skb_pull(new, pkt_offset); 108962306a36Sopenharmony_ci 109062306a36Sopenharmony_ci rtw_rx_stats(rtwdev, pkt_stat.vif, new); 109162306a36Sopenharmony_ci memcpy(new->cb, &rx_status, sizeof(rx_status)); 109262306a36Sopenharmony_ci ieee80211_rx_napi(rtwdev->hw, NULL, new, napi); 109362306a36Sopenharmony_ci rx_done++; 109462306a36Sopenharmony_ci } 109562306a36Sopenharmony_ci 109662306a36Sopenharmony_cinext_rp: 109762306a36Sopenharmony_ci /* new skb delivered to mac80211, re-enable original skb DMA */ 109862306a36Sopenharmony_ci rtw_pci_sync_rx_desc_device(rtwdev, dma, ring, cur_rp, 109962306a36Sopenharmony_ci buf_desc_sz); 110062306a36Sopenharmony_ci 110162306a36Sopenharmony_ci /* host read next element in ring */ 110262306a36Sopenharmony_ci if (++cur_rp >= ring->r.len) 110362306a36Sopenharmony_ci cur_rp = 0; 110462306a36Sopenharmony_ci } 110562306a36Sopenharmony_ci 110662306a36Sopenharmony_ci ring->r.rp = cur_rp; 110762306a36Sopenharmony_ci /* 'rp', the last position we have read, is seen as previous posistion 110862306a36Sopenharmony_ci * of 'wp' that is used to calculate 'count' next time. 110962306a36Sopenharmony_ci */ 111062306a36Sopenharmony_ci ring->r.wp = cur_rp; 111162306a36Sopenharmony_ci rtw_write16(rtwdev, RTK_PCI_RXBD_IDX_MPDUQ, ring->r.rp); 111262306a36Sopenharmony_ci 111362306a36Sopenharmony_ci return rx_done; 111462306a36Sopenharmony_ci} 111562306a36Sopenharmony_ci 111662306a36Sopenharmony_cistatic void rtw_pci_irq_recognized(struct rtw_dev *rtwdev, 111762306a36Sopenharmony_ci struct rtw_pci *rtwpci, u32 *irq_status) 111862306a36Sopenharmony_ci{ 111962306a36Sopenharmony_ci unsigned long flags; 112062306a36Sopenharmony_ci 112162306a36Sopenharmony_ci spin_lock_irqsave(&rtwpci->hwirq_lock, flags); 112262306a36Sopenharmony_ci 112362306a36Sopenharmony_ci irq_status[0] = rtw_read32(rtwdev, RTK_PCI_HISR0); 112462306a36Sopenharmony_ci irq_status[1] = rtw_read32(rtwdev, RTK_PCI_HISR1); 112562306a36Sopenharmony_ci if (rtw_chip_wcpu_11ac(rtwdev)) 112662306a36Sopenharmony_ci irq_status[3] = rtw_read32(rtwdev, RTK_PCI_HISR3); 112762306a36Sopenharmony_ci else 112862306a36Sopenharmony_ci irq_status[3] = 0; 112962306a36Sopenharmony_ci irq_status[0] &= rtwpci->irq_mask[0]; 113062306a36Sopenharmony_ci irq_status[1] &= rtwpci->irq_mask[1]; 113162306a36Sopenharmony_ci irq_status[3] &= rtwpci->irq_mask[3]; 113262306a36Sopenharmony_ci rtw_write32(rtwdev, RTK_PCI_HISR0, irq_status[0]); 113362306a36Sopenharmony_ci rtw_write32(rtwdev, RTK_PCI_HISR1, irq_status[1]); 113462306a36Sopenharmony_ci if (rtw_chip_wcpu_11ac(rtwdev)) 113562306a36Sopenharmony_ci rtw_write32(rtwdev, RTK_PCI_HISR3, irq_status[3]); 113662306a36Sopenharmony_ci 113762306a36Sopenharmony_ci spin_unlock_irqrestore(&rtwpci->hwirq_lock, flags); 113862306a36Sopenharmony_ci} 113962306a36Sopenharmony_ci 114062306a36Sopenharmony_cistatic irqreturn_t rtw_pci_interrupt_handler(int irq, void *dev) 114162306a36Sopenharmony_ci{ 114262306a36Sopenharmony_ci struct rtw_dev *rtwdev = dev; 114362306a36Sopenharmony_ci struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; 114462306a36Sopenharmony_ci 114562306a36Sopenharmony_ci /* disable RTW PCI interrupt to avoid more interrupts before the end of 114662306a36Sopenharmony_ci * thread function 114762306a36Sopenharmony_ci * 114862306a36Sopenharmony_ci * disable HIMR here to also avoid new HISR flag being raised before 114962306a36Sopenharmony_ci * the HISRs have been Write-1-cleared for MSI. If not all of the HISRs 115062306a36Sopenharmony_ci * are cleared, the edge-triggered interrupt will not be generated when 115162306a36Sopenharmony_ci * a new HISR flag is set. 115262306a36Sopenharmony_ci */ 115362306a36Sopenharmony_ci rtw_pci_disable_interrupt(rtwdev, rtwpci); 115462306a36Sopenharmony_ci 115562306a36Sopenharmony_ci return IRQ_WAKE_THREAD; 115662306a36Sopenharmony_ci} 115762306a36Sopenharmony_ci 115862306a36Sopenharmony_cistatic irqreturn_t rtw_pci_interrupt_threadfn(int irq, void *dev) 115962306a36Sopenharmony_ci{ 116062306a36Sopenharmony_ci struct rtw_dev *rtwdev = dev; 116162306a36Sopenharmony_ci struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; 116262306a36Sopenharmony_ci u32 irq_status[4]; 116362306a36Sopenharmony_ci bool rx = false; 116462306a36Sopenharmony_ci 116562306a36Sopenharmony_ci spin_lock_bh(&rtwpci->irq_lock); 116662306a36Sopenharmony_ci rtw_pci_irq_recognized(rtwdev, rtwpci, irq_status); 116762306a36Sopenharmony_ci 116862306a36Sopenharmony_ci if (irq_status[0] & IMR_MGNTDOK) 116962306a36Sopenharmony_ci rtw_pci_tx_isr(rtwdev, rtwpci, RTW_TX_QUEUE_MGMT); 117062306a36Sopenharmony_ci if (irq_status[0] & IMR_HIGHDOK) 117162306a36Sopenharmony_ci rtw_pci_tx_isr(rtwdev, rtwpci, RTW_TX_QUEUE_HI0); 117262306a36Sopenharmony_ci if (irq_status[0] & IMR_BEDOK) 117362306a36Sopenharmony_ci rtw_pci_tx_isr(rtwdev, rtwpci, RTW_TX_QUEUE_BE); 117462306a36Sopenharmony_ci if (irq_status[0] & IMR_BKDOK) 117562306a36Sopenharmony_ci rtw_pci_tx_isr(rtwdev, rtwpci, RTW_TX_QUEUE_BK); 117662306a36Sopenharmony_ci if (irq_status[0] & IMR_VODOK) 117762306a36Sopenharmony_ci rtw_pci_tx_isr(rtwdev, rtwpci, RTW_TX_QUEUE_VO); 117862306a36Sopenharmony_ci if (irq_status[0] & IMR_VIDOK) 117962306a36Sopenharmony_ci rtw_pci_tx_isr(rtwdev, rtwpci, RTW_TX_QUEUE_VI); 118062306a36Sopenharmony_ci if (irq_status[3] & IMR_H2CDOK) 118162306a36Sopenharmony_ci rtw_pci_tx_isr(rtwdev, rtwpci, RTW_TX_QUEUE_H2C); 118262306a36Sopenharmony_ci if (irq_status[0] & IMR_ROK) { 118362306a36Sopenharmony_ci rtw_pci_rx_isr(rtwdev); 118462306a36Sopenharmony_ci rx = true; 118562306a36Sopenharmony_ci } 118662306a36Sopenharmony_ci if (unlikely(irq_status[0] & IMR_C2HCMD)) 118762306a36Sopenharmony_ci rtw_fw_c2h_cmd_isr(rtwdev); 118862306a36Sopenharmony_ci 118962306a36Sopenharmony_ci /* all of the jobs for this interrupt have been done */ 119062306a36Sopenharmony_ci if (rtwpci->running) 119162306a36Sopenharmony_ci rtw_pci_enable_interrupt(rtwdev, rtwpci, rx); 119262306a36Sopenharmony_ci spin_unlock_bh(&rtwpci->irq_lock); 119362306a36Sopenharmony_ci 119462306a36Sopenharmony_ci return IRQ_HANDLED; 119562306a36Sopenharmony_ci} 119662306a36Sopenharmony_ci 119762306a36Sopenharmony_cistatic int rtw_pci_io_mapping(struct rtw_dev *rtwdev, 119862306a36Sopenharmony_ci struct pci_dev *pdev) 119962306a36Sopenharmony_ci{ 120062306a36Sopenharmony_ci struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; 120162306a36Sopenharmony_ci unsigned long len; 120262306a36Sopenharmony_ci u8 bar_id = 2; 120362306a36Sopenharmony_ci int ret; 120462306a36Sopenharmony_ci 120562306a36Sopenharmony_ci ret = pci_request_regions(pdev, KBUILD_MODNAME); 120662306a36Sopenharmony_ci if (ret) { 120762306a36Sopenharmony_ci rtw_err(rtwdev, "failed to request pci regions\n"); 120862306a36Sopenharmony_ci return ret; 120962306a36Sopenharmony_ci } 121062306a36Sopenharmony_ci 121162306a36Sopenharmony_ci len = pci_resource_len(pdev, bar_id); 121262306a36Sopenharmony_ci rtwpci->mmap = pci_iomap(pdev, bar_id, len); 121362306a36Sopenharmony_ci if (!rtwpci->mmap) { 121462306a36Sopenharmony_ci pci_release_regions(pdev); 121562306a36Sopenharmony_ci rtw_err(rtwdev, "failed to map pci memory\n"); 121662306a36Sopenharmony_ci return -ENOMEM; 121762306a36Sopenharmony_ci } 121862306a36Sopenharmony_ci 121962306a36Sopenharmony_ci return 0; 122062306a36Sopenharmony_ci} 122162306a36Sopenharmony_ci 122262306a36Sopenharmony_cistatic void rtw_pci_io_unmapping(struct rtw_dev *rtwdev, 122362306a36Sopenharmony_ci struct pci_dev *pdev) 122462306a36Sopenharmony_ci{ 122562306a36Sopenharmony_ci struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; 122662306a36Sopenharmony_ci 122762306a36Sopenharmony_ci if (rtwpci->mmap) { 122862306a36Sopenharmony_ci pci_iounmap(pdev, rtwpci->mmap); 122962306a36Sopenharmony_ci pci_release_regions(pdev); 123062306a36Sopenharmony_ci } 123162306a36Sopenharmony_ci} 123262306a36Sopenharmony_ci 123362306a36Sopenharmony_cistatic void rtw_dbi_write8(struct rtw_dev *rtwdev, u16 addr, u8 data) 123462306a36Sopenharmony_ci{ 123562306a36Sopenharmony_ci u16 write_addr; 123662306a36Sopenharmony_ci u16 remainder = addr & ~(BITS_DBI_WREN | BITS_DBI_ADDR_MASK); 123762306a36Sopenharmony_ci u8 flag; 123862306a36Sopenharmony_ci u8 cnt; 123962306a36Sopenharmony_ci 124062306a36Sopenharmony_ci write_addr = addr & BITS_DBI_ADDR_MASK; 124162306a36Sopenharmony_ci write_addr |= u16_encode_bits(BIT(remainder), BITS_DBI_WREN); 124262306a36Sopenharmony_ci rtw_write8(rtwdev, REG_DBI_WDATA_V1 + remainder, data); 124362306a36Sopenharmony_ci rtw_write16(rtwdev, REG_DBI_FLAG_V1, write_addr); 124462306a36Sopenharmony_ci rtw_write8(rtwdev, REG_DBI_FLAG_V1 + 2, BIT_DBI_WFLAG >> 16); 124562306a36Sopenharmony_ci 124662306a36Sopenharmony_ci for (cnt = 0; cnt < RTW_PCI_WR_RETRY_CNT; cnt++) { 124762306a36Sopenharmony_ci flag = rtw_read8(rtwdev, REG_DBI_FLAG_V1 + 2); 124862306a36Sopenharmony_ci if (flag == 0) 124962306a36Sopenharmony_ci return; 125062306a36Sopenharmony_ci 125162306a36Sopenharmony_ci udelay(10); 125262306a36Sopenharmony_ci } 125362306a36Sopenharmony_ci 125462306a36Sopenharmony_ci WARN(flag, "failed to write to DBI register, addr=0x%04x\n", addr); 125562306a36Sopenharmony_ci} 125662306a36Sopenharmony_ci 125762306a36Sopenharmony_cistatic int rtw_dbi_read8(struct rtw_dev *rtwdev, u16 addr, u8 *value) 125862306a36Sopenharmony_ci{ 125962306a36Sopenharmony_ci u16 read_addr = addr & BITS_DBI_ADDR_MASK; 126062306a36Sopenharmony_ci u8 flag; 126162306a36Sopenharmony_ci u8 cnt; 126262306a36Sopenharmony_ci 126362306a36Sopenharmony_ci rtw_write16(rtwdev, REG_DBI_FLAG_V1, read_addr); 126462306a36Sopenharmony_ci rtw_write8(rtwdev, REG_DBI_FLAG_V1 + 2, BIT_DBI_RFLAG >> 16); 126562306a36Sopenharmony_ci 126662306a36Sopenharmony_ci for (cnt = 0; cnt < RTW_PCI_WR_RETRY_CNT; cnt++) { 126762306a36Sopenharmony_ci flag = rtw_read8(rtwdev, REG_DBI_FLAG_V1 + 2); 126862306a36Sopenharmony_ci if (flag == 0) { 126962306a36Sopenharmony_ci read_addr = REG_DBI_RDATA_V1 + (addr & 3); 127062306a36Sopenharmony_ci *value = rtw_read8(rtwdev, read_addr); 127162306a36Sopenharmony_ci return 0; 127262306a36Sopenharmony_ci } 127362306a36Sopenharmony_ci 127462306a36Sopenharmony_ci udelay(10); 127562306a36Sopenharmony_ci } 127662306a36Sopenharmony_ci 127762306a36Sopenharmony_ci WARN(1, "failed to read DBI register, addr=0x%04x\n", addr); 127862306a36Sopenharmony_ci return -EIO; 127962306a36Sopenharmony_ci} 128062306a36Sopenharmony_ci 128162306a36Sopenharmony_cistatic void rtw_mdio_write(struct rtw_dev *rtwdev, u8 addr, u16 data, bool g1) 128262306a36Sopenharmony_ci{ 128362306a36Sopenharmony_ci u8 page; 128462306a36Sopenharmony_ci u8 wflag; 128562306a36Sopenharmony_ci u8 cnt; 128662306a36Sopenharmony_ci 128762306a36Sopenharmony_ci rtw_write16(rtwdev, REG_MDIO_V1, data); 128862306a36Sopenharmony_ci 128962306a36Sopenharmony_ci page = addr < RTW_PCI_MDIO_PG_SZ ? 0 : 1; 129062306a36Sopenharmony_ci page += g1 ? RTW_PCI_MDIO_PG_OFFS_G1 : RTW_PCI_MDIO_PG_OFFS_G2; 129162306a36Sopenharmony_ci rtw_write8(rtwdev, REG_PCIE_MIX_CFG, addr & BITS_MDIO_ADDR_MASK); 129262306a36Sopenharmony_ci rtw_write8(rtwdev, REG_PCIE_MIX_CFG + 3, page); 129362306a36Sopenharmony_ci rtw_write32_mask(rtwdev, REG_PCIE_MIX_CFG, BIT_MDIO_WFLAG_V1, 1); 129462306a36Sopenharmony_ci 129562306a36Sopenharmony_ci for (cnt = 0; cnt < RTW_PCI_WR_RETRY_CNT; cnt++) { 129662306a36Sopenharmony_ci wflag = rtw_read32_mask(rtwdev, REG_PCIE_MIX_CFG, 129762306a36Sopenharmony_ci BIT_MDIO_WFLAG_V1); 129862306a36Sopenharmony_ci if (wflag == 0) 129962306a36Sopenharmony_ci return; 130062306a36Sopenharmony_ci 130162306a36Sopenharmony_ci udelay(10); 130262306a36Sopenharmony_ci } 130362306a36Sopenharmony_ci 130462306a36Sopenharmony_ci WARN(wflag, "failed to write to MDIO register, addr=0x%02x\n", addr); 130562306a36Sopenharmony_ci} 130662306a36Sopenharmony_ci 130762306a36Sopenharmony_cistatic void rtw_pci_clkreq_set(struct rtw_dev *rtwdev, bool enable) 130862306a36Sopenharmony_ci{ 130962306a36Sopenharmony_ci u8 value; 131062306a36Sopenharmony_ci int ret; 131162306a36Sopenharmony_ci 131262306a36Sopenharmony_ci if (rtw_pci_disable_aspm) 131362306a36Sopenharmony_ci return; 131462306a36Sopenharmony_ci 131562306a36Sopenharmony_ci ret = rtw_dbi_read8(rtwdev, RTK_PCIE_LINK_CFG, &value); 131662306a36Sopenharmony_ci if (ret) { 131762306a36Sopenharmony_ci rtw_err(rtwdev, "failed to read CLKREQ_L1, ret=%d", ret); 131862306a36Sopenharmony_ci return; 131962306a36Sopenharmony_ci } 132062306a36Sopenharmony_ci 132162306a36Sopenharmony_ci if (enable) 132262306a36Sopenharmony_ci value |= BIT_CLKREQ_SW_EN; 132362306a36Sopenharmony_ci else 132462306a36Sopenharmony_ci value &= ~BIT_CLKREQ_SW_EN; 132562306a36Sopenharmony_ci 132662306a36Sopenharmony_ci rtw_dbi_write8(rtwdev, RTK_PCIE_LINK_CFG, value); 132762306a36Sopenharmony_ci} 132862306a36Sopenharmony_ci 132962306a36Sopenharmony_cistatic void rtw_pci_clkreq_pad_low(struct rtw_dev *rtwdev, bool enable) 133062306a36Sopenharmony_ci{ 133162306a36Sopenharmony_ci u8 value; 133262306a36Sopenharmony_ci int ret; 133362306a36Sopenharmony_ci 133462306a36Sopenharmony_ci ret = rtw_dbi_read8(rtwdev, RTK_PCIE_LINK_CFG, &value); 133562306a36Sopenharmony_ci if (ret) { 133662306a36Sopenharmony_ci rtw_err(rtwdev, "failed to read CLKREQ_L1, ret=%d", ret); 133762306a36Sopenharmony_ci return; 133862306a36Sopenharmony_ci } 133962306a36Sopenharmony_ci 134062306a36Sopenharmony_ci if (enable) 134162306a36Sopenharmony_ci value &= ~BIT_CLKREQ_N_PAD; 134262306a36Sopenharmony_ci else 134362306a36Sopenharmony_ci value |= BIT_CLKREQ_N_PAD; 134462306a36Sopenharmony_ci 134562306a36Sopenharmony_ci rtw_dbi_write8(rtwdev, RTK_PCIE_LINK_CFG, value); 134662306a36Sopenharmony_ci} 134762306a36Sopenharmony_ci 134862306a36Sopenharmony_cistatic void rtw_pci_aspm_set(struct rtw_dev *rtwdev, bool enable) 134962306a36Sopenharmony_ci{ 135062306a36Sopenharmony_ci u8 value; 135162306a36Sopenharmony_ci int ret; 135262306a36Sopenharmony_ci 135362306a36Sopenharmony_ci if (rtw_pci_disable_aspm) 135462306a36Sopenharmony_ci return; 135562306a36Sopenharmony_ci 135662306a36Sopenharmony_ci ret = rtw_dbi_read8(rtwdev, RTK_PCIE_LINK_CFG, &value); 135762306a36Sopenharmony_ci if (ret) { 135862306a36Sopenharmony_ci rtw_err(rtwdev, "failed to read ASPM, ret=%d", ret); 135962306a36Sopenharmony_ci return; 136062306a36Sopenharmony_ci } 136162306a36Sopenharmony_ci 136262306a36Sopenharmony_ci if (enable) 136362306a36Sopenharmony_ci value |= BIT_L1_SW_EN; 136462306a36Sopenharmony_ci else 136562306a36Sopenharmony_ci value &= ~BIT_L1_SW_EN; 136662306a36Sopenharmony_ci 136762306a36Sopenharmony_ci rtw_dbi_write8(rtwdev, RTK_PCIE_LINK_CFG, value); 136862306a36Sopenharmony_ci} 136962306a36Sopenharmony_ci 137062306a36Sopenharmony_cistatic void rtw_pci_link_ps(struct rtw_dev *rtwdev, bool enter) 137162306a36Sopenharmony_ci{ 137262306a36Sopenharmony_ci struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; 137362306a36Sopenharmony_ci 137462306a36Sopenharmony_ci /* Like CLKREQ, ASPM is also implemented by two HW modules, and can 137562306a36Sopenharmony_ci * only be enabled when host supports it. 137662306a36Sopenharmony_ci * 137762306a36Sopenharmony_ci * And ASPM mechanism should be enabled when driver/firmware enters 137862306a36Sopenharmony_ci * power save mode, without having heavy traffic. Because we've 137962306a36Sopenharmony_ci * experienced some inter-operability issues that the link tends 138062306a36Sopenharmony_ci * to enter L1 state on the fly even when driver is having high 138162306a36Sopenharmony_ci * throughput. This is probably because the ASPM behavior slightly 138262306a36Sopenharmony_ci * varies from different SOC. 138362306a36Sopenharmony_ci */ 138462306a36Sopenharmony_ci if (!(rtwpci->link_ctrl & PCI_EXP_LNKCTL_ASPM_L1)) 138562306a36Sopenharmony_ci return; 138662306a36Sopenharmony_ci 138762306a36Sopenharmony_ci if ((enter && atomic_dec_if_positive(&rtwpci->link_usage) == 0) || 138862306a36Sopenharmony_ci (!enter && atomic_inc_return(&rtwpci->link_usage) == 1)) 138962306a36Sopenharmony_ci rtw_pci_aspm_set(rtwdev, enter); 139062306a36Sopenharmony_ci} 139162306a36Sopenharmony_ci 139262306a36Sopenharmony_cistatic void rtw_pci_link_cfg(struct rtw_dev *rtwdev) 139362306a36Sopenharmony_ci{ 139462306a36Sopenharmony_ci const struct rtw_chip_info *chip = rtwdev->chip; 139562306a36Sopenharmony_ci struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; 139662306a36Sopenharmony_ci struct pci_dev *pdev = rtwpci->pdev; 139762306a36Sopenharmony_ci u16 link_ctrl; 139862306a36Sopenharmony_ci int ret; 139962306a36Sopenharmony_ci 140062306a36Sopenharmony_ci /* RTL8822CE has enabled REFCLK auto calibration, it does not need 140162306a36Sopenharmony_ci * to add clock delay to cover the REFCLK timing gap. 140262306a36Sopenharmony_ci */ 140362306a36Sopenharmony_ci if (chip->id == RTW_CHIP_TYPE_8822C) 140462306a36Sopenharmony_ci rtw_dbi_write8(rtwdev, RTK_PCIE_CLKDLY_CTRL, 0); 140562306a36Sopenharmony_ci 140662306a36Sopenharmony_ci /* Though there is standard PCIE configuration space to set the 140762306a36Sopenharmony_ci * link control register, but by Realtek's design, driver should 140862306a36Sopenharmony_ci * check if host supports CLKREQ/ASPM to enable the HW module. 140962306a36Sopenharmony_ci * 141062306a36Sopenharmony_ci * These functions are implemented by two HW modules associated, 141162306a36Sopenharmony_ci * one is responsible to access PCIE configuration space to 141262306a36Sopenharmony_ci * follow the host settings, and another is in charge of doing 141362306a36Sopenharmony_ci * CLKREQ/ASPM mechanisms, it is default disabled. Because sometimes 141462306a36Sopenharmony_ci * the host does not support it, and due to some reasons or wrong 141562306a36Sopenharmony_ci * settings (ex. CLKREQ# not Bi-Direction), it could lead to device 141662306a36Sopenharmony_ci * loss if HW misbehaves on the link. 141762306a36Sopenharmony_ci * 141862306a36Sopenharmony_ci * Hence it's designed that driver should first check the PCIE 141962306a36Sopenharmony_ci * configuration space is sync'ed and enabled, then driver can turn 142062306a36Sopenharmony_ci * on the other module that is actually working on the mechanism. 142162306a36Sopenharmony_ci */ 142262306a36Sopenharmony_ci ret = pcie_capability_read_word(pdev, PCI_EXP_LNKCTL, &link_ctrl); 142362306a36Sopenharmony_ci if (ret) { 142462306a36Sopenharmony_ci rtw_err(rtwdev, "failed to read PCI cap, ret=%d\n", ret); 142562306a36Sopenharmony_ci return; 142662306a36Sopenharmony_ci } 142762306a36Sopenharmony_ci 142862306a36Sopenharmony_ci if (link_ctrl & PCI_EXP_LNKCTL_CLKREQ_EN) 142962306a36Sopenharmony_ci rtw_pci_clkreq_set(rtwdev, true); 143062306a36Sopenharmony_ci 143162306a36Sopenharmony_ci rtwpci->link_ctrl = link_ctrl; 143262306a36Sopenharmony_ci} 143362306a36Sopenharmony_ci 143462306a36Sopenharmony_cistatic void rtw_pci_interface_cfg(struct rtw_dev *rtwdev) 143562306a36Sopenharmony_ci{ 143662306a36Sopenharmony_ci const struct rtw_chip_info *chip = rtwdev->chip; 143762306a36Sopenharmony_ci 143862306a36Sopenharmony_ci switch (chip->id) { 143962306a36Sopenharmony_ci case RTW_CHIP_TYPE_8822C: 144062306a36Sopenharmony_ci if (rtwdev->hal.cut_version >= RTW_CHIP_VER_CUT_D) 144162306a36Sopenharmony_ci rtw_write32_mask(rtwdev, REG_HCI_MIX_CFG, 144262306a36Sopenharmony_ci BIT_PCIE_EMAC_PDN_AUX_TO_FAST_CLK, 1); 144362306a36Sopenharmony_ci break; 144462306a36Sopenharmony_ci default: 144562306a36Sopenharmony_ci break; 144662306a36Sopenharmony_ci } 144762306a36Sopenharmony_ci} 144862306a36Sopenharmony_ci 144962306a36Sopenharmony_cistatic void rtw_pci_phy_cfg(struct rtw_dev *rtwdev) 145062306a36Sopenharmony_ci{ 145162306a36Sopenharmony_ci struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; 145262306a36Sopenharmony_ci const struct rtw_chip_info *chip = rtwdev->chip; 145362306a36Sopenharmony_ci struct pci_dev *pdev = rtwpci->pdev; 145462306a36Sopenharmony_ci const struct rtw_intf_phy_para *para; 145562306a36Sopenharmony_ci u16 cut; 145662306a36Sopenharmony_ci u16 value; 145762306a36Sopenharmony_ci u16 offset; 145862306a36Sopenharmony_ci int i; 145962306a36Sopenharmony_ci int ret; 146062306a36Sopenharmony_ci 146162306a36Sopenharmony_ci cut = BIT(0) << rtwdev->hal.cut_version; 146262306a36Sopenharmony_ci 146362306a36Sopenharmony_ci for (i = 0; i < chip->intf_table->n_gen1_para; i++) { 146462306a36Sopenharmony_ci para = &chip->intf_table->gen1_para[i]; 146562306a36Sopenharmony_ci if (!(para->cut_mask & cut)) 146662306a36Sopenharmony_ci continue; 146762306a36Sopenharmony_ci if (para->offset == 0xffff) 146862306a36Sopenharmony_ci break; 146962306a36Sopenharmony_ci offset = para->offset; 147062306a36Sopenharmony_ci value = para->value; 147162306a36Sopenharmony_ci if (para->ip_sel == RTW_IP_SEL_PHY) 147262306a36Sopenharmony_ci rtw_mdio_write(rtwdev, offset, value, true); 147362306a36Sopenharmony_ci else 147462306a36Sopenharmony_ci rtw_dbi_write8(rtwdev, offset, value); 147562306a36Sopenharmony_ci } 147662306a36Sopenharmony_ci 147762306a36Sopenharmony_ci for (i = 0; i < chip->intf_table->n_gen2_para; i++) { 147862306a36Sopenharmony_ci para = &chip->intf_table->gen2_para[i]; 147962306a36Sopenharmony_ci if (!(para->cut_mask & cut)) 148062306a36Sopenharmony_ci continue; 148162306a36Sopenharmony_ci if (para->offset == 0xffff) 148262306a36Sopenharmony_ci break; 148362306a36Sopenharmony_ci offset = para->offset; 148462306a36Sopenharmony_ci value = para->value; 148562306a36Sopenharmony_ci if (para->ip_sel == RTW_IP_SEL_PHY) 148662306a36Sopenharmony_ci rtw_mdio_write(rtwdev, offset, value, false); 148762306a36Sopenharmony_ci else 148862306a36Sopenharmony_ci rtw_dbi_write8(rtwdev, offset, value); 148962306a36Sopenharmony_ci } 149062306a36Sopenharmony_ci 149162306a36Sopenharmony_ci rtw_pci_link_cfg(rtwdev); 149262306a36Sopenharmony_ci 149362306a36Sopenharmony_ci /* Disable 8821ce completion timeout by default */ 149462306a36Sopenharmony_ci if (chip->id == RTW_CHIP_TYPE_8821C) { 149562306a36Sopenharmony_ci ret = pcie_capability_set_word(pdev, PCI_EXP_DEVCTL2, 149662306a36Sopenharmony_ci PCI_EXP_DEVCTL2_COMP_TMOUT_DIS); 149762306a36Sopenharmony_ci if (ret) 149862306a36Sopenharmony_ci rtw_err(rtwdev, "failed to set PCI cap, ret = %d\n", 149962306a36Sopenharmony_ci ret); 150062306a36Sopenharmony_ci } 150162306a36Sopenharmony_ci} 150262306a36Sopenharmony_ci 150362306a36Sopenharmony_cistatic int __maybe_unused rtw_pci_suspend(struct device *dev) 150462306a36Sopenharmony_ci{ 150562306a36Sopenharmony_ci struct ieee80211_hw *hw = dev_get_drvdata(dev); 150662306a36Sopenharmony_ci struct rtw_dev *rtwdev = hw->priv; 150762306a36Sopenharmony_ci const struct rtw_chip_info *chip = rtwdev->chip; 150862306a36Sopenharmony_ci struct rtw_efuse *efuse = &rtwdev->efuse; 150962306a36Sopenharmony_ci 151062306a36Sopenharmony_ci if (chip->id == RTW_CHIP_TYPE_8822C && efuse->rfe_option == 6) 151162306a36Sopenharmony_ci rtw_pci_clkreq_pad_low(rtwdev, true); 151262306a36Sopenharmony_ci return 0; 151362306a36Sopenharmony_ci} 151462306a36Sopenharmony_ci 151562306a36Sopenharmony_cistatic int __maybe_unused rtw_pci_resume(struct device *dev) 151662306a36Sopenharmony_ci{ 151762306a36Sopenharmony_ci struct ieee80211_hw *hw = dev_get_drvdata(dev); 151862306a36Sopenharmony_ci struct rtw_dev *rtwdev = hw->priv; 151962306a36Sopenharmony_ci const struct rtw_chip_info *chip = rtwdev->chip; 152062306a36Sopenharmony_ci struct rtw_efuse *efuse = &rtwdev->efuse; 152162306a36Sopenharmony_ci 152262306a36Sopenharmony_ci if (chip->id == RTW_CHIP_TYPE_8822C && efuse->rfe_option == 6) 152362306a36Sopenharmony_ci rtw_pci_clkreq_pad_low(rtwdev, false); 152462306a36Sopenharmony_ci return 0; 152562306a36Sopenharmony_ci} 152662306a36Sopenharmony_ci 152762306a36Sopenharmony_ciSIMPLE_DEV_PM_OPS(rtw_pm_ops, rtw_pci_suspend, rtw_pci_resume); 152862306a36Sopenharmony_ciEXPORT_SYMBOL(rtw_pm_ops); 152962306a36Sopenharmony_ci 153062306a36Sopenharmony_cistatic int rtw_pci_claim(struct rtw_dev *rtwdev, struct pci_dev *pdev) 153162306a36Sopenharmony_ci{ 153262306a36Sopenharmony_ci int ret; 153362306a36Sopenharmony_ci 153462306a36Sopenharmony_ci ret = pci_enable_device(pdev); 153562306a36Sopenharmony_ci if (ret) { 153662306a36Sopenharmony_ci rtw_err(rtwdev, "failed to enable pci device\n"); 153762306a36Sopenharmony_ci return ret; 153862306a36Sopenharmony_ci } 153962306a36Sopenharmony_ci 154062306a36Sopenharmony_ci pci_set_master(pdev); 154162306a36Sopenharmony_ci pci_set_drvdata(pdev, rtwdev->hw); 154262306a36Sopenharmony_ci SET_IEEE80211_DEV(rtwdev->hw, &pdev->dev); 154362306a36Sopenharmony_ci 154462306a36Sopenharmony_ci return 0; 154562306a36Sopenharmony_ci} 154662306a36Sopenharmony_ci 154762306a36Sopenharmony_cistatic void rtw_pci_declaim(struct rtw_dev *rtwdev, struct pci_dev *pdev) 154862306a36Sopenharmony_ci{ 154962306a36Sopenharmony_ci pci_disable_device(pdev); 155062306a36Sopenharmony_ci} 155162306a36Sopenharmony_ci 155262306a36Sopenharmony_cistatic int rtw_pci_setup_resource(struct rtw_dev *rtwdev, struct pci_dev *pdev) 155362306a36Sopenharmony_ci{ 155462306a36Sopenharmony_ci struct rtw_pci *rtwpci; 155562306a36Sopenharmony_ci int ret; 155662306a36Sopenharmony_ci 155762306a36Sopenharmony_ci rtwpci = (struct rtw_pci *)rtwdev->priv; 155862306a36Sopenharmony_ci rtwpci->pdev = pdev; 155962306a36Sopenharmony_ci 156062306a36Sopenharmony_ci /* after this driver can access to hw registers */ 156162306a36Sopenharmony_ci ret = rtw_pci_io_mapping(rtwdev, pdev); 156262306a36Sopenharmony_ci if (ret) { 156362306a36Sopenharmony_ci rtw_err(rtwdev, "failed to request pci io region\n"); 156462306a36Sopenharmony_ci goto err_out; 156562306a36Sopenharmony_ci } 156662306a36Sopenharmony_ci 156762306a36Sopenharmony_ci ret = rtw_pci_init(rtwdev); 156862306a36Sopenharmony_ci if (ret) { 156962306a36Sopenharmony_ci rtw_err(rtwdev, "failed to allocate pci resources\n"); 157062306a36Sopenharmony_ci goto err_io_unmap; 157162306a36Sopenharmony_ci } 157262306a36Sopenharmony_ci 157362306a36Sopenharmony_ci return 0; 157462306a36Sopenharmony_ci 157562306a36Sopenharmony_cierr_io_unmap: 157662306a36Sopenharmony_ci rtw_pci_io_unmapping(rtwdev, pdev); 157762306a36Sopenharmony_ci 157862306a36Sopenharmony_cierr_out: 157962306a36Sopenharmony_ci return ret; 158062306a36Sopenharmony_ci} 158162306a36Sopenharmony_ci 158262306a36Sopenharmony_cistatic void rtw_pci_destroy(struct rtw_dev *rtwdev, struct pci_dev *pdev) 158362306a36Sopenharmony_ci{ 158462306a36Sopenharmony_ci rtw_pci_deinit(rtwdev); 158562306a36Sopenharmony_ci rtw_pci_io_unmapping(rtwdev, pdev); 158662306a36Sopenharmony_ci} 158762306a36Sopenharmony_ci 158862306a36Sopenharmony_cistatic struct rtw_hci_ops rtw_pci_ops = { 158962306a36Sopenharmony_ci .tx_write = rtw_pci_tx_write, 159062306a36Sopenharmony_ci .tx_kick_off = rtw_pci_tx_kick_off, 159162306a36Sopenharmony_ci .flush_queues = rtw_pci_flush_queues, 159262306a36Sopenharmony_ci .setup = rtw_pci_setup, 159362306a36Sopenharmony_ci .start = rtw_pci_start, 159462306a36Sopenharmony_ci .stop = rtw_pci_stop, 159562306a36Sopenharmony_ci .deep_ps = rtw_pci_deep_ps, 159662306a36Sopenharmony_ci .link_ps = rtw_pci_link_ps, 159762306a36Sopenharmony_ci .interface_cfg = rtw_pci_interface_cfg, 159862306a36Sopenharmony_ci 159962306a36Sopenharmony_ci .read8 = rtw_pci_read8, 160062306a36Sopenharmony_ci .read16 = rtw_pci_read16, 160162306a36Sopenharmony_ci .read32 = rtw_pci_read32, 160262306a36Sopenharmony_ci .write8 = rtw_pci_write8, 160362306a36Sopenharmony_ci .write16 = rtw_pci_write16, 160462306a36Sopenharmony_ci .write32 = rtw_pci_write32, 160562306a36Sopenharmony_ci .write_data_rsvd_page = rtw_pci_write_data_rsvd_page, 160662306a36Sopenharmony_ci .write_data_h2c = rtw_pci_write_data_h2c, 160762306a36Sopenharmony_ci}; 160862306a36Sopenharmony_ci 160962306a36Sopenharmony_cistatic int rtw_pci_request_irq(struct rtw_dev *rtwdev, struct pci_dev *pdev) 161062306a36Sopenharmony_ci{ 161162306a36Sopenharmony_ci unsigned int flags = PCI_IRQ_LEGACY; 161262306a36Sopenharmony_ci int ret; 161362306a36Sopenharmony_ci 161462306a36Sopenharmony_ci if (!rtw_disable_msi) 161562306a36Sopenharmony_ci flags |= PCI_IRQ_MSI; 161662306a36Sopenharmony_ci 161762306a36Sopenharmony_ci ret = pci_alloc_irq_vectors(pdev, 1, 1, flags); 161862306a36Sopenharmony_ci if (ret < 0) { 161962306a36Sopenharmony_ci rtw_err(rtwdev, "failed to alloc PCI irq vectors\n"); 162062306a36Sopenharmony_ci return ret; 162162306a36Sopenharmony_ci } 162262306a36Sopenharmony_ci 162362306a36Sopenharmony_ci ret = devm_request_threaded_irq(rtwdev->dev, pdev->irq, 162462306a36Sopenharmony_ci rtw_pci_interrupt_handler, 162562306a36Sopenharmony_ci rtw_pci_interrupt_threadfn, 162662306a36Sopenharmony_ci IRQF_SHARED, KBUILD_MODNAME, rtwdev); 162762306a36Sopenharmony_ci if (ret) { 162862306a36Sopenharmony_ci rtw_err(rtwdev, "failed to request irq %d\n", ret); 162962306a36Sopenharmony_ci pci_free_irq_vectors(pdev); 163062306a36Sopenharmony_ci } 163162306a36Sopenharmony_ci 163262306a36Sopenharmony_ci return ret; 163362306a36Sopenharmony_ci} 163462306a36Sopenharmony_ci 163562306a36Sopenharmony_cistatic void rtw_pci_free_irq(struct rtw_dev *rtwdev, struct pci_dev *pdev) 163662306a36Sopenharmony_ci{ 163762306a36Sopenharmony_ci devm_free_irq(rtwdev->dev, pdev->irq, rtwdev); 163862306a36Sopenharmony_ci pci_free_irq_vectors(pdev); 163962306a36Sopenharmony_ci} 164062306a36Sopenharmony_ci 164162306a36Sopenharmony_cistatic int rtw_pci_napi_poll(struct napi_struct *napi, int budget) 164262306a36Sopenharmony_ci{ 164362306a36Sopenharmony_ci struct rtw_pci *rtwpci = container_of(napi, struct rtw_pci, napi); 164462306a36Sopenharmony_ci struct rtw_dev *rtwdev = container_of((void *)rtwpci, struct rtw_dev, 164562306a36Sopenharmony_ci priv); 164662306a36Sopenharmony_ci int work_done = 0; 164762306a36Sopenharmony_ci 164862306a36Sopenharmony_ci if (rtwpci->rx_no_aspm) 164962306a36Sopenharmony_ci rtw_pci_link_ps(rtwdev, false); 165062306a36Sopenharmony_ci 165162306a36Sopenharmony_ci while (work_done < budget) { 165262306a36Sopenharmony_ci u32 work_done_once; 165362306a36Sopenharmony_ci 165462306a36Sopenharmony_ci work_done_once = rtw_pci_rx_napi(rtwdev, rtwpci, RTW_RX_QUEUE_MPDU, 165562306a36Sopenharmony_ci budget - work_done); 165662306a36Sopenharmony_ci if (work_done_once == 0) 165762306a36Sopenharmony_ci break; 165862306a36Sopenharmony_ci work_done += work_done_once; 165962306a36Sopenharmony_ci } 166062306a36Sopenharmony_ci if (work_done < budget) { 166162306a36Sopenharmony_ci napi_complete_done(napi, work_done); 166262306a36Sopenharmony_ci spin_lock_bh(&rtwpci->irq_lock); 166362306a36Sopenharmony_ci if (rtwpci->running) 166462306a36Sopenharmony_ci rtw_pci_enable_interrupt(rtwdev, rtwpci, false); 166562306a36Sopenharmony_ci spin_unlock_bh(&rtwpci->irq_lock); 166662306a36Sopenharmony_ci /* When ISR happens during polling and before napi_complete 166762306a36Sopenharmony_ci * while no further data is received. Data on the dma_ring will 166862306a36Sopenharmony_ci * not be processed immediately. Check whether dma ring is 166962306a36Sopenharmony_ci * empty and perform napi_schedule accordingly. 167062306a36Sopenharmony_ci */ 167162306a36Sopenharmony_ci if (rtw_pci_get_hw_rx_ring_nr(rtwdev, rtwpci)) 167262306a36Sopenharmony_ci napi_schedule(napi); 167362306a36Sopenharmony_ci } 167462306a36Sopenharmony_ci if (rtwpci->rx_no_aspm) 167562306a36Sopenharmony_ci rtw_pci_link_ps(rtwdev, true); 167662306a36Sopenharmony_ci 167762306a36Sopenharmony_ci return work_done; 167862306a36Sopenharmony_ci} 167962306a36Sopenharmony_ci 168062306a36Sopenharmony_cistatic void rtw_pci_napi_init(struct rtw_dev *rtwdev) 168162306a36Sopenharmony_ci{ 168262306a36Sopenharmony_ci struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; 168362306a36Sopenharmony_ci 168462306a36Sopenharmony_ci init_dummy_netdev(&rtwpci->netdev); 168562306a36Sopenharmony_ci netif_napi_add(&rtwpci->netdev, &rtwpci->napi, rtw_pci_napi_poll); 168662306a36Sopenharmony_ci} 168762306a36Sopenharmony_ci 168862306a36Sopenharmony_cistatic void rtw_pci_napi_deinit(struct rtw_dev *rtwdev) 168962306a36Sopenharmony_ci{ 169062306a36Sopenharmony_ci struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; 169162306a36Sopenharmony_ci 169262306a36Sopenharmony_ci rtw_pci_napi_stop(rtwdev); 169362306a36Sopenharmony_ci netif_napi_del(&rtwpci->napi); 169462306a36Sopenharmony_ci} 169562306a36Sopenharmony_ci 169662306a36Sopenharmony_ciint rtw_pci_probe(struct pci_dev *pdev, 169762306a36Sopenharmony_ci const struct pci_device_id *id) 169862306a36Sopenharmony_ci{ 169962306a36Sopenharmony_ci struct pci_dev *bridge = pci_upstream_bridge(pdev); 170062306a36Sopenharmony_ci struct ieee80211_hw *hw; 170162306a36Sopenharmony_ci struct rtw_dev *rtwdev; 170262306a36Sopenharmony_ci struct rtw_pci *rtwpci; 170362306a36Sopenharmony_ci int drv_data_size; 170462306a36Sopenharmony_ci int ret; 170562306a36Sopenharmony_ci 170662306a36Sopenharmony_ci drv_data_size = sizeof(struct rtw_dev) + sizeof(struct rtw_pci); 170762306a36Sopenharmony_ci hw = ieee80211_alloc_hw(drv_data_size, &rtw_ops); 170862306a36Sopenharmony_ci if (!hw) { 170962306a36Sopenharmony_ci dev_err(&pdev->dev, "failed to allocate hw\n"); 171062306a36Sopenharmony_ci return -ENOMEM; 171162306a36Sopenharmony_ci } 171262306a36Sopenharmony_ci 171362306a36Sopenharmony_ci rtwdev = hw->priv; 171462306a36Sopenharmony_ci rtwdev->hw = hw; 171562306a36Sopenharmony_ci rtwdev->dev = &pdev->dev; 171662306a36Sopenharmony_ci rtwdev->chip = (struct rtw_chip_info *)id->driver_data; 171762306a36Sopenharmony_ci rtwdev->hci.ops = &rtw_pci_ops; 171862306a36Sopenharmony_ci rtwdev->hci.type = RTW_HCI_TYPE_PCIE; 171962306a36Sopenharmony_ci 172062306a36Sopenharmony_ci rtwpci = (struct rtw_pci *)rtwdev->priv; 172162306a36Sopenharmony_ci atomic_set(&rtwpci->link_usage, 1); 172262306a36Sopenharmony_ci 172362306a36Sopenharmony_ci ret = rtw_core_init(rtwdev); 172462306a36Sopenharmony_ci if (ret) 172562306a36Sopenharmony_ci goto err_release_hw; 172662306a36Sopenharmony_ci 172762306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_PCI, 172862306a36Sopenharmony_ci "rtw88 pci probe: vendor=0x%4.04X device=0x%4.04X rev=%d\n", 172962306a36Sopenharmony_ci pdev->vendor, pdev->device, pdev->revision); 173062306a36Sopenharmony_ci 173162306a36Sopenharmony_ci ret = rtw_pci_claim(rtwdev, pdev); 173262306a36Sopenharmony_ci if (ret) { 173362306a36Sopenharmony_ci rtw_err(rtwdev, "failed to claim pci device\n"); 173462306a36Sopenharmony_ci goto err_deinit_core; 173562306a36Sopenharmony_ci } 173662306a36Sopenharmony_ci 173762306a36Sopenharmony_ci ret = rtw_pci_setup_resource(rtwdev, pdev); 173862306a36Sopenharmony_ci if (ret) { 173962306a36Sopenharmony_ci rtw_err(rtwdev, "failed to setup pci resources\n"); 174062306a36Sopenharmony_ci goto err_pci_declaim; 174162306a36Sopenharmony_ci } 174262306a36Sopenharmony_ci 174362306a36Sopenharmony_ci rtw_pci_napi_init(rtwdev); 174462306a36Sopenharmony_ci 174562306a36Sopenharmony_ci ret = rtw_chip_info_setup(rtwdev); 174662306a36Sopenharmony_ci if (ret) { 174762306a36Sopenharmony_ci rtw_err(rtwdev, "failed to setup chip information\n"); 174862306a36Sopenharmony_ci goto err_destroy_pci; 174962306a36Sopenharmony_ci } 175062306a36Sopenharmony_ci 175162306a36Sopenharmony_ci /* Disable PCIe ASPM L1 while doing NAPI poll for 8821CE */ 175262306a36Sopenharmony_ci if (rtwdev->chip->id == RTW_CHIP_TYPE_8821C && bridge->vendor == PCI_VENDOR_ID_INTEL) 175362306a36Sopenharmony_ci rtwpci->rx_no_aspm = true; 175462306a36Sopenharmony_ci 175562306a36Sopenharmony_ci rtw_pci_phy_cfg(rtwdev); 175662306a36Sopenharmony_ci 175762306a36Sopenharmony_ci ret = rtw_register_hw(rtwdev, hw); 175862306a36Sopenharmony_ci if (ret) { 175962306a36Sopenharmony_ci rtw_err(rtwdev, "failed to register hw\n"); 176062306a36Sopenharmony_ci goto err_destroy_pci; 176162306a36Sopenharmony_ci } 176262306a36Sopenharmony_ci 176362306a36Sopenharmony_ci ret = rtw_pci_request_irq(rtwdev, pdev); 176462306a36Sopenharmony_ci if (ret) { 176562306a36Sopenharmony_ci ieee80211_unregister_hw(hw); 176662306a36Sopenharmony_ci goto err_destroy_pci; 176762306a36Sopenharmony_ci } 176862306a36Sopenharmony_ci 176962306a36Sopenharmony_ci return 0; 177062306a36Sopenharmony_ci 177162306a36Sopenharmony_cierr_destroy_pci: 177262306a36Sopenharmony_ci rtw_pci_napi_deinit(rtwdev); 177362306a36Sopenharmony_ci rtw_pci_destroy(rtwdev, pdev); 177462306a36Sopenharmony_ci 177562306a36Sopenharmony_cierr_pci_declaim: 177662306a36Sopenharmony_ci rtw_pci_declaim(rtwdev, pdev); 177762306a36Sopenharmony_ci 177862306a36Sopenharmony_cierr_deinit_core: 177962306a36Sopenharmony_ci rtw_core_deinit(rtwdev); 178062306a36Sopenharmony_ci 178162306a36Sopenharmony_cierr_release_hw: 178262306a36Sopenharmony_ci ieee80211_free_hw(hw); 178362306a36Sopenharmony_ci 178462306a36Sopenharmony_ci return ret; 178562306a36Sopenharmony_ci} 178662306a36Sopenharmony_ciEXPORT_SYMBOL(rtw_pci_probe); 178762306a36Sopenharmony_ci 178862306a36Sopenharmony_civoid rtw_pci_remove(struct pci_dev *pdev) 178962306a36Sopenharmony_ci{ 179062306a36Sopenharmony_ci struct ieee80211_hw *hw = pci_get_drvdata(pdev); 179162306a36Sopenharmony_ci struct rtw_dev *rtwdev; 179262306a36Sopenharmony_ci struct rtw_pci *rtwpci; 179362306a36Sopenharmony_ci 179462306a36Sopenharmony_ci if (!hw) 179562306a36Sopenharmony_ci return; 179662306a36Sopenharmony_ci 179762306a36Sopenharmony_ci rtwdev = hw->priv; 179862306a36Sopenharmony_ci rtwpci = (struct rtw_pci *)rtwdev->priv; 179962306a36Sopenharmony_ci 180062306a36Sopenharmony_ci rtw_unregister_hw(rtwdev, hw); 180162306a36Sopenharmony_ci rtw_pci_disable_interrupt(rtwdev, rtwpci); 180262306a36Sopenharmony_ci rtw_pci_napi_deinit(rtwdev); 180362306a36Sopenharmony_ci rtw_pci_destroy(rtwdev, pdev); 180462306a36Sopenharmony_ci rtw_pci_declaim(rtwdev, pdev); 180562306a36Sopenharmony_ci rtw_pci_free_irq(rtwdev, pdev); 180662306a36Sopenharmony_ci rtw_core_deinit(rtwdev); 180762306a36Sopenharmony_ci ieee80211_free_hw(hw); 180862306a36Sopenharmony_ci} 180962306a36Sopenharmony_ciEXPORT_SYMBOL(rtw_pci_remove); 181062306a36Sopenharmony_ci 181162306a36Sopenharmony_civoid rtw_pci_shutdown(struct pci_dev *pdev) 181262306a36Sopenharmony_ci{ 181362306a36Sopenharmony_ci struct ieee80211_hw *hw = pci_get_drvdata(pdev); 181462306a36Sopenharmony_ci struct rtw_dev *rtwdev; 181562306a36Sopenharmony_ci const struct rtw_chip_info *chip; 181662306a36Sopenharmony_ci 181762306a36Sopenharmony_ci if (!hw) 181862306a36Sopenharmony_ci return; 181962306a36Sopenharmony_ci 182062306a36Sopenharmony_ci rtwdev = hw->priv; 182162306a36Sopenharmony_ci chip = rtwdev->chip; 182262306a36Sopenharmony_ci 182362306a36Sopenharmony_ci if (chip->ops->shutdown) 182462306a36Sopenharmony_ci chip->ops->shutdown(rtwdev); 182562306a36Sopenharmony_ci 182662306a36Sopenharmony_ci pci_set_power_state(pdev, PCI_D3hot); 182762306a36Sopenharmony_ci} 182862306a36Sopenharmony_ciEXPORT_SYMBOL(rtw_pci_shutdown); 182962306a36Sopenharmony_ci 183062306a36Sopenharmony_ciMODULE_AUTHOR("Realtek Corporation"); 183162306a36Sopenharmony_ciMODULE_DESCRIPTION("Realtek PCI 802.11ac wireless driver"); 183262306a36Sopenharmony_ciMODULE_LICENSE("Dual BSD/GPL"); 1833