Commit 00e1b3a3 authored by Krzysztof Halasa's avatar Krzysztof Halasa Committed by Arnd Bergmann

IXP4xx: Fix DMA masks.

Now, devices will have 32-bit default DMA masks (0xFFFFFFFF) as per DMA API.

Fixes:
$ ifconfig eth0 up
net eth0: coherent DMA mask is unset

$ ifconfig hdlc0 up
net hdlc0: coherent DMA mask is unset

Also fixes a cosmetic off-by-one bug which caused DMA transfers ending exactly
on the 64 MiB boundary to go through dmabounce unnecessarily.
Signed-off-by: default avatarKrzysztof Hałasa <khc@pm.waw.pl>
Tested-by: default avatarSimon Kagstrom <simon.kagstrom@netinsight.net>
Signed-off-by: default avatarArnd Bergmann <arnd@arndb.de>
parent 53ad835c
...@@ -315,33 +315,6 @@ static int abort_handler(unsigned long addr, unsigned int fsr, struct pt_regs *r ...@@ -315,33 +315,6 @@ static int abort_handler(unsigned long addr, unsigned int fsr, struct pt_regs *r
return 0; return 0;
} }
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.
*/
static int ixp4xx_pci_platform_notify(struct device *dev)
{
if (dev_is_pci(dev)) {
*dev->dma_mask = SZ_64M - 1;
dev->coherent_dma_mask = SZ_64M - 1;
dmabounce_register_dev(dev, 2048, 4096, ixp4xx_needs_bounce);
}
return 0;
}
static int ixp4xx_pci_platform_notify_remove(struct device *dev)
{
if (dev_is_pci(dev))
dmabounce_unregister_dev(dev);
return 0;
}
void __init ixp4xx_pci_preinit(void) void __init ixp4xx_pci_preinit(void)
{ {
unsigned long cpuid = read_cpuid_id(); unsigned long cpuid = read_cpuid_id();
...@@ -475,20 +448,8 @@ int ixp4xx_setup(int nr, struct pci_sys_data *sys) ...@@ -475,20 +448,8 @@ int ixp4xx_setup(int nr, struct pci_sys_data *sys)
pci_add_resource_offset(&sys->resources, &res[0], sys->io_offset); pci_add_resource_offset(&sys->resources, &res[0], sys->io_offset);
pci_add_resource_offset(&sys->resources, &res[1], sys->mem_offset); pci_add_resource_offset(&sys->resources, &res[1], sys->mem_offset);
platform_notify = ixp4xx_pci_platform_notify;
platform_notify_remove = ixp4xx_pci_platform_notify_remove;
return 1; return 1;
} }
int dma_set_coherent_mask(struct device *dev, u64 mask)
{
if (mask >= SZ_64M - 1)
return 0;
return -EIO;
}
EXPORT_SYMBOL(ixp4xx_pci_read); EXPORT_SYMBOL(ixp4xx_pci_read);
EXPORT_SYMBOL(ixp4xx_pci_write); EXPORT_SYMBOL(ixp4xx_pci_write);
EXPORT_SYMBOL(dma_set_coherent_mask);
...@@ -30,8 +30,8 @@ ...@@ -30,8 +30,8 @@
#include <linux/export.h> #include <linux/export.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/cpu.h> #include <linux/cpu.h>
#include <linux/pci.h>
#include <linux/sched_clock.h> #include <linux/sched_clock.h>
#include <mach/udc.h> #include <mach/udc.h>
#include <mach/hardware.h> #include <mach/hardware.h>
#include <mach/io.h> #include <mach/io.h>
...@@ -40,7 +40,6 @@ ...@@ -40,7 +40,6 @@
#include <asm/page.h> #include <asm/page.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/system_misc.h> #include <asm/system_misc.h>
#include <asm/mach/map.h> #include <asm/mach/map.h>
#include <asm/mach/irq.h> #include <asm/mach/irq.h>
#include <asm/mach/time.h> #include <asm/mach/time.h>
...@@ -578,6 +577,54 @@ void ixp4xx_restart(enum reboot_mode mode, const char *cmd) ...@@ -578,6 +577,54 @@ void ixp4xx_restart(enum reboot_mode mode, const char *cmd)
} }
} }
#ifdef CONFIG_PCI
static int ixp4xx_needs_bounce(struct device *dev, dma_addr_t dma_addr, size_t size)
{
return (dma_addr + size) > SZ_64M;
}
static int ixp4xx_platform_notify_remove(struct device *dev)
{
if (dev_is_pci(dev))
dmabounce_unregister_dev(dev);
return 0;
}
#endif
/*
* Setup DMA mask to 64MB on PCI devices and 4 GB on all other things.
*/
static int ixp4xx_platform_notify(struct device *dev)
{
dev->dma_mask = &dev->coherent_dma_mask;
#ifdef CONFIG_PCI
if (dev_is_pci(dev)) {
dev->coherent_dma_mask = DMA_BIT_MASK(28); /* 64 MB */
dmabounce_register_dev(dev, 2048, 4096, ixp4xx_needs_bounce);
return 0;
}
#endif
dev->coherent_dma_mask = DMA_BIT_MASK(32);
return 0;
}
int dma_set_coherent_mask(struct device *dev, u64 mask)
{
if (dev_is_pci(dev))
mask &= DMA_BIT_MASK(28); /* 64 MB */
if ((mask & DMA_BIT_MASK(28)) == DMA_BIT_MASK(28)) {
dev->coherent_dma_mask = mask;
return 0;
}
return -EIO; /* device wanted sub-64MB mask */
}
EXPORT_SYMBOL(dma_set_coherent_mask);
#ifdef CONFIG_IXP4XX_INDIRECT_PCI #ifdef CONFIG_IXP4XX_INDIRECT_PCI
/* /*
* In the case of using indirect PCI, we simply return the actual PCI * In the case of using indirect PCI, we simply return the actual PCI
...@@ -600,12 +647,16 @@ static void ixp4xx_iounmap(void __iomem *addr) ...@@ -600,12 +647,16 @@ static void ixp4xx_iounmap(void __iomem *addr)
if (!is_pci_memory((__force u32)addr)) if (!is_pci_memory((__force u32)addr))
__iounmap(addr); __iounmap(addr);
} }
#endif
void __init ixp4xx_init_early(void) void __init ixp4xx_init_early(void)
{ {
platform_notify = ixp4xx_platform_notify;
#ifdef CONFIG_PCI
platform_notify_remove = ixp4xx_platform_notify_remove;
#endif
#ifdef CONFIG_IXP4XX_INDIRECT_PCI
arch_ioremap_caller = ixp4xx_ioremap_caller; arch_ioremap_caller = ixp4xx_ioremap_caller;
arch_iounmap = ixp4xx_iounmap; arch_iounmap = ixp4xx_iounmap;
}
#else
void __init ixp4xx_init_early(void) {}
#endif #endif
}
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