Merge tag 'ntb-5.20' of https://github.com/jonmason/ntb
[sfrench/cifs-2.6.git] / drivers / pci / controller / dwc / pcie-designware-ep.c
index b4cb65d851cd89f9ac0f43494b1a49239bf7d90a..83ddb190292e4f5569254d735851f51ad4ef986d 100644 (file)
@@ -154,9 +154,8 @@ static int dw_pcie_ep_write_header(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
        return 0;
 }
 
-static int dw_pcie_ep_inbound_atu(struct dw_pcie_ep *ep, u8 func_no,
-                                 enum pci_barno bar, dma_addr_t cpu_addr,
-                                 enum dw_pcie_as_type as_type)
+static int dw_pcie_ep_inbound_atu(struct dw_pcie_ep *ep, u8 func_no, int type,
+                                 dma_addr_t cpu_addr, enum pci_barno bar)
 {
        int ret;
        u32 free_win;
@@ -172,8 +171,8 @@ static int dw_pcie_ep_inbound_atu(struct dw_pcie_ep *ep, u8 func_no,
                return -EINVAL;
        }
 
-       ret = dw_pcie_prog_inbound_atu(pci, func_no, free_win, bar, cpu_addr,
-                                      as_type);
+       ret = dw_pcie_prog_inbound_atu(pci, func_no, free_win, type,
+                                      cpu_addr, bar);
        if (ret < 0) {
                dev_err(pci->dev, "Failed to program IB window\n");
                return ret;
@@ -189,8 +188,9 @@ static int dw_pcie_ep_outbound_atu(struct dw_pcie_ep *ep, u8 func_no,
                                   phys_addr_t phys_addr,
                                   u64 pci_addr, size_t size)
 {
-       u32 free_win;
        struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+       u32 free_win;
+       int ret;
 
        free_win = find_first_zero_bit(ep->ob_window_map, pci->num_ob_windows);
        if (free_win >= pci->num_ob_windows) {
@@ -198,8 +198,10 @@ static int dw_pcie_ep_outbound_atu(struct dw_pcie_ep *ep, u8 func_no,
                return -EINVAL;
        }
 
-       dw_pcie_prog_ep_outbound_atu(pci, func_no, free_win, PCIE_ATU_TYPE_MEM,
-                                    phys_addr, pci_addr, size);
+       ret = dw_pcie_prog_ep_outbound_atu(pci, func_no, free_win, PCIE_ATU_TYPE_MEM,
+                                          phys_addr, pci_addr, size);
+       if (ret)
+               return ret;
 
        set_bit(free_win, ep->ob_window_map);
        ep->outbound_addr[free_win] = phys_addr;
@@ -217,7 +219,7 @@ static void dw_pcie_ep_clear_bar(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
 
        __dw_pcie_ep_reset_bar(pci, func_no, bar, epf_bar->flags);
 
-       dw_pcie_disable_atu(pci, atu_index, DW_PCIE_REGION_INBOUND);
+       dw_pcie_disable_atu(pci, PCIE_ATU_REGION_DIR_IB, atu_index);
        clear_bit(atu_index, ep->ib_window_map);
        ep->epf_bar[bar] = NULL;
        ep->bar_to_atu[bar] = 0;
@@ -226,27 +228,25 @@ static void dw_pcie_ep_clear_bar(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
 static int dw_pcie_ep_set_bar(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
                              struct pci_epf_bar *epf_bar)
 {
-       int ret;
        struct dw_pcie_ep *ep = epc_get_drvdata(epc);
        struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
        enum pci_barno bar = epf_bar->barno;
        size_t size = epf_bar->size;
        int flags = epf_bar->flags;
-       enum dw_pcie_as_type as_type;
-       u32 reg;
        unsigned int func_offset = 0;
+       int ret, type;
+       u32 reg;
 
        func_offset = dw_pcie_ep_func_select(ep, func_no);
 
        reg = PCI_BASE_ADDRESS_0 + (4 * bar) + func_offset;
 
        if (!(flags & PCI_BASE_ADDRESS_SPACE))
-               as_type = DW_PCIE_AS_MEM;
+               type = PCIE_ATU_TYPE_MEM;
        else
-               as_type = DW_PCIE_AS_IO;
+               type = PCIE_ATU_TYPE_IO;
 
-       ret = dw_pcie_ep_inbound_atu(ep, func_no, bar,
-                                    epf_bar->phys_addr, as_type);
+       ret = dw_pcie_ep_inbound_atu(ep, func_no, type, epf_bar->phys_addr, bar);
        if (ret)
                return ret;
 
@@ -297,7 +297,7 @@ static void dw_pcie_ep_unmap_addr(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
        if (ret < 0)
                return;
 
-       dw_pcie_disable_atu(pci, atu_index, DW_PCIE_REGION_OUTBOUND);
+       dw_pcie_disable_atu(pci, PCIE_ATU_REGION_DIR_OB, atu_index);
        clear_bit(atu_index, ep->ob_window_map);
 }
 
@@ -443,8 +443,7 @@ static void dw_pcie_ep_stop(struct pci_epc *epc)
        struct dw_pcie_ep *ep = epc_get_drvdata(epc);
        struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
 
-       if (pci->ops && pci->ops->stop_link)
-               pci->ops->stop_link(pci);
+       dw_pcie_stop_link(pci);
 }
 
 static int dw_pcie_ep_start(struct pci_epc *epc)
@@ -452,10 +451,7 @@ static int dw_pcie_ep_start(struct pci_epc *epc)
        struct dw_pcie_ep *ep = epc_get_drvdata(epc);
        struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
 
-       if (!pci->ops || !pci->ops->start_link)
-               return -EINVAL;
-
-       return pci->ops->start_link(pci);
+       return dw_pcie_start_link(pci);
 }
 
 static const struct pci_epc_features*
@@ -707,17 +703,15 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)
 
        if (!pci->dbi_base2) {
                res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi2");
-               if (!res)
+               if (!res) {
                        pci->dbi_base2 = pci->dbi_base + SZ_4K;
-               else {
+               else {
                        pci->dbi_base2 = devm_pci_remap_cfg_resource(dev, res);
                        if (IS_ERR(pci->dbi_base2))
                                return PTR_ERR(pci->dbi_base2);
                }
        }
 
-       dw_pcie_iatu_detect(pci);
-
        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "addr_space");
        if (!res)
                return -EINVAL;
@@ -725,17 +719,17 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)
        ep->phys_base = res->start;
        ep->addr_size = resource_size(res);
 
-       ep->ib_window_map = devm_kcalloc(dev,
-                                        BITS_TO_LONGS(pci->num_ib_windows),
-                                        sizeof(long),
-                                        GFP_KERNEL);
+       dw_pcie_version_detect(pci);
+
+       dw_pcie_iatu_detect(pci);
+
+       ep->ib_window_map = devm_bitmap_zalloc(dev, pci->num_ib_windows,
+                                              GFP_KERNEL);
        if (!ep->ib_window_map)
                return -ENOMEM;
 
-       ep->ob_window_map = devm_kcalloc(dev,
-                                        BITS_TO_LONGS(pci->num_ob_windows),
-                                        sizeof(long),
-                                        GFP_KERNEL);
+       ep->ob_window_map = devm_bitmap_zalloc(dev, pci->num_ob_windows,
+                                              GFP_KERNEL);
        if (!ep->ob_window_map)
                return -ENOMEM;
 
@@ -788,8 +782,9 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)
        ep->msi_mem = pci_epc_mem_alloc_addr(epc, &ep->msi_mem_phys,
                                             epc->mem->window.page_size);
        if (!ep->msi_mem) {
+               ret = -ENOMEM;
                dev_err(dev, "Failed to reserve memory for MSI/MSI-X\n");
-               return -ENOMEM;
+               goto err_exit_epc_mem;
        }
 
        if (ep->ops->get_features) {
@@ -798,6 +793,19 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)
                        return 0;
        }
 
-       return dw_pcie_ep_init_complete(ep);
+       ret = dw_pcie_ep_init_complete(ep);
+       if (ret)
+               goto err_free_epc_mem;
+
+       return 0;
+
+err_free_epc_mem:
+       pci_epc_mem_free_addr(epc, ep->msi_mem_phys, ep->msi_mem,
+                             epc->mem->window.page_size);
+
+err_exit_epc_mem:
+       pci_epc_mem_exit(epc);
+
+       return ret;
 }
 EXPORT_SYMBOL_GPL(dw_pcie_ep_init);