Hi Kunihiko, On 01/09/21 10:46 am, Kunihiko Hayashi wrote: > The driver using core_init_notifier, e.g. pcie-tegra194.c, runs according > to the following sequence: > > probe() > dw_pcie_ep_init() > > bind() > dw_pcie_ep_start() > enable_irq() > > (interrupt occurred) > handler() > [enable controller] > dw_pcie_ep_init_complete() > dw_pcie_ep_init_notify() > > After receiving an interrupt from RC, the handler enables the controller > and the controller registers can be accessed. > So accessing the registers should do in dw_pcie_ep_init_complete(). > > Currently dw_pcie_ep_init() has functions dw_iatu_detect() and > dw_pcie_ep_find_capability() that include accesses to DWC registers. > As a result, accessing the registers before enabling the controller, > the access will fail. > > The function dw_pcie_ep_init() shouldn't have any access to DWC registers > if the controller is enabled after calling bind(). This moves access codes > to DBI/iATU registers and depending variables from dw_pcie_ep_init() to > dw_pcie_ep_init_complete(). Ideally pci_epc_create() should be the last step by the controller driver before handing the control to the core EPC framework. Since after this step the EPC framework can start invoking the epc_ops. Here more stuff is being added to dw_pcie_ep_init_complete() which is required for epc_ops and this could result in aborts for platforms which does not add core_init_notifier. Thanks, Kishon > > Cc: Xiaowei Bao <xiaowei.bao@xxxxxxx> > Cc: Vidya Sagar <vidyas@xxxxxxxxxx> > Fixes: 6bfc9c3a2c70 ("PCI: designware-ep: Move the function of getting MSI capability forward") > Signed-off-by: Kunihiko Hayashi <hayashi.kunihiko@xxxxxxxxxxxxx> > Acked-by: Om Prakash Singh <omp@xxxxxxxxxx> > Reviewed-by: Vidya Sagar <vidyas@xxxxxxxxxx> > --- > drivers/pci/controller/dwc/pcie-designware-ep.c | 81 +++++++++++++------------ > 1 file changed, 41 insertions(+), 40 deletions(-) > > diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c > index 998b698..00ce83c 100644 > --- a/drivers/pci/controller/dwc/pcie-designware-ep.c > +++ b/drivers/pci/controller/dwc/pcie-designware-ep.c > @@ -636,16 +636,56 @@ static unsigned int dw_pcie_ep_find_ext_capability(struct dw_pcie *pci, int cap) > int dw_pcie_ep_init_complete(struct dw_pcie_ep *ep) > { > struct dw_pcie *pci = to_dw_pcie_from_ep(ep); > + struct dw_pcie_ep_func *ep_func; > + struct device *dev = pci->dev; > unsigned int offset; > unsigned int nbars; > u8 hdr_type; > + u8 func_no; > + void *addr; > u32 reg; > int i; > > + dw_pcie_iatu_detect(pci); > + > + ep->ib_window_map = devm_kcalloc(dev, > + BITS_TO_LONGS(pci->num_ib_windows), > + sizeof(long), > + 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); > + if (!ep->ob_window_map) > + return -ENOMEM; > + > + addr = devm_kcalloc(dev, pci->num_ob_windows, sizeof(phys_addr_t), > + GFP_KERNEL); > + if (!addr) > + return -ENOMEM; > + ep->outbound_addr = addr; > + > + for (func_no = 0; func_no < ep->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); > + } > + > 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, > + dev_err(dev, > "PCIe controller is not set to EP mode (hdr_type:0x%x)!\n", > hdr_type); > return -EIO; > @@ -674,8 +714,6 @@ EXPORT_SYMBOL_GPL(dw_pcie_ep_init_complete); > int dw_pcie_ep_init(struct dw_pcie_ep *ep) > { > int ret; > - void *addr; > - u8 func_no; > struct resource *res; > struct pci_epc *epc; > struct dw_pcie *pci = to_dw_pcie_from_ep(ep); > @@ -683,7 +721,6 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep) > struct platform_device *pdev = to_platform_device(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); > > @@ -705,8 +742,6 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep) > } > } > > - dw_pcie_iatu_detect(pci); > - > res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "addr_space"); > if (!res) > return -EINVAL; > @@ -714,26 +749,6 @@ 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); > - 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); > - if (!ep->ob_window_map) > - return -ENOMEM; > - > - addr = devm_kcalloc(dev, pci->num_ob_windows, sizeof(phys_addr_t), > - GFP_KERNEL); > - if (!addr) > - return -ENOMEM; > - ep->outbound_addr = addr; > - > if (pci->link_gen < 1) > pci->link_gen = of_pci_get_max_link_speed(np); > > @@ -750,20 +765,6 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep) > 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); > >