Commit 10b35b2b authored by Alexey Kardashevskiy's avatar Alexey Kardashevskiy Committed by Michael Ellerman

powerpc/powernv: Do not set "read" flag if direction==DMA_NONE

Normally a bitmap from the iommu_table is used to track what TCE entry
is in use. Since we are going to use iommu_table without its locks and
do xchg() instead, it becomes essential not to put bits which are not
implied in the direction flag as the old TCE value (more precisely -
the permission bits) will be used to decide whether to put the page or not.

This adds iommu_direction_to_tce_perm() (its counterpart is there already)
and uses it for powernv's pnv_tce_build().
Signed-off-by: default avatarAlexey Kardashevskiy <aik@ozlabs.ru>
Reviewed-by: default avatarDavid Gibson <david@gibson.dropbear.id.au>
Reviewed-by: default avatarGavin Shan <gwshan@linux.vnet.ibm.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent 22af4859
...@@ -200,6 +200,7 @@ extern int iommu_take_ownership(struct iommu_table *tbl); ...@@ -200,6 +200,7 @@ extern int iommu_take_ownership(struct iommu_table *tbl);
extern void iommu_release_ownership(struct iommu_table *tbl); extern void iommu_release_ownership(struct iommu_table *tbl);
extern enum dma_data_direction iommu_tce_direction(unsigned long tce); extern enum dma_data_direction iommu_tce_direction(unsigned long tce);
extern unsigned long iommu_direction_to_tce_perm(enum dma_data_direction dir);
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#endif /* _ASM_IOMMU_H */ #endif /* _ASM_IOMMU_H */
...@@ -866,6 +866,21 @@ void iommu_free_coherent(struct iommu_table *tbl, size_t size, ...@@ -866,6 +866,21 @@ void iommu_free_coherent(struct iommu_table *tbl, size_t size,
} }
} }
unsigned long iommu_direction_to_tce_perm(enum dma_data_direction dir)
{
switch (dir) {
case DMA_BIDIRECTIONAL:
return TCE_PCI_READ | TCE_PCI_WRITE;
case DMA_FROM_DEVICE:
return TCE_PCI_WRITE;
case DMA_TO_DEVICE:
return TCE_PCI_READ;
default:
return 0;
}
}
EXPORT_SYMBOL_GPL(iommu_direction_to_tce_perm);
#ifdef CONFIG_IOMMU_API #ifdef CONFIG_IOMMU_API
/* /*
* SPAPR TCE API * SPAPR TCE API
......
...@@ -576,15 +576,10 @@ static int pnv_tce_build(struct iommu_table *tbl, long index, long npages, ...@@ -576,15 +576,10 @@ static int pnv_tce_build(struct iommu_table *tbl, long index, long npages,
unsigned long uaddr, enum dma_data_direction direction, unsigned long uaddr, enum dma_data_direction direction,
struct dma_attrs *attrs, bool rm) struct dma_attrs *attrs, bool rm)
{ {
u64 proto_tce; u64 proto_tce = iommu_direction_to_tce_perm(direction);
__be64 *tcep, *tces; __be64 *tcep, *tces;
u64 rpn; u64 rpn;
proto_tce = TCE_PCI_READ; // Read allowed
if (direction != DMA_TO_DEVICE)
proto_tce |= TCE_PCI_WRITE;
tces = tcep = ((__be64 *)tbl->it_base) + index - tbl->it_offset; tces = tcep = ((__be64 *)tbl->it_base) + index - tbl->it_offset;
rpn = __pa(uaddr) >> tbl->it_page_shift; rpn = __pa(uaddr) >> tbl->it_page_shift;
......
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