aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexey Kardashevskiy <aik@ozlabs.ru>2016-02-17 02:26:31 -0500
committerMichael Ellerman <mpe@ellerman.id.au>2016-02-17 07:52:17 -0500
commit6ecad912a0073c768db1491c27ca55ad2d0ee68f (patch)
tree96345d14a7c00b56cb8afa50cfa32d6b7e0bda9c
parentc777e2a8b65420b31dac28a453e35be984f5808b (diff)
powerpc/ioda: Set "read" permission when "write" is set
Quite often drivers set only "write" permission assuming that this includes "read" permission as well and this works on plenty of platforms. However IODA2 is strict about this and produces an EEH when "read" permission is not set and reading happens. This adds a workaround in the IODA code to always add the "read" bit when the "write" bit is set. Fixes: 10b35b2b7485 ("powerpc/powernv: Do not set "read" flag if direction==DMA_NONE") Cc: stable@vger.kernel.org # 4.2+ Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru> Tested-by: Douglas Miller <dougmill@linux.vnet.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
-rw-r--r--arch/powerpc/platforms/powernv/pci.c6
1 files changed, 6 insertions, 0 deletions
diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c
index d25ff2292ae2..b1ef84a6c9d1 100644
--- a/arch/powerpc/platforms/powernv/pci.c
+++ b/arch/powerpc/platforms/powernv/pci.c
@@ -599,6 +599,9 @@ int pnv_tce_build(struct iommu_table *tbl, long index, long npages,
599 u64 rpn = __pa(uaddr) >> tbl->it_page_shift; 599 u64 rpn = __pa(uaddr) >> tbl->it_page_shift;
600 long i; 600 long i;
601 601
602 if (proto_tce & TCE_PCI_WRITE)
603 proto_tce |= TCE_PCI_READ;
604
602 for (i = 0; i < npages; i++) { 605 for (i = 0; i < npages; i++) {
603 unsigned long newtce = proto_tce | 606 unsigned long newtce = proto_tce |
604 ((rpn + i) << tbl->it_page_shift); 607 ((rpn + i) << tbl->it_page_shift);
@@ -620,6 +623,9 @@ int pnv_tce_xchg(struct iommu_table *tbl, long index,
620 623
621 BUG_ON(*hpa & ~IOMMU_PAGE_MASK(tbl)); 624 BUG_ON(*hpa & ~IOMMU_PAGE_MASK(tbl));
622 625
626 if (newtce & TCE_PCI_WRITE)
627 newtce |= TCE_PCI_READ;
628
623 oldtce = xchg(pnv_tce(tbl, idx), cpu_to_be64(newtce)); 629 oldtce = xchg(pnv_tce(tbl, idx), cpu_to_be64(newtce));
624 *hpa = be64_to_cpu(oldtce) & ~(TCE_PCI_READ | TCE_PCI_WRITE); 630 *hpa = be64_to_cpu(oldtce) & ~(TCE_PCI_READ | TCE_PCI_WRITE);
625 *direction = iommu_tce_direction(oldtce); 631 *direction = iommu_tce_direction(oldtce);