On Thu, 21 Dec 2023 at 04:23, Kai-Heng Feng <kai.heng.feng@xxxxxxxxxxxxx> wrote: > > Spamming `lspci -vv` can still observe the replay timer timeout error > even after commit 015c9cbcf0ad ("mmc: sdhci-pci-gli: GL9750: Mask the > replay timer timeout of AER"), albeit with a lower reproduce rate. > > Such AER interrupt can still prevent the system from suspending, so let > root port mask and unmask replay timer timeout during suspend and > resume, respectively. > > Cc: Victor Shih <victor.shih@xxxxxxxxxxxxxxxxxxx> > Cc: Ben Chuang <benchuanggli@xxxxxxxxx> > Signed-off-by: Kai-Heng Feng <kai.heng.feng@xxxxxxxxxxxxx> > --- > v2: > - Change subject to reflect it works on GL9750 & GL9755 > - Fix when aer_cap is missing > > drivers/mmc/host/sdhci-pci-core.c | 2 +- > drivers/mmc/host/sdhci-pci-gli.c | 55 +++++++++++++++++++++++++++++-- > drivers/mmc/host/sdhci-pci.h | 1 + > 3 files changed, 55 insertions(+), 3 deletions(-) > > diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c > index 025b31aa712c..59ae4da72974 100644 > --- a/drivers/mmc/host/sdhci-pci-core.c > +++ b/drivers/mmc/host/sdhci-pci-core.c > @@ -68,7 +68,7 @@ static int sdhci_pci_init_wakeup(struct sdhci_pci_chip *chip) > return 0; > } > > -static int sdhci_pci_suspend_host(struct sdhci_pci_chip *chip) > +int sdhci_pci_suspend_host(struct sdhci_pci_chip *chip) > { > int i, ret; > > diff --git a/drivers/mmc/host/sdhci-pci-gli.c b/drivers/mmc/host/sdhci-pci-gli.c > index 77911a57b12c..54943e9df835 100644 > --- a/drivers/mmc/host/sdhci-pci-gli.c > +++ b/drivers/mmc/host/sdhci-pci-gli.c > @@ -1429,6 +1429,55 @@ static int sdhci_pci_gli_resume(struct sdhci_pci_chip *chip) > return sdhci_pci_resume_host(chip); > } > > +#ifdef CONFIG_PCIEAER > +static void mask_replay_timer_timeout(struct pci_dev *pdev) > +{ > + struct pci_dev *parent = pci_upstream_bridge(pdev); > + u32 val; > + > + if (!parent || !parent->aer_cap) Wouldn't it be more correct to use pci_aer_available(), rather than just checking the aer_cap? If pci_aer_available() can be used, we wouldn't even need the stubs as the is already stubs for pci_aer_available(). > + return; > + > + pci_read_config_dword(parent, parent->aer_cap + PCI_ERR_COR_MASK, &val); > + val |= PCI_ERR_COR_REP_TIMER; > + pci_write_config_dword(parent, parent->aer_cap + PCI_ERR_COR_MASK, val); > +} > + > +static void unmask_replay_timer_timeout(struct pci_dev *pdev) > +{ > + struct pci_dev *parent = pci_upstream_bridge(pdev); > + u32 val; > + > + if (!parent || !parent->aer_cap) > + return; > + > + pci_read_config_dword(pdev, parent->aer_cap + PCI_ERR_COR_MASK, &val); > + val &= ~PCI_ERR_COR_REP_TIMER; > + pci_write_config_dword(pdev, parent->aer_cap + PCI_ERR_COR_MASK, val); > +} > +#else > +static inline void mask_replay_timer_timeout(struct pci_dev *pdev) { } > +static inline void unmask_replay_timer_timeout(struct pci_dev *pdev) { } > +#endif > + > +static int sdhci_pci_gl975x_suspend(struct sdhci_pci_chip *chip) > +{ > + mask_replay_timer_timeout(chip->pdev); > + > + return sdhci_pci_suspend_host(chip); > +} > + > +static int sdhci_pci_gl975x_resume(struct sdhci_pci_chip *chip) > +{ > + int ret; > + > + ret = sdhci_pci_gli_resume(chip); > + > + unmask_replay_timer_timeout(chip->pdev); > + > + return ret; > +} > + > static int gl9763e_resume(struct sdhci_pci_chip *chip) > { > struct sdhci_pci_slot *slot = chip->slots[0]; > @@ -1547,7 +1596,8 @@ const struct sdhci_pci_fixes sdhci_gl9755 = { > .probe_slot = gli_probe_slot_gl9755, > .ops = &sdhci_gl9755_ops, > #ifdef CONFIG_PM_SLEEP > - .resume = sdhci_pci_gli_resume, > + .suspend = sdhci_pci_gl975x_suspend, > + .resume = sdhci_pci_gl975x_resume, > #endif > }; > > @@ -1570,7 +1620,8 @@ const struct sdhci_pci_fixes sdhci_gl9750 = { > .probe_slot = gli_probe_slot_gl9750, > .ops = &sdhci_gl9750_ops, > #ifdef CONFIG_PM_SLEEP > - .resume = sdhci_pci_gli_resume, > + .suspend = sdhci_pci_gl975x_suspend, > + .resume = sdhci_pci_gl975x_resume, > #endif > }; > > diff --git a/drivers/mmc/host/sdhci-pci.h b/drivers/mmc/host/sdhci-pci.h > index 153704f812ed..19253dce687d 100644 > --- a/drivers/mmc/host/sdhci-pci.h > +++ b/drivers/mmc/host/sdhci-pci.h > @@ -190,6 +190,7 @@ static inline void *sdhci_pci_priv(struct sdhci_pci_slot *slot) > } > > #ifdef CONFIG_PM_SLEEP > +int sdhci_pci_suspend_host(struct sdhci_pci_chip *chip); > int sdhci_pci_resume_host(struct sdhci_pci_chip *chip); > #endif > int sdhci_pci_enable_dma(struct sdhci_host *host); Kind regards Uffe