Skip to content

Commit

Permalink
PCI: designware: Use iATU0 for cfg and IO, iATU1 for MEM
Browse files Browse the repository at this point in the history
Most transactions' type are cfg0 and MEM, so the current iATU usage is not
balanced: iATU0 is hot while iATU1 is rarely used.

Refactor the iATU usage so we use iATU0 for cfg and IO and iATU1 for MEM.
This allocation idea comes from Minghuan Lian
<Minghuan.Lian@freescale.com>:

[bhelgaas: use link with Message-ID]
Link: http://lkml.kernel.org/r/1429091315-31891-3-git-send-email-Minghuan.Lian@freescale.com
Signed-off-by: Jisheng Zhang <jszhang@marvell.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Acked-by: Pratyush Anand <pratyush.anand@gmail.com>
  • Loading branch information
Jisheng Zhang authored and Bjorn Helgaas committed May 20, 2015
1 parent 63503c8 commit 2d91b49
Showing 1 changed file with 45 additions and 36 deletions.
81 changes: 45 additions & 36 deletions drivers/pci/host/pcie-designware.c
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,11 @@ int dw_pcie_host_init(struct pcie_port *pp)
if (pp->ops->host_init)
pp->ops->host_init(pp);

if (!pp->ops->rd_other_conf)
dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX1,
PCIE_ATU_TYPE_MEM, pp->mem_mod_base,
pp->mem_bus_addr, pp->mem_size);

dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0);

/* program correct class for RC */
Expand All @@ -535,66 +540,70 @@ int dw_pcie_host_init(struct pcie_port *pp)
static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
u32 devfn, int where, int size, u32 *val)
{
int ret = PCIBIOS_SUCCESSFUL;
u32 address, busdev;
int ret, type;
u32 address, busdev, cfg_size;
u64 cpu_addr;
void __iomem *va_cfg_base;

busdev = PCIE_ATU_BUS(bus->number) | PCIE_ATU_DEV(PCI_SLOT(devfn)) |
PCIE_ATU_FUNC(PCI_FUNC(devfn));
address = where & ~0x3;

if (bus->parent->number == pp->root_bus_nr) {
dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
PCIE_ATU_TYPE_CFG0, pp->cfg0_mod_base,
busdev, pp->cfg0_size);
ret = dw_pcie_cfg_read(pp->va_cfg0_base + address, where, size,
val);
dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
PCIE_ATU_TYPE_MEM, pp->mem_mod_base,
pp->mem_bus_addr, pp->mem_size);
type = PCIE_ATU_TYPE_CFG0;
cpu_addr = pp->cfg0_mod_base;
cfg_size = pp->cfg0_size;
va_cfg_base = pp->va_cfg0_base;
} else {
dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX1,
PCIE_ATU_TYPE_CFG1, pp->cfg1_mod_base,
busdev, pp->cfg1_size);
ret = dw_pcie_cfg_read(pp->va_cfg1_base + address, where, size,
val);
dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX1,
PCIE_ATU_TYPE_IO, pp->io_mod_base,
pp->io_bus_addr, pp->io_size);
type = PCIE_ATU_TYPE_CFG1;
cpu_addr = pp->cfg1_mod_base;
cfg_size = pp->cfg1_size;
va_cfg_base = pp->va_cfg1_base;
}

dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
type, cpu_addr,
busdev, cfg_size);
ret = dw_pcie_cfg_read(va_cfg_base + address, where, size, val);
dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
PCIE_ATU_TYPE_IO, pp->io_mod_base,
pp->io_bus_addr, pp->io_size);

return ret;
}

static int dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,
u32 devfn, int where, int size, u32 val)
{
int ret = PCIBIOS_SUCCESSFUL;
u32 address, busdev;
int ret, type;
u32 address, busdev, cfg_size;
u64 cpu_addr;
void __iomem *va_cfg_base;

busdev = PCIE_ATU_BUS(bus->number) | PCIE_ATU_DEV(PCI_SLOT(devfn)) |
PCIE_ATU_FUNC(PCI_FUNC(devfn));
address = where & ~0x3;

if (bus->parent->number == pp->root_bus_nr) {
dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
PCIE_ATU_TYPE_CFG0, pp->cfg0_mod_base,
busdev, pp->cfg0_size);
ret = dw_pcie_cfg_write(pp->va_cfg0_base + address, where, size,
val);
dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
PCIE_ATU_TYPE_MEM, pp->mem_mod_base,
pp->mem_bus_addr, pp->mem_size);
type = PCIE_ATU_TYPE_CFG0;
cpu_addr = pp->cfg0_mod_base;
cfg_size = pp->cfg0_size;
va_cfg_base = pp->va_cfg0_base;
} else {
dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX1,
PCIE_ATU_TYPE_CFG1, pp->cfg1_mod_base,
busdev, pp->cfg1_size);
ret = dw_pcie_cfg_write(pp->va_cfg1_base + address, where, size,
val);
dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX1,
PCIE_ATU_TYPE_IO, pp->io_mod_base,
pp->io_bus_addr, pp->io_size);
type = PCIE_ATU_TYPE_CFG1;
cpu_addr = pp->cfg1_mod_base;
cfg_size = pp->cfg1_size;
va_cfg_base = pp->va_cfg1_base;
}

dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
type, cpu_addr,
busdev, cfg_size);
ret = dw_pcie_cfg_write(va_cfg_base + address, where, size, val);
dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
PCIE_ATU_TYPE_IO, pp->io_mod_base,
pp->io_bus_addr, pp->io_size);

return ret;
}

Expand Down

0 comments on commit 2d91b49

Please sign in to comment.