]> Git Repo - linux.git/commitdiff
wifi: rtw89: pci: early chips only enable 36-bit DMA on specific PCI hosts
authorPing-Ke Shih <[email protected]>
Tue, 24 Sep 2024 02:16:33 +0000 (10:16 +0800)
committerKalle Valo <[email protected]>
Thu, 17 Oct 2024 14:23:15 +0000 (17:23 +0300)
The early chips including RTL8852A, RTL8851B, RTL8852B and RTL8852BT have
interoperability problems of 36-bit DMA with some PCI hosts. Rollback
to 32-bit DMA by default, and only enable 36-bit DMA for tested platforms.

Since all Intel platforms we have can work correctly, add the vendor ID to
white list. Otherwise, list vendor/device ID of bridge we have tested.

Fixes: 1fd4b3fe52ef ("wifi: rtw89: pci: support 36-bit PCI DMA address")
Reported-by: Marcel Weißenbach <[email protected]>
Closes: https://lore.kernel.org/linux-wireless/[email protected]/T/#m07c5694df1acb173a42e1a0bab7ac22bd231a2b8
Signed-off-by: Ping-Ke Shih <[email protected]>
Tested-by: Marcel Weißenbach <[email protected]>
Signed-off-by: Kalle Valo <[email protected]>
Link: https://patch.msgid.link/[email protected]
drivers/net/wireless/realtek/rtw89/pci.c

index 02afeb3acce469927a08bf81d45dd2c638345c06..5aef7fa378788c5d219c3ed19259aff3f4c67ddf 100644 (file)
@@ -3026,24 +3026,54 @@ static void rtw89_pci_declaim_device(struct rtw89_dev *rtwdev,
        pci_disable_device(pdev);
 }
 
-static void rtw89_pci_cfg_dac(struct rtw89_dev *rtwdev)
+static bool rtw89_pci_chip_is_manual_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:
        case RTL8851B:
        case RTL8852BT:
-               break;
+               return true;
        default:
-               return;
+               return false;
+       }
+}
+
+static bool rtw89_pci_is_dac_compatible_bridge(struct rtw89_dev *rtwdev)
+{
+       struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv;
+       struct pci_dev *bridge = pci_upstream_bridge(rtwpci->pdev);
+
+       if (!rtw89_pci_chip_is_manual_dac(rtwdev))
+               return true;
+
+       if (!bridge)
+               return false;
+
+       switch (bridge->vendor) {
+       case PCI_VENDOR_ID_INTEL:
+               return true;
+       case PCI_VENDOR_ID_ASMEDIA:
+               if (bridge->device == 0x2806)
+                       return true;
+               break;
        }
 
+       return false;
+}
+
+static void rtw89_pci_cfg_dac(struct rtw89_dev *rtwdev)
+{
+       struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv;
+
+       if (!rtwpci->enable_dac)
+               return;
+
+       if (!rtw89_pci_chip_is_manual_dac(rtwdev))
+               return;
+
        rtw89_pci_config_byte_set(rtwdev, RTW89_PCIE_L1_CTRL, RTW89_PCIE_BIT_EN_64BITS);
 }
 
@@ -3061,6 +3091,9 @@ static int rtw89_pci_setup_mapping(struct rtw89_dev *rtwdev,
                goto err;
        }
 
+       if (!rtw89_pci_is_dac_compatible_bridge(rtwdev))
+               goto no_dac;
+
        ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(36));
        if (!ret) {
                rtwpci->enable_dac = true;
@@ -3073,6 +3106,7 @@ static int rtw89_pci_setup_mapping(struct rtw89_dev *rtwdev,
                        goto err_release_regions;
                }
        }
+no_dac:
 
        resource_len = pci_resource_len(pdev, bar_id);
        rtwpci->mmap = pci_iomap(pdev, bar_id, resource_len);
This page took 0.07399 seconds and 4 git commands to generate.