diff options
author | Krzysztof Halasa <khc@pm.waw.pl> | 2014-03-22 20:36:48 -0400 |
---|---|---|
committer | Arnd Bergmann <arnd@arndb.de> | 2014-03-26 18:08:11 -0400 |
commit | 00e1b3a3d196ae876370633b32007bf98584e748 (patch) | |
tree | c3a74ed0f4b674b25a5c7664735476b3ad0dcaf2 | |
parent | 53ad835ce7050dc3a3b3343fb07636db86783e26 (diff) |
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: Krzysztof HaĆasa <khc@pm.waw.pl>
Tested-by: Simon Kagstrom <simon.kagstrom@netinsight.net>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
-rw-r--r-- | arch/arm/mach-ixp4xx/common-pci.c | 39 | ||||
-rw-r--r-- | arch/arm/mach-ixp4xx/common.c | 61 |
2 files changed, 56 insertions, 44 deletions
diff --git a/arch/arm/mach-ixp4xx/common-pci.c b/arch/arm/mach-ixp4xx/common-pci.c index 200970d56f6d..4977296f0c78 100644 --- a/arch/arm/mach-ixp4xx/common-pci.c +++ b/arch/arm/mach-ixp4xx/common-pci.c | |||
@@ -315,33 +315,6 @@ static int abort_handler(unsigned long addr, unsigned int fsr, struct pt_regs *r | |||
315 | return 0; | 315 | return 0; |
316 | } | 316 | } |
317 | 317 | ||
318 | |||
319 | static int ixp4xx_needs_bounce(struct device *dev, dma_addr_t dma_addr, size_t size) | ||
320 | { | ||
321 | return (dma_addr + size) >= SZ_64M; | ||
322 | } | ||
323 | |||
324 | /* | ||
325 | * Setup DMA mask to 64MB on PCI devices. Ignore all other devices. | ||
326 | */ | ||
327 | static int ixp4xx_pci_platform_notify(struct device *dev) | ||
328 | { | ||
329 | if (dev_is_pci(dev)) { | ||
330 | *dev->dma_mask = SZ_64M - 1; | ||
331 | dev->coherent_dma_mask = SZ_64M - 1; | ||
332 | dmabounce_register_dev(dev, 2048, 4096, ixp4xx_needs_bounce); | ||
333 | } | ||
334 | return 0; | ||
335 | } | ||
336 | |||
337 | static int ixp4xx_pci_platform_notify_remove(struct device *dev) | ||
338 | { | ||
339 | if (dev_is_pci(dev)) | ||
340 | dmabounce_unregister_dev(dev); | ||
341 | |||
342 | return 0; | ||
343 | } | ||
344 | |||
345 | void __init ixp4xx_pci_preinit(void) | 318 | void __init ixp4xx_pci_preinit(void) |
346 | { | 319 | { |
347 | unsigned long cpuid = read_cpuid_id(); | 320 | unsigned long cpuid = read_cpuid_id(); |
@@ -475,20 +448,8 @@ int ixp4xx_setup(int nr, struct pci_sys_data *sys) | |||
475 | pci_add_resource_offset(&sys->resources, &res[0], sys->io_offset); | 448 | pci_add_resource_offset(&sys->resources, &res[0], sys->io_offset); |
476 | pci_add_resource_offset(&sys->resources, &res[1], sys->mem_offset); | 449 | pci_add_resource_offset(&sys->resources, &res[1], sys->mem_offset); |
477 | 450 | ||
478 | platform_notify = ixp4xx_pci_platform_notify; | ||
479 | platform_notify_remove = ixp4xx_pci_platform_notify_remove; | ||
480 | |||
481 | return 1; | 451 | return 1; |
482 | } | 452 | } |
483 | 453 | ||
484 | int dma_set_coherent_mask(struct device *dev, u64 mask) | ||
485 | { | ||
486 | if (mask >= SZ_64M - 1) | ||
487 | return 0; | ||
488 | |||
489 | return -EIO; | ||
490 | } | ||
491 | |||
492 | EXPORT_SYMBOL(ixp4xx_pci_read); | 454 | EXPORT_SYMBOL(ixp4xx_pci_read); |
493 | EXPORT_SYMBOL(ixp4xx_pci_write); | 455 | EXPORT_SYMBOL(ixp4xx_pci_write); |
494 | EXPORT_SYMBOL(dma_set_coherent_mask); | ||
diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c index 6d68aed6548a..12c71a4a42a0 100644 --- a/arch/arm/mach-ixp4xx/common.c +++ b/arch/arm/mach-ixp4xx/common.c | |||
@@ -30,8 +30,8 @@ | |||
30 | #include <linux/export.h> | 30 | #include <linux/export.h> |
31 | #include <linux/gpio.h> | 31 | #include <linux/gpio.h> |
32 | #include <linux/cpu.h> | 32 | #include <linux/cpu.h> |
33 | #include <linux/pci.h> | ||
33 | #include <linux/sched_clock.h> | 34 | #include <linux/sched_clock.h> |
34 | |||
35 | #include <mach/udc.h> | 35 | #include <mach/udc.h> |
36 | #include <mach/hardware.h> | 36 | #include <mach/hardware.h> |
37 | #include <mach/io.h> | 37 | #include <mach/io.h> |
@@ -40,7 +40,6 @@ | |||
40 | #include <asm/page.h> | 40 | #include <asm/page.h> |
41 | #include <asm/irq.h> | 41 | #include <asm/irq.h> |
42 | #include <asm/system_misc.h> | 42 | #include <asm/system_misc.h> |
43 | |||
44 | #include <asm/mach/map.h> | 43 | #include <asm/mach/map.h> |
45 | #include <asm/mach/irq.h> | 44 | #include <asm/mach/irq.h> |
46 | #include <asm/mach/time.h> | 45 | #include <asm/mach/time.h> |
@@ -578,6 +577,54 @@ void ixp4xx_restart(enum reboot_mode mode, const char *cmd) | |||
578 | } | 577 | } |
579 | } | 578 | } |
580 | 579 | ||
580 | #ifdef CONFIG_PCI | ||
581 | static int ixp4xx_needs_bounce(struct device *dev, dma_addr_t dma_addr, size_t size) | ||
582 | { | ||
583 | return (dma_addr + size) > SZ_64M; | ||
584 | } | ||
585 | |||
586 | static int ixp4xx_platform_notify_remove(struct device *dev) | ||
587 | { | ||
588 | if (dev_is_pci(dev)) | ||
589 | dmabounce_unregister_dev(dev); | ||
590 | |||
591 | return 0; | ||
592 | } | ||
593 | #endif | ||
594 | |||
595 | /* | ||
596 | * Setup DMA mask to 64MB on PCI devices and 4 GB on all other things. | ||
597 | */ | ||
598 | static int ixp4xx_platform_notify(struct device *dev) | ||
599 | { | ||
600 | dev->dma_mask = &dev->coherent_dma_mask; | ||
601 | |||
602 | #ifdef CONFIG_PCI | ||
603 | if (dev_is_pci(dev)) { | ||
604 | dev->coherent_dma_mask = DMA_BIT_MASK(28); /* 64 MB */ | ||
605 | dmabounce_register_dev(dev, 2048, 4096, ixp4xx_needs_bounce); | ||
606 | return 0; | ||
607 | } | ||
608 | #endif | ||
609 | |||
610 | dev->coherent_dma_mask = DMA_BIT_MASK(32); | ||
611 | return 0; | ||
612 | } | ||
613 | |||
614 | int dma_set_coherent_mask(struct device *dev, u64 mask) | ||
615 | { | ||
616 | if (dev_is_pci(dev)) | ||
617 | mask &= DMA_BIT_MASK(28); /* 64 MB */ | ||
618 | |||
619 | if ((mask & DMA_BIT_MASK(28)) == DMA_BIT_MASK(28)) { | ||
620 | dev->coherent_dma_mask = mask; | ||
621 | return 0; | ||
622 | } | ||
623 | |||
624 | return -EIO; /* device wanted sub-64MB mask */ | ||
625 | } | ||
626 | EXPORT_SYMBOL(dma_set_coherent_mask); | ||
627 | |||
581 | #ifdef CONFIG_IXP4XX_INDIRECT_PCI | 628 | #ifdef CONFIG_IXP4XX_INDIRECT_PCI |
582 | /* | 629 | /* |
583 | * In the case of using indirect PCI, we simply return the actual PCI | 630 | * 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 | if (!is_pci_memory((__force u32)addr)) | 647 | if (!is_pci_memory((__force u32)addr)) |
601 | __iounmap(addr); | 648 | __iounmap(addr); |
602 | } | 649 | } |
650 | #endif | ||
603 | 651 | ||
604 | void __init ixp4xx_init_early(void) | 652 | void __init ixp4xx_init_early(void) |
605 | { | 653 | { |
654 | platform_notify = ixp4xx_platform_notify; | ||
655 | #ifdef CONFIG_PCI | ||
656 | platform_notify_remove = ixp4xx_platform_notify_remove; | ||
657 | #endif | ||
658 | #ifdef CONFIG_IXP4XX_INDIRECT_PCI | ||
606 | arch_ioremap_caller = ixp4xx_ioremap_caller; | 659 | arch_ioremap_caller = ixp4xx_ioremap_caller; |
607 | arch_iounmap = ixp4xx_iounmap; | 660 | arch_iounmap = ixp4xx_iounmap; |
608 | } | ||
609 | #else | ||
610 | void __init ixp4xx_init_early(void) {} | ||
611 | #endif | 661 | #endif |
662 | } | ||