Commit 4a301766 authored by Bjorn Andersson's avatar Bjorn Andersson Committed by Bjorn Helgaas

PCI: dwc: designware: Handle ->host_init() failures

In several dwc-based drivers, ->host_init() can fail, so make sure to
propagate and handle this to avoid continuing operation of a driver or
hardware in an invalid state.
Signed-off-by: default avatarBjorn Andersson <bjorn.andersson@linaro.org>
Signed-off-by: default avatarBjorn Helgaas <bhelgaas@google.com>
Acked-by: default avatarJoao Pinto <jpinto@synopsys.com>
Acked-by: default avatarJingoo Han <jingoohan1@gmail.com>
parent e9be4d78
...@@ -195,7 +195,7 @@ static void dra7xx_pcie_enable_interrupts(struct dra7xx_pcie *dra7xx) ...@@ -195,7 +195,7 @@ static void dra7xx_pcie_enable_interrupts(struct dra7xx_pcie *dra7xx)
dra7xx_pcie_enable_msi_interrupts(dra7xx); dra7xx_pcie_enable_msi_interrupts(dra7xx);
} }
static void dra7xx_pcie_host_init(struct pcie_port *pp) static int dra7xx_pcie_host_init(struct pcie_port *pp)
{ {
struct dw_pcie *pci = to_dw_pcie_from_pp(pp); struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pci); struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pci);
...@@ -206,6 +206,8 @@ static void dra7xx_pcie_host_init(struct pcie_port *pp) ...@@ -206,6 +206,8 @@ static void dra7xx_pcie_host_init(struct pcie_port *pp)
dw_pcie_wait_for_link(pci); dw_pcie_wait_for_link(pci);
dw_pcie_msi_init(pp); dw_pcie_msi_init(pp);
dra7xx_pcie_enable_interrupts(dra7xx); dra7xx_pcie_enable_interrupts(dra7xx);
return 0;
} }
static const struct dw_pcie_host_ops dra7xx_pcie_host_ops = { static const struct dw_pcie_host_ops dra7xx_pcie_host_ops = {
......
...@@ -581,13 +581,15 @@ static int exynos_pcie_link_up(struct dw_pcie *pci) ...@@ -581,13 +581,15 @@ static int exynos_pcie_link_up(struct dw_pcie *pci)
return 0; return 0;
} }
static void exynos_pcie_host_init(struct pcie_port *pp) static int exynos_pcie_host_init(struct pcie_port *pp)
{ {
struct dw_pcie *pci = to_dw_pcie_from_pp(pp); struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct exynos_pcie *ep = to_exynos_pcie(pci); struct exynos_pcie *ep = to_exynos_pcie(pci);
exynos_pcie_establish_link(ep); exynos_pcie_establish_link(ep);
exynos_pcie_enable_interrupts(ep); exynos_pcie_enable_interrupts(ep);
return 0;
} }
static const struct dw_pcie_host_ops exynos_pcie_host_ops = { static const struct dw_pcie_host_ops exynos_pcie_host_ops = {
......
...@@ -636,7 +636,7 @@ static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie) ...@@ -636,7 +636,7 @@ static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie)
return ret; return ret;
} }
static void imx6_pcie_host_init(struct pcie_port *pp) static int imx6_pcie_host_init(struct pcie_port *pp)
{ {
struct dw_pcie *pci = to_dw_pcie_from_pp(pp); struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct imx6_pcie *imx6_pcie = to_imx6_pcie(pci); struct imx6_pcie *imx6_pcie = to_imx6_pcie(pci);
...@@ -649,6 +649,8 @@ static void imx6_pcie_host_init(struct pcie_port *pp) ...@@ -649,6 +649,8 @@ static void imx6_pcie_host_init(struct pcie_port *pp)
if (IS_ENABLED(CONFIG_PCI_MSI)) if (IS_ENABLED(CONFIG_PCI_MSI))
dw_pcie_msi_init(pp); dw_pcie_msi_init(pp);
return 0;
} }
static int imx6_pcie_link_up(struct dw_pcie *pci) static int imx6_pcie_link_up(struct dw_pcie *pci)
......
...@@ -261,7 +261,7 @@ static int keystone_pcie_fault(unsigned long addr, unsigned int fsr, ...@@ -261,7 +261,7 @@ static int keystone_pcie_fault(unsigned long addr, unsigned int fsr,
return 0; return 0;
} }
static void __init ks_pcie_host_init(struct pcie_port *pp) static int __init ks_pcie_host_init(struct pcie_port *pp)
{ {
struct dw_pcie *pci = to_dw_pcie_from_pp(pp); struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct keystone_pcie *ks_pcie = to_keystone_pcie(pci); struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);
...@@ -289,6 +289,8 @@ static void __init ks_pcie_host_init(struct pcie_port *pp) ...@@ -289,6 +289,8 @@ static void __init ks_pcie_host_init(struct pcie_port *pp)
*/ */
hook_fault_code(17, keystone_pcie_fault, SIGBUS, 0, hook_fault_code(17, keystone_pcie_fault, SIGBUS, 0,
"Asynchronous external abort"); "Asynchronous external abort");
return 0;
} }
static const struct dw_pcie_host_ops keystone_pcie_host_ops = { static const struct dw_pcie_host_ops keystone_pcie_host_ops = {
......
...@@ -108,31 +108,35 @@ static int ls1021_pcie_link_up(struct dw_pcie *pci) ...@@ -108,31 +108,35 @@ static int ls1021_pcie_link_up(struct dw_pcie *pci)
return 1; return 1;
} }
static void ls1021_pcie_host_init(struct pcie_port *pp) static int ls1021_pcie_host_init(struct pcie_port *pp)
{ {
struct dw_pcie *pci = to_dw_pcie_from_pp(pp); struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct ls_pcie *pcie = to_ls_pcie(pci); struct ls_pcie *pcie = to_ls_pcie(pci);
struct device *dev = pci->dev; struct device *dev = pci->dev;
u32 index[2]; u32 index[2];
int ret;
pcie->scfg = syscon_regmap_lookup_by_phandle(dev->of_node, pcie->scfg = syscon_regmap_lookup_by_phandle(dev->of_node,
"fsl,pcie-scfg"); "fsl,pcie-scfg");
if (IS_ERR(pcie->scfg)) { if (IS_ERR(pcie->scfg)) {
ret = PTR_ERR(pcie->scfg);
dev_err(dev, "No syscfg phandle specified\n"); dev_err(dev, "No syscfg phandle specified\n");
pcie->scfg = NULL; pcie->scfg = NULL;
return; return ret;
} }
if (of_property_read_u32_array(dev->of_node, if (of_property_read_u32_array(dev->of_node,
"fsl,pcie-scfg", index, 2)) { "fsl,pcie-scfg", index, 2)) {
pcie->scfg = NULL; pcie->scfg = NULL;
return; return -EINVAL;
} }
pcie->index = index[1]; pcie->index = index[1];
dw_pcie_setup_rc(pp); dw_pcie_setup_rc(pp);
ls_pcie_drop_msg_tlp(pcie); ls_pcie_drop_msg_tlp(pcie);
return 0;
} }
static int ls_pcie_link_up(struct dw_pcie *pci) static int ls_pcie_link_up(struct dw_pcie *pci)
...@@ -150,7 +154,7 @@ static int ls_pcie_link_up(struct dw_pcie *pci) ...@@ -150,7 +154,7 @@ static int ls_pcie_link_up(struct dw_pcie *pci)
return 1; return 1;
} }
static void ls_pcie_host_init(struct pcie_port *pp) static int ls_pcie_host_init(struct pcie_port *pp)
{ {
struct dw_pcie *pci = to_dw_pcie_from_pp(pp); struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct ls_pcie *pcie = to_ls_pcie(pci); struct ls_pcie *pcie = to_ls_pcie(pci);
...@@ -160,6 +164,8 @@ static void ls_pcie_host_init(struct pcie_port *pp) ...@@ -160,6 +164,8 @@ static void ls_pcie_host_init(struct pcie_port *pp)
ls_pcie_clear_multifunction(pcie); ls_pcie_clear_multifunction(pcie);
ls_pcie_drop_msg_tlp(pcie); ls_pcie_drop_msg_tlp(pcie);
iowrite32(0, pci->dbi_base + PCIE_DBI_RO_WR_EN); iowrite32(0, pci->dbi_base + PCIE_DBI_RO_WR_EN);
return 0;
} }
static int ls_pcie_msi_host_init(struct pcie_port *pp, static int ls_pcie_msi_host_init(struct pcie_port *pp,
......
...@@ -134,13 +134,15 @@ static void armada8k_pcie_establish_link(struct armada8k_pcie *pcie) ...@@ -134,13 +134,15 @@ static void armada8k_pcie_establish_link(struct armada8k_pcie *pcie)
dev_err(pci->dev, "Link not up after reconfiguration\n"); dev_err(pci->dev, "Link not up after reconfiguration\n");
} }
static void armada8k_pcie_host_init(struct pcie_port *pp) static int armada8k_pcie_host_init(struct pcie_port *pp)
{ {
struct dw_pcie *pci = to_dw_pcie_from_pp(pp); struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct armada8k_pcie *pcie = to_armada8k_pcie(pci); struct armada8k_pcie *pcie = to_armada8k_pcie(pci);
dw_pcie_setup_rc(pp); dw_pcie_setup_rc(pp);
armada8k_pcie_establish_link(pcie); armada8k_pcie_establish_link(pcie);
return 0;
} }
static irqreturn_t armada8k_pcie_irq_handler(int irq, void *arg) static irqreturn_t armada8k_pcie_irq_handler(int irq, void *arg)
......
...@@ -175,13 +175,15 @@ static void artpec6_pcie_enable_interrupts(struct artpec6_pcie *artpec6_pcie) ...@@ -175,13 +175,15 @@ static void artpec6_pcie_enable_interrupts(struct artpec6_pcie *artpec6_pcie)
dw_pcie_msi_init(pp); dw_pcie_msi_init(pp);
} }
static void artpec6_pcie_host_init(struct pcie_port *pp) static int artpec6_pcie_host_init(struct pcie_port *pp)
{ {
struct dw_pcie *pci = to_dw_pcie_from_pp(pp); struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct artpec6_pcie *artpec6_pcie = to_artpec6_pcie(pci); struct artpec6_pcie *artpec6_pcie = to_artpec6_pcie(pci);
artpec6_pcie_establish_link(artpec6_pcie); artpec6_pcie_establish_link(artpec6_pcie);
artpec6_pcie_enable_interrupts(artpec6_pcie); artpec6_pcie_enable_interrupts(artpec6_pcie);
return 0;
} }
static const struct dw_pcie_host_ops artpec6_pcie_host_ops = { static const struct dw_pcie_host_ops artpec6_pcie_host_ops = {
......
...@@ -401,8 +401,11 @@ int dw_pcie_host_init(struct pcie_port *pp) ...@@ -401,8 +401,11 @@ int dw_pcie_host_init(struct pcie_port *pp)
} }
} }
if (pp->ops->host_init) if (pp->ops->host_init) {
pp->ops->host_init(pp); ret = pp->ops->host_init(pp);
if (ret)
goto error;
}
pp->root_bus_nr = pp->busn->start; pp->root_bus_nr = pp->busn->start;
......
...@@ -35,7 +35,7 @@ static irqreturn_t dw_plat_pcie_msi_irq_handler(int irq, void *arg) ...@@ -35,7 +35,7 @@ static irqreturn_t dw_plat_pcie_msi_irq_handler(int irq, void *arg)
return dw_handle_msi_irq(pp); return dw_handle_msi_irq(pp);
} }
static void dw_plat_pcie_host_init(struct pcie_port *pp) static int dw_plat_pcie_host_init(struct pcie_port *pp)
{ {
struct dw_pcie *pci = to_dw_pcie_from_pp(pp); struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
...@@ -44,6 +44,8 @@ static void dw_plat_pcie_host_init(struct pcie_port *pp) ...@@ -44,6 +44,8 @@ static void dw_plat_pcie_host_init(struct pcie_port *pp)
if (IS_ENABLED(CONFIG_PCI_MSI)) if (IS_ENABLED(CONFIG_PCI_MSI))
dw_pcie_msi_init(pp); dw_pcie_msi_init(pp);
return 0;
} }
static const struct dw_pcie_host_ops dw_plat_pcie_host_ops = { static const struct dw_pcie_host_ops dw_plat_pcie_host_ops = {
......
...@@ -134,7 +134,7 @@ struct dw_pcie_host_ops { ...@@ -134,7 +134,7 @@ struct dw_pcie_host_ops {
unsigned int devfn, int where, int size, u32 *val); unsigned int devfn, int where, int size, u32 *val);
int (*wr_other_conf)(struct pcie_port *pp, struct pci_bus *bus, int (*wr_other_conf)(struct pcie_port *pp, struct pci_bus *bus,
unsigned int devfn, int where, int size, u32 val); unsigned int devfn, int where, int size, u32 val);
void (*host_init)(struct pcie_port *pp); int (*host_init)(struct pcie_port *pp);
void (*msi_set_irq)(struct pcie_port *pp, int irq); void (*msi_set_irq)(struct pcie_port *pp, int irq);
void (*msi_clear_irq)(struct pcie_port *pp, int irq); void (*msi_clear_irq)(struct pcie_port *pp, int irq);
phys_addr_t (*get_msi_addr)(struct pcie_port *pp); phys_addr_t (*get_msi_addr)(struct pcie_port *pp);
......
...@@ -430,9 +430,11 @@ static int kirin_pcie_establish_link(struct pcie_port *pp) ...@@ -430,9 +430,11 @@ static int kirin_pcie_establish_link(struct pcie_port *pp)
return 0; return 0;
} }
static void kirin_pcie_host_init(struct pcie_port *pp) static int kirin_pcie_host_init(struct pcie_port *pp)
{ {
kirin_pcie_establish_link(pp); kirin_pcie_establish_link(pp);
return 0;
} }
static struct dw_pcie_ops kirin_dw_pcie_ops = { static struct dw_pcie_ops kirin_dw_pcie_ops = {
......
...@@ -891,7 +891,7 @@ static int qcom_pcie_link_up(struct dw_pcie *pci) ...@@ -891,7 +891,7 @@ static int qcom_pcie_link_up(struct dw_pcie *pci)
return !!(val & PCI_EXP_LNKSTA_DLLLA); return !!(val & PCI_EXP_LNKSTA_DLLLA);
} }
static void qcom_pcie_host_init(struct pcie_port *pp) static int qcom_pcie_host_init(struct pcie_port *pp)
{ {
struct dw_pcie *pci = to_dw_pcie_from_pp(pp); struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct qcom_pcie *pcie = to_qcom_pcie(pci); struct qcom_pcie *pcie = to_qcom_pcie(pci);
...@@ -921,12 +921,14 @@ static void qcom_pcie_host_init(struct pcie_port *pp) ...@@ -921,12 +921,14 @@ static void qcom_pcie_host_init(struct pcie_port *pp)
if (ret) if (ret)
goto err; goto err;
return; return 0;
err: err:
qcom_ep_reset_assert(pcie); qcom_ep_reset_assert(pcie);
phy_power_off(pcie->phy); phy_power_off(pcie->phy);
err_deinit: err_deinit:
pcie->ops->deinit(pcie); pcie->ops->deinit(pcie);
return ret;
} }
static int qcom_pcie_rd_own_conf(struct pcie_port *pp, int where, int size, static int qcom_pcie_rd_own_conf(struct pcie_port *pp, int where, int size,
......
...@@ -177,13 +177,15 @@ static int spear13xx_pcie_link_up(struct dw_pcie *pci) ...@@ -177,13 +177,15 @@ static int spear13xx_pcie_link_up(struct dw_pcie *pci)
return 0; return 0;
} }
static void spear13xx_pcie_host_init(struct pcie_port *pp) static int spear13xx_pcie_host_init(struct pcie_port *pp)
{ {
struct dw_pcie *pci = to_dw_pcie_from_pp(pp); struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct spear13xx_pcie *spear13xx_pcie = to_spear13xx_pcie(pci); struct spear13xx_pcie *spear13xx_pcie = to_spear13xx_pcie(pci);
spear13xx_pcie_establish_link(spear13xx_pcie); spear13xx_pcie_establish_link(spear13xx_pcie);
spear13xx_pcie_enable_interrupts(spear13xx_pcie); spear13xx_pcie_enable_interrupts(spear13xx_pcie);
return 0;
} }
static const struct dw_pcie_host_ops spear13xx_pcie_host_ops = { static const struct dw_pcie_host_ops spear13xx_pcie_host_ops = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment