powerpc: Add sync_*_for_* to dma_ops
We need to swap these out once we start using swiotlb, so add them to dma_ops. Create CONFIG_PPC_NEED_DMA_SYNC_OPS Kconfig option; this is currently enabled automatically if we're CONFIG_NOT_COHERENT_CACHE. In the future, this will also be enabled for builds that need swiotlb. If PPC_NEED_DMA_SYNC_OPS is not defined, the dma_sync_*_for_* ops compile to nothing. Otherwise, they access the dma_ops pointers for the sync ops. This patch also changes dma_sync_single_range_* to actually sync the range - previously it was using a generous dma_sync_single. dma_sync_single_* is now implemented as a dma_sync_single_range with an offset of 0. Signed-off-by: Becky Bruce <becky.bruce@freescale.com> Signed-off-by: Paul Mackerras <paulus@samba.org>
This commit is contained in:
committed by
Paul Mackerras
parent
c4d04be11f
commit
15e09c0eca
@@ -285,6 +285,10 @@ config IOMMU_VMERGE
|
|||||||
config IOMMU_HELPER
|
config IOMMU_HELPER
|
||||||
def_bool PPC64
|
def_bool PPC64
|
||||||
|
|
||||||
|
config PPC_NEED_DMA_SYNC_OPS
|
||||||
|
def_bool y
|
||||||
|
depends on NOT_COHERENT_CACHE
|
||||||
|
|
||||||
config HOTPLUG_CPU
|
config HOTPLUG_CPU
|
||||||
bool "Support for enabling/disabling CPUs"
|
bool "Support for enabling/disabling CPUs"
|
||||||
depends on SMP && HOTPLUG && EXPERIMENTAL && (PPC_PSERIES || PPC_PMAC)
|
depends on SMP && HOTPLUG && EXPERIMENTAL && (PPC_PSERIES || PPC_PMAC)
|
||||||
|
@@ -76,6 +76,22 @@ struct dma_mapping_ops {
|
|||||||
dma_addr_t dma_address, size_t size,
|
dma_addr_t dma_address, size_t size,
|
||||||
enum dma_data_direction direction,
|
enum dma_data_direction direction,
|
||||||
struct dma_attrs *attrs);
|
struct dma_attrs *attrs);
|
||||||
|
#ifdef CONFIG_PPC_NEED_DMA_SYNC_OPS
|
||||||
|
void (*sync_single_range_for_cpu)(struct device *hwdev,
|
||||||
|
dma_addr_t dma_handle, unsigned long offset,
|
||||||
|
size_t size,
|
||||||
|
enum dma_data_direction direction);
|
||||||
|
void (*sync_single_range_for_device)(struct device *hwdev,
|
||||||
|
dma_addr_t dma_handle, unsigned long offset,
|
||||||
|
size_t size,
|
||||||
|
enum dma_data_direction direction);
|
||||||
|
void (*sync_sg_for_cpu)(struct device *hwdev,
|
||||||
|
struct scatterlist *sg, int nelems,
|
||||||
|
enum dma_data_direction direction);
|
||||||
|
void (*sync_sg_for_device)(struct device *hwdev,
|
||||||
|
struct scatterlist *sg, int nelems,
|
||||||
|
enum dma_data_direction direction);
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -282,48 +298,79 @@ static inline void dma_unmap_sg(struct device *dev, struct scatterlist *sg,
|
|||||||
dma_unmap_sg_attrs(dev, sg, nhwentries, direction, NULL);
|
dma_unmap_sg_attrs(dev, sg, nhwentries, direction, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_PPC_NEED_DMA_SYNC_OPS
|
||||||
static inline void dma_sync_single_for_cpu(struct device *dev,
|
static inline void dma_sync_single_for_cpu(struct device *dev,
|
||||||
dma_addr_t dma_handle, size_t size,
|
dma_addr_t dma_handle, size_t size,
|
||||||
enum dma_data_direction direction)
|
enum dma_data_direction direction)
|
||||||
{
|
{
|
||||||
BUG_ON(direction == DMA_NONE);
|
struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
|
||||||
__dma_sync(bus_to_virt(dma_handle), size, direction);
|
|
||||||
|
BUG_ON(!dma_ops);
|
||||||
|
dma_ops->sync_single_range_for_cpu(dev, dma_handle, 0,
|
||||||
|
size, direction);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void dma_sync_single_for_device(struct device *dev,
|
static inline void dma_sync_single_for_device(struct device *dev,
|
||||||
dma_addr_t dma_handle, size_t size,
|
dma_addr_t dma_handle, size_t size,
|
||||||
enum dma_data_direction direction)
|
enum dma_data_direction direction)
|
||||||
{
|
{
|
||||||
BUG_ON(direction == DMA_NONE);
|
struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
|
||||||
__dma_sync(bus_to_virt(dma_handle), size, direction);
|
|
||||||
|
BUG_ON(!dma_ops);
|
||||||
|
dma_ops->sync_single_range_for_device(dev, dma_handle,
|
||||||
|
0, size, direction);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void dma_sync_sg_for_cpu(struct device *dev,
|
static inline void dma_sync_sg_for_cpu(struct device *dev,
|
||||||
struct scatterlist *sgl, int nents,
|
struct scatterlist *sgl, int nents,
|
||||||
enum dma_data_direction direction)
|
enum dma_data_direction direction)
|
||||||
{
|
{
|
||||||
struct scatterlist *sg;
|
struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
|
||||||
int i;
|
|
||||||
|
|
||||||
BUG_ON(direction == DMA_NONE);
|
BUG_ON(!dma_ops);
|
||||||
|
dma_ops->sync_sg_for_cpu(dev, sgl, nents, direction);
|
||||||
for_each_sg(sgl, sg, nents, i)
|
|
||||||
__dma_sync_page(sg_page(sg), sg->offset, sg->length, direction);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void dma_sync_sg_for_device(struct device *dev,
|
static inline void dma_sync_sg_for_device(struct device *dev,
|
||||||
struct scatterlist *sgl, int nents,
|
struct scatterlist *sgl, int nents,
|
||||||
enum dma_data_direction direction)
|
enum dma_data_direction direction)
|
||||||
{
|
{
|
||||||
struct scatterlist *sg;
|
struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
|
||||||
int i;
|
|
||||||
|
|
||||||
BUG_ON(direction == DMA_NONE);
|
BUG_ON(!dma_ops);
|
||||||
|
dma_ops->sync_sg_for_device(dev, sgl, nents, direction);
|
||||||
for_each_sg(sgl, sg, nents, i)
|
|
||||||
__dma_sync_page(sg_page(sg), sg->offset, sg->length, direction);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void dma_sync_single_range_for_cpu(struct device *dev,
|
||||||
|
dma_addr_t dma_handle, unsigned long offset, size_t size,
|
||||||
|
enum dma_data_direction direction)
|
||||||
|
{
|
||||||
|
struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
|
||||||
|
|
||||||
|
BUG_ON(!dma_ops);
|
||||||
|
dma_ops->sync_single_range_for_cpu(dev, dma_handle,
|
||||||
|
offset, size, direction);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void dma_sync_single_range_for_device(struct device *dev,
|
||||||
|
dma_addr_t dma_handle, unsigned long offset, size_t size,
|
||||||
|
enum dma_data_direction direction)
|
||||||
|
{
|
||||||
|
struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
|
||||||
|
|
||||||
|
BUG_ON(!dma_ops);
|
||||||
|
dma_ops->sync_single_range_for_device(dev, dma_handle, offset,
|
||||||
|
size, direction);
|
||||||
|
}
|
||||||
|
#else /* CONFIG_PPC_NEED_DMA_SYNC_OPS */
|
||||||
|
#define dma_sync_single_for_cpu(d, h, s, dir) ((void)0)
|
||||||
|
#define dma_sync_single_for_device(d, h, s, dir) ((void)0)
|
||||||
|
#define dma_sync_single_range_for_cpu(d, h, o, s, dir) ((void)0)
|
||||||
|
#define dma_sync_single_range_for_device(d, h, o, s, dir) ((void)0)
|
||||||
|
#define dma_sync_sg_for_cpu(d, s, n, dir) ((void)0)
|
||||||
|
#define dma_sync_sg_for_device(d, s, n, dir) ((void)0)
|
||||||
|
#endif
|
||||||
|
|
||||||
static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
|
static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_PPC64
|
#ifdef CONFIG_PPC64
|
||||||
@@ -356,22 +403,6 @@ static inline int dma_get_cache_alignment(void)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void dma_sync_single_range_for_cpu(struct device *dev,
|
|
||||||
dma_addr_t dma_handle, unsigned long offset, size_t size,
|
|
||||||
enum dma_data_direction direction)
|
|
||||||
{
|
|
||||||
/* just sync everything for now */
|
|
||||||
dma_sync_single_for_cpu(dev, dma_handle, offset + size, direction);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void dma_sync_single_range_for_device(struct device *dev,
|
|
||||||
dma_addr_t dma_handle, unsigned long offset, size_t size,
|
|
||||||
enum dma_data_direction direction)
|
|
||||||
{
|
|
||||||
/* just sync everything for now */
|
|
||||||
dma_sync_single_for_device(dev, dma_handle, offset + size, direction);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
|
static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
|
||||||
enum dma_data_direction direction)
|
enum dma_data_direction direction)
|
||||||
{
|
{
|
||||||
|
@@ -120,6 +120,26 @@ static inline void dma_direct_unmap_page(struct device *dev,
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_NOT_COHERENT_CACHE
|
||||||
|
static inline void dma_direct_sync_sg(struct device *dev,
|
||||||
|
struct scatterlist *sgl, int nents,
|
||||||
|
enum dma_data_direction direction)
|
||||||
|
{
|
||||||
|
struct scatterlist *sg;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for_each_sg(sgl, sg, nents, i)
|
||||||
|
__dma_sync_page(sg_page(sg), sg->offset, sg->length, direction);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void dma_direct_sync_single_range(struct device *dev,
|
||||||
|
dma_addr_t dma_handle, unsigned long offset, size_t size,
|
||||||
|
enum dma_data_direction direction)
|
||||||
|
{
|
||||||
|
__dma_sync(bus_to_virt(dma_handle+offset), size, direction);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
struct dma_mapping_ops dma_direct_ops = {
|
struct dma_mapping_ops dma_direct_ops = {
|
||||||
.alloc_coherent = dma_direct_alloc_coherent,
|
.alloc_coherent = dma_direct_alloc_coherent,
|
||||||
.free_coherent = dma_direct_free_coherent,
|
.free_coherent = dma_direct_free_coherent,
|
||||||
@@ -128,5 +148,11 @@ struct dma_mapping_ops dma_direct_ops = {
|
|||||||
.dma_supported = dma_direct_dma_supported,
|
.dma_supported = dma_direct_dma_supported,
|
||||||
.map_page = dma_direct_map_page,
|
.map_page = dma_direct_map_page,
|
||||||
.unmap_page = dma_direct_unmap_page,
|
.unmap_page = dma_direct_unmap_page,
|
||||||
|
#ifdef CONFIG_NOT_COHERENT_CACHE
|
||||||
|
.sync_single_range_for_cpu = dma_direct_sync_single_range,
|
||||||
|
.sync_single_range_for_device = dma_direct_sync_single_range,
|
||||||
|
.sync_sg_for_cpu = dma_direct_sync_sg,
|
||||||
|
.sync_sg_for_device = dma_direct_sync_sg,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
EXPORT_SYMBOL(dma_direct_ops);
|
EXPORT_SYMBOL(dma_direct_ops);
|
||||||
|
Reference in New Issue
Block a user