diff options
Diffstat (limited to 'drivers/pci/controller')
| -rw-r--r-- | drivers/pci/controller/dwc/pcie-designware-ep.c | 15 |
1 files changed, 12 insertions, 3 deletions
diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c index 7e7844ff0f7e..295076cf70de 100644 --- a/drivers/pci/controller/dwc/pcie-designware-ep.c +++ b/drivers/pci/controller/dwc/pcie-designware-ep.c @@ -165,6 +165,7 @@ static void dw_pcie_ep_clear_ib_maps(struct dw_pcie_ep *ep, u8 func_no, enum pci dw_pcie_disable_atu(pci, PCIE_ATU_REGION_DIR_IB, atu_index); clear_bit(atu_index, ep->ib_window_map); ep_func->bar_to_atu[bar] = 0; + return; } /* Tear down all Address Match Mode mappings, if any. */ @@ -518,6 +519,12 @@ static int dw_pcie_ep_set_bar(struct pci_epc *epc, u8 func_no, u8 vfunc_no, /* * We can only dynamically change a BAR if the new BAR size and * BAR flags do not differ from the existing configuration. + * + * Note: this safety check only works when the caller uses + * a new struct pci_epf_bar in the second set_bar() call. + * If the same instance is updated in place and passed in, + * we cannot reliably detect invalid barno/size/flags + * changes here. */ if (ep_func->epf_bar[bar]->barno != bar || ep_func->epf_bar[bar]->size != size || @@ -526,10 +533,12 @@ static int dw_pcie_ep_set_bar(struct pci_epc *epc, u8 func_no, u8 vfunc_no, /* * When dynamically changing a BAR, tear down any existing - * mappings before re-programming. + * mappings before re-programming. This is redundant when + * both the old and new mappings are BAR Match Mode, but + * required to handle in-place updates and match-mode + * changes reliably. */ - if (ep_func->epf_bar[bar]->num_submap || epf_bar->num_submap) - dw_pcie_ep_clear_ib_maps(ep, func_no, bar); + dw_pcie_ep_clear_ib_maps(ep, func_no, bar); /* * When dynamically changing a BAR, skip writing the BAR reg, as |
