aboutsummaryrefslogtreecommitdiff
path: root/sys/contrib/dev/rtw89/pci.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/contrib/dev/rtw89/pci.c')
-rw-r--r--sys/contrib/dev/rtw89/pci.c78
1 files changed, 66 insertions, 12 deletions
diff --git a/sys/contrib/dev/rtw89/pci.c b/sys/contrib/dev/rtw89/pci.c
index 2b2f1c7f09b4..fd61ddf3841c 100644
--- a/sys/contrib/dev/rtw89/pci.c
+++ b/sys/contrib/dev/rtw89/pci.c
@@ -235,7 +235,7 @@ int rtw89_pci_sync_skb_for_device_and_validate_rx_info(struct rtw89_dev *rtwdev,
struct sk_buff *skb)
{
struct rtw89_pci_rx_info *rx_info = RTW89_PCI_RX_SKB_CB(skb);
- int rx_tag_retry = 100;
+ int rx_tag_retry = 1000;
int ret;
do {
@@ -2710,6 +2710,10 @@ static void rtw89_pci_set_dbg(struct rtw89_dev *rtwdev)
rtw89_write32_set(rtwdev, R_AX_PCIE_DBG_CTRL,
B_AX_ASFF_FULL_NO_STK | B_AX_EN_STUCK_DBG);
+ rtw89_write32_mask(rtwdev, R_AX_PCIE_EXP_CTRL,
+ B_AX_EN_STUCK_DBG | B_AX_ASFF_FULL_NO_STK,
+ B_AX_EN_STUCK_DBG);
+
if (rtwdev->chip->chip_id == RTL8852A)
rtw89_write32_set(rtwdev, R_AX_PCIE_EXP_CTRL,
B_AX_EN_CHKDSC_NO_RX_STUCK);
@@ -3177,17 +3181,26 @@ static bool rtw89_pci_is_dac_compatible_bridge(struct rtw89_dev *rtwdev)
return false;
}
-static void rtw89_pci_cfg_dac(struct rtw89_dev *rtwdev)
+static int rtw89_pci_cfg_dac(struct rtw89_dev *rtwdev, bool force)
{
struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv;
+ struct pci_dev *pdev = rtwpci->pdev;
+ int ret;
+ u8 val;
- if (!rtwpci->enable_dac)
- return;
+ if (!rtwpci->enable_dac && !force)
+ return 0;
if (!rtw89_pci_chip_is_manual_dac(rtwdev))
- return;
+ return 0;
+
+ /* Configure DAC only via PCI config API, not DBI interfaces */
+ ret = pci_read_config_byte(pdev, RTW89_PCIE_L1_CTRL, &val);
+ if (ret)
+ return ret;
- rtw89_pci_config_byte_set(rtwdev, RTW89_PCIE_L1_CTRL, RTW89_PCIE_BIT_EN_64BITS);
+ val |= RTW89_PCIE_BIT_EN_64BITS;
+ return pci_write_config_byte(pdev, RTW89_PCIE_L1_CTRL, val);
}
static int rtw89_pci_setup_mapping(struct rtw89_dev *rtwdev,
@@ -3205,13 +3218,16 @@ static int rtw89_pci_setup_mapping(struct rtw89_dev *rtwdev,
}
if (!rtw89_pci_is_dac_compatible_bridge(rtwdev))
- goto no_dac;
+ goto try_dac_done;
ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(36));
if (!ret) {
- rtwpci->enable_dac = true;
- rtw89_pci_cfg_dac(rtwdev);
- } else {
+ ret = rtw89_pci_cfg_dac(rtwdev, true);
+ if (!ret) {
+ rtwpci->enable_dac = true;
+ goto try_dac_done;
+ }
+
ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
if (ret) {
rtw89_err(rtwdev,
@@ -3219,7 +3235,7 @@ static int rtw89_pci_setup_mapping(struct rtw89_dev *rtwdev,
goto err_release_regions;
}
}
-no_dac:
+try_dac_done:
#if defined(__FreeBSD__)
linuxkpi_pcim_want_to_use_bus_functions(pdev);
@@ -4385,7 +4401,7 @@ static void rtw89_pci_l2_hci_ldo(struct rtw89_dev *rtwdev)
void rtw89_pci_basic_cfg(struct rtw89_dev *rtwdev, bool resume)
{
if (resume)
- rtw89_pci_cfg_dac(rtwdev);
+ rtw89_pci_cfg_dac(rtwdev, false);
rtw89_pci_disable_eq(rtwdev);
rtw89_pci_filter_out(rtwdev);
@@ -4424,6 +4440,43 @@ static int __maybe_unused rtw89_pci_resume(struct device *dev)
SIMPLE_DEV_PM_OPS(rtw89_pm_ops, rtw89_pci_suspend, rtw89_pci_resume);
EXPORT_SYMBOL(rtw89_pm_ops);
+static pci_ers_result_t rtw89_pci_io_error_detected(struct pci_dev *pdev,
+ pci_channel_state_t state)
+{
+ struct net_device *netdev = pci_get_drvdata(pdev);
+
+ netif_device_detach(netdev);
+
+ return PCI_ERS_RESULT_NEED_RESET;
+}
+
+static pci_ers_result_t rtw89_pci_io_slot_reset(struct pci_dev *pdev)
+{
+ struct ieee80211_hw *hw = pci_get_drvdata(pdev);
+ struct rtw89_dev *rtwdev = hw->priv;
+
+ rtw89_ser_notify(rtwdev, MAC_AX_ERR_ASSERTION);
+
+ return PCI_ERS_RESULT_RECOVERED;
+}
+
+static void rtw89_pci_io_resume(struct pci_dev *pdev)
+{
+ struct net_device *netdev = pci_get_drvdata(pdev);
+
+ /* ack any pending wake events, disable PME */
+ pci_enable_wake(pdev, PCI_D0, 0);
+
+ netif_device_attach(netdev);
+}
+
+const struct pci_error_handlers rtw89_pci_err_handler = {
+ .error_detected = rtw89_pci_io_error_detected,
+ .slot_reset = rtw89_pci_io_slot_reset,
+ .resume = rtw89_pci_io_resume,
+};
+EXPORT_SYMBOL(rtw89_pci_err_handler);
+
const struct rtw89_pci_gen_def rtw89_pci_gen_ax = {
.isr_rdu = B_AX_RDU_INT,
.isr_halt_c2h = B_AX_HALT_C2H_INT_EN,
@@ -4520,6 +4573,7 @@ int rtw89_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
rtwdev->pci_info = info->bus.pci;
rtwdev->hci.ops = &rtw89_pci_ops;
rtwdev->hci.type = RTW89_HCI_TYPE_PCIE;
+ rtwdev->hci.dle_type = RTW89_HCI_DLE_TYPE_PCIE;
rtwdev->hci.rpwm_addr = pci_info->rpwm_addr;
rtwdev->hci.cpwm_addr = pci_info->cpwm_addr;