Skip to content

Commit f4620f6

Browse files
committed
Merge branch 'pci/controller/brcmstb'
- Disable advertising ASPM L0s support correctly (Jim Quinlan) - Add a panic/die handler to print diagnostic info in case PCIe caused an unrecoverable abort (Jim Quinlan) * pci/controller/brcmstb: PCI: brcmstb: Add panic/die handler to driver PCI: brcmstb: Add a way to indicate if PCIe bridge is active PCI: brcmstb: Fix disabling L0s capability
2 parents 12390db + 8d4ec3f commit f4620f6

1 file changed

Lines changed: 196 additions & 13 deletions

File tree

drivers/pci/controller/pcie-brcmstb.c

Lines changed: 196 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,23 +14,28 @@
1414
#include <linux/irqchip/chained_irq.h>
1515
#include <linux/irqchip/irq-msi-lib.h>
1616
#include <linux/irqdomain.h>
17+
#include <linux/kdebug.h>
1718
#include <linux/kernel.h>
1819
#include <linux/list.h>
1920
#include <linux/log2.h>
2021
#include <linux/module.h>
2122
#include <linux/msi.h>
23+
#include <linux/notifier.h>
2224
#include <linux/of_address.h>
2325
#include <linux/of_irq.h>
2426
#include <linux/of_pci.h>
2527
#include <linux/of_platform.h>
28+
#include <linux/panic_notifier.h>
2629
#include <linux/pci.h>
2730
#include <linux/pci-ecam.h>
2831
#include <linux/printk.h>
2932
#include <linux/regulator/consumer.h>
3033
#include <linux/reset.h>
3134
#include <linux/sizes.h>
3235
#include <linux/slab.h>
36+
#include <linux/spinlock.h>
3337
#include <linux/string.h>
38+
#include <linux/string_choices.h>
3439
#include <linux/types.h>
3540

3641
#include "../pci.h"
@@ -48,7 +53,6 @@
4853

4954
#define PCIE_RC_CFG_PRIV1_LINK_CAPABILITY 0x04dc
5055
#define PCIE_RC_CFG_PRIV1_LINK_CAPABILITY_MAX_LINK_WIDTH_MASK 0x1f0
51-
#define PCIE_RC_CFG_PRIV1_LINK_CAPABILITY_ASPM_SUPPORT_MASK 0xc00
5256

5357
#define PCIE_RC_CFG_PRIV1_ROOT_CAP 0x4f8
5458
#define PCIE_RC_CFG_PRIV1_ROOT_CAP_L1SS_MODE_MASK 0xf8
@@ -155,8 +159,40 @@
155159
#define MSI_INT_MASK_SET 0x10
156160
#define MSI_INT_MASK_CLR 0x14
157161

162+
/* Error report registers */
163+
#define PCIE_OUTB_ERR_TREAT 0x6000
164+
#define PCIE_OUTB_ERR_TREAT_CONFIG 0x1
165+
#define PCIE_OUTB_ERR_TREAT_MEM 0x2
166+
#define PCIE_OUTB_ERR_VALID 0x6004
167+
#define PCIE_OUTB_ERR_CLEAR 0x6008
168+
#define PCIE_OUTB_ERR_ACC_INFO 0x600c
169+
#define PCIE_OUTB_ERR_ACC_INFO_CFG_ERR BIT(0)
170+
#define PCIE_OUTB_ERR_ACC_INFO_MEM_ERR BIT(1)
171+
#define PCIE_OUTB_ERR_ACC_INFO_TYPE_64 BIT(2)
172+
#define PCIE_OUTB_ERR_ACC_INFO_DIR_WRITE BIT(4)
173+
#define PCIE_OUTB_ERR_ACC_INFO_BYTE_LANES 0xff00
174+
#define PCIE_OUTB_ERR_ACC_ADDR 0x6010
175+
#define PCIE_OUTB_ERR_ACC_ADDR_BUS 0xff00000
176+
#define PCIE_OUTB_ERR_ACC_ADDR_DEV 0xf8000
177+
#define PCIE_OUTB_ERR_ACC_ADDR_FUNC 0x7000
178+
#define PCIE_OUTB_ERR_ACC_ADDR_REG 0xfff
179+
#define PCIE_OUTB_ERR_CFG_CAUSE 0x6014
180+
#define PCIE_OUTB_ERR_CFG_CAUSE_TIMEOUT BIT(6)
181+
#define PCIE_OUTB_ERR_CFG_CAUSE_ABORT BIT(5)
182+
#define PCIE_OUTB_ERR_CFG_CAUSE_UNSUPP_REQ BIT(4)
183+
#define PCIE_OUTB_ERR_CFG_CAUSE_ACC_TIMEOUT BIT(2)
184+
#define PCIE_OUTB_ERR_CFG_CAUSE_ACC_DISABLED BIT(1)
185+
#define PCIE_OUTB_ERR_CFG_CAUSE_ACC_64BIT BIT(0)
186+
#define PCIE_OUTB_ERR_MEM_ADDR_LO 0x6018
187+
#define PCIE_OUTB_ERR_MEM_ADDR_HI 0x601c
188+
#define PCIE_OUTB_ERR_MEM_CAUSE 0x6020
189+
#define PCIE_OUTB_ERR_MEM_CAUSE_TIMEOUT BIT(6)
190+
#define PCIE_OUTB_ERR_MEM_CAUSE_ABORT BIT(5)
191+
#define PCIE_OUTB_ERR_MEM_CAUSE_UNSUPP_REQ BIT(4)
192+
#define PCIE_OUTB_ERR_MEM_CAUSE_ACC_DISABLED BIT(1)
193+
#define PCIE_OUTB_ERR_MEM_CAUSE_BAD_ADDR BIT(0)
194+
158195
#define PCIE_RGR1_SW_INIT_1_PERST_MASK 0x1
159-
#define PCIE_RGR1_SW_INIT_1_PERST_SHIFT 0x0
160196

161197
#define RGR1_SW_INIT_1_INIT_GENERIC_MASK 0x2
162198
#define RGR1_SW_INIT_1_INIT_GENERIC_SHIFT 0x1
@@ -259,6 +295,7 @@ struct pcie_cfg_data {
259295
int (*perst_set)(struct brcm_pcie *pcie, u32 val);
260296
int (*bridge_sw_init_set)(struct brcm_pcie *pcie, u32 val);
261297
int (*post_setup)(struct brcm_pcie *pcie);
298+
bool has_err_report;
262299
};
263300

264301
struct subdev_regulators {
@@ -303,13 +340,35 @@ struct brcm_pcie {
303340
struct subdev_regulators *sr;
304341
bool ep_wakeup_capable;
305342
const struct pcie_cfg_data *cfg;
343+
bool bridge_in_reset;
344+
struct notifier_block die_notifier;
345+
struct notifier_block panic_notifier;
346+
spinlock_t bridge_lock;
306347
};
307348

308349
static inline bool is_bmips(const struct brcm_pcie *pcie)
309350
{
310351
return pcie->cfg->soc_base == BCM7435 || pcie->cfg->soc_base == BCM7425;
311352
}
312353

354+
static int brcm_pcie_bridge_sw_init_set(struct brcm_pcie *pcie, u32 val)
355+
{
356+
unsigned long flags;
357+
int ret;
358+
359+
if (pcie->cfg->has_err_report)
360+
spin_lock_irqsave(&pcie->bridge_lock, flags);
361+
362+
ret = pcie->cfg->bridge_sw_init_set(pcie, val);
363+
/* If we fail, assume the bridge is in reset (off) */
364+
pcie->bridge_in_reset = ret ? true : val;
365+
366+
if (pcie->cfg->has_err_report)
367+
spin_unlock_irqrestore(&pcie->bridge_lock, flags);
368+
369+
return ret;
370+
}
371+
313372
/*
314373
* This is to convert the size of the inbound "BAR" region to the
315374
* non-linear values of PCIE_X_MISC_RC_BAR[123]_CONFIG_LO.SIZE
@@ -1075,13 +1134,13 @@ static int brcm_pcie_setup(struct brcm_pcie *pcie)
10751134
void __iomem *base = pcie->base;
10761135
struct pci_host_bridge *bridge;
10771136
struct resource_entry *entry;
1078-
u32 tmp, burst, aspm_support, num_lanes, num_lanes_cap;
1137+
u32 tmp, burst, num_lanes, num_lanes_cap;
10791138
u8 num_out_wins = 0;
10801139
int num_inbound_wins = 0;
10811140
int memc, ret;
10821141

10831142
/* Reset the bridge */
1084-
ret = pcie->cfg->bridge_sw_init_set(pcie, 1);
1143+
ret = brcm_pcie_bridge_sw_init_set(pcie, 1);
10851144
if (ret)
10861145
return ret;
10871146

@@ -1097,7 +1156,7 @@ static int brcm_pcie_setup(struct brcm_pcie *pcie)
10971156
usleep_range(100, 200);
10981157

10991158
/* Take the bridge out of reset */
1100-
ret = pcie->cfg->bridge_sw_init_set(pcie, 0);
1159+
ret = brcm_pcie_bridge_sw_init_set(pcie, 0);
11011160
if (ret)
11021161
return ret;
11031162

@@ -1175,12 +1234,9 @@ static int brcm_pcie_setup(struct brcm_pcie *pcie)
11751234

11761235

11771236
/* Don't advertise L0s capability if 'aspm-no-l0s' */
1178-
aspm_support = PCIE_LINK_STATE_L1;
1179-
if (!of_property_read_bool(pcie->np, "aspm-no-l0s"))
1180-
aspm_support |= PCIE_LINK_STATE_L0S;
11811237
tmp = readl(base + PCIE_RC_CFG_PRIV1_LINK_CAPABILITY);
1182-
u32p_replace_bits(&tmp, aspm_support,
1183-
PCIE_RC_CFG_PRIV1_LINK_CAPABILITY_ASPM_SUPPORT_MASK);
1238+
if (of_property_read_bool(pcie->np, "aspm-no-l0s"))
1239+
tmp &= ~PCI_EXP_LNKCAP_ASPM_L0S;
11841240
writel(tmp, base + PCIE_RC_CFG_PRIV1_LINK_CAPABILITY);
11851241

11861242
/* 'tmp' still holds the contents of PRIV1_LINK_CAPABILITY */
@@ -1565,7 +1621,7 @@ static int brcm_pcie_turn_off(struct brcm_pcie *pcie)
15651621

15661622
if (!(pcie->cfg->quirks & CFG_QUIRK_AVOID_BRIDGE_SHUTDOWN))
15671623
/* Shutdown PCIe bridge */
1568-
ret = pcie->cfg->bridge_sw_init_set(pcie, 1);
1624+
ret = brcm_pcie_bridge_sw_init_set(pcie, 1);
15691625

15701626
return ret;
15711627
}
@@ -1653,7 +1709,9 @@ static int brcm_pcie_resume_noirq(struct device *dev)
16531709
goto err_reset;
16541710

16551711
/* Take bridge out of reset so we can access the SERDES reg */
1656-
pcie->cfg->bridge_sw_init_set(pcie, 0);
1712+
ret = brcm_pcie_bridge_sw_init_set(pcie, 0);
1713+
if (ret)
1714+
goto err_reset;
16571715

16581716
/* SERDES_IDDQ = 0 */
16591717
tmp = readl(base + HARD_DEBUG(pcie));
@@ -1707,6 +1765,119 @@ static int brcm_pcie_resume_noirq(struct device *dev)
17071765
return ret;
17081766
}
17091767

1768+
/* Dump out PCIe errors on die or panic */
1769+
static int brcm_pcie_dump_err(struct brcm_pcie *pcie,
1770+
const char *type)
1771+
{
1772+
void __iomem *base = pcie->base;
1773+
int i, is_cfg_err, is_mem_err, lanes;
1774+
const char *width_str, *direction_str;
1775+
u32 info, cfg_addr, cfg_cause, mem_cause, lo, hi;
1776+
struct pci_host_bridge *bridge = pci_host_bridge_from_priv(pcie);
1777+
unsigned long flags;
1778+
char lanes_str[9];
1779+
1780+
spin_lock_irqsave(&pcie->bridge_lock, flags);
1781+
/* Don't access registers when the bridge is off */
1782+
if (pcie->bridge_in_reset || readl(base + PCIE_OUTB_ERR_VALID) == 0) {
1783+
spin_unlock_irqrestore(&pcie->bridge_lock, flags);
1784+
return NOTIFY_DONE;
1785+
}
1786+
1787+
/* Read all necessary registers so we can release the spinlock ASAP */
1788+
info = readl(base + PCIE_OUTB_ERR_ACC_INFO);
1789+
is_cfg_err = !!(info & PCIE_OUTB_ERR_ACC_INFO_CFG_ERR);
1790+
is_mem_err = !!(info & PCIE_OUTB_ERR_ACC_INFO_MEM_ERR);
1791+
if (is_cfg_err) {
1792+
cfg_addr = readl(base + PCIE_OUTB_ERR_ACC_ADDR);
1793+
cfg_cause = readl(base + PCIE_OUTB_ERR_CFG_CAUSE);
1794+
}
1795+
if (is_mem_err) {
1796+
mem_cause = readl(base + PCIE_OUTB_ERR_MEM_CAUSE);
1797+
lo = readl(base + PCIE_OUTB_ERR_MEM_ADDR_LO);
1798+
hi = readl(base + PCIE_OUTB_ERR_MEM_ADDR_HI);
1799+
}
1800+
/* We've got all of the info, clear the error */
1801+
writel(1, base + PCIE_OUTB_ERR_CLEAR);
1802+
spin_unlock_irqrestore(&pcie->bridge_lock, flags);
1803+
1804+
dev_err(pcie->dev, "reporting PCIe info which may be related to %s error\n",
1805+
type);
1806+
width_str = (info & PCIE_OUTB_ERR_ACC_INFO_TYPE_64) ? "64bit" : "32bit";
1807+
direction_str = str_read_write(!(info & PCIE_OUTB_ERR_ACC_INFO_DIR_WRITE));
1808+
lanes = FIELD_GET(PCIE_OUTB_ERR_ACC_INFO_BYTE_LANES, info);
1809+
for (i = 0, lanes_str[8] = 0; i < 8; i++)
1810+
lanes_str[i] = (lanes & (1 << i)) ? '1' : '0';
1811+
1812+
if (is_cfg_err) {
1813+
int bus = FIELD_GET(PCIE_OUTB_ERR_ACC_ADDR_BUS, cfg_addr);
1814+
int dev = FIELD_GET(PCIE_OUTB_ERR_ACC_ADDR_DEV, cfg_addr);
1815+
int func = FIELD_GET(PCIE_OUTB_ERR_ACC_ADDR_FUNC, cfg_addr);
1816+
int reg = FIELD_GET(PCIE_OUTB_ERR_ACC_ADDR_REG, cfg_addr);
1817+
1818+
dev_err(pcie->dev, "Error: CFG Acc, %s, %s (%04x:%02x:%02x.%d) reg=0x%x, lanes=%s\n",
1819+
width_str, direction_str, bridge->domain_nr, bus, dev,
1820+
func, reg, lanes_str);
1821+
dev_err(pcie->dev, " Type: TO=%d Abt=%d UnsupReq=%d AccTO=%d AccDsbld=%d Acc64bit=%d\n",
1822+
!!(cfg_cause & PCIE_OUTB_ERR_CFG_CAUSE_TIMEOUT),
1823+
!!(cfg_cause & PCIE_OUTB_ERR_CFG_CAUSE_ABORT),
1824+
!!(cfg_cause & PCIE_OUTB_ERR_CFG_CAUSE_UNSUPP_REQ),
1825+
!!(cfg_cause & PCIE_OUTB_ERR_CFG_CAUSE_ACC_TIMEOUT),
1826+
!!(cfg_cause & PCIE_OUTB_ERR_CFG_CAUSE_ACC_DISABLED),
1827+
!!(cfg_cause & PCIE_OUTB_ERR_CFG_CAUSE_ACC_64BIT));
1828+
}
1829+
1830+
if (is_mem_err) {
1831+
u64 addr = ((u64)hi << 32) | (u64)lo;
1832+
1833+
dev_err(pcie->dev, "Error: Mem Acc, %s, %s, @0x%llx, lanes=%s\n",
1834+
width_str, direction_str, addr, lanes_str);
1835+
dev_err(pcie->dev, " Type: TO=%d Abt=%d UnsupReq=%d AccDsble=%d BadAddr=%d\n",
1836+
!!(mem_cause & PCIE_OUTB_ERR_MEM_CAUSE_TIMEOUT),
1837+
!!(mem_cause & PCIE_OUTB_ERR_MEM_CAUSE_ABORT),
1838+
!!(mem_cause & PCIE_OUTB_ERR_MEM_CAUSE_UNSUPP_REQ),
1839+
!!(mem_cause & PCIE_OUTB_ERR_MEM_CAUSE_ACC_DISABLED),
1840+
!!(mem_cause & PCIE_OUTB_ERR_MEM_CAUSE_BAD_ADDR));
1841+
}
1842+
1843+
return NOTIFY_DONE;
1844+
}
1845+
1846+
static int brcm_pcie_die_notify_cb(struct notifier_block *self,
1847+
unsigned long v, void *p)
1848+
{
1849+
struct brcm_pcie *pcie =
1850+
container_of(self, struct brcm_pcie, die_notifier);
1851+
1852+
return brcm_pcie_dump_err(pcie, "Die");
1853+
}
1854+
1855+
static int brcm_pcie_panic_notify_cb(struct notifier_block *self,
1856+
unsigned long v, void *p)
1857+
{
1858+
struct brcm_pcie *pcie =
1859+
container_of(self, struct brcm_pcie, panic_notifier);
1860+
1861+
return brcm_pcie_dump_err(pcie, "Panic");
1862+
}
1863+
1864+
static void brcm_register_die_notifiers(struct brcm_pcie *pcie)
1865+
{
1866+
pcie->panic_notifier.notifier_call = brcm_pcie_panic_notify_cb;
1867+
atomic_notifier_chain_register(&panic_notifier_list,
1868+
&pcie->panic_notifier);
1869+
1870+
pcie->die_notifier.notifier_call = brcm_pcie_die_notify_cb;
1871+
register_die_notifier(&pcie->die_notifier);
1872+
}
1873+
1874+
static void brcm_unregister_die_notifiers(struct brcm_pcie *pcie)
1875+
{
1876+
unregister_die_notifier(&pcie->die_notifier);
1877+
atomic_notifier_chain_unregister(&panic_notifier_list,
1878+
&pcie->panic_notifier);
1879+
}
1880+
17101881
static void __brcm_pcie_remove(struct brcm_pcie *pcie)
17111882
{
17121883
brcm_msi_remove(pcie);
@@ -1725,6 +1896,9 @@ static void brcm_pcie_remove(struct platform_device *pdev)
17251896

17261897
pci_stop_root_bus(bridge->bus);
17271898
pci_remove_root_bus(bridge->bus);
1899+
if (pcie->cfg->has_err_report)
1900+
brcm_unregister_die_notifiers(pcie);
1901+
17281902
__brcm_pcie_remove(pcie);
17291903
}
17301904

@@ -1825,6 +1999,7 @@ static const struct pcie_cfg_data bcm7216_cfg = {
18251999
.bridge_sw_init_set = brcm_pcie_bridge_sw_init_set_7278,
18262000
.has_phy = true,
18272001
.num_inbound_wins = 3,
2002+
.has_err_report = true,
18282003
};
18292004

18302005
static const struct pcie_cfg_data bcm7712_cfg = {
@@ -1921,7 +2096,10 @@ static int brcm_pcie_probe(struct platform_device *pdev)
19212096
if (ret)
19222097
return dev_err_probe(&pdev->dev, ret, "could not enable clock\n");
19232098

1924-
pcie->cfg->bridge_sw_init_set(pcie, 0);
2099+
ret = brcm_pcie_bridge_sw_init_set(pcie, 0);
2100+
if (ret)
2101+
return dev_err_probe(&pdev->dev, ret,
2102+
"could not de-assert bridge reset\n");
19252103

19262104
if (pcie->swinit_reset) {
19272105
ret = reset_control_assert(pcie->swinit_reset);
@@ -1996,6 +2174,11 @@ static int brcm_pcie_probe(struct platform_device *pdev)
19962174
return ret;
19972175
}
19982176

2177+
if (pcie->cfg->has_err_report) {
2178+
spin_lock_init(&pcie->bridge_lock);
2179+
brcm_register_die_notifiers(pcie);
2180+
}
2181+
19992182
return 0;
20002183

20012184
fail:

0 commit comments

Comments
 (0)