提交 07f1c295 编写于 作者: R Russell King

Merge branch 'dma' of http://git.linaro.org/git/people/nico/linux into devel-stable

...@@ -79,6 +79,8 @@ struct dmabounce_device_info { ...@@ -79,6 +79,8 @@ struct dmabounce_device_info {
struct dmabounce_pool large; struct dmabounce_pool large;
rwlock_t lock; rwlock_t lock;
int (*needs_bounce)(struct device *, dma_addr_t, size_t);
}; };
#ifdef STATS #ifdef STATS
...@@ -210,114 +212,91 @@ static struct safe_buffer *find_safe_buffer_dev(struct device *dev, ...@@ -210,114 +212,91 @@ static struct safe_buffer *find_safe_buffer_dev(struct device *dev,
if (!dev || !dev->archdata.dmabounce) if (!dev || !dev->archdata.dmabounce)
return NULL; return NULL;
if (dma_mapping_error(dev, dma_addr)) { if (dma_mapping_error(dev, dma_addr)) {
if (dev) dev_err(dev, "Trying to %s invalid mapping\n", where);
dev_err(dev, "Trying to %s invalid mapping\n", where);
else
pr_err("unknown device: Trying to %s invalid mapping\n", where);
return NULL; return NULL;
} }
return find_safe_buffer(dev->archdata.dmabounce, dma_addr); return find_safe_buffer(dev->archdata.dmabounce, dma_addr);
} }
static inline dma_addr_t map_single(struct device *dev, void *ptr, size_t size, static int needs_bounce(struct device *dev, dma_addr_t dma_addr, size_t size)
enum dma_data_direction dir)
{ {
struct dmabounce_device_info *device_info = dev->archdata.dmabounce; if (!dev || !dev->archdata.dmabounce)
dma_addr_t dma_addr; return 0;
int needs_bounce = 0;
if (device_info)
DO_STATS ( device_info->map_op_count++ );
dma_addr = virt_to_dma(dev, ptr);
if (dev->dma_mask) { if (dev->dma_mask) {
unsigned long mask = *dev->dma_mask; unsigned long limit, mask = *dev->dma_mask;
unsigned long limit;
limit = (mask + 1) & ~mask; limit = (mask + 1) & ~mask;
if (limit && size > limit) { if (limit && size > limit) {
dev_err(dev, "DMA mapping too big (requested %#x " dev_err(dev, "DMA mapping too big (requested %#x "
"mask %#Lx)\n", size, *dev->dma_mask); "mask %#Lx)\n", size, *dev->dma_mask);
return ~0; return -E2BIG;
} }
/* /* Figure out if we need to bounce from the DMA mask. */
* Figure out if we need to bounce from the DMA mask. if ((dma_addr | (dma_addr + size - 1)) & ~mask)
*/ return 1;
needs_bounce = (dma_addr | (dma_addr + size - 1)) & ~mask;
} }
if (device_info && (needs_bounce || dma_needs_bounce(dev, dma_addr, size))) { return !!dev->archdata.dmabounce->needs_bounce(dev, dma_addr, size);
struct safe_buffer *buf; }
buf = alloc_safe_buffer(device_info, ptr, size, dir); static inline dma_addr_t map_single(struct device *dev, void *ptr, size_t size,
if (buf == 0) { enum dma_data_direction dir)
dev_err(dev, "%s: unable to map unsafe buffer %p!\n", {
__func__, ptr); struct dmabounce_device_info *device_info = dev->archdata.dmabounce;
return ~0; struct safe_buffer *buf;
}
dev_dbg(dev, if (device_info)
"%s: unsafe buffer %p (dma=%#x) mapped to %p (dma=%#x)\n", DO_STATS ( device_info->map_op_count++ );
__func__, buf->ptr, virt_to_dma(dev, buf->ptr),
buf->safe, buf->safe_dma_addr);
if ((dir == DMA_TO_DEVICE) || buf = alloc_safe_buffer(device_info, ptr, size, dir);
(dir == DMA_BIDIRECTIONAL)) { if (buf == NULL) {
dev_dbg(dev, "%s: copy unsafe %p to safe %p, size %d\n", dev_err(dev, "%s: unable to map unsafe buffer %p!\n",
__func__, ptr, buf->safe, size); __func__, ptr);
memcpy(buf->safe, ptr, size); return ~0;
} }
ptr = buf->safe;
dma_addr = buf->safe_dma_addr; dev_dbg(dev, "%s: unsafe buffer %p (dma=%#x) mapped to %p (dma=%#x)\n",
} else { __func__, buf->ptr, virt_to_dma(dev, buf->ptr),
/* buf->safe, buf->safe_dma_addr);
* We don't need to sync the DMA buffer since
* it was allocated via the coherent allocators. if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL) {
*/ dev_dbg(dev, "%s: copy unsafe %p to safe %p, size %d\n",
__dma_single_cpu_to_dev(ptr, size, dir); __func__, ptr, buf->safe, size);
memcpy(buf->safe, ptr, size);
} }
return dma_addr; return buf->safe_dma_addr;
} }
static inline void unmap_single(struct device *dev, dma_addr_t dma_addr, static inline void unmap_single(struct device *dev, struct safe_buffer *buf,
size_t size, enum dma_data_direction dir) size_t size, enum dma_data_direction dir)
{ {
struct safe_buffer *buf = find_safe_buffer_dev(dev, dma_addr, "unmap"); BUG_ON(buf->size != size);
BUG_ON(buf->direction != dir);
if (buf) {
BUG_ON(buf->size != size);
BUG_ON(buf->direction != dir);
dev_dbg(dev, dev_dbg(dev, "%s: unsafe buffer %p (dma=%#x) mapped to %p (dma=%#x)\n",
"%s: unsafe buffer %p (dma=%#x) mapped to %p (dma=%#x)\n", __func__, buf->ptr, virt_to_dma(dev, buf->ptr),
__func__, buf->ptr, virt_to_dma(dev, buf->ptr), buf->safe, buf->safe_dma_addr);
buf->safe, buf->safe_dma_addr);
DO_STATS(dev->archdata.dmabounce->bounce_count++); DO_STATS(dev->archdata.dmabounce->bounce_count++);
if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL) { if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL) {
void *ptr = buf->ptr; void *ptr = buf->ptr;
dev_dbg(dev, dev_dbg(dev, "%s: copy back safe %p to unsafe %p size %d\n",
"%s: copy back safe %p to unsafe %p size %d\n", __func__, buf->safe, ptr, size);
__func__, buf->safe, ptr, size); memcpy(ptr, buf->safe, size);
memcpy(ptr, buf->safe, size);
/* /*
* Since we may have written to a page cache page, * Since we may have written to a page cache page,
* we need to ensure that the data will be coherent * we need to ensure that the data will be coherent
* with user mappings. * with user mappings.
*/ */
__cpuc_flush_dcache_area(ptr, size); __cpuc_flush_dcache_area(ptr, size);
}
free_safe_buffer(dev->archdata.dmabounce, buf);
} else {
__dma_single_dev_to_cpu(dma_to_virt(dev, dma_addr), size, dir);
} }
free_safe_buffer(dev->archdata.dmabounce, buf);
} }
/* ************************************************** */ /* ************************************************** */
...@@ -328,45 +307,28 @@ static inline void unmap_single(struct device *dev, dma_addr_t dma_addr, ...@@ -328,45 +307,28 @@ static inline void unmap_single(struct device *dev, dma_addr_t dma_addr,
* substitute the safe buffer for the unsafe one. * substitute the safe buffer for the unsafe one.
* (basically move the buffer from an unsafe area to a safe one) * (basically move the buffer from an unsafe area to a safe one)
*/ */
dma_addr_t __dma_map_single(struct device *dev, void *ptr, size_t size,
enum dma_data_direction dir)
{
dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n",
__func__, ptr, size, dir);
BUG_ON(!valid_dma_direction(dir));
return map_single(dev, ptr, size, dir);
}
EXPORT_SYMBOL(__dma_map_single);
/*
* see if a mapped address was really a "safe" buffer and if so, copy
* the data from the safe buffer back to the unsafe buffer and free up
* the safe buffer. (basically return things back to the way they
* should be)
*/
void __dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
enum dma_data_direction dir)
{
dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n",
__func__, (void *) dma_addr, size, dir);
unmap_single(dev, dma_addr, size, dir);
}
EXPORT_SYMBOL(__dma_unmap_single);
dma_addr_t __dma_map_page(struct device *dev, struct page *page, dma_addr_t __dma_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size, enum dma_data_direction dir) unsigned long offset, size_t size, enum dma_data_direction dir)
{ {
dma_addr_t dma_addr;
int ret;
dev_dbg(dev, "%s(page=%p,off=%#lx,size=%zx,dir=%x)\n", dev_dbg(dev, "%s(page=%p,off=%#lx,size=%zx,dir=%x)\n",
__func__, page, offset, size, dir); __func__, page, offset, size, dir);
BUG_ON(!valid_dma_direction(dir)); dma_addr = pfn_to_dma(dev, page_to_pfn(page)) + offset;
ret = needs_bounce(dev, dma_addr, size);
if (ret < 0)
return ~0;
if (ret == 0) {
__dma_page_cpu_to_dev(page, offset, size, dir);
return dma_addr;
}
if (PageHighMem(page)) { if (PageHighMem(page)) {
dev_err(dev, "DMA buffer bouncing of HIGHMEM pages " dev_err(dev, "DMA buffer bouncing of HIGHMEM pages is not supported\n");
"is not supported\n");
return ~0; return ~0;
} }
...@@ -383,10 +345,19 @@ EXPORT_SYMBOL(__dma_map_page); ...@@ -383,10 +345,19 @@ EXPORT_SYMBOL(__dma_map_page);
void __dma_unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size, void __dma_unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size,
enum dma_data_direction dir) enum dma_data_direction dir)
{ {
dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n", struct safe_buffer *buf;
__func__, (void *) dma_addr, size, dir);
dev_dbg(dev, "%s(dma=%#x,size=%d,dir=%x)\n",
__func__, dma_addr, size, dir);
buf = find_safe_buffer_dev(dev, dma_addr, __func__);
if (!buf) {
__dma_page_dev_to_cpu(pfn_to_page(dma_to_pfn(dev, dma_addr)),
dma_addr & ~PAGE_MASK, size, dir);
return;
}
unmap_single(dev, dma_addr, size, dir); unmap_single(dev, buf, size, dir);
} }
EXPORT_SYMBOL(__dma_unmap_page); EXPORT_SYMBOL(__dma_unmap_page);
...@@ -461,7 +432,8 @@ static int dmabounce_init_pool(struct dmabounce_pool *pool, struct device *dev, ...@@ -461,7 +432,8 @@ static int dmabounce_init_pool(struct dmabounce_pool *pool, struct device *dev,
} }
int dmabounce_register_dev(struct device *dev, unsigned long small_buffer_size, int dmabounce_register_dev(struct device *dev, unsigned long small_buffer_size,
unsigned long large_buffer_size) unsigned long large_buffer_size,
int (*needs_bounce_fn)(struct device *, dma_addr_t, size_t))
{ {
struct dmabounce_device_info *device_info; struct dmabounce_device_info *device_info;
int ret; int ret;
...@@ -497,6 +469,7 @@ int dmabounce_register_dev(struct device *dev, unsigned long small_buffer_size, ...@@ -497,6 +469,7 @@ int dmabounce_register_dev(struct device *dev, unsigned long small_buffer_size,
device_info->dev = dev; device_info->dev = dev;
INIT_LIST_HEAD(&device_info->safe_buffers); INIT_LIST_HEAD(&device_info->safe_buffers);
rwlock_init(&device_info->lock); rwlock_init(&device_info->lock);
device_info->needs_bounce = needs_bounce_fn;
#ifdef STATS #ifdef STATS
device_info->total_allocs = 0; device_info->total_allocs = 0;
......
...@@ -243,6 +243,12 @@ static struct resource it8152_mem = { ...@@ -243,6 +243,12 @@ static struct resource it8152_mem = {
* ITE8152 chip can address up to 64MByte, so all the devices * ITE8152 chip can address up to 64MByte, so all the devices
* connected to ITE8152 (PCI and USB) should have limited DMA window * connected to ITE8152 (PCI and USB) should have limited DMA window
*/ */
static int it8152_needs_bounce(struct device *dev, dma_addr_t dma_addr, size_t size)
{
dev_dbg(dev, "%s: dma_addr %08x, size %08x\n",
__func__, dma_addr, size);
return (dma_addr + size - PHYS_OFFSET) >= SZ_64M;
}
/* /*
* Setup DMA mask to 64MB on devices connected to ITE8152. Ignore all * Setup DMA mask to 64MB on devices connected to ITE8152. Ignore all
...@@ -254,7 +260,7 @@ static int it8152_pci_platform_notify(struct device *dev) ...@@ -254,7 +260,7 @@ static int it8152_pci_platform_notify(struct device *dev)
if (dev->dma_mask) if (dev->dma_mask)
*dev->dma_mask = (SZ_64M - 1) | PHYS_OFFSET; *dev->dma_mask = (SZ_64M - 1) | PHYS_OFFSET;
dev->coherent_dma_mask = (SZ_64M - 1) | PHYS_OFFSET; dev->coherent_dma_mask = (SZ_64M - 1) | PHYS_OFFSET;
dmabounce_register_dev(dev, 2048, 4096); dmabounce_register_dev(dev, 2048, 4096, it8152_needs_bounce);
} }
return 0; return 0;
} }
...@@ -267,14 +273,6 @@ static int it8152_pci_platform_notify_remove(struct device *dev) ...@@ -267,14 +273,6 @@ static int it8152_pci_platform_notify_remove(struct device *dev)
return 0; return 0;
} }
int dma_needs_bounce(struct device *dev, dma_addr_t dma_addr, size_t size)
{
dev_dbg(dev, "%s: dma_addr %08x, size %08x\n",
__func__, dma_addr, size);
return (dev->bus == &pci_bus_type) &&
((dma_addr + size - PHYS_OFFSET) >= SZ_64M);
}
int dma_set_coherent_mask(struct device *dev, u64 mask) int dma_set_coherent_mask(struct device *dev, u64 mask)
{ {
if (mask >= PHYS_OFFSET + SZ_64M - 1) if (mask >= PHYS_OFFSET + SZ_64M - 1)
......
...@@ -579,7 +579,36 @@ sa1111_configure_smc(struct sa1111 *sachip, int sdram, unsigned int drac, ...@@ -579,7 +579,36 @@ sa1111_configure_smc(struct sa1111 *sachip, int sdram, unsigned int drac,
sachip->dev->coherent_dma_mask &= sa1111_dma_mask[drac >> 2]; sachip->dev->coherent_dma_mask &= sa1111_dma_mask[drac >> 2];
} }
#endif
#ifdef CONFIG_DMABOUNCE
/*
* According to the "Intel StrongARM SA-1111 Microprocessor Companion
* Chip Specification Update" (June 2000), erratum #7, there is a
* significant bug in the SA1111 SDRAM shared memory controller. If
* an access to a region of memory above 1MB relative to the bank base,
* it is important that address bit 10 _NOT_ be asserted. Depending
* on the configuration of the RAM, bit 10 may correspond to one
* of several different (processor-relative) address bits.
*
* This routine only identifies whether or not a given DMA address
* is susceptible to the bug.
*
* This should only get called for sa1111_device types due to the
* way we configure our device dma_masks.
*/
static int sa1111_needs_bounce(struct device *dev, dma_addr_t addr, size_t size)
{
/*
* Section 4.6 of the "Intel StrongARM SA-1111 Development Module
* User's Guide" mentions that jumpers R51 and R52 control the
* target of SA-1111 DMA (either SDRAM bank 0 on Assabet, or
* SDRAM bank 1 on Neponset). The default configuration selects
* Assabet, so any address in bank 1 is necessarily invalid.
*/
return (machine_is_assabet() || machine_is_pfs168()) &&
(addr >= 0xc8000000 || (addr + size) >= 0xc8000000);
}
#endif #endif
static void sa1111_dev_release(struct device *_dev) static void sa1111_dev_release(struct device *_dev)
...@@ -644,7 +673,8 @@ sa1111_init_one_child(struct sa1111 *sachip, struct resource *parent, ...@@ -644,7 +673,8 @@ sa1111_init_one_child(struct sa1111 *sachip, struct resource *parent,
dev->dev.dma_mask = &dev->dma_mask; dev->dev.dma_mask = &dev->dma_mask;
if (dev->dma_mask != 0xffffffffUL) { if (dev->dma_mask != 0xffffffffUL) {
ret = dmabounce_register_dev(&dev->dev, 1024, 4096); ret = dmabounce_register_dev(&dev->dev, 1024, 4096,
sa1111_needs_bounce);
if (ret) { if (ret) {
dev_err(&dev->dev, "SA1111: Failed to register" dev_err(&dev->dev, "SA1111: Failed to register"
" with dmabounce\n"); " with dmabounce\n");
...@@ -818,34 +848,6 @@ static void __sa1111_remove(struct sa1111 *sachip) ...@@ -818,34 +848,6 @@ static void __sa1111_remove(struct sa1111 *sachip)
kfree(sachip); kfree(sachip);
} }
/*
* According to the "Intel StrongARM SA-1111 Microprocessor Companion
* Chip Specification Update" (June 2000), erratum #7, there is a
* significant bug in the SA1111 SDRAM shared memory controller. If
* an access to a region of memory above 1MB relative to the bank base,
* it is important that address bit 10 _NOT_ be asserted. Depending
* on the configuration of the RAM, bit 10 may correspond to one
* of several different (processor-relative) address bits.
*
* This routine only identifies whether or not a given DMA address
* is susceptible to the bug.
*
* This should only get called for sa1111_device types due to the
* way we configure our device dma_masks.
*/
int dma_needs_bounce(struct device *dev, dma_addr_t addr, size_t size)
{
/*
* Section 4.6 of the "Intel StrongARM SA-1111 Development Module
* User's Guide" mentions that jumpers R51 and R52 control the
* target of SA-1111 DMA (either SDRAM bank 0 on Assabet, or
* SDRAM bank 1 on Neponset). The default configuration selects
* Assabet, so any address in bank 1 is necessarily invalid.
*/
return ((machine_is_assabet() || machine_is_pfs168()) &&
(addr >= 0xc8000000 || (addr + size) >= 0xc8000000));
}
struct sa1111_save_data { struct sa1111_save_data {
unsigned int skcr; unsigned int skcr;
unsigned int skpcr; unsigned int skpcr;
......
...@@ -115,39 +115,8 @@ static inline void __dma_page_dev_to_cpu(struct page *page, unsigned long off, ...@@ -115,39 +115,8 @@ static inline void __dma_page_dev_to_cpu(struct page *page, unsigned long off,
___dma_page_dev_to_cpu(page, off, size, dir); ___dma_page_dev_to_cpu(page, off, size, dir);
} }
/* extern int dma_supported(struct device *, u64);
* Return whether the given device DMA address mask can be supported extern int dma_set_mask(struct device *, u64);
* properly. For example, if your device can only drive the low 24-bits
* during bus mastering, then you would pass 0x00ffffff as the mask
* to this function.
*
* FIXME: This should really be a platform specific issue - we should
* return false if GFP_DMA allocations may not satisfy the supplied 'mask'.
*/
static inline int dma_supported(struct device *dev, u64 mask)
{
if (mask < ISA_DMA_THRESHOLD)
return 0;
return 1;
}
static inline int dma_set_mask(struct device *dev, u64 dma_mask)
{
#ifdef CONFIG_DMABOUNCE
if (dev->archdata.dmabounce) {
if (dma_mask >= ISA_DMA_THRESHOLD)
return 0;
else
return -EIO;
}
#endif
if (!dev->dma_mask || !dma_supported(dev, dma_mask))
return -EIO;
*dev->dma_mask = dma_mask;
return 0;
}
/* /*
* DMA errors are defined by all-bits-set in the DMA address. * DMA errors are defined by all-bits-set in the DMA address.
...@@ -256,14 +225,14 @@ int dma_mmap_writecombine(struct device *, struct vm_area_struct *, ...@@ -256,14 +225,14 @@ int dma_mmap_writecombine(struct device *, struct vm_area_struct *,
* @dev: valid struct device pointer * @dev: valid struct device pointer
* @small_buf_size: size of buffers to use with small buffer pool * @small_buf_size: size of buffers to use with small buffer pool
* @large_buf_size: size of buffers to use with large buffer pool (can be 0) * @large_buf_size: size of buffers to use with large buffer pool (can be 0)
* @needs_bounce_fn: called to determine whether buffer needs bouncing
* *
* This function should be called by low-level platform code to register * This function should be called by low-level platform code to register
* a device as requireing DMA buffer bouncing. The function will allocate * a device as requireing DMA buffer bouncing. The function will allocate
* appropriate DMA pools for the device. * appropriate DMA pools for the device.
*
*/ */
extern int dmabounce_register_dev(struct device *, unsigned long, extern int dmabounce_register_dev(struct device *, unsigned long,
unsigned long); unsigned long, int (*)(struct device *, dma_addr_t, size_t));
/** /**
* dmabounce_unregister_dev * dmabounce_unregister_dev
...@@ -277,31 +246,9 @@ extern int dmabounce_register_dev(struct device *, unsigned long, ...@@ -277,31 +246,9 @@ extern int dmabounce_register_dev(struct device *, unsigned long,
*/ */
extern void dmabounce_unregister_dev(struct device *); extern void dmabounce_unregister_dev(struct device *);
/**
* dma_needs_bounce
*
* @dev: valid struct device pointer
* @dma_handle: dma_handle of unbounced buffer
* @size: size of region being mapped
*
* Platforms that utilize the dmabounce mechanism must implement
* this function.
*
* The dmabounce routines call this function whenever a dma-mapping
* is requested to determine whether a given buffer needs to be bounced
* or not. The function must return 0 if the buffer is OK for
* DMA access and 1 if the buffer needs to be bounced.
*
*/
extern int dma_needs_bounce(struct device*, dma_addr_t, size_t);
/* /*
* The DMA API, implemented by dmabounce.c. See below for descriptions. * The DMA API, implemented by dmabounce.c. See below for descriptions.
*/ */
extern dma_addr_t __dma_map_single(struct device *, void *, size_t,
enum dma_data_direction);
extern void __dma_unmap_single(struct device *, dma_addr_t, size_t,
enum dma_data_direction);
extern dma_addr_t __dma_map_page(struct device *, struct page *, extern dma_addr_t __dma_map_page(struct device *, struct page *,
unsigned long, size_t, enum dma_data_direction); unsigned long, size_t, enum dma_data_direction);
extern void __dma_unmap_page(struct device *, dma_addr_t, size_t, extern void __dma_unmap_page(struct device *, dma_addr_t, size_t,
...@@ -328,13 +275,6 @@ static inline int dmabounce_sync_for_device(struct device *d, dma_addr_t addr, ...@@ -328,13 +275,6 @@ static inline int dmabounce_sync_for_device(struct device *d, dma_addr_t addr,
} }
static inline dma_addr_t __dma_map_single(struct device *dev, void *cpu_addr,
size_t size, enum dma_data_direction dir)
{
__dma_single_cpu_to_dev(cpu_addr, size, dir);
return virt_to_dma(dev, cpu_addr);
}
static inline dma_addr_t __dma_map_page(struct device *dev, struct page *page, static inline dma_addr_t __dma_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size, enum dma_data_direction dir) unsigned long offset, size_t size, enum dma_data_direction dir)
{ {
...@@ -342,12 +282,6 @@ static inline dma_addr_t __dma_map_page(struct device *dev, struct page *page, ...@@ -342,12 +282,6 @@ static inline dma_addr_t __dma_map_page(struct device *dev, struct page *page,
return pfn_to_dma(dev, page_to_pfn(page)) + offset; return pfn_to_dma(dev, page_to_pfn(page)) + offset;
} }
static inline void __dma_unmap_single(struct device *dev, dma_addr_t handle,
size_t size, enum dma_data_direction dir)
{
__dma_single_dev_to_cpu(dma_to_virt(dev, handle), size, dir);
}
static inline void __dma_unmap_page(struct device *dev, dma_addr_t handle, static inline void __dma_unmap_page(struct device *dev, dma_addr_t handle,
size_t size, enum dma_data_direction dir) size_t size, enum dma_data_direction dir)
{ {
...@@ -373,14 +307,18 @@ static inline void __dma_unmap_page(struct device *dev, dma_addr_t handle, ...@@ -373,14 +307,18 @@ static inline void __dma_unmap_page(struct device *dev, dma_addr_t handle,
static inline dma_addr_t dma_map_single(struct device *dev, void *cpu_addr, static inline dma_addr_t dma_map_single(struct device *dev, void *cpu_addr,
size_t size, enum dma_data_direction dir) size_t size, enum dma_data_direction dir)
{ {
unsigned long offset;
struct page *page;
dma_addr_t addr; dma_addr_t addr;
BUG_ON(!virt_addr_valid(cpu_addr));
BUG_ON(!virt_addr_valid(cpu_addr + size - 1));
BUG_ON(!valid_dma_direction(dir)); BUG_ON(!valid_dma_direction(dir));
addr = __dma_map_single(dev, cpu_addr, size, dir); page = virt_to_page(cpu_addr);
debug_dma_map_page(dev, virt_to_page(cpu_addr), offset = (unsigned long)cpu_addr & ~PAGE_MASK;
(unsigned long)cpu_addr & ~PAGE_MASK, size, addr = __dma_map_page(dev, page, offset, size, dir);
dir, addr, true); debug_dma_map_page(dev, page, offset, size, dir, addr, true);
return addr; return addr;
} }
...@@ -430,7 +368,7 @@ static inline void dma_unmap_single(struct device *dev, dma_addr_t handle, ...@@ -430,7 +368,7 @@ static inline void dma_unmap_single(struct device *dev, dma_addr_t handle,
size_t size, enum dma_data_direction dir) size_t size, enum dma_data_direction dir)
{ {
debug_dma_unmap_page(dev, handle, size, dir, true); debug_dma_unmap_page(dev, handle, size, dir, true);
__dma_unmap_single(dev, handle, size, dir); __dma_unmap_page(dev, handle, size, dir);
} }
/** /**
......
#ifndef __ASM_ARM_DMA_H #ifndef __ASM_ARM_DMA_H
#define __ASM_ARM_DMA_H #define __ASM_ARM_DMA_H
#include <asm/memory.h>
/* /*
* This is the maximum virtual address which can be DMA'd from. * This is the maximum virtual address which can be DMA'd from.
*/ */
#ifndef ARM_DMA_ZONE_SIZE #ifndef CONFIG_ZONE_DMA
#define MAX_DMA_ADDRESS 0xffffffff #define MAX_DMA_ADDRESS 0xffffffffUL
#else #else
#define MAX_DMA_ADDRESS (PAGE_OFFSET + ARM_DMA_ZONE_SIZE) #define MAX_DMA_ADDRESS ({ \
extern unsigned long arm_dma_zone_size; \
arm_dma_zone_size ? \
(PAGE_OFFSET + arm_dma_zone_size) : 0xffffffffUL; })
#endif #endif
#ifdef CONFIG_ISA_DMA_API #ifdef CONFIG_ISA_DMA_API
......
...@@ -23,6 +23,10 @@ struct machine_desc { ...@@ -23,6 +23,10 @@ struct machine_desc {
unsigned int nr_irqs; /* number of IRQs */ unsigned int nr_irqs; /* number of IRQs */
#ifdef CONFIG_ZONE_DMA
unsigned long dma_zone_size; /* size of DMA-able area */
#endif
unsigned int video_start; /* start of video RAM */ unsigned int video_start; /* start of video RAM */
unsigned int video_end; /* end of video RAM */ unsigned int video_end; /* end of video RAM */
......
...@@ -203,18 +203,6 @@ static inline unsigned long __phys_to_virt(unsigned long x) ...@@ -203,18 +203,6 @@ static inline unsigned long __phys_to_virt(unsigned long x)
#define PHYS_OFFSET PLAT_PHYS_OFFSET #define PHYS_OFFSET PLAT_PHYS_OFFSET
#endif #endif
/*
* The DMA mask corresponding to the maximum bus address allocatable
* using GFP_DMA. The default here places no restriction on DMA
* allocations. This must be the smallest DMA mask in the system,
* so a successful GFP_DMA allocation will always satisfy this.
*/
#ifndef ARM_DMA_ZONE_SIZE
#define ISA_DMA_THRESHOLD (0xffffffffULL)
#else
#define ISA_DMA_THRESHOLD (PHYS_OFFSET + ARM_DMA_ZONE_SIZE - 1)
#endif
/* /*
* PFNs are used to describe any physical page; this means * PFNs are used to describe any physical page; this means
* PFN 0 == physical address 0. * PFN 0 == physical address 0.
......
...@@ -918,6 +918,12 @@ void __init setup_arch(char **cmdline_p) ...@@ -918,6 +918,12 @@ void __init setup_arch(char **cmdline_p)
cpu_init(); cpu_init();
tcm_init(); tcm_init();
#ifdef CONFIG_ZONE_DMA
if (mdesc->dma_zone_size) {
extern unsigned long arm_dma_zone_size;
arm_dma_zone_size = mdesc->dma_zone_size;
}
#endif
#ifdef CONFIG_MULTI_IRQ_HANDLER #ifdef CONFIG_MULTI_IRQ_HANDLER
handle_arch_irq = mdesc->handle_irq; handle_arch_irq = mdesc->handle_irq;
#endif #endif
......
...@@ -681,4 +681,5 @@ MACHINE_START(DAVINCI_DA830_EVM, "DaVinci DA830/OMAP-L137/AM17x EVM") ...@@ -681,4 +681,5 @@ MACHINE_START(DAVINCI_DA830_EVM, "DaVinci DA830/OMAP-L137/AM17x EVM")
.init_irq = cp_intc_init, .init_irq = cp_intc_init,
.timer = &davinci_timer, .timer = &davinci_timer,
.init_machine = da830_evm_init, .init_machine = da830_evm_init,
.dma_zone_size = SZ_128M,
MACHINE_END MACHINE_END
...@@ -1261,4 +1261,5 @@ MACHINE_START(DAVINCI_DA850_EVM, "DaVinci DA850/OMAP-L138/AM18x EVM") ...@@ -1261,4 +1261,5 @@ MACHINE_START(DAVINCI_DA850_EVM, "DaVinci DA850/OMAP-L138/AM18x EVM")
.init_irq = cp_intc_init, .init_irq = cp_intc_init,
.timer = &davinci_timer, .timer = &davinci_timer,
.init_machine = da850_evm_init, .init_machine = da850_evm_init,
.dma_zone_size = SZ_128M,
MACHINE_END MACHINE_END
...@@ -356,4 +356,5 @@ MACHINE_START(DAVINCI_DM355_EVM, "DaVinci DM355 EVM") ...@@ -356,4 +356,5 @@ MACHINE_START(DAVINCI_DM355_EVM, "DaVinci DM355 EVM")
.init_irq = davinci_irq_init, .init_irq = davinci_irq_init,
.timer = &davinci_timer, .timer = &davinci_timer,
.init_machine = dm355_evm_init, .init_machine = dm355_evm_init,
.dma_zone_size = SZ_128M,
MACHINE_END MACHINE_END
...@@ -275,4 +275,5 @@ MACHINE_START(DM355_LEOPARD, "DaVinci DM355 leopard") ...@@ -275,4 +275,5 @@ MACHINE_START(DM355_LEOPARD, "DaVinci DM355 leopard")
.init_irq = davinci_irq_init, .init_irq = davinci_irq_init,
.timer = &davinci_timer, .timer = &davinci_timer,
.init_machine = dm355_leopard_init, .init_machine = dm355_leopard_init,
.dma_zone_size = SZ_128M,
MACHINE_END MACHINE_END
...@@ -617,5 +617,6 @@ MACHINE_START(DAVINCI_DM365_EVM, "DaVinci DM365 EVM") ...@@ -617,5 +617,6 @@ MACHINE_START(DAVINCI_DM365_EVM, "DaVinci DM365 EVM")
.init_irq = davinci_irq_init, .init_irq = davinci_irq_init,
.timer = &davinci_timer, .timer = &davinci_timer,
.init_machine = dm365_evm_init, .init_machine = dm365_evm_init,
.dma_zone_size = SZ_128M,
MACHINE_END MACHINE_END
...@@ -717,4 +717,5 @@ MACHINE_START(DAVINCI_EVM, "DaVinci DM644x EVM") ...@@ -717,4 +717,5 @@ MACHINE_START(DAVINCI_EVM, "DaVinci DM644x EVM")
.init_irq = davinci_irq_init, .init_irq = davinci_irq_init,
.timer = &davinci_timer, .timer = &davinci_timer,
.init_machine = davinci_evm_init, .init_machine = davinci_evm_init,
.dma_zone_size = SZ_128M,
MACHINE_END MACHINE_END
...@@ -802,6 +802,7 @@ MACHINE_START(DAVINCI_DM6467_EVM, "DaVinci DM646x EVM") ...@@ -802,6 +802,7 @@ MACHINE_START(DAVINCI_DM6467_EVM, "DaVinci DM646x EVM")
.init_irq = davinci_irq_init, .init_irq = davinci_irq_init,
.timer = &davinci_timer, .timer = &davinci_timer,
.init_machine = evm_init, .init_machine = evm_init,
.dma_zone_size = SZ_128M,
MACHINE_END MACHINE_END
MACHINE_START(DAVINCI_DM6467TEVM, "DaVinci DM6467T EVM") MACHINE_START(DAVINCI_DM6467TEVM, "DaVinci DM6467T EVM")
...@@ -810,5 +811,6 @@ MACHINE_START(DAVINCI_DM6467TEVM, "DaVinci DM6467T EVM") ...@@ -810,5 +811,6 @@ MACHINE_START(DAVINCI_DM6467TEVM, "DaVinci DM6467T EVM")
.init_irq = davinci_irq_init, .init_irq = davinci_irq_init,
.timer = &davinci_timer, .timer = &davinci_timer,
.init_machine = evm_init, .init_machine = evm_init,
.dma_zone_size = SZ_128M,
MACHINE_END MACHINE_END
...@@ -570,4 +570,5 @@ MACHINE_START(MITYOMAPL138, "MityDSP-L138/MityARM-1808") ...@@ -570,4 +570,5 @@ MACHINE_START(MITYOMAPL138, "MityDSP-L138/MityARM-1808")
.init_irq = cp_intc_init, .init_irq = cp_intc_init,
.timer = &davinci_timer, .timer = &davinci_timer,
.init_machine = mityomapl138_init, .init_machine = mityomapl138_init,
.dma_zone_size = SZ_128M,
MACHINE_END MACHINE_END
...@@ -277,4 +277,5 @@ MACHINE_START(NEUROS_OSD2, "Neuros OSD2") ...@@ -277,4 +277,5 @@ MACHINE_START(NEUROS_OSD2, "Neuros OSD2")
.init_irq = davinci_irq_init, .init_irq = davinci_irq_init,
.timer = &davinci_timer, .timer = &davinci_timer,
.init_machine = davinci_ntosd2_init, .init_machine = davinci_ntosd2_init,
.dma_zone_size = SZ_128M,
MACHINE_END MACHINE_END
...@@ -343,4 +343,5 @@ MACHINE_START(OMAPL138_HAWKBOARD, "AM18x/OMAP-L138 Hawkboard") ...@@ -343,4 +343,5 @@ MACHINE_START(OMAPL138_HAWKBOARD, "AM18x/OMAP-L138 Hawkboard")
.init_irq = cp_intc_init, .init_irq = cp_intc_init,
.timer = &davinci_timer, .timer = &davinci_timer,
.init_machine = omapl138_hawk_init, .init_machine = omapl138_hawk_init,
.dma_zone_size = SZ_128M,
MACHINE_END MACHINE_END
...@@ -156,4 +156,5 @@ MACHINE_START(SFFSDR, "Lyrtech SFFSDR") ...@@ -156,4 +156,5 @@ MACHINE_START(SFFSDR, "Lyrtech SFFSDR")
.init_irq = davinci_irq_init, .init_irq = davinci_irq_init,
.timer = &davinci_timer, .timer = &davinci_timer,
.init_machine = davinci_sffsdr_init, .init_machine = davinci_sffsdr_init,
.dma_zone_size = SZ_128M,
MACHINE_END MACHINE_END
...@@ -282,4 +282,5 @@ MACHINE_START(TNETV107X, "TNETV107X EVM") ...@@ -282,4 +282,5 @@ MACHINE_START(TNETV107X, "TNETV107X EVM")
.init_irq = cp_intc_init, .init_irq = cp_intc_init,
.timer = &davinci_timer, .timer = &davinci_timer,
.init_machine = tnetv107x_evm_board_init, .init_machine = tnetv107x_evm_board_init,
.dma_zone_size = SZ_128M,
MACHINE_END MACHINE_END
...@@ -41,11 +41,4 @@ ...@@ -41,11 +41,4 @@
*/ */
#define CONSISTENT_DMA_SIZE (14<<20) #define CONSISTENT_DMA_SIZE (14<<20)
/*
* Restrict DMA-able region to workaround silicon bug. The bug
* restricts buffers available for DMA to video hardware to be
* below 128M
*/
#define ARM_DMA_ZONE_SIZE SZ_128M
#endif /* __ASM_ARCH_MEMORY_H */ #endif /* __ASM_ARCH_MEMORY_H */
...@@ -33,4 +33,5 @@ MACHINE_START(H7201, "Hynix GMS30C7201") ...@@ -33,4 +33,5 @@ MACHINE_START(H7201, "Hynix GMS30C7201")
.map_io = h720x_map_io, .map_io = h720x_map_io,
.init_irq = h720x_init_irq, .init_irq = h720x_init_irq,
.timer = &h7201_timer, .timer = &h7201_timer,
.dma_zone_size = SZ_256M,
MACHINE_END MACHINE_END
...@@ -76,4 +76,5 @@ MACHINE_START(H7202, "Hynix HMS30C7202") ...@@ -76,4 +76,5 @@ MACHINE_START(H7202, "Hynix HMS30C7202")
.init_irq = h7202_init_irq, .init_irq = h7202_init_irq,
.timer = &h7202_timer, .timer = &h7202_timer,
.init_machine = init_eval_h7202, .init_machine = init_eval_h7202,
.dma_zone_size = SZ_256M,
MACHINE_END MACHINE_END
...@@ -8,11 +8,4 @@ ...@@ -8,11 +8,4 @@
#define __ASM_ARCH_MEMORY_H #define __ASM_ARCH_MEMORY_H
#define PLAT_PHYS_OFFSET UL(0x40000000) #define PLAT_PHYS_OFFSET UL(0x40000000)
/*
* This is the maximum DMA address that can be DMAd to.
* There should not be more than (0xd0000000 - 0xc0000000)
* bytes of RAM.
*/
#define ARM_DMA_ZONE_SIZE SZ_256M
#endif #endif
...@@ -169,6 +169,9 @@ MACHINE_START(AVILA, "Gateworks Avila Network Platform") ...@@ -169,6 +169,9 @@ MACHINE_START(AVILA, "Gateworks Avila Network Platform")
.timer = &ixp4xx_timer, .timer = &ixp4xx_timer,
.boot_params = 0x0100, .boot_params = 0x0100,
.init_machine = avila_init, .init_machine = avila_init,
#if defined(CONFIG_PCI)
.dma_zone_size = SZ_64M,
#endif
MACHINE_END MACHINE_END
/* /*
...@@ -184,6 +187,9 @@ MACHINE_START(LOFT, "Giant Shoulder Inc Loft board") ...@@ -184,6 +187,9 @@ MACHINE_START(LOFT, "Giant Shoulder Inc Loft board")
.timer = &ixp4xx_timer, .timer = &ixp4xx_timer,
.boot_params = 0x0100, .boot_params = 0x0100,
.init_machine = avila_init, .init_machine = avila_init,
#if defined(CONFIG_PCI)
.dma_zone_size = SZ_64M,
#endif
MACHINE_END MACHINE_END
#endif #endif
...@@ -316,6 +316,11 @@ static int abort_handler(unsigned long addr, unsigned int fsr, struct pt_regs *r ...@@ -316,6 +316,11 @@ static int abort_handler(unsigned long addr, unsigned int fsr, struct pt_regs *r
} }
static int ixp4xx_needs_bounce(struct device *dev, dma_addr_t dma_addr, size_t size)
{
return (dma_addr + size) >= SZ_64M;
}
/* /*
* Setup DMA mask to 64MB on PCI devices. Ignore all other devices. * Setup DMA mask to 64MB on PCI devices. Ignore all other devices.
*/ */
...@@ -324,7 +329,7 @@ static int ixp4xx_pci_platform_notify(struct device *dev) ...@@ -324,7 +329,7 @@ static int ixp4xx_pci_platform_notify(struct device *dev)
if(dev->bus == &pci_bus_type) { if(dev->bus == &pci_bus_type) {
*dev->dma_mask = SZ_64M - 1; *dev->dma_mask = SZ_64M - 1;
dev->coherent_dma_mask = SZ_64M - 1; dev->coherent_dma_mask = SZ_64M - 1;
dmabounce_register_dev(dev, 2048, 4096); dmabounce_register_dev(dev, 2048, 4096, ixp4xx_needs_bounce);
} }
return 0; return 0;
} }
...@@ -337,11 +342,6 @@ static int ixp4xx_pci_platform_notify_remove(struct device *dev) ...@@ -337,11 +342,6 @@ static int ixp4xx_pci_platform_notify_remove(struct device *dev)
return 0; return 0;
} }
int dma_needs_bounce(struct device *dev, dma_addr_t dma_addr, size_t size)
{
return (dev->bus == &pci_bus_type ) && ((dma_addr + size) >= SZ_64M);
}
void __init ixp4xx_pci_preinit(void) void __init ixp4xx_pci_preinit(void)
{ {
unsigned long cpuid = read_cpuid_id(); unsigned long cpuid = read_cpuid_id();
......
...@@ -114,6 +114,9 @@ MACHINE_START(ADI_COYOTE, "ADI Engineering Coyote") ...@@ -114,6 +114,9 @@ MACHINE_START(ADI_COYOTE, "ADI Engineering Coyote")
.timer = &ixp4xx_timer, .timer = &ixp4xx_timer,
.boot_params = 0x0100, .boot_params = 0x0100,
.init_machine = coyote_init, .init_machine = coyote_init,
#if defined(CONFIG_PCI)
.dma_zone_size = SZ_64M,
#endif
MACHINE_END MACHINE_END
#endif #endif
......
...@@ -284,4 +284,7 @@ MACHINE_START(DSMG600, "D-Link DSM-G600 RevA") ...@@ -284,4 +284,7 @@ MACHINE_START(DSMG600, "D-Link DSM-G600 RevA")
.init_irq = ixp4xx_init_irq, .init_irq = ixp4xx_init_irq,
.timer = &dsmg600_timer, .timer = &dsmg600_timer,
.init_machine = dsmg600_init, .init_machine = dsmg600_init,
#if defined(CONFIG_PCI)
.dma_zone_size = SZ_64M,
#endif
MACHINE_END MACHINE_END
...@@ -275,5 +275,8 @@ MACHINE_START(FSG, "Freecom FSG-3") ...@@ -275,5 +275,8 @@ MACHINE_START(FSG, "Freecom FSG-3")
.timer = &ixp4xx_timer, .timer = &ixp4xx_timer,
.boot_params = 0x0100, .boot_params = 0x0100,
.init_machine = fsg_init, .init_machine = fsg_init,
#if defined(CONFIG_PCI)
.dma_zone_size = SZ_64M,
#endif
MACHINE_END MACHINE_END
...@@ -101,5 +101,8 @@ MACHINE_START(GATEWAY7001, "Gateway 7001 AP") ...@@ -101,5 +101,8 @@ MACHINE_START(GATEWAY7001, "Gateway 7001 AP")
.timer = &ixp4xx_timer, .timer = &ixp4xx_timer,
.boot_params = 0x0100, .boot_params = 0x0100,
.init_machine = gateway7001_init, .init_machine = gateway7001_init,
#if defined(CONFIG_PCI)
.dma_zone_size = SZ_64M,
#endif
MACHINE_END MACHINE_END
#endif #endif
...@@ -501,4 +501,7 @@ MACHINE_START(GORAMO_MLR, "MultiLink") ...@@ -501,4 +501,7 @@ MACHINE_START(GORAMO_MLR, "MultiLink")
.timer = &ixp4xx_timer, .timer = &ixp4xx_timer,
.boot_params = 0x0100, .boot_params = 0x0100,
.init_machine = gmlr_init, .init_machine = gmlr_init,
#if defined(CONFIG_PCI)
.dma_zone_size = SZ_64M,
#endif
MACHINE_END MACHINE_END
...@@ -169,6 +169,9 @@ MACHINE_START(GTWX5715, "Gemtek GTWX5715 (Linksys WRV54G)") ...@@ -169,6 +169,9 @@ MACHINE_START(GTWX5715, "Gemtek GTWX5715 (Linksys WRV54G)")
.timer = &ixp4xx_timer, .timer = &ixp4xx_timer,
.boot_params = 0x0100, .boot_params = 0x0100,
.init_machine = gtwx5715_init, .init_machine = gtwx5715_init,
#if defined(CONFIG_PCI)
.dma_zone_size = SZ_64M,
#endif
MACHINE_END MACHINE_END
...@@ -14,8 +14,4 @@ ...@@ -14,8 +14,4 @@
*/ */
#define PLAT_PHYS_OFFSET UL(0x00000000) #define PLAT_PHYS_OFFSET UL(0x00000000)
#ifdef CONFIG_PCI
#define ARM_DMA_ZONE_SIZE SZ_64M
#endif
#endif #endif
...@@ -258,6 +258,9 @@ MACHINE_START(IXDP425, "Intel IXDP425 Development Platform") ...@@ -258,6 +258,9 @@ MACHINE_START(IXDP425, "Intel IXDP425 Development Platform")
.timer = &ixp4xx_timer, .timer = &ixp4xx_timer,
.boot_params = 0x0100, .boot_params = 0x0100,
.init_machine = ixdp425_init, .init_machine = ixdp425_init,
#if defined(CONFIG_PCI)
.dma_zone_size = SZ_64M,
#endif
MACHINE_END MACHINE_END
#endif #endif
...@@ -269,6 +272,9 @@ MACHINE_START(IXDP465, "Intel IXDP465 Development Platform") ...@@ -269,6 +272,9 @@ MACHINE_START(IXDP465, "Intel IXDP465 Development Platform")
.timer = &ixp4xx_timer, .timer = &ixp4xx_timer,
.boot_params = 0x0100, .boot_params = 0x0100,
.init_machine = ixdp425_init, .init_machine = ixdp425_init,
#if defined(CONFIG_PCI)
.dma_zone_size = SZ_64M,
#endif
MACHINE_END MACHINE_END
#endif #endif
...@@ -280,6 +286,9 @@ MACHINE_START(IXCDP1100, "Intel IXCDP1100 Development Platform") ...@@ -280,6 +286,9 @@ MACHINE_START(IXCDP1100, "Intel IXCDP1100 Development Platform")
.timer = &ixp4xx_timer, .timer = &ixp4xx_timer,
.boot_params = 0x0100, .boot_params = 0x0100,
.init_machine = ixdp425_init, .init_machine = ixdp425_init,
#if defined(CONFIG_PCI)
.dma_zone_size = SZ_64M,
#endif
MACHINE_END MACHINE_END
#endif #endif
...@@ -291,5 +300,8 @@ MACHINE_START(KIXRP435, "Intel KIXRP435 Reference Platform") ...@@ -291,5 +300,8 @@ MACHINE_START(KIXRP435, "Intel KIXRP435 Reference Platform")
.timer = &ixp4xx_timer, .timer = &ixp4xx_timer,
.boot_params = 0x0100, .boot_params = 0x0100,
.init_machine = ixdp425_init, .init_machine = ixdp425_init,
#if defined(CONFIG_PCI)
.dma_zone_size = SZ_64M,
#endif
MACHINE_END MACHINE_END
#endif #endif
...@@ -319,4 +319,7 @@ MACHINE_START(NAS100D, "Iomega NAS 100d") ...@@ -319,4 +319,7 @@ MACHINE_START(NAS100D, "Iomega NAS 100d")
.init_irq = ixp4xx_init_irq, .init_irq = ixp4xx_init_irq,
.timer = &ixp4xx_timer, .timer = &ixp4xx_timer,
.init_machine = nas100d_init, .init_machine = nas100d_init,
#if defined(CONFIG_PCI)
.dma_zone_size = SZ_64M,
#endif
MACHINE_END MACHINE_END
...@@ -305,4 +305,7 @@ MACHINE_START(NSLU2, "Linksys NSLU2") ...@@ -305,4 +305,7 @@ MACHINE_START(NSLU2, "Linksys NSLU2")
.init_irq = ixp4xx_init_irq, .init_irq = ixp4xx_init_irq,
.timer = &nslu2_timer, .timer = &nslu2_timer,
.init_machine = nslu2_init, .init_machine = nslu2_init,
#if defined(CONFIG_PCI)
.dma_zone_size = SZ_64M,
#endif
MACHINE_END MACHINE_END
...@@ -241,4 +241,7 @@ MACHINE_START(ARCOM_VULCAN, "Arcom/Eurotech Vulcan") ...@@ -241,4 +241,7 @@ MACHINE_START(ARCOM_VULCAN, "Arcom/Eurotech Vulcan")
.timer = &ixp4xx_timer, .timer = &ixp4xx_timer,
.boot_params = 0x0100, .boot_params = 0x0100,
.init_machine = vulcan_init, .init_machine = vulcan_init,
#if defined(CONFIG_PCI)
.dma_zone_size = SZ_64M,
#endif
MACHINE_END MACHINE_END
...@@ -102,5 +102,8 @@ MACHINE_START(WG302V2, "Netgear WG302 v2 / WAG302 v2") ...@@ -102,5 +102,8 @@ MACHINE_START(WG302V2, "Netgear WG302 v2 / WAG302 v2")
.timer = &ixp4xx_timer, .timer = &ixp4xx_timer,
.boot_params = 0x0100, .boot_params = 0x0100,
.init_machine = wg302v2_init, .init_machine = wg302v2_init,
#if defined(CONFIG_PCI)
.dma_zone_size = SZ_64M,
#endif
MACHINE_END MACHINE_END
#endif #endif
...@@ -518,4 +518,7 @@ MACHINE_START(ARMCORE, "Compulab CM-X2XX") ...@@ -518,4 +518,7 @@ MACHINE_START(ARMCORE, "Compulab CM-X2XX")
.init_irq = cmx2xx_init_irq, .init_irq = cmx2xx_init_irq,
.timer = &pxa_timer, .timer = &pxa_timer,
.init_machine = cmx2xx_init, .init_machine = cmx2xx_init,
#ifdef CONFIG_PCI
.dma_zone_size = SZ_64M,
#endif
MACHINE_END MACHINE_END
...@@ -17,8 +17,4 @@ ...@@ -17,8 +17,4 @@
*/ */
#define PLAT_PHYS_OFFSET UL(0xa0000000) #define PLAT_PHYS_OFFSET UL(0xa0000000)
#if defined(CONFIG_MACH_ARMCORE) && defined(CONFIG_PCI)
#define ARM_DMA_ZONE_SIZE SZ_64M
#endif
#endif #endif
...@@ -29,10 +29,6 @@ ...@@ -29,10 +29,6 @@
#define PLAT_PHYS_OFFSET UL(0x00000000) #define PLAT_PHYS_OFFSET UL(0x00000000)
#endif #endif
#ifdef CONFIG_ZONE_DMA
#define ARM_DMA_ZONE_SIZE SZ_256M
#endif
#ifdef CONFIG_SPARSEMEM #ifdef CONFIG_SPARSEMEM
/* /*
......
...@@ -470,4 +470,7 @@ MACHINE_START(REALVIEW_EB, "ARM-RealView EB") ...@@ -470,4 +470,7 @@ MACHINE_START(REALVIEW_EB, "ARM-RealView EB")
.init_irq = gic_init_irq, .init_irq = gic_init_irq,
.timer = &realview_eb_timer, .timer = &realview_eb_timer,
.init_machine = realview_eb_init, .init_machine = realview_eb_init,
#ifdef CONFIG_ZONE_DMA
.dma_zone_size = SZ_256M,
#endif
MACHINE_END MACHINE_END
...@@ -365,4 +365,7 @@ MACHINE_START(REALVIEW_PB1176, "ARM-RealView PB1176") ...@@ -365,4 +365,7 @@ MACHINE_START(REALVIEW_PB1176, "ARM-RealView PB1176")
.init_irq = gic_init_irq, .init_irq = gic_init_irq,
.timer = &realview_pb1176_timer, .timer = &realview_pb1176_timer,
.init_machine = realview_pb1176_init, .init_machine = realview_pb1176_init,
#ifdef CONFIG_ZONE_DMA
.dma_zone_size = SZ_256M,
#endif
MACHINE_END MACHINE_END
...@@ -367,4 +367,7 @@ MACHINE_START(REALVIEW_PB11MP, "ARM-RealView PB11MPCore") ...@@ -367,4 +367,7 @@ MACHINE_START(REALVIEW_PB11MP, "ARM-RealView PB11MPCore")
.init_irq = gic_init_irq, .init_irq = gic_init_irq,
.timer = &realview_pb11mp_timer, .timer = &realview_pb11mp_timer,
.init_machine = realview_pb11mp_init, .init_machine = realview_pb11mp_init,
#ifdef CONFIG_ZONE_DMA
.dma_zone_size = SZ_256M,
#endif
MACHINE_END MACHINE_END
...@@ -317,4 +317,7 @@ MACHINE_START(REALVIEW_PBA8, "ARM-RealView PB-A8") ...@@ -317,4 +317,7 @@ MACHINE_START(REALVIEW_PBA8, "ARM-RealView PB-A8")
.init_irq = gic_init_irq, .init_irq = gic_init_irq,
.timer = &realview_pba8_timer, .timer = &realview_pba8_timer,
.init_machine = realview_pba8_init, .init_machine = realview_pba8_init,
#ifdef CONFIG_ZONE_DMA
.dma_zone_size = SZ_256M,
#endif
MACHINE_END MACHINE_END
...@@ -400,4 +400,7 @@ MACHINE_START(REALVIEW_PBX, "ARM-RealView PBX") ...@@ -400,4 +400,7 @@ MACHINE_START(REALVIEW_PBX, "ARM-RealView PBX")
.init_irq = gic_init_irq, .init_irq = gic_init_irq,
.timer = &realview_pbx_timer, .timer = &realview_pbx_timer,
.init_machine = realview_pbx_init, .init_machine = realview_pbx_init,
#ifdef CONFIG_ZONE_DMA
.dma_zone_size = SZ_256M,
#endif
MACHINE_END MACHINE_END
...@@ -453,4 +453,7 @@ MACHINE_START(ASSABET, "Intel-Assabet") ...@@ -453,4 +453,7 @@ MACHINE_START(ASSABET, "Intel-Assabet")
.init_irq = sa1100_init_irq, .init_irq = sa1100_init_irq,
.timer = &sa1100_timer, .timer = &sa1100_timer,
.init_machine = assabet_init, .init_machine = assabet_init,
#ifdef CONFIG_SA1111
.dma_zone_size = SZ_1M,
#endif
MACHINE_END MACHINE_END
...@@ -306,4 +306,7 @@ MACHINE_START(BADGE4, "Hewlett-Packard Laboratories BadgePAD 4") ...@@ -306,4 +306,7 @@ MACHINE_START(BADGE4, "Hewlett-Packard Laboratories BadgePAD 4")
.map_io = badge4_map_io, .map_io = badge4_map_io,
.init_irq = sa1100_init_irq, .init_irq = sa1100_init_irq,
.timer = &sa1100_timer, .timer = &sa1100_timer,
#ifdef CONFIG_SA1111
.dma_zone_size = SZ_1M,
#endif
MACHINE_END MACHINE_END
...@@ -14,10 +14,6 @@ ...@@ -14,10 +14,6 @@
*/ */
#define PLAT_PHYS_OFFSET UL(0xc0000000) #define PLAT_PHYS_OFFSET UL(0xc0000000)
#ifdef CONFIG_SA1111
#define ARM_DMA_ZONE_SIZE SZ_1M
#endif
/* /*
* Because of the wide memory address space between physical RAM banks on the * Because of the wide memory address space between physical RAM banks on the
* SA1100, it's much convenient to use Linux's SparseMEM support to implement * SA1100, it's much convenient to use Linux's SparseMEM support to implement
......
...@@ -369,4 +369,7 @@ MACHINE_START(JORNADA720, "HP Jornada 720") ...@@ -369,4 +369,7 @@ MACHINE_START(JORNADA720, "HP Jornada 720")
.init_irq = sa1100_init_irq, .init_irq = sa1100_init_irq,
.timer = &sa1100_timer, .timer = &sa1100_timer,
.init_machine = jornada720_mach_init, .init_machine = jornada720_mach_init,
#ifdef CONFIG_SA1111
.dma_zone_size = SZ_1M,
#endif
MACHINE_END MACHINE_END
...@@ -156,4 +156,5 @@ MACHINE_START(SHARK, "Shark") ...@@ -156,4 +156,5 @@ MACHINE_START(SHARK, "Shark")
.map_io = shark_map_io, .map_io = shark_map_io,
.init_irq = shark_init_irq, .init_irq = shark_init_irq,
.timer = &shark_timer, .timer = &shark_timer,
.dma_zone_size = SZ_4M,
MACHINE_END MACHINE_END
...@@ -17,8 +17,6 @@ ...@@ -17,8 +17,6 @@
*/ */
#define PLAT_PHYS_OFFSET UL(0x08000000) #define PLAT_PHYS_OFFSET UL(0x08000000)
#define ARM_DMA_ZONE_SIZE SZ_4M
/* /*
* Cache flushing area * Cache flushing area
*/ */
......
...@@ -25,9 +25,11 @@ ...@@ -25,9 +25,11 @@
#include <asm/tlbflush.h> #include <asm/tlbflush.h>
#include <asm/sizes.h> #include <asm/sizes.h>
#include "mm.h"
static u64 get_coherent_dma_mask(struct device *dev) static u64 get_coherent_dma_mask(struct device *dev)
{ {
u64 mask = ISA_DMA_THRESHOLD; u64 mask = (u64)arm_dma_limit;
if (dev) { if (dev) {
mask = dev->coherent_dma_mask; mask = dev->coherent_dma_mask;
...@@ -41,10 +43,10 @@ static u64 get_coherent_dma_mask(struct device *dev) ...@@ -41,10 +43,10 @@ static u64 get_coherent_dma_mask(struct device *dev)
return 0; return 0;
} }
if ((~mask) & ISA_DMA_THRESHOLD) { if ((~mask) & (u64)arm_dma_limit) {
dev_warn(dev, "coherent DMA mask %#llx is smaller " dev_warn(dev, "coherent DMA mask %#llx is smaller "
"than system GFP_DMA mask %#llx\n", "than system GFP_DMA mask %#llx\n",
mask, (unsigned long long)ISA_DMA_THRESHOLD); mask, (u64)arm_dma_limit);
return 0; return 0;
} }
} }
...@@ -657,6 +659,33 @@ void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, ...@@ -657,6 +659,33 @@ void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
} }
EXPORT_SYMBOL(dma_sync_sg_for_device); EXPORT_SYMBOL(dma_sync_sg_for_device);
/*
* Return whether the given device DMA address mask can be supported
* properly. For example, if your device can only drive the low 24-bits
* during bus mastering, then you would pass 0x00ffffff as the mask
* to this function.
*/
int dma_supported(struct device *dev, u64 mask)
{
if (mask < (u64)arm_dma_limit)
return 0;
return 1;
}
EXPORT_SYMBOL(dma_supported);
int dma_set_mask(struct device *dev, u64 dma_mask)
{
if (!dev->dma_mask || !dma_supported(dev, dma_mask))
return -EIO;
#ifndef CONFIG_DMABOUNCE
*dev->dma_mask = dma_mask;
#endif
return 0;
}
EXPORT_SYMBOL(dma_set_mask);
#define PREALLOC_DMA_DEBUG_ENTRIES 4096 #define PREALLOC_DMA_DEBUG_ENTRIES 4096
static int __init dma_debug_do_init(void) static int __init dma_debug_do_init(void)
......
...@@ -212,6 +212,18 @@ static void __init arm_bootmem_init(unsigned long start_pfn, ...@@ -212,6 +212,18 @@ static void __init arm_bootmem_init(unsigned long start_pfn,
} }
#ifdef CONFIG_ZONE_DMA #ifdef CONFIG_ZONE_DMA
unsigned long arm_dma_zone_size __read_mostly;
EXPORT_SYMBOL(arm_dma_zone_size);
/*
* The DMA mask corresponding to the maximum bus address allocatable
* using GFP_DMA. The default here places no restriction on DMA
* allocations. This must be the smallest DMA mask in the system,
* so a successful GFP_DMA allocation will always satisfy this.
*/
u32 arm_dma_limit;
static void __init arm_adjust_dma_zone(unsigned long *size, unsigned long *hole, static void __init arm_adjust_dma_zone(unsigned long *size, unsigned long *hole,
unsigned long dma_size) unsigned long dma_size)
{ {
...@@ -267,17 +279,17 @@ static void __init arm_bootmem_free(unsigned long min, unsigned long max_low, ...@@ -267,17 +279,17 @@ static void __init arm_bootmem_free(unsigned long min, unsigned long max_low,
#endif #endif
} }
#ifdef ARM_DMA_ZONE_SIZE #ifdef CONFIG_ZONE_DMA
#ifndef CONFIG_ZONE_DMA
#error ARM_DMA_ZONE_SIZE set but no DMA zone to limit allocations
#endif
/* /*
* Adjust the sizes according to any special requirements for * Adjust the sizes according to any special requirements for
* this machine type. * this machine type.
*/ */
arm_adjust_dma_zone(zone_size, zhole_size, if (arm_dma_zone_size) {
ARM_DMA_ZONE_SIZE >> PAGE_SHIFT); arm_adjust_dma_zone(zone_size, zhole_size,
arm_dma_zone_size >> PAGE_SHIFT);
arm_dma_limit = PHYS_OFFSET + arm_dma_zone_size - 1;
} else
arm_dma_limit = 0xffffffff;
#endif #endif
free_area_init_node(0, zone_size, min, zhole_size); free_area_init_node(0, zone_size, min, zhole_size);
......
...@@ -23,5 +23,11 @@ extern void __flush_dcache_page(struct address_space *mapping, struct page *page ...@@ -23,5 +23,11 @@ extern void __flush_dcache_page(struct address_space *mapping, struct page *page
#endif #endif
#ifdef CONFIG_ZONE_DMA
extern u32 arm_dma_limit;
#else
#define arm_dma_limit ((u32)~0)
#endif
void __init bootmem_init(void); void __init bootmem_init(void);
void arm_mm_memblock_reserve(void); void arm_mm_memblock_reserve(void);
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册