Merge tag 'vfio-v5.10-rc3' of git://github.com/awilliam/linux-vfio
[linux-2.6-microblaze.git] / drivers / pci / controller / dwc / pcie-designware-ep.c
index 305bfec..ad7da4e 100644 (file)
@@ -12,6 +12,8 @@
 #include <linux/pci-epc.h>
 #include <linux/pci-epf.h>
 
+#include "../../pci.h"
+
 void dw_pcie_ep_linkup(struct dw_pcie_ep *ep)
 {
        struct pci_epc *epc = ep->epc;
@@ -28,12 +30,39 @@ void dw_pcie_ep_init_notify(struct dw_pcie_ep *ep)
 }
 EXPORT_SYMBOL_GPL(dw_pcie_ep_init_notify);
 
-static void __dw_pcie_ep_reset_bar(struct dw_pcie *pci, enum pci_barno bar,
-                                  int flags)
+struct dw_pcie_ep_func *
+dw_pcie_ep_get_func_from_ep(struct dw_pcie_ep *ep, u8 func_no)
+{
+       struct dw_pcie_ep_func *ep_func;
+
+       list_for_each_entry(ep_func, &ep->func_list, list) {
+               if (ep_func->func_no == func_no)
+                       return ep_func;
+       }
+
+       return NULL;
+}
+
+static unsigned int dw_pcie_ep_func_select(struct dw_pcie_ep *ep, u8 func_no)
+{
+       unsigned int func_offset = 0;
+
+       if (ep->ops->func_conf_select)
+               func_offset = ep->ops->func_conf_select(ep, func_no);
+
+       return func_offset;
+}
+
+static void __dw_pcie_ep_reset_bar(struct dw_pcie *pci, u8 func_no,
+                                  enum pci_barno bar, int flags)
 {
        u32 reg;
+       unsigned int func_offset = 0;
+       struct dw_pcie_ep *ep = &pci->ep;
 
-       reg = PCI_BASE_ADDRESS_0 + (4 * bar);
+       func_offset = dw_pcie_ep_func_select(ep, func_no);
+
+       reg = func_offset + PCI_BASE_ADDRESS_0 + (4 * bar);
        dw_pcie_dbi_ro_wr_en(pci);
        dw_pcie_writel_dbi2(pci, reg, 0x0);
        dw_pcie_writel_dbi(pci, reg, 0x0);
@@ -46,7 +75,53 @@ static void __dw_pcie_ep_reset_bar(struct dw_pcie *pci, enum pci_barno bar,
 
 void dw_pcie_ep_reset_bar(struct dw_pcie *pci, enum pci_barno bar)
 {
-       __dw_pcie_ep_reset_bar(pci, bar, 0);
+       u8 func_no, funcs;
+
+       funcs = pci->ep.epc->max_functions;
+
+       for (func_no = 0; func_no < funcs; func_no++)
+               __dw_pcie_ep_reset_bar(pci, func_no, bar, 0);
+}
+
+static u8 __dw_pcie_ep_find_next_cap(struct dw_pcie_ep *ep, u8 func_no,
+               u8 cap_ptr, u8 cap)
+{
+       struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+       unsigned int func_offset = 0;
+       u8 cap_id, next_cap_ptr;
+       u16 reg;
+
+       if (!cap_ptr)
+               return 0;
+
+       func_offset = dw_pcie_ep_func_select(ep, func_no);
+
+       reg = dw_pcie_readw_dbi(pci, func_offset + cap_ptr);
+       cap_id = (reg & 0x00ff);
+
+       if (cap_id > PCI_CAP_ID_MAX)
+               return 0;
+
+       if (cap_id == cap)
+               return cap_ptr;
+
+       next_cap_ptr = (reg & 0xff00) >> 8;
+       return __dw_pcie_ep_find_next_cap(ep, func_no, next_cap_ptr, cap);
+}
+
+static u8 dw_pcie_ep_find_capability(struct dw_pcie_ep *ep, u8 func_no, u8 cap)
+{
+       struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+       unsigned int func_offset = 0;
+       u8 next_cap_ptr;
+       u16 reg;
+
+       func_offset = dw_pcie_ep_func_select(ep, func_no);
+
+       reg = dw_pcie_readw_dbi(pci, func_offset + PCI_CAPABILITY_LIST);
+       next_cap_ptr = (reg & 0x00ff);
+
+       return __dw_pcie_ep_find_next_cap(ep, func_no, next_cap_ptr, cap);
 }
 
 static int dw_pcie_ep_write_header(struct pci_epc *epc, u8 func_no,
@@ -54,28 +129,31 @@ static int dw_pcie_ep_write_header(struct pci_epc *epc, u8 func_no,
 {
        struct dw_pcie_ep *ep = epc_get_drvdata(epc);
        struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+       unsigned int func_offset = 0;
+
+       func_offset = dw_pcie_ep_func_select(ep, func_no);
 
        dw_pcie_dbi_ro_wr_en(pci);
-       dw_pcie_writew_dbi(pci, PCI_VENDOR_ID, hdr->vendorid);
-       dw_pcie_writew_dbi(pci, PCI_DEVICE_ID, hdr->deviceid);
-       dw_pcie_writeb_dbi(pci, PCI_REVISION_ID, hdr->revid);
-       dw_pcie_writeb_dbi(pci, PCI_CLASS_PROG, hdr->progif_code);
-       dw_pcie_writew_dbi(pci, PCI_CLASS_DEVICE,
+       dw_pcie_writew_dbi(pci, func_offset + PCI_VENDOR_ID, hdr->vendorid);
+       dw_pcie_writew_dbi(pci, func_offset + PCI_DEVICE_ID, hdr->deviceid);
+       dw_pcie_writeb_dbi(pci, func_offset + PCI_REVISION_ID, hdr->revid);
+       dw_pcie_writeb_dbi(pci, func_offset + PCI_CLASS_PROG, hdr->progif_code);
+       dw_pcie_writew_dbi(pci, func_offset + PCI_CLASS_DEVICE,
                           hdr->subclass_code | hdr->baseclass_code << 8);
-       dw_pcie_writeb_dbi(pci, PCI_CACHE_LINE_SIZE,
+       dw_pcie_writeb_dbi(pci, func_offset + PCI_CACHE_LINE_SIZE,
                           hdr->cache_line_size);
-       dw_pcie_writew_dbi(pci, PCI_SUBSYSTEM_VENDOR_ID,
+       dw_pcie_writew_dbi(pci, func_offset + PCI_SUBSYSTEM_VENDOR_ID,
                           hdr->subsys_vendor_id);
-       dw_pcie_writew_dbi(pci, PCI_SUBSYSTEM_ID, hdr->subsys_id);
-       dw_pcie_writeb_dbi(pci, PCI_INTERRUPT_PIN,
+       dw_pcie_writew_dbi(pci, func_offset + PCI_SUBSYSTEM_ID, hdr->subsys_id);
+       dw_pcie_writeb_dbi(pci, func_offset + PCI_INTERRUPT_PIN,
                           hdr->interrupt_pin);
        dw_pcie_dbi_ro_wr_dis(pci);
 
        return 0;
 }
 
-static int dw_pcie_ep_inbound_atu(struct dw_pcie_ep *ep, enum pci_barno bar,
-                                 dma_addr_t cpu_addr,
+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)
 {
        int ret;
@@ -88,7 +166,7 @@ static int dw_pcie_ep_inbound_atu(struct dw_pcie_ep *ep, enum pci_barno bar,
                return -EINVAL;
        }
 
-       ret = dw_pcie_prog_inbound_atu(pci, free_win, bar, cpu_addr,
+       ret = dw_pcie_prog_inbound_atu(pci, func_no, free_win, bar, cpu_addr,
                                       as_type);
        if (ret < 0) {
                dev_err(pci->dev, "Failed to program IB window\n");
@@ -101,7 +179,8 @@ static int dw_pcie_ep_inbound_atu(struct dw_pcie_ep *ep, enum pci_barno bar,
        return 0;
 }
 
-static int dw_pcie_ep_outbound_atu(struct dw_pcie_ep *ep, phys_addr_t phys_addr,
+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;
@@ -113,8 +192,8 @@ static int dw_pcie_ep_outbound_atu(struct dw_pcie_ep *ep, phys_addr_t phys_addr,
                return -EINVAL;
        }
 
-       dw_pcie_prog_outbound_atu(pci, free_win, PCIE_ATU_TYPE_MEM,
-                                 phys_addr, pci_addr, size);
+       dw_pcie_prog_ep_outbound_atu(pci, func_no, free_win, PCIE_ATU_TYPE_MEM,
+                                    phys_addr, pci_addr, size);
 
        set_bit(free_win, ep->ob_window_map);
        ep->outbound_addr[free_win] = phys_addr;
@@ -130,7 +209,7 @@ static void dw_pcie_ep_clear_bar(struct pci_epc *epc, u8 func_no,
        enum pci_barno bar = epf_bar->barno;
        u32 atu_index = ep->bar_to_atu[bar];
 
-       __dw_pcie_ep_reset_bar(pci, bar, epf_bar->flags);
+       __dw_pcie_ep_reset_bar(pci, func_no, bar, epf_bar->flags);
 
        dw_pcie_disable_atu(pci, atu_index, DW_PCIE_REGION_INBOUND);
        clear_bit(atu_index, ep->ib_window_map);
@@ -147,14 +226,20 @@ static int dw_pcie_ep_set_bar(struct pci_epc *epc, u8 func_no,
        size_t size = epf_bar->size;
        int flags = epf_bar->flags;
        enum dw_pcie_as_type as_type;
-       u32 reg = PCI_BASE_ADDRESS_0 + (4 * bar);
+       u32 reg;
+       unsigned int func_offset = 0;
+
+       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;
        else
                as_type = DW_PCIE_AS_IO;
 
-       ret = dw_pcie_ep_inbound_atu(ep, bar, epf_bar->phys_addr, as_type);
+       ret = dw_pcie_ep_inbound_atu(ep, func_no, bar,
+                                    epf_bar->phys_addr, as_type);
        if (ret)
                return ret;
 
@@ -213,7 +298,7 @@ static int dw_pcie_ep_map_addr(struct pci_epc *epc, u8 func_no,
        struct dw_pcie_ep *ep = epc_get_drvdata(epc);
        struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
 
-       ret = dw_pcie_ep_outbound_atu(ep, addr, pci_addr, size);
+       ret = dw_pcie_ep_outbound_atu(ep, func_no, addr, pci_addr, size);
        if (ret) {
                dev_err(pci->dev, "Failed to enable address\n");
                return ret;
@@ -227,11 +312,16 @@ static int dw_pcie_ep_get_msi(struct pci_epc *epc, u8 func_no)
        struct dw_pcie_ep *ep = epc_get_drvdata(epc);
        struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
        u32 val, reg;
+       unsigned int func_offset = 0;
+       struct dw_pcie_ep_func *ep_func;
 
-       if (!ep->msi_cap)
+       ep_func = dw_pcie_ep_get_func_from_ep(ep, func_no);
+       if (!ep_func || !ep_func->msi_cap)
                return -EINVAL;
 
-       reg = ep->msi_cap + PCI_MSI_FLAGS;
+       func_offset = dw_pcie_ep_func_select(ep, func_no);
+
+       reg = ep_func->msi_cap + func_offset + PCI_MSI_FLAGS;
        val = dw_pcie_readw_dbi(pci, reg);
        if (!(val & PCI_MSI_FLAGS_ENABLE))
                return -EINVAL;
@@ -246,11 +336,16 @@ static int dw_pcie_ep_set_msi(struct pci_epc *epc, u8 func_no, u8 interrupts)
        struct dw_pcie_ep *ep = epc_get_drvdata(epc);
        struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
        u32 val, reg;
+       unsigned int func_offset = 0;
+       struct dw_pcie_ep_func *ep_func;
 
-       if (!ep->msi_cap)
+       ep_func = dw_pcie_ep_get_func_from_ep(ep, func_no);
+       if (!ep_func || !ep_func->msi_cap)
                return -EINVAL;
 
-       reg = ep->msi_cap + PCI_MSI_FLAGS;
+       func_offset = dw_pcie_ep_func_select(ep, func_no);
+
+       reg = ep_func->msi_cap + func_offset + PCI_MSI_FLAGS;
        val = dw_pcie_readw_dbi(pci, reg);
        val &= ~PCI_MSI_FLAGS_QMASK;
        val |= (interrupts << 1) & PCI_MSI_FLAGS_QMASK;
@@ -266,11 +361,16 @@ static int dw_pcie_ep_get_msix(struct pci_epc *epc, u8 func_no)
        struct dw_pcie_ep *ep = epc_get_drvdata(epc);
        struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
        u32 val, reg;
+       unsigned int func_offset = 0;
+       struct dw_pcie_ep_func *ep_func;
 
-       if (!ep->msix_cap)
+       ep_func = dw_pcie_ep_get_func_from_ep(ep, func_no);
+       if (!ep_func || !ep_func->msix_cap)
                return -EINVAL;
 
-       reg = ep->msix_cap + PCI_MSIX_FLAGS;
+       func_offset = dw_pcie_ep_func_select(ep, func_no);
+
+       reg = ep_func->msix_cap + func_offset + PCI_MSIX_FLAGS;
        val = dw_pcie_readw_dbi(pci, reg);
        if (!(val & PCI_MSIX_FLAGS_ENABLE))
                return -EINVAL;
@@ -286,23 +386,28 @@ static int dw_pcie_ep_set_msix(struct pci_epc *epc, u8 func_no, u16 interrupts,
        struct dw_pcie_ep *ep = epc_get_drvdata(epc);
        struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
        u32 val, reg;
+       unsigned int func_offset = 0;
+       struct dw_pcie_ep_func *ep_func;
 
-       if (!ep->msix_cap)
+       ep_func = dw_pcie_ep_get_func_from_ep(ep, func_no);
+       if (!ep_func || !ep_func->msix_cap)
                return -EINVAL;
 
        dw_pcie_dbi_ro_wr_en(pci);
 
-       reg = ep->msix_cap + PCI_MSIX_FLAGS;
+       func_offset = dw_pcie_ep_func_select(ep, func_no);
+
+       reg = ep_func->msix_cap + func_offset + PCI_MSIX_FLAGS;
        val = dw_pcie_readw_dbi(pci, reg);
        val &= ~PCI_MSIX_FLAGS_QSIZE;
        val |= interrupts;
        dw_pcie_writew_dbi(pci, reg, val);
 
-       reg = ep->msix_cap + PCI_MSIX_TABLE;
+       reg = ep_func->msix_cap + func_offset + PCI_MSIX_TABLE;
        val = offset | bir;
        dw_pcie_writel_dbi(pci, reg, val);
 
-       reg = ep->msix_cap + PCI_MSIX_PBA;
+       reg = ep_func->msix_cap + func_offset + PCI_MSIX_PBA;
        val = (offset + (interrupts * PCI_MSIX_ENTRY_SIZE)) | bir;
        dw_pcie_writel_dbi(pci, reg, val);
 
@@ -385,31 +490,36 @@ int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 func_no,
                             u8 interrupt_num)
 {
        struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+       struct dw_pcie_ep_func *ep_func;
        struct pci_epc *epc = ep->epc;
        unsigned int aligned_offset;
+       unsigned int func_offset = 0;
        u16 msg_ctrl, msg_data;
        u32 msg_addr_lower, msg_addr_upper, reg;
        u64 msg_addr;
        bool has_upper;
        int ret;
 
-       if (!ep->msi_cap)
+       ep_func = dw_pcie_ep_get_func_from_ep(ep, func_no);
+       if (!ep_func || !ep_func->msi_cap)
                return -EINVAL;
 
+       func_offset = dw_pcie_ep_func_select(ep, func_no);
+
        /* Raise MSI per the PCI Local Bus Specification Revision 3.0, 6.8.1. */
-       reg = ep->msi_cap + PCI_MSI_FLAGS;
+       reg = ep_func->msi_cap + func_offset + PCI_MSI_FLAGS;
        msg_ctrl = dw_pcie_readw_dbi(pci, reg);
        has_upper = !!(msg_ctrl & PCI_MSI_FLAGS_64BIT);
-       reg = ep->msi_cap + PCI_MSI_ADDRESS_LO;
+       reg = ep_func->msi_cap + func_offset + PCI_MSI_ADDRESS_LO;
        msg_addr_lower = dw_pcie_readl_dbi(pci, reg);
        if (has_upper) {
-               reg = ep->msi_cap + PCI_MSI_ADDRESS_HI;
+               reg = ep_func->msi_cap + func_offset + PCI_MSI_ADDRESS_HI;
                msg_addr_upper = dw_pcie_readl_dbi(pci, reg);
-               reg = ep->msi_cap + PCI_MSI_DATA_64;
+               reg = ep_func->msi_cap + func_offset + PCI_MSI_DATA_64;
                msg_data = dw_pcie_readw_dbi(pci, reg);
        } else {
                msg_addr_upper = 0;
-               reg = ep->msi_cap + PCI_MSI_DATA_32;
+               reg = ep_func->msi_cap + func_offset + PCI_MSI_DATA_32;
                msg_data = dw_pcie_readw_dbi(pci, reg);
        }
        aligned_offset = msg_addr_lower & (epc->mem->window.page_size - 1);
@@ -427,12 +537,33 @@ int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 func_no,
        return 0;
 }
 
+int dw_pcie_ep_raise_msix_irq_doorbell(struct dw_pcie_ep *ep, u8 func_no,
+                                      u16 interrupt_num)
+{
+       struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+       struct dw_pcie_ep_func *ep_func;
+       u32 msg_data;
+
+       ep_func = dw_pcie_ep_get_func_from_ep(ep, func_no);
+       if (!ep_func || !ep_func->msix_cap)
+               return -EINVAL;
+
+       msg_data = (func_no << PCIE_MSIX_DOORBELL_PF_SHIFT) |
+                  (interrupt_num - 1);
+
+       dw_pcie_writel_dbi(pci, PCIE_MSIX_DOORBELL, msg_data);
+
+       return 0;
+}
+
 int dw_pcie_ep_raise_msix_irq(struct dw_pcie_ep *ep, u8 func_no,
-                            u16 interrupt_num)
+                             u16 interrupt_num)
 {
        struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+       struct dw_pcie_ep_func *ep_func;
        struct pci_epf_msix_tbl *msix_tbl;
        struct pci_epc *epc = ep->epc;
+       unsigned int func_offset = 0;
        u32 reg, msg_data, vec_ctrl;
        unsigned int aligned_offset;
        u32 tbl_offset;
@@ -440,7 +571,13 @@ int dw_pcie_ep_raise_msix_irq(struct dw_pcie_ep *ep, u8 func_no,
        int ret;
        u8 bir;
 
-       reg = ep->msix_cap + PCI_MSIX_TABLE;
+       ep_func = dw_pcie_ep_get_func_from_ep(ep, func_no);
+       if (!ep_func || !ep_func->msix_cap)
+               return -EINVAL;
+
+       func_offset = dw_pcie_ep_func_select(ep, func_no);
+
+       reg = ep_func->msix_cap + func_offset + PCI_MSIX_TABLE;
        tbl_offset = dw_pcie_readl_dbi(pci, reg);
        bir = (tbl_offset & PCI_MSIX_TABLE_BIR);
        tbl_offset &= PCI_MSIX_TABLE_OFFSET;
@@ -505,7 +642,8 @@ int dw_pcie_ep_init_complete(struct dw_pcie_ep *ep)
        u32 reg;
        int i;
 
-       hdr_type = dw_pcie_readb_dbi(pci, PCI_HEADER_TYPE);
+       hdr_type = dw_pcie_readb_dbi(pci, PCI_HEADER_TYPE) &
+                  PCI_HEADER_TYPE_MASK;
        if (hdr_type != PCI_HEADER_TYPE_NORMAL) {
                dev_err(pci->dev,
                        "PCIe controller is not set to EP mode (hdr_type:0x%x)!\n",
@@ -513,23 +651,21 @@ int dw_pcie_ep_init_complete(struct dw_pcie_ep *ep)
                return -EIO;
        }
 
-       ep->msi_cap = dw_pcie_find_capability(pci, PCI_CAP_ID_MSI);
+       offset = dw_pcie_ep_find_ext_capability(pci, PCI_EXT_CAP_ID_REBAR);
 
-       ep->msix_cap = dw_pcie_find_capability(pci, PCI_CAP_ID_MSIX);
+       dw_pcie_dbi_ro_wr_en(pci);
 
-       offset = dw_pcie_ep_find_ext_capability(pci, PCI_EXT_CAP_ID_REBAR);
        if (offset) {
                reg = dw_pcie_readl_dbi(pci, offset + PCI_REBAR_CTRL);
                nbars = (reg & PCI_REBAR_CTRL_NBAR_MASK) >>
                        PCI_REBAR_CTRL_NBAR_SHIFT;
 
-               dw_pcie_dbi_ro_wr_en(pci);
                for (i = 0; i < nbars; i++, offset += PCI_REBAR_CTRL)
                        dw_pcie_writel_dbi(pci, offset + PCI_REBAR_CAP, 0x0);
-               dw_pcie_dbi_ro_wr_dis(pci);
        }
 
        dw_pcie_setup(pci);
+       dw_pcie_dbi_ro_wr_dis(pci);
 
        return 0;
 }
@@ -539,11 +675,15 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)
 {
        int ret;
        void *addr;
+       u8 func_no;
        struct pci_epc *epc;
        struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
        struct device *dev = pci->dev;
        struct device_node *np = dev->of_node;
        const struct pci_epc_features *epc_features;
+       struct dw_pcie_ep_func *ep_func;
+
+       INIT_LIST_HEAD(&ep->func_list);
 
        if (!pci->dbi_base || !pci->dbi_base2) {
                dev_err(dev, "dbi_base/dbi_base2 is not populated\n");
@@ -590,6 +730,9 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)
                return -ENOMEM;
        ep->outbound_addr = addr;
 
+       if (pci->link_gen < 1)
+               pci->link_gen = of_pci_get_max_link_speed(np);
+
        epc = devm_pci_epc_create(dev, &epc_ops);
        if (IS_ERR(epc)) {
                dev_err(dev, "Failed to create epc device\n");
@@ -599,13 +742,27 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)
        ep->epc = epc;
        epc_set_drvdata(epc, ep);
 
-       if (ep->ops->ep_init)
-               ep->ops->ep_init(ep);
-
        ret = of_property_read_u8(np, "max-functions", &epc->max_functions);
        if (ret < 0)
                epc->max_functions = 1;
 
+       for (func_no = 0; func_no < epc->max_functions; func_no++) {
+               ep_func = devm_kzalloc(dev, sizeof(*ep_func), GFP_KERNEL);
+               if (!ep_func)
+                       return -ENOMEM;
+
+               ep_func->func_no = func_no;
+               ep_func->msi_cap = dw_pcie_ep_find_capability(ep, func_no,
+                                                             PCI_CAP_ID_MSI);
+               ep_func->msix_cap = dw_pcie_ep_find_capability(ep, func_no,
+                                                              PCI_CAP_ID_MSIX);
+
+               list_add_tail(&ep_func->list, &ep->func_list);
+       }
+
+       if (ep->ops->ep_init)
+               ep->ops->ep_init(ep);
+
        ret = pci_epc_mem_init(epc, ep->phys_base, ep->addr_size,
                               ep->page_size);
        if (ret < 0) {