[PATCH 2/4] PCI: dwc: Add CFG offset info into function's represented structure

From: Zhiqiang Hou
Date: Thu Jan 07 2021 - 04:04:16 EST


From: Hou Zhiqiang <Zhiqiang.Hou@xxxxxxx>

To avoid multiple calculating of the CFG offset for each function, store
the CFG offset info to the function's represented structure, and only do
one time calculation during the initialization.

Signed-off-by: Hou Zhiqiang <Zhiqiang.Hou@xxxxxxx>
---
.../pci/controller/dwc/pcie-designware-ep.c | 138 ++++++++----------
drivers/pci/controller/dwc/pcie-designware.h | 1 +
2 files changed, 59 insertions(+), 80 deletions(-)

diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c
index e583700b5ba3..bc6ad1f96a48 100644
--- a/drivers/pci/controller/dwc/pcie-designware-ep.c
+++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
@@ -42,24 +42,23 @@ dw_pcie_ep_get_func_from_ep(struct dw_pcie_ep *ep, u8 func_no)

static unsigned int dw_pcie_ep_func_select(struct dw_pcie_ep *ep, u8 func_no)
{
- unsigned int func_offset = 0;
-
if (ep->ops->func_conf_select)
- func_offset = ep->ops->func_conf_select(ep, func_no);
+ return ep->ops->func_conf_select(ep, func_no);

- return func_offset;
+ return 0;
}

static void __dw_pcie_ep_reset_bar(struct dw_pcie *pci, u8 func_no,
enum pci_barno bar, int flags)
{
u32 reg;
- unsigned int func_offset = 0;
struct dw_pcie_ep *ep = &pci->ep;
+ struct dw_pcie_ep_func *func = dw_pcie_ep_get_func_from_ep(ep, func_no);

- func_offset = dw_pcie_ep_func_select(ep, func_no);
+ if (!func)
+ return;

- reg = func_offset + PCI_BASE_ADDRESS_0 + (4 * bar);
+ reg = func->cfg_off + PCI_BASE_ADDRESS_0 + (4 * bar);
dw_pcie_dbi_ro_wr_en(pci);
dw_pcie_writel_dbi2(pci, reg, 0x0);
dw_pcie_writel_dbi(pci, reg, 0x0);
@@ -83,17 +82,15 @@ void dw_pcie_ep_reset_bar(struct dw_pcie *pci, enum pci_barno bar)
static u8 __dw_pcie_ep_find_next_cap(struct dw_pcie_ep *ep, u8 func_no,
u8 cap_ptr, u8 cap)
{
+ struct dw_pcie_ep_func *func = dw_pcie_ep_get_func_from_ep(ep, func_no);
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
- unsigned int func_offset = 0;
u8 cap_id, next_cap_ptr;
u16 reg;

- if (!cap_ptr)
+ if (!cap_ptr || !func)
return 0;

- func_offset = dw_pcie_ep_func_select(ep, func_no);
-
- reg = dw_pcie_readw_dbi(pci, func_offset + cap_ptr);
+ reg = dw_pcie_readw_dbi(pci, func->cfg_off + cap_ptr);
cap_id = (reg & 0x00ff);

if (cap_id > PCI_CAP_ID_MAX)
@@ -108,14 +105,15 @@ static u8 __dw_pcie_ep_find_next_cap(struct dw_pcie_ep *ep, u8 func_no,

static u8 dw_pcie_ep_find_capability(struct dw_pcie_ep *ep, u8 func_no, u8 cap)
{
+ struct dw_pcie_ep_func *func = dw_pcie_ep_get_func_from_ep(ep, func_no);
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
- unsigned int func_offset = 0;
u8 next_cap_ptr;
u16 reg;

- func_offset = dw_pcie_ep_func_select(ep, func_no);
+ if (!func)
+ return 0;

- reg = dw_pcie_readw_dbi(pci, func_offset + PCI_CAPABILITY_LIST);
+ reg = dw_pcie_readw_dbi(pci, func->cfg_off + PCI_CAPABILITY_LIST);
next_cap_ptr = (reg & 0x00ff);

return __dw_pcie_ep_find_next_cap(ep, func_no, next_cap_ptr, cap);
@@ -126,23 +124,26 @@ static int dw_pcie_ep_write_header(struct pci_epc *epc, u8 func_no,
{
struct dw_pcie_ep *ep = epc_get_drvdata(epc);
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
- unsigned int func_offset = 0;
+ struct dw_pcie_ep_func *func = dw_pcie_ep_get_func_from_ep(ep, func_no);
+ u32 cfg_off;

- func_offset = dw_pcie_ep_func_select(ep, func_no);
+ if (!func)
+ return -EINVAL;

+ cfg_off = func->cfg_off;
dw_pcie_dbi_ro_wr_en(pci);
- dw_pcie_writew_dbi(pci, func_offset + PCI_VENDOR_ID, hdr->vendorid);
- dw_pcie_writew_dbi(pci, func_offset + PCI_DEVICE_ID, hdr->deviceid);
- dw_pcie_writeb_dbi(pci, func_offset + PCI_REVISION_ID, hdr->revid);
- dw_pcie_writeb_dbi(pci, func_offset + PCI_CLASS_PROG, hdr->progif_code);
- dw_pcie_writew_dbi(pci, func_offset + PCI_CLASS_DEVICE,
+ dw_pcie_writew_dbi(pci, cfg_off + PCI_VENDOR_ID, hdr->vendorid);
+ dw_pcie_writew_dbi(pci, cfg_off + PCI_DEVICE_ID, hdr->deviceid);
+ dw_pcie_writeb_dbi(pci, cfg_off + PCI_REVISION_ID, hdr->revid);
+ dw_pcie_writeb_dbi(pci, cfg_off + PCI_CLASS_PROG, hdr->progif_code);
+ dw_pcie_writew_dbi(pci, cfg_off + PCI_CLASS_DEVICE,
hdr->subclass_code | hdr->baseclass_code << 8);
- dw_pcie_writeb_dbi(pci, func_offset + PCI_CACHE_LINE_SIZE,
+ dw_pcie_writeb_dbi(pci, cfg_off + PCI_CACHE_LINE_SIZE,
hdr->cache_line_size);
- dw_pcie_writew_dbi(pci, func_offset + PCI_SUBSYSTEM_VENDOR_ID,
+ dw_pcie_writew_dbi(pci, cfg_off + PCI_SUBSYSTEM_VENDOR_ID,
hdr->subsys_vendor_id);
- dw_pcie_writew_dbi(pci, func_offset + PCI_SUBSYSTEM_ID, hdr->subsys_id);
- dw_pcie_writeb_dbi(pci, func_offset + PCI_INTERRUPT_PIN,
+ dw_pcie_writew_dbi(pci, cfg_off + PCI_SUBSYSTEM_ID, hdr->subsys_id);
+ dw_pcie_writeb_dbi(pci, cfg_off + PCI_INTERRUPT_PIN,
hdr->interrupt_pin);
dw_pcie_dbi_ro_wr_dis(pci);

@@ -223,12 +224,13 @@ static int dw_pcie_ep_set_bar(struct pci_epc *epc, u8 func_no,
size_t size = epf_bar->size;
int flags = epf_bar->flags;
enum dw_pcie_as_type as_type;
+ struct dw_pcie_ep_func *func = dw_pcie_ep_get_func_from_ep(ep, func_no);
u32 reg;
- unsigned int func_offset = 0;

- func_offset = dw_pcie_ep_func_select(ep, func_no);
+ if (!func)
+ return -EINVAL;

- reg = PCI_BASE_ADDRESS_0 + (4 * bar) + func_offset;
+ reg = PCI_BASE_ADDRESS_0 + (4 * bar) + func->cfg_off;

if (!(flags & PCI_BASE_ADDRESS_SPACE))
as_type = DW_PCIE_AS_MEM;
@@ -309,17 +311,13 @@ static int dw_pcie_ep_get_msi(struct pci_epc *epc, 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 *func = dw_pcie_ep_get_func_from_ep(ep, func_no);
u32 val, reg;
- unsigned int func_offset = 0;
- struct dw_pcie_ep_func *ep_func;

- ep_func = dw_pcie_ep_get_func_from_ep(ep, func_no);
- if (!ep_func || !ep_func->msi_cap)
+ if (!func || !func->msi_cap)
return -EINVAL;

- func_offset = dw_pcie_ep_func_select(ep, func_no);
-
- reg = ep_func->msi_cap + func_offset + PCI_MSI_FLAGS;
+ reg = func->msi_cap + func->cfg_off + PCI_MSI_FLAGS;
val = dw_pcie_readw_dbi(pci, reg);
if (!(val & PCI_MSI_FLAGS_ENABLE))
return -EINVAL;
@@ -333,17 +331,13 @@ static int dw_pcie_ep_set_msi(struct pci_epc *epc, u8 func_no, u8 interrupts)
{
struct dw_pcie_ep *ep = epc_get_drvdata(epc);
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+ struct dw_pcie_ep_func *func = dw_pcie_ep_get_func_from_ep(ep, func_no);
u32 val, reg;
- unsigned int func_offset = 0;
- struct dw_pcie_ep_func *ep_func;

- ep_func = dw_pcie_ep_get_func_from_ep(ep, func_no);
- if (!ep_func || !ep_func->msi_cap)
+ if (!func || !func->msi_cap)
return -EINVAL;

- func_offset = dw_pcie_ep_func_select(ep, func_no);
-
- reg = ep_func->msi_cap + func_offset + PCI_MSI_FLAGS;
+ reg = func->msi_cap + func->cfg_off + PCI_MSI_FLAGS;
val = dw_pcie_readw_dbi(pci, reg);
val &= ~PCI_MSI_FLAGS_QMASK;
val |= (interrupts << 1) & PCI_MSI_FLAGS_QMASK;
@@ -358,17 +352,13 @@ static int dw_pcie_ep_get_msix(struct pci_epc *epc, 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 *func = dw_pcie_ep_get_func_from_ep(ep, func_no);
u32 val, reg;
- unsigned int func_offset = 0;
- struct dw_pcie_ep_func *ep_func;

- ep_func = dw_pcie_ep_get_func_from_ep(ep, func_no);
- if (!ep_func || !ep_func->msix_cap)
+ if (!func || !func->msix_cap)
return -EINVAL;

- func_offset = dw_pcie_ep_func_select(ep, func_no);
-
- reg = ep_func->msix_cap + func_offset + PCI_MSIX_FLAGS;
+ reg = func->msi_cap + func->cfg_off + PCI_MSIX_FLAGS;
val = dw_pcie_readw_dbi(pci, reg);
if (!(val & PCI_MSIX_FLAGS_ENABLE))
return -EINVAL;
@@ -383,29 +373,25 @@ static int dw_pcie_ep_set_msix(struct pci_epc *epc, u8 func_no, u16 interrupts,
{
struct dw_pcie_ep *ep = epc_get_drvdata(epc);
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+ struct dw_pcie_ep_func *func = dw_pcie_ep_get_func_from_ep(ep, func_no);
u32 val, reg;
- unsigned int func_offset = 0;
- struct dw_pcie_ep_func *ep_func;

- ep_func = dw_pcie_ep_get_func_from_ep(ep, func_no);
- if (!ep_func || !ep_func->msix_cap)
+ if (!func || !func->msix_cap)
return -EINVAL;

dw_pcie_dbi_ro_wr_en(pci);

- func_offset = dw_pcie_ep_func_select(ep, func_no);
-
- reg = ep_func->msix_cap + func_offset + PCI_MSIX_FLAGS;
+ reg = func->msi_cap + func->cfg_off + PCI_MSIX_FLAGS;
val = dw_pcie_readw_dbi(pci, reg);
val &= ~PCI_MSIX_FLAGS_QSIZE;
val |= interrupts;
dw_pcie_writew_dbi(pci, reg, val);

- reg = ep_func->msix_cap + func_offset + PCI_MSIX_TABLE;
+ reg = func->msi_cap + func->cfg_off + PCI_MSIX_TABLE;
val = offset | bir;
dw_pcie_writel_dbi(pci, reg, val);

- reg = ep_func->msix_cap + func_offset + PCI_MSIX_PBA;
+ reg = func->msi_cap + func->cfg_off + PCI_MSIX_PBA;
val = (offset + (interrupts * PCI_MSIX_ENTRY_SIZE)) | bir;
dw_pcie_writel_dbi(pci, reg, val);

@@ -487,37 +473,33 @@ int dw_pcie_ep_raise_legacy_irq(struct dw_pcie_ep *ep, u8 func_no)
int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 func_no,
u8 interrupt_num)
{
+ struct dw_pcie_ep_func *func = dw_pcie_ep_get_func_from_ep(ep, func_no);
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
- struct dw_pcie_ep_func *ep_func;
struct pci_epc *epc = ep->epc;
unsigned int aligned_offset;
- unsigned int func_offset = 0;
u16 msg_ctrl, msg_data;
u32 msg_addr_lower, msg_addr_upper, reg;
u64 msg_addr;
bool has_upper;
int ret;

- ep_func = dw_pcie_ep_get_func_from_ep(ep, func_no);
- if (!ep_func || !ep_func->msi_cap)
+ if (!func || !func->msi_cap)
return -EINVAL;

- func_offset = dw_pcie_ep_func_select(ep, func_no);
-
/* Raise MSI per the PCI Local Bus Specification Revision 3.0, 6.8.1. */
- reg = ep_func->msi_cap + func_offset + PCI_MSI_FLAGS;
+ reg = func->msi_cap + func->cfg_off + PCI_MSI_FLAGS;
msg_ctrl = dw_pcie_readw_dbi(pci, reg);
has_upper = !!(msg_ctrl & PCI_MSI_FLAGS_64BIT);
- reg = ep_func->msi_cap + func_offset + PCI_MSI_ADDRESS_LO;
+ reg = func->msi_cap + func->cfg_off + PCI_MSI_ADDRESS_LO;
msg_addr_lower = dw_pcie_readl_dbi(pci, reg);
if (has_upper) {
- reg = ep_func->msi_cap + func_offset + PCI_MSI_ADDRESS_HI;
+ reg = func->msi_cap + func->cfg_off + PCI_MSI_ADDRESS_HI;
msg_addr_upper = dw_pcie_readl_dbi(pci, reg);
- reg = ep_func->msi_cap + func_offset + PCI_MSI_DATA_64;
+ reg = func->msi_cap + func->cfg_off + PCI_MSI_DATA_64;
msg_data = dw_pcie_readw_dbi(pci, reg);
} else {
msg_addr_upper = 0;
- reg = ep_func->msi_cap + func_offset + PCI_MSI_DATA_32;
+ reg = func->msi_cap + func->cfg_off + PCI_MSI_DATA_32;
msg_data = dw_pcie_readw_dbi(pci, reg);
}
aligned_offset = msg_addr_lower & (epc->mem->window.page_size - 1);
@@ -538,12 +520,11 @@ int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 func_no,
int dw_pcie_ep_raise_msix_irq_doorbell(struct dw_pcie_ep *ep, u8 func_no,
u16 interrupt_num)
{
+ struct dw_pcie_ep_func *func = dw_pcie_ep_get_func_from_ep(ep, func_no);
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
- struct dw_pcie_ep_func *ep_func;
u32 msg_data;

- ep_func = dw_pcie_ep_get_func_from_ep(ep, func_no);
- if (!ep_func || !ep_func->msix_cap)
+ if (!func || !func->msix_cap)
return -EINVAL;

msg_data = (func_no << PCIE_MSIX_DOORBELL_PF_SHIFT) |
@@ -557,11 +538,10 @@ int dw_pcie_ep_raise_msix_irq_doorbell(struct dw_pcie_ep *ep, u8 func_no,
int dw_pcie_ep_raise_msix_irq(struct dw_pcie_ep *ep, u8 func_no,
u16 interrupt_num)
{
+ struct dw_pcie_ep_func *func = dw_pcie_ep_get_func_from_ep(ep, func_no);
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
- struct dw_pcie_ep_func *ep_func;
struct pci_epf_msix_tbl *msix_tbl;
struct pci_epc *epc = ep->epc;
- unsigned int func_offset = 0;
u32 reg, msg_data, vec_ctrl;
unsigned int aligned_offset;
u32 tbl_offset;
@@ -569,13 +549,10 @@ int dw_pcie_ep_raise_msix_irq(struct dw_pcie_ep *ep, u8 func_no,
int ret;
u8 bir;

- ep_func = dw_pcie_ep_get_func_from_ep(ep, func_no);
- if (!ep_func || !ep_func->msix_cap)
+ if (!func || !func->msix_cap)
return -EINVAL;

- func_offset = dw_pcie_ep_func_select(ep, func_no);
-
- reg = ep_func->msix_cap + func_offset + PCI_MSIX_TABLE;
+ reg = func->msix_cap + func->cfg_off + PCI_MSIX_TABLE;
tbl_offset = dw_pcie_readl_dbi(pci, reg);
bir = (tbl_offset & PCI_MSIX_TABLE_BIR);
tbl_offset &= PCI_MSIX_TABLE_OFFSET;
@@ -753,6 +730,7 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)

for (i = 0; i < epc->max_functions; i++) {
funcs[i].func_no = i;
+ funcs[i].cfg_off = dw_pcie_ep_func_select(ep, i);
funcs[i].msi_cap = dw_pcie_ep_find_capability(ep, i,
PCI_CAP_ID_MSI);
funcs[i].msix_cap = dw_pcie_ep_find_capability(ep, i,
diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h
index 16d239c4d09b..8ee67d4b8109 100644
--- a/drivers/pci/controller/dwc/pcie-designware.h
+++ b/drivers/pci/controller/dwc/pcie-designware.h
@@ -224,6 +224,7 @@ struct dw_pcie_ep_func {
u8 func_no;
u8 msi_cap; /* MSI capability offset */
u8 msix_cap; /* MSI-X capability offset */
+ u32 cfg_off; /* CFG offset from DBI base */
};

struct dw_pcie_ep {
--
2.17.1