提交 075af61c 编写于 作者: S Stefan Agner 提交者: Lorenzo Pieralisi

PCI: imx6: Limit DBI register length

Define the length of the DBI registers and limit config space to its
length. This makes sure that the kernel does not access registers
beyond that point, avoiding the following abort on a i.MX 6Quad:

  # cat /sys/devices/soc0/soc/1ffc000.pcie/pci0000\:00/0000\:00\:00.0/config
  [  100.021433] Unhandled fault: imprecise external abort (0x1406) at 0xb6ea7000
  ...
  [  100.056423] PC is at dw_pcie_read+0x50/0x84
  [  100.060790] LR is at dw_pcie_rd_own_conf+0x44/0x48
  ...
Signed-off-by: NStefan Agner <stefan@agner.ch>
Signed-off-by: NLorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Reviewed-by: NLucas Stach <l.stach@pengutronix.de>
上级 5f9e832c
...@@ -57,6 +57,7 @@ enum imx6_pcie_variants { ...@@ -57,6 +57,7 @@ enum imx6_pcie_variants {
struct imx6_pcie_drvdata { struct imx6_pcie_drvdata {
enum imx6_pcie_variants variant; enum imx6_pcie_variants variant;
u32 flags; u32 flags;
int dbi_length;
}; };
struct imx6_pcie { struct imx6_pcie {
...@@ -1212,6 +1213,7 @@ static const struct imx6_pcie_drvdata drvdata[] = { ...@@ -1212,6 +1213,7 @@ static const struct imx6_pcie_drvdata drvdata[] = {
.variant = IMX6Q, .variant = IMX6Q,
.flags = IMX6_PCIE_FLAG_IMX6_PHY | .flags = IMX6_PCIE_FLAG_IMX6_PHY |
IMX6_PCIE_FLAG_IMX6_SPEED_CHANGE, IMX6_PCIE_FLAG_IMX6_SPEED_CHANGE,
.dbi_length = 0x200,
}, },
[IMX6SX] = { [IMX6SX] = {
.variant = IMX6SX, .variant = IMX6SX,
...@@ -1254,6 +1256,37 @@ static struct platform_driver imx6_pcie_driver = { ...@@ -1254,6 +1256,37 @@ static struct platform_driver imx6_pcie_driver = {
.shutdown = imx6_pcie_shutdown, .shutdown = imx6_pcie_shutdown,
}; };
static void imx6_pcie_quirk(struct pci_dev *dev)
{
struct pci_bus *bus = dev->bus;
struct pcie_port *pp = bus->sysdata;
/* Bus parent is the PCI bridge, its parent is this platform driver */
if (!bus->dev.parent || !bus->dev.parent->parent)
return;
/* Make sure we only quirk devices associated with this driver */
if (bus->dev.parent->parent->driver != &imx6_pcie_driver.driver)
return;
if (bus->number == pp->root_bus_nr) {
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct imx6_pcie *imx6_pcie = to_imx6_pcie(pci);
/*
* Limit config length to avoid the kernel reading beyond
* the register set and causing an abort on i.MX 6Quad
*/
if (imx6_pcie->drvdata->dbi_length) {
dev->cfg_size = imx6_pcie->drvdata->dbi_length;
dev_info(&dev->dev, "Limiting cfg_size to %d\n",
dev->cfg_size);
}
}
}
DECLARE_PCI_FIXUP_CLASS_HEADER(PCI_VENDOR_ID_SYNOPSYS, 0xabcd,
PCI_CLASS_BRIDGE_PCI, 8, imx6_pcie_quirk);
static int __init imx6_pcie_init(void) static int __init imx6_pcie_init(void)
{ {
#ifdef CONFIG_ARM #ifdef CONFIG_ARM
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册