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: Bjorn Andersson <bjorn.andersson@linaro.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Acked-by: Joao Pinto <jpinto@synopsys.com>
Acked-by: Jingoo Han <jingoohan1@gmail.com>
This commit is contained in:
Bjorn Andersson 2017-07-15 23:39:45 -07:00 committed by Bjorn Helgaas
parent e9be4d7861
commit 4a301766f5
13 changed files with 47 additions and 18 deletions

View File

@ -195,7 +195,7 @@ static void dra7xx_pcie_enable_interrupts(struct dra7xx_pcie *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 dra7xx_pcie *dra7xx = to_dra7xx_pcie(pci);
@ -206,6 +206,8 @@ static void dra7xx_pcie_host_init(struct pcie_port *pp)
dw_pcie_wait_for_link(pci);
dw_pcie_msi_init(pp);
dra7xx_pcie_enable_interrupts(dra7xx);
return 0;
}
static const struct dw_pcie_host_ops dra7xx_pcie_host_ops = {

View File

@ -581,13 +581,15 @@ static int exynos_pcie_link_up(struct dw_pcie *pci)
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 exynos_pcie *ep = to_exynos_pcie(pci);
exynos_pcie_establish_link(ep);
exynos_pcie_enable_interrupts(ep);
return 0;
}
static const struct dw_pcie_host_ops exynos_pcie_host_ops = {

View File

@ -636,7 +636,7 @@ err_reset_phy:
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 imx6_pcie *imx6_pcie = to_imx6_pcie(pci);
@ -649,6 +649,8 @@ static void imx6_pcie_host_init(struct pcie_port *pp)
if (IS_ENABLED(CONFIG_PCI_MSI))
dw_pcie_msi_init(pp);
return 0;
}
static int imx6_pcie_link_up(struct dw_pcie *pci)

View File

@ -261,7 +261,7 @@ static int keystone_pcie_fault(unsigned long addr, unsigned int fsr,
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 keystone_pcie *ks_pcie = to_keystone_pcie(pci);
@ -289,6 +289,8 @@ static void __init ks_pcie_host_init(struct pcie_port *pp)
*/
hook_fault_code(17, keystone_pcie_fault, SIGBUS, 0,
"Asynchronous external abort");
return 0;
}
static const struct dw_pcie_host_ops keystone_pcie_host_ops = {

View File

@ -108,31 +108,35 @@ static int ls1021_pcie_link_up(struct dw_pcie *pci)
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 ls_pcie *pcie = to_ls_pcie(pci);
struct device *dev = pci->dev;
u32 index[2];
int ret;
pcie->scfg = syscon_regmap_lookup_by_phandle(dev->of_node,
"fsl,pcie-scfg");
if (IS_ERR(pcie->scfg)) {
ret = PTR_ERR(pcie->scfg);
dev_err(dev, "No syscfg phandle specified\n");
pcie->scfg = NULL;
return;
return ret;
}
if (of_property_read_u32_array(dev->of_node,
"fsl,pcie-scfg", index, 2)) {
pcie->scfg = NULL;
return;
return -EINVAL;
}
pcie->index = index[1];
dw_pcie_setup_rc(pp);
ls_pcie_drop_msg_tlp(pcie);
return 0;
}
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;
}
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 ls_pcie *pcie = to_ls_pcie(pci);
@ -160,6 +164,8 @@ static void ls_pcie_host_init(struct pcie_port *pp)
ls_pcie_clear_multifunction(pcie);
ls_pcie_drop_msg_tlp(pcie);
iowrite32(0, pci->dbi_base + PCIE_DBI_RO_WR_EN);
return 0;
}
static int ls_pcie_msi_host_init(struct pcie_port *pp,

View File

@ -134,13 +134,15 @@ static void armada8k_pcie_establish_link(struct armada8k_pcie *pcie)
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 armada8k_pcie *pcie = to_armada8k_pcie(pci);
dw_pcie_setup_rc(pp);
armada8k_pcie_establish_link(pcie);
return 0;
}
static irqreturn_t armada8k_pcie_irq_handler(int irq, void *arg)

View File

@ -175,13 +175,15 @@ static void artpec6_pcie_enable_interrupts(struct artpec6_pcie *artpec6_pcie)
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 artpec6_pcie *artpec6_pcie = to_artpec6_pcie(pci);
artpec6_pcie_establish_link(artpec6_pcie);
artpec6_pcie_enable_interrupts(artpec6_pcie);
return 0;
}
static const struct dw_pcie_host_ops artpec6_pcie_host_ops = {

View File

@ -401,8 +401,11 @@ int dw_pcie_host_init(struct pcie_port *pp)
}
}
if (pp->ops->host_init)
pp->ops->host_init(pp);
if (pp->ops->host_init) {
ret = pp->ops->host_init(pp);
if (ret)
goto error;
}
pp->root_bus_nr = pp->busn->start;

View File

@ -35,7 +35,7 @@ static irqreturn_t dw_plat_pcie_msi_irq_handler(int irq, void *arg)
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);
@ -44,6 +44,8 @@ static void dw_plat_pcie_host_init(struct pcie_port *pp)
if (IS_ENABLED(CONFIG_PCI_MSI))
dw_pcie_msi_init(pp);
return 0;
}
static const struct dw_pcie_host_ops dw_plat_pcie_host_ops = {

View File

@ -134,7 +134,7 @@ struct dw_pcie_host_ops {
unsigned int devfn, int where, int size, u32 *val);
int (*wr_other_conf)(struct pcie_port *pp, struct pci_bus *bus,
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_clear_irq)(struct pcie_port *pp, int irq);
phys_addr_t (*get_msi_addr)(struct pcie_port *pp);

View File

@ -430,9 +430,11 @@ static int kirin_pcie_establish_link(struct pcie_port *pp)
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);
return 0;
}
static struct dw_pcie_ops kirin_dw_pcie_ops = {

View File

@ -891,7 +891,7 @@ static int qcom_pcie_link_up(struct dw_pcie *pci)
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 qcom_pcie *pcie = to_qcom_pcie(pci);
@ -921,12 +921,14 @@ static void qcom_pcie_host_init(struct pcie_port *pp)
if (ret)
goto err;
return;
return 0;
err:
qcom_ep_reset_assert(pcie);
phy_power_off(pcie->phy);
err_deinit:
pcie->ops->deinit(pcie);
return ret;
}
static int qcom_pcie_rd_own_conf(struct pcie_port *pp, int where, int size,

View File

@ -177,13 +177,15 @@ static int spear13xx_pcie_link_up(struct dw_pcie *pci)
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 spear13xx_pcie *spear13xx_pcie = to_spear13xx_pcie(pci);
spear13xx_pcie_establish_link(spear13xx_pcie);
spear13xx_pcie_enable_interrupts(spear13xx_pcie);
return 0;
}
static const struct dw_pcie_host_ops spear13xx_pcie_host_ops = {