Commit fd141d1a authored by Benjamin Herrenschmidt's avatar Benjamin Herrenschmidt Committed by Michael Ellerman

powerpc/powernv/pci: Rework accessing the TCE invalidate register

It's architected, always in a known place, so there is no need
to keep a separate pointer to it, we use the existing "regs",
and we complement it with a real mode variant.
Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>

# Conflicts:
#	arch/powerpc/platforms/powernv/pci-ioda.c
#	arch/powerpc/platforms/powernv/pci.h
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent 08acce1c
...@@ -1721,6 +1721,13 @@ static void pnv_ioda_setup_bus_dma(struct pnv_ioda_pe *pe, ...@@ -1721,6 +1721,13 @@ static void pnv_ioda_setup_bus_dma(struct pnv_ioda_pe *pe,
} }
} }
static inline __be64 __iomem *pnv_ioda_get_inval_reg(struct pnv_phb *phb,
bool real_mode)
{
return real_mode ? (__be64 __iomem *)(phb->regs_phys + 0x210) :
(phb->regs + 0x210);
}
static void pnv_pci_p7ioc_tce_invalidate(struct iommu_table *tbl, static void pnv_pci_p7ioc_tce_invalidate(struct iommu_table *tbl,
unsigned long index, unsigned long npages, bool rm) unsigned long index, unsigned long npages, bool rm)
{ {
...@@ -1729,9 +1736,7 @@ static void pnv_pci_p7ioc_tce_invalidate(struct iommu_table *tbl, ...@@ -1729,9 +1736,7 @@ static void pnv_pci_p7ioc_tce_invalidate(struct iommu_table *tbl,
next); next);
struct pnv_ioda_pe *pe = container_of(tgl->table_group, struct pnv_ioda_pe *pe = container_of(tgl->table_group,
struct pnv_ioda_pe, table_group); struct pnv_ioda_pe, table_group);
__be64 __iomem *invalidate = rm ? __be64 __iomem *invalidate = pnv_ioda_get_inval_reg(pe->phb, rm);
(__be64 __iomem *)pe->phb->ioda.tce_inval_reg_phys :
pe->phb->ioda.tce_inval_reg;
unsigned long start, end, inc; unsigned long start, end, inc;
start = __pa(((__be64 *)tbl->it_base) + index - tbl->it_offset); start = __pa(((__be64 *)tbl->it_base) + index - tbl->it_offset);
...@@ -1809,39 +1814,36 @@ static struct iommu_table_ops pnv_ioda1_iommu_ops = { ...@@ -1809,39 +1814,36 @@ static struct iommu_table_ops pnv_ioda1_iommu_ops = {
void pnv_pci_phb3_tce_invalidate_entire(struct pnv_phb *phb, bool rm) void pnv_pci_phb3_tce_invalidate_entire(struct pnv_phb *phb, bool rm)
{ {
__be64 __iomem *invalidate = pnv_ioda_get_inval_reg(phb, rm);
const unsigned long val = PHB3_TCE_KILL_INVAL_ALL; const unsigned long val = PHB3_TCE_KILL_INVAL_ALL;
mb(); /* Ensure previous TCE table stores are visible */ mb(); /* Ensure previous TCE table stores are visible */
if (rm) if (rm)
__raw_rm_writeq(cpu_to_be64(val), __raw_rm_writeq(cpu_to_be64(val), invalidate);
(__be64 __iomem *)
phb->ioda.tce_inval_reg_phys);
else else
__raw_writeq(cpu_to_be64(val), phb->ioda.tce_inval_reg); __raw_writeq(cpu_to_be64(val), invalidate);
} }
static inline void pnv_pci_phb3_tce_invalidate_pe(struct pnv_ioda_pe *pe) static inline void pnv_pci_phb3_tce_invalidate_pe(struct pnv_ioda_pe *pe)
{ {
/* 01xb - invalidate TCEs that match the specified PE# */ /* 01xb - invalidate TCEs that match the specified PE# */
__be64 __iomem *invalidate = pnv_ioda_get_inval_reg(pe->phb, false);
unsigned long val = PHB3_TCE_KILL_INVAL_PE | (pe->pe_number & 0xFF); unsigned long val = PHB3_TCE_KILL_INVAL_PE | (pe->pe_number & 0xFF);
struct pnv_phb *phb = pe->phb;
if (!phb->ioda.tce_inval_reg)
return;
mb(); /* Ensure above stores are visible */ mb(); /* Ensure above stores are visible */
__raw_writeq(cpu_to_be64(val), phb->ioda.tce_inval_reg); __raw_writeq(cpu_to_be64(val), invalidate);
} }
static void pnv_pci_phb3_tce_invalidate(unsigned pe_number, bool rm, static void pnv_pci_phb3_tce_invalidate(struct pnv_ioda_pe *pe, bool rm,
__be64 __iomem *invalidate, unsigned shift, unsigned shift, unsigned long index,
unsigned long index, unsigned long npages) unsigned long npages)
{ {
__be64 __iomem *invalidate = pnv_ioda_get_inval_reg(pe->phb, false);
unsigned long start, end, inc; unsigned long start, end, inc;
/* We'll invalidate DMA address in PE scope */ /* We'll invalidate DMA address in PE scope */
start = PHB3_TCE_KILL_INVAL_ONE; start = PHB3_TCE_KILL_INVAL_ONE;
start |= (pe_number & 0xFF); start |= (pe->pe_number & 0xFF);
end = start; end = start;
/* Figure out the start, end and step */ /* Figure out the start, end and step */
...@@ -1867,10 +1869,6 @@ static void pnv_pci_ioda2_tce_invalidate(struct iommu_table *tbl, ...@@ -1867,10 +1869,6 @@ static void pnv_pci_ioda2_tce_invalidate(struct iommu_table *tbl,
list_for_each_entry_rcu(tgl, &tbl->it_group_list, next) { list_for_each_entry_rcu(tgl, &tbl->it_group_list, next) {
struct pnv_ioda_pe *pe = container_of(tgl->table_group, struct pnv_ioda_pe *pe = container_of(tgl->table_group,
struct pnv_ioda_pe, table_group); struct pnv_ioda_pe, table_group);
__be64 __iomem *invalidate = rm ?
(__be64 __iomem *)pe->phb->ioda.tce_inval_reg_phys :
pe->phb->ioda.tce_inval_reg;
if (pe->phb->type == PNV_PHB_NPU) { if (pe->phb->type == PNV_PHB_NPU) {
/* /*
* The NVLink hardware does not support TCE kill * The NVLink hardware does not support TCE kill
...@@ -1880,9 +1878,8 @@ static void pnv_pci_ioda2_tce_invalidate(struct iommu_table *tbl, ...@@ -1880,9 +1878,8 @@ static void pnv_pci_ioda2_tce_invalidate(struct iommu_table *tbl,
pnv_pci_phb3_tce_invalidate_entire(pe->phb, rm); pnv_pci_phb3_tce_invalidate_entire(pe->phb, rm);
continue; continue;
} }
pnv_pci_phb3_tce_invalidate(pe->pe_number, rm, pnv_pci_phb3_tce_invalidate(pe, rm, tbl->it_page_shift,
invalidate, tbl->it_page_shift, index, npages);
index, npages);
} }
} }
...@@ -2467,19 +2464,6 @@ static void pnv_pci_ioda_setup_iommu_api(void) ...@@ -2467,19 +2464,6 @@ static void pnv_pci_ioda_setup_iommu_api(void)
static void pnv_pci_ioda_setup_iommu_api(void) { }; static void pnv_pci_ioda_setup_iommu_api(void) { };
#endif #endif
static void pnv_pci_ioda_setup_opal_tce_kill(struct pnv_phb *phb)
{
const __be64 *swinvp;
/* OPAL variant of PHB3 invalidated TCEs */
swinvp = of_get_property(phb->hose->dn, "ibm,opal-tce-kill", NULL);
if (!swinvp)
return;
phb->ioda.tce_inval_reg_phys = be64_to_cpup(swinvp);
phb->ioda.tce_inval_reg = ioremap(phb->ioda.tce_inval_reg_phys, 8);
}
static __be64 *pnv_pci_ioda2_table_do_alloc_pages(int nid, unsigned shift, static __be64 *pnv_pci_ioda2_table_do_alloc_pages(int nid, unsigned shift,
unsigned levels, unsigned long limit, unsigned levels, unsigned long limit,
unsigned long *current_offset, unsigned long *total_allocated) unsigned long *current_offset, unsigned long *total_allocated)
...@@ -3459,6 +3443,7 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np, ...@@ -3459,6 +3443,7 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np,
struct pnv_phb *phb; struct pnv_phb *phb;
unsigned long size, m64map_off, m32map_off, pemap_off; unsigned long size, m64map_off, m32map_off, pemap_off;
unsigned long iomap_off = 0, dma32map_off = 0; unsigned long iomap_off = 0, dma32map_off = 0;
struct resource r;
const __be64 *prop64; const __be64 *prop64;
const __be32 *prop32; const __be32 *prop32;
int len; int len;
...@@ -3519,12 +3504,12 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np, ...@@ -3519,12 +3504,12 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np,
pci_process_bridge_OF_ranges(hose, np, !hose->global_number); pci_process_bridge_OF_ranges(hose, np, !hose->global_number);
/* Get registers */ /* Get registers */
phb->regs = of_iomap(np, 0); if (!of_address_to_resource(np, 0, &r)) {
if (phb->regs == NULL) phb->regs_phys = r.start;
pr_err(" Failed to map registers !\n"); phb->regs = ioremap(r.start, resource_size(&r));
if (phb->regs == NULL)
/* Initialize TCE kill register */ pr_err(" Failed to map registers !\n");
pnv_pci_ioda_setup_opal_tce_kill(phb); }
/* Initialize more IODA stuff */ /* Initialize more IODA stuff */
phb->ioda.total_pe_num = 1; phb->ioda.total_pe_num = 1;
......
...@@ -86,6 +86,7 @@ struct pnv_phb { ...@@ -86,6 +86,7 @@ struct pnv_phb {
u64 opal_id; u64 opal_id;
int flags; int flags;
void __iomem *regs; void __iomem *regs;
u64 regs_phys;
int initialized; int initialized;
spinlock_t lock; spinlock_t lock;
...@@ -162,12 +163,6 @@ struct pnv_phb { ...@@ -162,12 +163,6 @@ struct pnv_phb {
/* Reverse map of PEs, indexed by {bus, devfn} */ /* Reverse map of PEs, indexed by {bus, devfn} */
unsigned int pe_rmap[0x10000]; unsigned int pe_rmap[0x10000];
/* TCE cache invalidate registers (physical and
* remapped)
*/
phys_addr_t tce_inval_reg_phys;
__be64 __iomem *tce_inval_reg;
} ioda; } ioda;
/* PHB and hub status structure */ /* PHB and hub status structure */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment