summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarek Vasut <marek.vasut+renesas@mailbox.org>2026-08-21 14:27:49 +0200
committerBjorn Helgaas <bhelgaas@google.com>2026-09-03 15:25:34 -0500
commit355039f010cee6d90bc76bc1bccf2afe12d8d461 (patch)
tree9e28b08a9299624e7258c1cdfde82e5a747a077f
parentf0a5c6bd797c2b9900034983a1118d27eb2f2f16 (diff)
downloadlinux-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.c8
-rw-r--r--drivers/pci/controller/dwc/pcie-designware.h1
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);