|
@@ -70,6 +70,16 @@ define_pe_printk_level(pe_err, KERN_ERR);
|
|
|
define_pe_printk_level(pe_warn, KERN_WARNING);
|
|
|
define_pe_printk_level(pe_info, KERN_INFO);
|
|
|
|
|
|
+/*
|
|
|
+ * stdcix is only supposed to be used in hypervisor real mode as per
|
|
|
+ * the architecture spec
|
|
|
+ */
|
|
|
+static inline void __raw_rm_writeq(u64 val, volatile void __iomem *paddr)
|
|
|
+{
|
|
|
+ __asm__ __volatile__("stdcix %0,0,%1"
|
|
|
+ : : "r" (val), "r" (paddr) : "memory");
|
|
|
+}
|
|
|
+
|
|
|
static int pnv_ioda_alloc_pe(struct pnv_phb *phb)
|
|
|
{
|
|
|
unsigned long pe;
|
|
@@ -454,10 +464,13 @@ static void pnv_ioda_setup_bus_dma(struct pnv_ioda_pe *pe, struct pci_bus *bus)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-static void pnv_pci_ioda1_tce_invalidate(struct iommu_table *tbl,
|
|
|
- u64 *startp, u64 *endp)
|
|
|
+static void pnv_pci_ioda1_tce_invalidate(struct pnv_ioda_pe *pe,
|
|
|
+ struct iommu_table *tbl,
|
|
|
+ u64 *startp, u64 *endp, bool rm)
|
|
|
{
|
|
|
- u64 __iomem *invalidate = (u64 __iomem *)tbl->it_index;
|
|
|
+ u64 __iomem *invalidate = rm ?
|
|
|
+ (u64 __iomem *)pe->tce_inval_reg_phys :
|
|
|
+ (u64 __iomem *)tbl->it_index;
|
|
|
unsigned long start, end, inc;
|
|
|
|
|
|
start = __pa(startp);
|
|
@@ -484,7 +497,10 @@ static void pnv_pci_ioda1_tce_invalidate(struct iommu_table *tbl,
|
|
|
|
|
|
mb(); /* Ensure above stores are visible */
|
|
|
while (start <= end) {
|
|
|
- __raw_writeq(start, invalidate);
|
|
|
+ if (rm)
|
|
|
+ __raw_rm_writeq(start, invalidate);
|
|
|
+ else
|
|
|
+ __raw_writeq(start, invalidate);
|
|
|
start += inc;
|
|
|
}
|
|
|
|
|
@@ -496,10 +512,12 @@ static void pnv_pci_ioda1_tce_invalidate(struct iommu_table *tbl,
|
|
|
|
|
|
static void pnv_pci_ioda2_tce_invalidate(struct pnv_ioda_pe *pe,
|
|
|
struct iommu_table *tbl,
|
|
|
- u64 *startp, u64 *endp)
|
|
|
+ u64 *startp, u64 *endp, bool rm)
|
|
|
{
|
|
|
unsigned long start, end, inc;
|
|
|
- u64 __iomem *invalidate = (u64 __iomem *)tbl->it_index;
|
|
|
+ u64 __iomem *invalidate = rm ?
|
|
|
+ (u64 __iomem *)pe->tce_inval_reg_phys :
|
|
|
+ (u64 __iomem *)tbl->it_index;
|
|
|
|
|
|
/* We'll invalidate DMA address in PE scope */
|
|
|
start = 0x2ul << 60;
|
|
@@ -515,22 +533,25 @@ static void pnv_pci_ioda2_tce_invalidate(struct pnv_ioda_pe *pe,
|
|
|
mb();
|
|
|
|
|
|
while (start <= end) {
|
|
|
- __raw_writeq(start, invalidate);
|
|
|
+ if (rm)
|
|
|
+ __raw_rm_writeq(start, invalidate);
|
|
|
+ else
|
|
|
+ __raw_writeq(start, invalidate);
|
|
|
start += inc;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void pnv_pci_ioda_tce_invalidate(struct iommu_table *tbl,
|
|
|
- u64 *startp, u64 *endp)
|
|
|
+ u64 *startp, u64 *endp, bool rm)
|
|
|
{
|
|
|
struct pnv_ioda_pe *pe = container_of(tbl, struct pnv_ioda_pe,
|
|
|
tce32_table);
|
|
|
struct pnv_phb *phb = pe->phb;
|
|
|
|
|
|
if (phb->type == PNV_PHB_IODA1)
|
|
|
- pnv_pci_ioda1_tce_invalidate(tbl, startp, endp);
|
|
|
+ pnv_pci_ioda1_tce_invalidate(pe, tbl, startp, endp, rm);
|
|
|
else
|
|
|
- pnv_pci_ioda2_tce_invalidate(pe, tbl, startp, endp);
|
|
|
+ pnv_pci_ioda2_tce_invalidate(pe, tbl, startp, endp, rm);
|
|
|
}
|
|
|
|
|
|
static void pnv_pci_ioda_setup_dma_pe(struct pnv_phb *phb,
|
|
@@ -603,7 +624,9 @@ static void pnv_pci_ioda_setup_dma_pe(struct pnv_phb *phb,
|
|
|
* bus number, print that out instead.
|
|
|
*/
|
|
|
tbl->it_busno = 0;
|
|
|
- tbl->it_index = (unsigned long)ioremap(be64_to_cpup(swinvp), 8);
|
|
|
+ pe->tce_inval_reg_phys = be64_to_cpup(swinvp);
|
|
|
+ tbl->it_index = (unsigned long)ioremap(pe->tce_inval_reg_phys,
|
|
|
+ 8);
|
|
|
tbl->it_type = TCE_PCI_SWINV_CREATE | TCE_PCI_SWINV_FREE |
|
|
|
TCE_PCI_SWINV_PAIR;
|
|
|
}
|
|
@@ -681,7 +704,9 @@ static void pnv_pci_ioda2_setup_dma_pe(struct pnv_phb *phb,
|
|
|
* bus number, print that out instead.
|
|
|
*/
|
|
|
tbl->it_busno = 0;
|
|
|
- tbl->it_index = (unsigned long)ioremap(be64_to_cpup(swinvp), 8);
|
|
|
+ pe->tce_inval_reg_phys = be64_to_cpup(swinvp);
|
|
|
+ tbl->it_index = (unsigned long)ioremap(pe->tce_inval_reg_phys,
|
|
|
+ 8);
|
|
|
tbl->it_type = TCE_PCI_SWINV_CREATE | TCE_PCI_SWINV_FREE;
|
|
|
}
|
|
|
iommu_init_table(tbl, phb->hose->node);
|