Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 123046
b: refs/heads/master
c: 15e09c0
h: refs/heads/master
v: v3
  • Loading branch information
Becky Bruce authored and Paul Mackerras committed Dec 3, 2008
1 parent 9ee7514 commit de15809
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 32 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: c4d04be11f99cc9ce4e3801a5da235727db704a9
refs/heads/master: 15e09c0ecaab4a1b4a7ed69db536c38948b92279
4 changes: 4 additions & 0 deletions trunk/arch/powerpc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,10 @@ config IOMMU_VMERGE
config IOMMU_HELPER
def_bool PPC64

config PPC_NEED_DMA_SYNC_OPS
def_bool y
depends on NOT_COHERENT_CACHE

config HOTPLUG_CPU
bool "Support for enabling/disabling CPUs"
depends on SMP && HOTPLUG && EXPERIMENTAL && (PPC_PSERIES || PPC_PMAC)
Expand Down
93 changes: 62 additions & 31 deletions trunk/arch/powerpc/include/asm/dma-mapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,22 @@ struct dma_mapping_ops {
dma_addr_t dma_address, size_t size,
enum dma_data_direction direction,
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
};

/*
Expand Down Expand Up @@ -282,47 +298,78 @@ static inline void dma_unmap_sg(struct device *dev, struct scatterlist *sg,
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,
dma_addr_t dma_handle, size_t size,
enum dma_data_direction direction)
{
BUG_ON(direction == DMA_NONE);
__dma_sync(bus_to_virt(dma_handle), size, 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, 0,
size, direction);
}

static inline void dma_sync_single_for_device(struct device *dev,
dma_addr_t dma_handle, size_t size,
enum dma_data_direction direction)
{
BUG_ON(direction == DMA_NONE);
__dma_sync(bus_to_virt(dma_handle), size, 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,
0, size, direction);
}

static inline void dma_sync_sg_for_cpu(struct device *dev,
struct scatterlist *sgl, int nents,
enum dma_data_direction direction)
{
struct scatterlist *sg;
int i;

BUG_ON(direction == DMA_NONE);
struct dma_mapping_ops *dma_ops = get_dma_ops(dev);

for_each_sg(sgl, sg, nents, i)
__dma_sync_page(sg_page(sg), sg->offset, sg->length, direction);
BUG_ON(!dma_ops);
dma_ops->sync_sg_for_cpu(dev, sgl, nents, direction);
}

static inline void dma_sync_sg_for_device(struct device *dev,
struct scatterlist *sgl, int nents,
enum dma_data_direction direction)
{
struct scatterlist *sg;
int i;
struct dma_mapping_ops *dma_ops = get_dma_ops(dev);

BUG_ON(direction == DMA_NONE);
BUG_ON(!dma_ops);
dma_ops->sync_sg_for_device(dev, sgl, nents, 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);

for_each_sg(sgl, sg, nents, i)
__dma_sync_page(sg_page(sg), sg->offset, sg->length, direction);
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)
{
Expand Down Expand Up @@ -356,22 +403,6 @@ static inline int dma_get_cache_alignment(void)
#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,
enum dma_data_direction direction)
{
Expand Down
26 changes: 26 additions & 0 deletions trunk/arch/powerpc/kernel/dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
.alloc_coherent = dma_direct_alloc_coherent,
.free_coherent = dma_direct_free_coherent,
Expand All @@ -128,5 +148,11 @@ struct dma_mapping_ops dma_direct_ops = {
.dma_supported = dma_direct_dma_supported,
.map_page = dma_direct_map_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);

0 comments on commit de15809

Please sign in to comment.