Message ID | 20210913180246.193388-5-jouni@codeaurora.org |
---|---|
State | New |
Headers | show |
Series | [1/5] ath11k: Change DMA_FROM_DEVICE to DMA_TO_DEVICE when map reinjected packets | expand |
Jouni Malinen <jouni@codeaurora.org> writes: > From: Baochen Qiang <bqiang@codeaurora.org> > > When doing "rmmod ath11k_pci", ath11k performs global SOC reset > and MHI reset, where 0 address access is captured by IOMMU. See > log below: > > ... > [ 133.953860] ath11k_pci 0000:02:00.0: setting mhi state: DEINIT(1) > [ 133.959714] ath11k_pci 0000:02:00.0: AMD-Vi: Event logged [IO_PAGE_FAULT domain=0x000a address=0x0 flags=0x0020] > [ 133.973854] ath11k_pci 0000:02:00.0: MHISTATUS 0xff04 > [ 133.974095] ath11k_pci 0000:02:00.0: AMD-Vi: Event logged [IO_PAGE_FAULT domain=0x000a address=0x0 flags=0x0020] > ... > > This issue is also observed in SSR process, cause a similar > sequence as above is performed. > > Such an invalid access occurs because, during rmmod or SSR, MSI > address is cleared but HW MSI functionality not disabled, thus HW > target is able to raise an MSI transaction with 0 as MSI address. > > So it can be fixed by simply disabling MSI before reset. For SSR, > since MSI functionality is still needed after target is brought > back, we need to reenable it. > > Also change naming of some interfaces related. > > Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1 > Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-01720.1-QCAHSPSWPL_V1_V2_SILICONZ_LITE-1 > > Signed-off-by: Baochen Qiang <bqiang@codeaurora.org> > Signed-off-by: Jouni Malinen <jouni@codeaurora.org> > --- > drivers/net/wireless/ath/ath11k/pci.c | 27 ++++++++++++++++++++++----- > 1 file changed, 22 insertions(+), 5 deletions(-) > > diff --git a/drivers/net/wireless/ath/ath11k/pci.c b/drivers/net/wireless/ath/ath11k/pci.c > index 7b3bce0ba76e..1094b53465bc 100644 > --- a/drivers/net/wireless/ath/ath11k/pci.c > +++ b/drivers/net/wireless/ath/ath11k/pci.c > @@ -855,7 +855,18 @@ static void ath11k_pci_ce_irqs_enable(struct ath11k_base *ab) > } > } > > -static int ath11k_pci_enable_msi(struct ath11k_pci *ab_pci) > +static void ath11k_pci_enable_msi(struct pci_dev *dev, bool enable) > +{ > + u16 control; > + > + pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &control); > + control &= ~PCI_MSI_FLAGS_ENABLE; > + if (enable) > + control |= PCI_MSI_FLAGS_ENABLE; > + pci_write_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, control); > +} To make the function cleaner I renamed this to ath11k_pci_msi_config(), added an else branch and changed it to take structh ath11k_pci. I also added helpers ath11k_pci_msi_enable() and ath11k_pci_msi_disable(). -- https://patchwork.kernel.org/project/linux-wireless/list/ https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
Jouni Malinen <jouni@codeaurora.org> wrote: > When doing "rmmod ath11k_pci", ath11k performs global SOC reset > and MHI reset, where 0 address access is captured by IOMMU. See > log below: > > ... > [ 133.953860] ath11k_pci 0000:02:00.0: setting mhi state: DEINIT(1) > [ 133.959714] ath11k_pci 0000:02:00.0: AMD-Vi: Event logged [IO_PAGE_FAULT domain=0x000a address=0x0 flags=0x0020] > [ 133.973854] ath11k_pci 0000:02:00.0: MHISTATUS 0xff04 > [ 133.974095] ath11k_pci 0000:02:00.0: AMD-Vi: Event logged [IO_PAGE_FAULT domain=0x000a address=0x0 flags=0x0020] > ... > > This issue is also observed in SSR process, cause a similar > sequence as above is performed. > > Such an invalid access occurs because, during rmmod or SSR, MSI > address is cleared but HW MSI functionality not disabled, thus HW > target is able to raise an MSI transaction with 0 as MSI address. > > So it can be fixed by simply disabling MSI before reset. For SSR, > since MSI functionality is still needed after target is brought > back, we need to reenable it. > > Also change naming of some interfaces related. > > Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1 > Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-01720.1-QCAHSPSWPL_V1_V2_SILICONZ_LITE-1 > > Signed-off-by: Baochen Qiang <bqiang@codeaurora.org> > Signed-off-by: Jouni Malinen <jouni@codeaurora.org> > Signed-off-by: Kalle Valo <kvalo@codeaurora.org> Patch applied to ath-next branch of ath.git, thanks. 96527d527b27 ath11k: Handle MSI enablement during rmmod and SSR -- https://patchwork.kernel.org/project/linux-wireless/patch/20210913180246.193388-5-jouni@codeaurora.org/ https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
diff --git a/drivers/net/wireless/ath/ath11k/pci.c b/drivers/net/wireless/ath/ath11k/pci.c index 7b3bce0ba76e..1094b53465bc 100644 --- a/drivers/net/wireless/ath/ath11k/pci.c +++ b/drivers/net/wireless/ath/ath11k/pci.c @@ -855,7 +855,18 @@ static void ath11k_pci_ce_irqs_enable(struct ath11k_base *ab) } } -static int ath11k_pci_enable_msi(struct ath11k_pci *ab_pci) +static void ath11k_pci_enable_msi(struct pci_dev *dev, bool enable) +{ + u16 control; + + pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &control); + control &= ~PCI_MSI_FLAGS_ENABLE; + if (enable) + control |= PCI_MSI_FLAGS_ENABLE; + pci_write_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, control); +} + +static int ath11k_pci_alloc_msi(struct ath11k_pci *ab_pci) { struct ath11k_base *ab = ab_pci->ab; const struct ath11k_msi_config *msi_config = ab_pci->msi_config; @@ -876,6 +887,7 @@ static int ath11k_pci_enable_msi(struct ath11k_pci *ab_pci) else return num_vectors; } + ath11k_pci_enable_msi(ab_pci->pdev, false); msi_desc = irq_get_msi_desc(ab_pci->pdev->irq); if (!msi_desc) { @@ -898,7 +910,7 @@ static int ath11k_pci_enable_msi(struct ath11k_pci *ab_pci) return ret; } -static void ath11k_pci_disable_msi(struct ath11k_pci *ab_pci) +static void ath11k_pci_free_msi(struct ath11k_pci *ab_pci) { pci_free_irq_vectors(ab_pci->pdev); } @@ -1019,6 +1031,8 @@ static int ath11k_pci_power_up(struct ath11k_base *ab) */ ath11k_pci_aspm_disable(ab_pci); + ath11k_pci_enable_msi(ab_pci->pdev, true); + ret = ath11k_mhi_start(ab_pci); if (ret) { ath11k_err(ab, "failed to start mhi: %d\n", ret); @@ -1039,6 +1053,9 @@ static void ath11k_pci_power_down(struct ath11k_base *ab) ath11k_pci_aspm_restore(ab_pci); ath11k_pci_force_wake(ab_pci->ab); + + ath11k_pci_enable_msi(ab_pci->pdev, false); + ath11k_mhi_stop(ab_pci); clear_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags); ath11k_pci_sw_reset(ab_pci->ab, false); @@ -1263,7 +1280,7 @@ static int ath11k_pci_probe(struct pci_dev *pdev, goto err_pci_free_region; } - ret = ath11k_pci_enable_msi(ab_pci); + ret = ath11k_pci_alloc_msi(ab_pci); if (ret) { ath11k_err(ab, "failed to enable msi: %d\n", ret); goto err_pci_free_region; @@ -1317,7 +1334,7 @@ static int ath11k_pci_probe(struct pci_dev *pdev, ath11k_mhi_unregister(ab_pci); err_pci_disable_msi: - ath11k_pci_disable_msi(ab_pci); + ath11k_pci_free_msi(ab_pci); err_pci_free_region: ath11k_pci_free_region(ab_pci); @@ -1348,7 +1365,7 @@ static void ath11k_pci_remove(struct pci_dev *pdev) ath11k_mhi_unregister(ab_pci); ath11k_pci_free_irq(ab); - ath11k_pci_disable_msi(ab_pci); + ath11k_pci_free_msi(ab_pci); ath11k_pci_free_region(ab_pci); ath11k_hal_srng_deinit(ab);