int ret;
u32 free_win;
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+ struct dw_pcie_ep_func *ep_func = dw_pcie_ep_get_func_from_ep(ep, func_no);
- if (!ep->bar_to_atu[bar])
+ if (!ep_func)
+ return -EINVAL;
+
+ if (!ep_func->bar_to_atu[bar])
free_win = find_first_zero_bit(ep->ib_window_map, pci->num_ib_windows);
else
- free_win = ep->bar_to_atu[bar] - 1;
+ free_win = ep_func->bar_to_atu[bar] - 1;
if (free_win >= pci->num_ib_windows) {
dev_err(pci->dev, "No free inbound window\n");
* Always increment free_win before assignment, since value 0 is used to identify
* unallocated mapping.
*/
- ep->bar_to_atu[bar] = free_win + 1;
+ ep_func->bar_to_atu[bar] = free_win + 1;
set_bit(free_win, ep->ib_window_map);
return 0;
}
-static void dw_pcie_ep_clear_ib_maps(struct dw_pcie_ep *ep, enum pci_barno bar)
+static void dw_pcie_ep_clear_ib_maps(struct dw_pcie_ep *ep, u8 func_no, enum pci_barno bar)
{
+ struct dw_pcie_ep_func *ep_func = dw_pcie_ep_get_func_from_ep(ep, func_no);
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
struct device *dev = pci->dev;
unsigned int i, num;
u32 atu_index;
u32 *indexes;
+ if (!ep_func)
+ return;
+
/* Tear down the BAR Match Mode mapping, if any. */
- if (ep->bar_to_atu[bar]) {
- atu_index = ep->bar_to_atu[bar] - 1;
+ if (ep_func->bar_to_atu[bar]) {
+ atu_index = ep_func->bar_to_atu[bar] - 1;
dw_pcie_disable_atu(pci, PCIE_ATU_REGION_DIR_IB, atu_index);
clear_bit(atu_index, ep->ib_window_map);
- ep->bar_to_atu[bar] = 0;
+ ep_func->bar_to_atu[bar] = 0;
}
/* Tear down all Address Match Mode mappings, if any. */
- indexes = ep->ib_atu_indexes[bar];
- num = ep->num_ib_atu_indexes[bar];
- ep->ib_atu_indexes[bar] = NULL;
- ep->num_ib_atu_indexes[bar] = 0;
+ indexes = ep_func->ib_atu_indexes[bar];
+ num = ep_func->num_ib_atu_indexes[bar];
+ ep_func->ib_atu_indexes[bar] = NULL;
+ ep_func->num_ib_atu_indexes[bar] = 0;
if (!indexes)
return;
for (i = 0; i < num; i++) {
static int dw_pcie_ep_ib_atu_addr(struct dw_pcie_ep *ep, u8 func_no, int type,
const struct pci_epf_bar *epf_bar)
{
+ struct dw_pcie_ep_func *ep_func = dw_pcie_ep_get_func_from_ep(ep, func_no);
const struct pci_epf_bar_submap *submap = epf_bar->submap;
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
enum pci_barno bar = epf_bar->barno;
unsigned int i;
u32 *indexes;
- if (!epf_bar->num_submap || !submap || !epf_bar->size)
+ if (!ep_func || !epf_bar->num_submap || !submap || !epf_bar->size)
return -EINVAL;
ret = dw_pcie_ep_validate_submap(ep, submap, epf_bar->num_submap,
if (!indexes)
return -ENOMEM;
- ep->ib_atu_indexes[bar] = indexes;
- ep->num_ib_atu_indexes[bar] = 0;
+ ep_func->ib_atu_indexes[bar] = indexes;
+ ep_func->num_ib_atu_indexes[bar] = 0;
for (i = 0; i < epf_bar->num_submap; i++) {
size = submap[i].size;
set_bit(free_win, ep->ib_window_map);
indexes[i] = free_win;
- ep->num_ib_atu_indexes[bar] = i + 1;
+ ep_func->num_ib_atu_indexes[bar] = i + 1;
}
return 0;
err:
- dw_pcie_ep_clear_ib_maps(ep, bar);
+ dw_pcie_ep_clear_ib_maps(ep, func_no, bar);
return ret;
}
struct dw_pcie_ep *ep = epc_get_drvdata(epc);
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
enum pci_barno bar = epf_bar->barno;
+ struct dw_pcie_ep_func *ep_func = dw_pcie_ep_get_func_from_ep(ep, func_no);
- if (!ep->epf_bar[bar])
+ if (!ep_func || !ep_func->epf_bar[bar])
return;
__dw_pcie_ep_reset_bar(pci, func_no, bar, epf_bar->flags);
- dw_pcie_ep_clear_ib_maps(ep, bar);
+ dw_pcie_ep_clear_ib_maps(ep, func_no, bar);
- ep->epf_bar[bar] = NULL;
+ ep_func->epf_bar[bar] = NULL;
}
static unsigned int dw_pcie_ep_get_rebar_offset(struct dw_pcie_ep *ep, u8 func_no,
{
struct dw_pcie_ep *ep = epc_get_drvdata(epc);
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+ struct dw_pcie_ep_func *ep_func = dw_pcie_ep_get_func_from_ep(ep, func_no);
enum pci_barno bar = epf_bar->barno;
size_t size = epf_bar->size;
enum pci_epc_bar_type bar_type;
int flags = epf_bar->flags;
int ret, type;
+ if (!ep_func)
+ return -EINVAL;
+
/*
* DWC does not allow BAR pairs to overlap, e.g. you cannot combine BARs
* 1 and 2 to form a 64-bit BAR.
* calling clear_bar() would clear the BAR's PCI address assigned by the
* host).
*/
- if (ep->epf_bar[bar]) {
+ if (ep_func->epf_bar[bar]) {
/*
* We can only dynamically change a BAR if the new BAR size and
* BAR flags do not differ from the existing configuration.
*/
- if (ep->epf_bar[bar]->barno != bar ||
- ep->epf_bar[bar]->size != size ||
- ep->epf_bar[bar]->flags != flags)
+ if (ep_func->epf_bar[bar]->barno != bar ||
+ ep_func->epf_bar[bar]->size != size ||
+ ep_func->epf_bar[bar]->flags != flags)
return -EINVAL;
/*
* When dynamically changing a BAR, tear down any existing
* mappings before re-programming.
*/
- if (ep->epf_bar[bar]->num_submap || epf_bar->num_submap)
- dw_pcie_ep_clear_ib_maps(ep, bar);
+ if (ep_func->epf_bar[bar]->num_submap || epf_bar->num_submap)
+ dw_pcie_ep_clear_ib_maps(ep, func_no, bar);
/*
* When dynamically changing a BAR, skip writing the BAR reg, as
if (ret)
return ret;
- ep->epf_bar[bar] = epf_bar;
+ ep_func->epf_bar[bar] = epf_bar;
return 0;
}
bir = FIELD_GET(PCI_MSIX_TABLE_BIR, tbl_offset);
tbl_offset &= PCI_MSIX_TABLE_OFFSET;
- msix_tbl = ep->epf_bar[bir]->addr + tbl_offset;
+ msix_tbl = ep_func->epf_bar[bir]->addr + tbl_offset;
msg_addr = msix_tbl[(interrupt_num - 1)].msg_addr;
msg_data = msix_tbl[(interrupt_num - 1)].msg_data;
vec_ctrl = msix_tbl[(interrupt_num - 1)].vector_ctrl;
static void dw_pcie_ep_init_rebar_registers(struct dw_pcie_ep *ep, u8 func_no)
{
- unsigned int offset;
- unsigned int nbars;
+ struct dw_pcie_ep_func *ep_func = dw_pcie_ep_get_func_from_ep(ep, func_no);
+ unsigned int offset, nbars;
enum pci_barno bar;
u32 reg, i, val;
+ if (!ep_func)
+ return;
+
offset = dw_pcie_ep_find_ext_capability(ep, func_no, PCI_EXT_CAP_ID_REBAR);
if (offset) {
*/
val = dw_pcie_ep_readl_dbi(ep, func_no, offset + PCI_REBAR_CTRL);
bar = FIELD_GET(PCI_REBAR_CTRL_BAR_IDX, val);
- if (ep->epf_bar[bar])
- pci_epc_bar_size_to_rebar_cap(ep->epf_bar[bar]->size, &val);
+ if (ep_func->epf_bar[bar])
+ pci_epc_bar_size_to_rebar_cap(ep_func->epf_bar[bar]->size, &val);
else
val = BIT(4);