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: Benjamin Herrenschmidt <benh@kernel.crashing.org> # Conflicts: # arch/powerpc/platforms/powernv/pci-ioda.c # arch/powerpc/platforms/powernv/pci.h Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
This commit is contained in:
parent
08acce1cab
commit
fd141d1a99
2 changed files with 28 additions and 48 deletions
|
@ -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,
|
||||||
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 = {
|
||||||
|
|
||||||
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,
|
||||||
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,
|
||||||
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)
|
||||||
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,
|
||||||
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,
|
||||||
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 {
|
||||||
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 {
|
||||||
|
|
||||||
/* 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 */
|
||||||
|
|
Loading…
Add table
Reference in a new issue