Skip to content

Commit

Permalink
wifi: rtw89: pci: support 36-bit PCI DMA address
Browse files Browse the repository at this point in the history
Modern platforms can install more than 4GB memory, so DMA address can
larger than 32 bits. If a platform doesn't enable IOMMU, kernel needs extra
works of swiotlb to help DMA that packets reside on memory over 4GB.

The DMA addressing capability of Realtek WiFi chips is 36 bits, so set
LSB 4 bits of high 32-bit address to register and TX/RX descriptor, which
below figure shows 3-level pointers in TX direction, and RX direction is
similar but 2-level pointers only.

  +--------+
  |        | register to head of TX BD
  +---|----+
      |       +---------+
      +-----> |  TX BD  | (in memory)
              +----|----+
                   |        +---------+
                   +------> |  TX WD  | (in memory)
                            +----|----+
                                 |        +--------+
                                 +------> |   skb  |
                                          +--------+

Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Link: https://msgid.link/20240611021901.26394-1-pkshih@realtek.com
[Conflicts:
       drivers/net/wireless/realtek/rtw89/pci.c]
(cherry picked from commit 1fd4b3fe52efd5ad1647966f619c10988e7a4457)
Signed-off-by: Wentao Guan <otgwt@outlook.com>
  • Loading branch information
Ping-Ke Shih authored and opsiff committed Aug 19, 2024
1 parent b822465 commit cc04397
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 10 deletions.
26 changes: 16 additions & 10 deletions drivers/net/wireless/realtek/rtw89/pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -1302,7 +1302,7 @@ u32 rtw89_pci_fill_txaddr_info(struct rtw89_dev *rtwdev,

txaddr_info->length = cpu_to_le16(total_len);
option = cpu_to_le16(RTW89_PCI_ADDR_MSDU_LS | RTW89_PCI_ADDR_NUM(1));
option |= le16_encode_bits(dma >> 32, RTW89_PCI_ADDR_HIGH_MASK);
option |= le16_encode_bits(upper_32_bits(dma), RTW89_PCI_ADDR_HIGH_MASK);
txaddr_info->option = option;
txaddr_info->dma = cpu_to_le32(dma);

Expand Down Expand Up @@ -1330,7 +1330,8 @@ u32 rtw89_pci_fill_txaddr_info_v1(struct rtw89_dev *rtwdev,
length_option = FIELD_PREP(B_PCIADDR_LEN_V1_MASK, len) |
FIELD_PREP(B_PCIADDR_HIGH_SEL_V1_MASK, 0) |
FIELD_PREP(B_PCIADDR_LS_V1_MASK, remain == 0);
length_option |= u16_encode_bits(dma >> 32, B_PCIADDR_HIGH_SEL_V1_MASK);
length_option |= u16_encode_bits(upper_32_bits(dma),
B_PCIADDR_HIGH_SEL_V1_MASK);
txaddr_info->length_opt = cpu_to_le16(length_option);
txaddr_info->dma_low_lsb = cpu_to_le16(FIELD_GET(GENMASK(15, 0), dma));
txaddr_info->dma_low_msb = cpu_to_le16(FIELD_GET(GENMASK(31, 16), dma));
Expand Down Expand Up @@ -1435,7 +1436,7 @@ static int rtw89_pci_fwcmd_submit(struct rtw89_dev *rtwdev,

tx_data->dma = dma;
opt = cpu_to_le16(RTW89_PCI_TXBD_OPT_LS);
opt |= le16_encode_bits(dma >> 32, RTW89_PCI_TXBD_OPT_DMA_HI);
opt |= le16_encode_bits(upper_32_bits(dma), RTW89_PCI_TXBD_OPT_DMA_HI);
txbd->opt = opt;
txbd->length = cpu_to_le16(skb->len);
txbd->dma = cpu_to_le32(tx_data->dma);
Expand Down Expand Up @@ -1478,7 +1479,7 @@ static int rtw89_pci_txbd_submit(struct rtw89_dev *rtwdev,
list_add_tail(&txwd->list, &tx_ring->busy_pages);

opt = cpu_to_le16(RTW89_PCI_TXBD_OPT_LS);
opt |= le16_encode_bits(txwd->paddr >> 32, RTW89_PCI_TXBD_OPT_DMA_HI);
opt |= le16_encode_bits(upper_32_bits(txwd->paddr), RTW89_PCI_TXBD_OPT_DMA_HI);
txbd->opt = opt;
txbd->length = cpu_to_le16(txwd->len);
txbd->dma = cpu_to_le32(txwd->paddr);
Expand Down Expand Up @@ -1635,7 +1636,7 @@ static void rtw89_pci_reset_trx_rings(struct rtw89_dev *rtwdev)
rtw89_write32(rtwdev, addr_bdram, val32);
}
rtw89_write32(rtwdev, addr_desa_l, bd_ring->dma);
rtw89_write32(rtwdev, addr_desa_l + 4, bd_ring->dma >> 32);
rtw89_write32(rtwdev, addr_desa_l + 4, upper_32_bits(bd_ring->dma));
}

for (i = 0; i < RTW89_RXCH_NUM; i++) {
Expand All @@ -1655,7 +1656,7 @@ static void rtw89_pci_reset_trx_rings(struct rtw89_dev *rtwdev)

rtw89_write16(rtwdev, addr_num, bd_ring->len);
rtw89_write32(rtwdev, addr_desa_l, bd_ring->dma);
rtw89_write32(rtwdev, addr_desa_l + 4, bd_ring->dma >> 32);
rtw89_write32(rtwdev, addr_desa_l + 4, upper_32_bits(bd_ring->dma));

if (info->rx_ring_eq_is_full)
rtw89_write16(rtwdev, addr_idx, bd_ring->wp);
Expand Down Expand Up @@ -3027,10 +3028,14 @@ static void rtw89_pci_declaim_device(struct rtw89_dev *rtwdev,
pci_disable_device(pdev);
}

static void rtw89_pci_enable_dma_64bits(struct rtw89_dev *rtwdev)
static void rtw89_pci_cfg_dac(struct rtw89_dev *rtwdev)
{
struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv;
const struct rtw89_chip_info *chip = rtwdev->chip;

if (!rtwpci->enable_dac)
return;

switch (chip->chip_id) {
case RTL8852A:
case RTL8852B:
Expand Down Expand Up @@ -3059,8 +3064,8 @@ static int rtw89_pci_setup_mapping(struct rtw89_dev *rtwdev,

ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(36));
if (!ret) {
/* enable PCIE DAC mode */
rtw89_pci_enable_dma_64bits(rtwdev);
rtwpci->enable_dac = true;
rtw89_pci_cfg_dac(rtwdev);
} else {
ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
if (ret) {
Expand Down Expand Up @@ -3218,7 +3223,7 @@ static int rtw89_pci_init_rx_bd(struct rtw89_dev *rtwdev, struct pci_dev *pdev,
memset(rx_bd, 0, sizeof(*rx_bd));
rx_bd->buf_size = cpu_to_le16(buf_sz);
rx_bd->dma = cpu_to_le32(dma);
rx_bd->opt = le16_encode_bits(dma >> 32, RTW89_PCI_RXBD_OPT_DMA_HI);
rx_bd->opt = le16_encode_bits(upper_32_bits(dma), RTW89_PCI_RXBD_OPT_DMA_HI);
rx_info->dma = dma;

return 0;
Expand Down Expand Up @@ -4210,6 +4215,7 @@ static int __maybe_unused rtw89_pci_resume(struct device *dev)
B_AX_SEL_REQ_ENTR_L1);
}
rtw89_pci_l2_hci_ldo(rtwdev);
rtw89_pci_cfg_dac(rtwdev);
rtw89_pci_filter_out(rtwdev);
rtw89_pci_link_cfg(rtwdev);
rtw89_pci_l1ss_cfg(rtwdev);
Expand Down
1 change: 1 addition & 0 deletions drivers/net/wireless/realtek/rtw89/pci.h
Original file line number Diff line number Diff line change
Expand Up @@ -1488,6 +1488,7 @@ struct rtw89_pci {
bool running;
bool low_power;
bool under_recovery;
bool enable_dac;
struct rtw89_pci_tx_ring tx_rings[RTW89_TXCH_NUM];
struct rtw89_pci_rx_ring rx_rings[RTW89_RXCH_NUM];
struct sk_buff_head h2c_queue;
Expand Down

0 comments on commit cc04397

Please sign in to comment.