Skip to content

Commit 84b5761

Browse files
Marek VasutLorenzo Pieralisi
authored andcommitted
PCI: rcar: Finish transition to L1 state in rcar_pcie_config_access()
In case the controller is transitioning to L1 in rcar_pcie_config_access(), any read/write access to PCIECDR triggers asynchronous external abort. This is because the transition to L1 link state must be manually finished by the driver. The PCIe IP can transition back from L1 state to L0 on its own. Avoid triggering the abort in rcar_pcie_config_access() by checking whether the controller is in the transition state, and if so, finish the transition right away. This prevents a lot of unnecessary exceptions, although not all of them. Link: https://lore.kernel.org/r/20220312212349.781799-1-marek.vasut@gmail.com Tested-by: Geert Uytterhoeven <geert+renesas@glider.be> Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be> Cc: Arnd Bergmann <arnd@arndb.de> Cc: Bjorn Helgaas <bhelgaas@google.com> Cc: Geert Uytterhoeven <geert+renesas@glider.be> Cc: Krzysztof Wilczyński <kw@linux.com> Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> Cc: Wolfram Sang <wsa@the-dreams.de> Cc: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> Cc: linux-renesas-soc@vger.kernel.org
1 parent e783362 commit 84b5761

1 file changed

Lines changed: 45 additions & 31 deletions

File tree

drivers/pci/controller/pcie-rcar-host.c

Lines changed: 45 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,42 @@ struct rcar_pcie_host {
6565
int (*phy_init_fn)(struct rcar_pcie_host *host);
6666
};
6767

68+
static DEFINE_SPINLOCK(pmsr_lock);
69+
70+
static int rcar_pcie_wakeup(struct device *pcie_dev, void __iomem *pcie_base)
71+
{
72+
unsigned long flags;
73+
u32 pmsr, val;
74+
int ret = 0;
75+
76+
spin_lock_irqsave(&pmsr_lock, flags);
77+
78+
if (!pcie_base || pm_runtime_suspended(pcie_dev)) {
79+
ret = -EINVAL;
80+
goto unlock_exit;
81+
}
82+
83+
pmsr = readl(pcie_base + PMSR);
84+
85+
/*
86+
* Test if the PCIe controller received PM_ENTER_L1 DLLP and
87+
* the PCIe controller is not in L1 link state. If true, apply
88+
* fix, which will put the controller into L1 link state, from
89+
* which it can return to L0s/L0 on its own.
90+
*/
91+
if ((pmsr & PMEL1RX) && ((pmsr & PMSTATE) != PMSTATE_L1)) {
92+
writel(L1IATN, pcie_base + PMCTLR);
93+
ret = readl_poll_timeout_atomic(pcie_base + PMSR, val,
94+
val & L1FAEG, 10, 1000);
95+
WARN(ret, "Timeout waiting for L1 link state, ret=%d\n", ret);
96+
writel(L1FAEG | PMEL1RX, pcie_base + PMSR);
97+
}
98+
99+
unlock_exit:
100+
spin_unlock_irqrestore(&pmsr_lock, flags);
101+
return ret;
102+
}
103+
68104
static struct rcar_pcie_host *msi_to_host(struct rcar_msi *msi)
69105
{
70106
return container_of(msi, struct rcar_pcie_host, msi);
@@ -85,6 +121,14 @@ static int rcar_pcie_config_access(struct rcar_pcie_host *host,
85121
{
86122
struct rcar_pcie *pcie = &host->pcie;
87123
unsigned int dev, func, reg, index;
124+
int ret;
125+
126+
/* Wake the bus up in case it is in L1 state. */
127+
ret = rcar_pcie_wakeup(pcie->dev, pcie->base);
128+
if (ret) {
129+
PCI_SET_ERROR_RESPONSE(data);
130+
return PCIBIOS_SET_FAILED;
131+
}
88132

89133
dev = PCI_SLOT(devfn);
90134
func = PCI_FUNC(devfn);
@@ -1050,40 +1094,10 @@ static struct platform_driver rcar_pcie_driver = {
10501094
};
10511095

10521096
#ifdef CONFIG_ARM
1053-
static DEFINE_SPINLOCK(pmsr_lock);
10541097
static int rcar_pcie_aarch32_abort_handler(unsigned long addr,
10551098
unsigned int fsr, struct pt_regs *regs)
10561099
{
1057-
unsigned long flags;
1058-
u32 pmsr, val;
1059-
int ret = 0;
1060-
1061-
spin_lock_irqsave(&pmsr_lock, flags);
1062-
1063-
if (!pcie_base || pm_runtime_suspended(pcie_dev)) {
1064-
ret = 1;
1065-
goto unlock_exit;
1066-
}
1067-
1068-
pmsr = readl(pcie_base + PMSR);
1069-
1070-
/*
1071-
* Test if the PCIe controller received PM_ENTER_L1 DLLP and
1072-
* the PCIe controller is not in L1 link state. If true, apply
1073-
* fix, which will put the controller into L1 link state, from
1074-
* which it can return to L0s/L0 on its own.
1075-
*/
1076-
if ((pmsr & PMEL1RX) && ((pmsr & PMSTATE) != PMSTATE_L1)) {
1077-
writel(L1IATN, pcie_base + PMCTLR);
1078-
ret = readl_poll_timeout_atomic(pcie_base + PMSR, val,
1079-
val & L1FAEG, 10, 1000);
1080-
WARN(ret, "Timeout waiting for L1 link state, ret=%d\n", ret);
1081-
writel(L1FAEG | PMEL1RX, pcie_base + PMSR);
1082-
}
1083-
1084-
unlock_exit:
1085-
spin_unlock_irqrestore(&pmsr_lock, flags);
1086-
return ret;
1100+
return !!rcar_pcie_wakeup(pcie_dev, pcie_base);
10871101
}
10881102

10891103
static const struct of_device_id rcar_pcie_abort_handler_of_match[] __initconst = {

0 commit comments

Comments
 (0)