PCI: dwc: designware: Handle ->host_init() failures
authorBjorn Andersson <bjorn.andersson@linaro.org>
Sun, 16 Jul 2017 06:39:45 +0000 (23:39 -0700)
committerBjorn Helgaas <bhelgaas@google.com>
Thu, 3 Aug 2017 21:14:32 +0000 (16:14 -0500)
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>
13 files changed:
drivers/pci/dwc/pci-dra7xx.c
drivers/pci/dwc/pci-exynos.c
drivers/pci/dwc/pci-imx6.c
drivers/pci/dwc/pci-keystone.c
drivers/pci/dwc/pci-layerscape.c
drivers/pci/dwc/pcie-armada8k.c
drivers/pci/dwc/pcie-artpec6.c
drivers/pci/dwc/pcie-designware-host.c
drivers/pci/dwc/pcie-designware-plat.c
drivers/pci/dwc/pcie-designware.h
drivers/pci/dwc/pcie-kirin.c
drivers/pci/dwc/pcie-qcom.c
drivers/pci/dwc/pcie-spear13xx.c

index f2fc5f47064ec5cf16cc163551c4305af35fcfdf..e8c13bb76169f54a5e72cfd6e4ab74f515ce638a 100644 (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 = {
index c78c065525900d57127ee12a73373ce61e4d0b88..f77f872e8b78080eb237eaac41ecca7ef321825f 100644 (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 = {
index bf5c3616e344845ccb89c0e2c55a50d12dbda79f..20aae4469ee4019ab27650ddb00e7cdbf9880cd2 100644 (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)
index 4783cec1f78d4f645d347602547215b7012a1dac..3ad3f8aa27b0949118a902f4f86be8b33283be23 100644 (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 = {
index fd861289ad8bc53a3e474ca2b922060bfddb7493..7581490f007c72e70aaf21d9d67e8f5148995954 100644 (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,
index ea8f34af6a851a5b0e721f8aca8dfb32c181a827..017a727a68db0ae196174d5d708b1582e5bfd340 100644 (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)
index 01c6f7823672520bc6e4e18f9afc4a1d90c32924..5d81f1d884e3bb3a405edb8f9de3bcdff0949e72 100644 (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 = {
index d29c020da08269caa2381d37c1f47c6dff82db58..15762117514746ec78a21fe567673f6ed7628a85 100644 (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;
 
index 091b4e7ad05959e27757326e592b78c9796bb709..168e2380f49399f57060b7faf6702ac9c7cd446f 100644 (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 = {
index b4d2a89f8e58591c6a08ea4e5204d56ddfc00466..7366c81674045ebcd90c61ae4d22cdf43882ab2b 100644 (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);
index 33fddb9f6739bf758d2c6a4e3dfbc464b7eae049..0b0eb67f26580e7a3fc4d2e1f53a907fb1e63971 100644 (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 = {
index 68c5f2ab5bc8f96f4c81709c80d306a579325ed4..d15657dc3990cf835d37a88f6393bdd133408e84 100644 (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,
index 80897291e0fbf976f4d6ad1760f06c08152a9f6c..52000bc3460086aeb9030d0c8d82f22377472a32 100644 (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 = {