diff options
| author | Marek Vasut <marek.vasut+renesas@mailbox.org> | 2026-08-21 14:27:49 +0200 |
|---|---|---|
| committer | Bjorn Helgaas <bhelgaas@google.com> | 2026-09-03 15:25:34 -0500 |
| commit | 355039f010cee6d90bc76bc1bccf2afe12d8d461 (patch) | |
| tree | 9e28b08a9299624e7258c1cdfde82e5a747a077f | |
| parent | f0a5c6bd797c2b9900034983a1118d27eb2f2f16 (diff) | |
| download | linux-next-355039f010cee6d90bc76bc1bccf2afe12d8d461.tar.gz linux-next-355039f010cee6d90bc76bc1bccf2afe12d8d461.zip | |
PCI: dwc: Add dw_pcie_ep_ops->post_deinit() callback
If .pre_init() succeeds but subsequent initialization fails, it is
mandatory to correctly undo the hardware configuration which the
.pre_init() callback did. Introduce a .post_deinit() callback to do exactly
that, undo what the .pre_init() callback did. Usually, that means stop the
clock, assert reset, and possibly program some registers to quiesce the
hardware. Invoke the .post_deinit() callback in dw_pcie_ep_deinit() to
retain functional symmetry.
Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Tested-by: Koichiro Den <den@valinux.co.jp>
Reviewed-by: Koichiro Den <den@valinux.co.jp>
Link: https://patch.msgid.link/20260821122808.238248-1-marek.vasut+renesas@mailbox.org
| -rw-r--r-- | drivers/pci/controller/dwc/pcie-designware-ep.c | 8 | ||||
| -rw-r--r-- | drivers/pci/controller/dwc/pcie-designware.h | 1 |
2 files changed, 8 insertions, 1 deletions
diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c index de8ee3db4360..1a3491b5003e 100644 --- a/drivers/pci/controller/dwc/pcie-designware-ep.c +++ b/drivers/pci/controller/dwc/pcie-designware-ep.c @@ -1194,6 +1194,9 @@ void dw_pcie_ep_deinit(struct dw_pcie_ep *ep) epc->mem->window.page_size); pci_epc_mem_exit(epc); + + if (ep->ops->post_deinit) + ep->ops->post_deinit(ep); } EXPORT_SYMBOL_GPL(dw_pcie_ep_deinit); @@ -1553,7 +1556,7 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep) ep->page_size); if (ret < 0) { dev_err(dev, "Failed to initialize address space\n"); - return ret; + goto err_deinit; } ep->msi_mem = pci_epc_mem_alloc_addr(epc, &ep->msi_mem_phys, @@ -1568,6 +1571,9 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep) err_exit_epc_mem: pci_epc_mem_exit(epc); +err_deinit: + if (ep->ops->post_deinit) + ep->ops->post_deinit(ep); return ret; } diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h index 0735ae940924..a53ac27cd244 100644 --- a/drivers/pci/controller/dwc/pcie-designware.h +++ b/drivers/pci/controller/dwc/pcie-designware.h @@ -475,6 +475,7 @@ struct dw_pcie_rp { struct dw_pcie_ep_ops { int (*pre_init)(struct dw_pcie_ep *ep); + void (*post_deinit)(struct dw_pcie_ep *ep); int (*init)(struct dw_pcie_ep *ep); int (*raise_irq)(struct dw_pcie_ep *ep, u8 func_no, unsigned int type, u16 interrupt_num); |
