Skip to content

Commit 473b2cf

Browse files
Mani-Sadhasivamkwilczynski
authored andcommitted
PCI: endpoint: Introduce 'epc_deinit' event and notify the EPF drivers
As like the 'epc_init' event, that is used to signal the EPF drivers about the EPC initialization, let's introduce 'epc_deinit' event that is used to signal EPC deinitialization. The EPC deinitialization applies only when any sort of fundamental reset is supported by the endpoint controller as per the PCIe spec. Reference: PCIe r6.0, sec 4.2.5.9.1 and 6.6.1. Currently, some EPC drivers like pcie-qcom-ep and pcie-tegra194 support PERST# as the fundamental reset. So the 'deinit' event will be notified to the EPF drivers when PERST# assert happens in the above mentioned EPC drivers. The EPF drivers, on receiving the event through the epc_deinit() callback should reset the EPF state machine and also cleanup any configuration that got affected by the fundamental reset like BAR, DMA etc... This change also warrants skipping the cleanups in unbind() if already done in epc_deinit(). Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Manivannan Sadhasivam <[email protected]> Signed-off-by: Krzysztof Wilczyński <[email protected]> Reviewed-by: Niklas Cassel <[email protected]> Reviewed-by: Siddharth Vadapalli <[email protected]> Reviewed-by: Frank Li <[email protected]>
1 parent cfc2d4c commit 473b2cf

File tree

8 files changed

+76
-3
lines changed

8 files changed

+76
-3
lines changed

drivers/pci/controller/dwc/pcie-designware-ep.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -632,7 +632,6 @@ void dw_pcie_ep_cleanup(struct dw_pcie_ep *ep)
632632
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
633633

634634
dw_pcie_edma_remove(pci);
635-
ep->epc->init_complete = false;
636635
}
637636
EXPORT_SYMBOL_GPL(dw_pcie_ep_cleanup);
638637

drivers/pci/controller/dwc/pcie-qcom-ep.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,7 @@ static void qcom_pcie_perst_assert(struct dw_pcie *pci)
507507
return;
508508
}
509509

510+
pci_epc_deinit_notify(pci->ep.epc);
510511
dw_pcie_ep_cleanup(&pci->ep);
511512
qcom_pcie_disable_resources(pcie_ep);
512513
pcie_ep->link_status = QCOM_PCIE_EP_LINK_DISABLED;

drivers/pci/controller/dwc/pcie-tegra194.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1715,6 +1715,7 @@ static void pex_ep_event_pex_rst_assert(struct tegra_pcie_dw *pcie)
17151715
if (ret)
17161716
dev_err(pcie->dev, "Failed to go Detect state: %d\n", ret);
17171717

1718+
pci_epc_deinit_notify(pcie->pci.ep.epc);
17181719
dw_pcie_ep_cleanup(&pcie->pci.ep);
17191720

17201721
reset_control_assert(pcie->core_rst);

drivers/pci/endpoint/functions/pci-epf-mhi.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -764,6 +764,24 @@ static int pci_epf_mhi_epc_init(struct pci_epf *epf)
764764
return 0;
765765
}
766766

767+
static void pci_epf_mhi_epc_deinit(struct pci_epf *epf)
768+
{
769+
struct pci_epf_mhi *epf_mhi = epf_get_drvdata(epf);
770+
const struct pci_epf_mhi_ep_info *info = epf_mhi->info;
771+
struct pci_epf_bar *epf_bar = &epf->bar[info->bar_num];
772+
struct mhi_ep_cntrl *mhi_cntrl = &epf_mhi->mhi_cntrl;
773+
struct pci_epc *epc = epf->epc;
774+
775+
if (mhi_cntrl->mhi_dev) {
776+
mhi_ep_power_down(mhi_cntrl);
777+
if (info->flags & MHI_EPF_USE_DMA)
778+
pci_epf_mhi_dma_deinit(epf_mhi);
779+
mhi_ep_unregister_controller(mhi_cntrl);
780+
}
781+
782+
pci_epc_clear_bar(epc, epf->func_no, epf->vfunc_no, epf_bar);
783+
}
784+
767785
static int pci_epf_mhi_link_up(struct pci_epf *epf)
768786
{
769787
struct pci_epf_mhi *epf_mhi = epf_get_drvdata(epf);
@@ -898,6 +916,7 @@ static void pci_epf_mhi_unbind(struct pci_epf *epf)
898916

899917
static const struct pci_epc_event_ops pci_epf_mhi_event_ops = {
900918
.epc_init = pci_epf_mhi_epc_init,
919+
.epc_deinit = pci_epf_mhi_epc_deinit,
901920
.link_up = pci_epf_mhi_link_up,
902921
.link_down = pci_epf_mhi_link_down,
903922
.bus_master_enable = pci_epf_mhi_bus_master_enable,

drivers/pci/endpoint/functions/pci-epf-test.c

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -782,6 +782,15 @@ static int pci_epf_test_epc_init(struct pci_epf *epf)
782782
return 0;
783783
}
784784

785+
static void pci_epf_test_epc_deinit(struct pci_epf *epf)
786+
{
787+
struct pci_epf_test *epf_test = epf_get_drvdata(epf);
788+
789+
cancel_delayed_work(&epf_test->cmd_handler);
790+
pci_epf_test_clean_dma_chan(epf_test);
791+
pci_epf_test_clear_bar(epf);
792+
}
793+
785794
static int pci_epf_test_link_up(struct pci_epf *epf)
786795
{
787796
struct pci_epf_test *epf_test = epf_get_drvdata(epf);
@@ -803,6 +812,7 @@ static int pci_epf_test_link_down(struct pci_epf *epf)
803812

804813
static const struct pci_epc_event_ops pci_epf_test_event_ops = {
805814
.epc_init = pci_epf_test_epc_init,
815+
.epc_deinit = pci_epf_test_epc_deinit,
806816
.link_up = pci_epf_test_link_up,
807817
.link_down = pci_epf_test_link_down,
808818
};
@@ -905,10 +915,13 @@ static int pci_epf_test_bind(struct pci_epf *epf)
905915
static void pci_epf_test_unbind(struct pci_epf *epf)
906916
{
907917
struct pci_epf_test *epf_test = epf_get_drvdata(epf);
918+
struct pci_epc *epc = epf->epc;
908919

909920
cancel_delayed_work(&epf_test->cmd_handler);
910-
pci_epf_test_clean_dma_chan(epf_test);
911-
pci_epf_test_clear_bar(epf);
921+
if (epc->init_complete) {
922+
pci_epf_test_clean_dma_chan(epf_test);
923+
pci_epf_test_clear_bar(epf);
924+
}
912925
pci_epf_test_free_space(epf);
913926
}
914927

drivers/pci/endpoint/pci-epc-core.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -774,6 +774,31 @@ void pci_epc_notify_pending_init(struct pci_epc *epc, struct pci_epf *epf)
774774
}
775775
EXPORT_SYMBOL_GPL(pci_epc_notify_pending_init);
776776

777+
/**
778+
* pci_epc_deinit_notify() - Notify the EPF device about EPC deinitialization
779+
* @epc: the EPC device whose deinitialization is completed
780+
*
781+
* Invoke to notify the EPF device that the EPC deinitialization is completed.
782+
*/
783+
void pci_epc_deinit_notify(struct pci_epc *epc)
784+
{
785+
struct pci_epf *epf;
786+
787+
if (IS_ERR_OR_NULL(epc))
788+
return;
789+
790+
mutex_lock(&epc->list_lock);
791+
list_for_each_entry(epf, &epc->pci_epf, list) {
792+
mutex_lock(&epf->lock);
793+
if (epf->event_ops && epf->event_ops->epc_deinit)
794+
epf->event_ops->epc_deinit(epf);
795+
mutex_unlock(&epf->lock);
796+
}
797+
epc->init_complete = false;
798+
mutex_unlock(&epc->list_lock);
799+
}
800+
EXPORT_SYMBOL_GPL(pci_epc_deinit_notify);
801+
777802
/**
778803
* pci_epc_bus_master_enable_notify() - Notify the EPF device that the EPC
779804
* device has received the Bus Master

include/linux/pci-epc.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,8 @@ struct pci_epc_features {
197197

198198
#define to_pci_epc(device) container_of((device), struct pci_epc, dev)
199199

200+
#ifdef CONFIG_PCI_ENDPOINT
201+
200202
#define pci_epc_create(dev, ops) \
201203
__pci_epc_create((dev), (ops), THIS_MODULE)
202204
#define devm_pci_epc_create(dev, ops) \
@@ -226,6 +228,7 @@ void pci_epc_linkup(struct pci_epc *epc);
226228
void pci_epc_linkdown(struct pci_epc *epc);
227229
void pci_epc_init_notify(struct pci_epc *epc);
228230
void pci_epc_notify_pending_init(struct pci_epc *epc, struct pci_epf *epf);
231+
void pci_epc_deinit_notify(struct pci_epc *epc);
229232
void pci_epc_bus_master_enable_notify(struct pci_epc *epc);
230233
void pci_epc_remove_epf(struct pci_epc *epc, struct pci_epf *epf,
231234
enum pci_epc_interface_type type);
@@ -272,4 +275,14 @@ void __iomem *pci_epc_mem_alloc_addr(struct pci_epc *epc,
272275
phys_addr_t *phys_addr, size_t size);
273276
void pci_epc_mem_free_addr(struct pci_epc *epc, phys_addr_t phys_addr,
274277
void __iomem *virt_addr, size_t size);
278+
279+
#else
280+
static inline void pci_epc_init_notify(struct pci_epc *epc)
281+
{
282+
}
283+
284+
static inline void pci_epc_deinit_notify(struct pci_epc *epc)
285+
{
286+
}
287+
#endif /* CONFIG_PCI_ENDPOINT */
275288
#endif /* __LINUX_PCI_EPC_H */

include/linux/pci-epf.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,12 +71,14 @@ struct pci_epf_ops {
7171
/**
7272
* struct pci_epc_event_ops - Callbacks for capturing the EPC events
7373
* @epc_init: Callback for the EPC initialization complete event
74+
* @epc_deinit: Callback for the EPC deinitialization event
7475
* @link_up: Callback for the EPC link up event
7576
* @link_down: Callback for the EPC link down event
7677
* @bus_master_enable: Callback for the EPC Bus Master Enable event
7778
*/
7879
struct pci_epc_event_ops {
7980
int (*epc_init)(struct pci_epf *epf);
81+
void (*epc_deinit)(struct pci_epf *epf);
8082
int (*link_up)(struct pci_epf *epf);
8183
int (*link_down)(struct pci_epf *epf);
8284
int (*bus_master_enable)(struct pci_epf *epf);

0 commit comments

Comments
 (0)