diff options
Diffstat (limited to 'arch/mips/cavium-octeon/dma-octeon.c')
-rw-r--r-- | arch/mips/cavium-octeon/dma-octeon.c | 191 |
1 files changed, 54 insertions, 137 deletions
diff --git a/arch/mips/cavium-octeon/dma-octeon.c b/arch/mips/cavium-octeon/dma-octeon.c index 7b335ab21697..236833be6fbe 100644 --- a/arch/mips/cavium-octeon/dma-octeon.c +++ b/arch/mips/cavium-octeon/dma-octeon.c @@ -11,9 +11,7 @@ * Copyright (C) 2010 Cavium Networks, Inc. */ #include <linux/dma-direct.h> -#include <linux/scatterlist.h> #include <linux/bootmem.h> -#include <linux/export.h> #include <linux/swiotlb.h> #include <linux/types.h> #include <linux/init.h> @@ -24,10 +22,16 @@ #include <asm/octeon/octeon.h> #ifdef CONFIG_PCI +#include <linux/pci.h> #include <asm/octeon/pci-octeon.h> #include <asm/octeon/cvmx-npi-defs.h> #include <asm/octeon/cvmx-pci-defs.h> +struct octeon_dma_map_ops { + dma_addr_t (*phys_to_dma)(struct device *dev, phys_addr_t paddr); + phys_addr_t (*dma_to_phys)(struct device *dev, dma_addr_t daddr); +}; + static dma_addr_t octeon_hole_phys_to_dma(phys_addr_t paddr) { if (paddr >= CVMX_PCIE_BAR1_PHYS_BASE && paddr < (CVMX_PCIE_BAR1_PHYS_BASE + CVMX_PCIE_BAR1_PHYS_SIZE)) @@ -61,6 +65,11 @@ static phys_addr_t octeon_gen1_dma_to_phys(struct device *dev, dma_addr_t daddr) return daddr; } +static const struct octeon_dma_map_ops octeon_gen1_ops = { + .phys_to_dma = octeon_gen1_phys_to_dma, + .dma_to_phys = octeon_gen1_dma_to_phys, +}; + static dma_addr_t octeon_gen2_phys_to_dma(struct device *dev, phys_addr_t paddr) { return octeon_hole_phys_to_dma(paddr); @@ -71,6 +80,11 @@ static phys_addr_t octeon_gen2_dma_to_phys(struct device *dev, dma_addr_t daddr) return octeon_hole_dma_to_phys(daddr); } +static const struct octeon_dma_map_ops octeon_gen2_ops = { + .phys_to_dma = octeon_gen2_phys_to_dma, + .dma_to_phys = octeon_gen2_dma_to_phys, +}; + static dma_addr_t octeon_big_phys_to_dma(struct device *dev, phys_addr_t paddr) { if (paddr >= 0x410000000ull && paddr < 0x420000000ull) @@ -93,6 +107,11 @@ static phys_addr_t octeon_big_dma_to_phys(struct device *dev, dma_addr_t daddr) return daddr; } +static const struct octeon_dma_map_ops octeon_big_ops = { + .phys_to_dma = octeon_big_phys_to_dma, + .dma_to_phys = octeon_big_dma_to_phys, +}; + static dma_addr_t octeon_small_phys_to_dma(struct device *dev, phys_addr_t paddr) { @@ -121,105 +140,51 @@ static phys_addr_t octeon_small_dma_to_phys(struct device *dev, return daddr; } -#endif /* CONFIG_PCI */ - -static dma_addr_t octeon_dma_map_page(struct device *dev, struct page *page, - unsigned long offset, size_t size, enum dma_data_direction direction, - unsigned long attrs) -{ - dma_addr_t daddr = swiotlb_map_page(dev, page, offset, size, - direction, attrs); - mb(); - - return daddr; -} - -static int octeon_dma_map_sg(struct device *dev, struct scatterlist *sg, - int nents, enum dma_data_direction direction, unsigned long attrs) -{ - int r = swiotlb_map_sg_attrs(dev, sg, nents, direction, attrs); - mb(); - return r; -} - -static void octeon_dma_sync_single_for_device(struct device *dev, - dma_addr_t dma_handle, size_t size, enum dma_data_direction direction) -{ - swiotlb_sync_single_for_device(dev, dma_handle, size, direction); - mb(); -} - -static void octeon_dma_sync_sg_for_device(struct device *dev, - struct scatterlist *sg, int nelems, enum dma_data_direction direction) -{ - swiotlb_sync_sg_for_device(dev, sg, nelems, direction); - mb(); -} - -static void *octeon_dma_alloc_coherent(struct device *dev, size_t size, - dma_addr_t *dma_handle, gfp_t gfp, unsigned long attrs) -{ - void *ret = swiotlb_alloc(dev, size, dma_handle, gfp, attrs); - - mb(); +static const struct octeon_dma_map_ops octeon_small_ops = { + .phys_to_dma = octeon_small_phys_to_dma, + .dma_to_phys = octeon_small_dma_to_phys, +}; - return ret; -} +static const struct octeon_dma_map_ops *octeon_pci_dma_ops; -static dma_addr_t octeon_unity_phys_to_dma(struct device *dev, phys_addr_t paddr) -{ - return paddr; -} - -static phys_addr_t octeon_unity_dma_to_phys(struct device *dev, dma_addr_t daddr) +void __init octeon_pci_dma_init(void) { - return daddr; + switch (octeon_dma_bar_type) { + case OCTEON_DMA_BAR_TYPE_PCIE: + octeon_pci_dma_ops = &octeon_gen1_ops; + break; + case OCTEON_DMA_BAR_TYPE_PCIE2: + octeon_pci_dma_ops = &octeon_gen2_ops; + break; + case OCTEON_DMA_BAR_TYPE_BIG: + octeon_pci_dma_ops = &octeon_big_ops; + break; + case OCTEON_DMA_BAR_TYPE_SMALL: + octeon_pci_dma_ops = &octeon_small_ops; + break; + default: + BUG(); + } } - -struct octeon_dma_map_ops { - const struct dma_map_ops dma_map_ops; - dma_addr_t (*phys_to_dma)(struct device *dev, phys_addr_t paddr); - phys_addr_t (*dma_to_phys)(struct device *dev, dma_addr_t daddr); -}; +#endif /* CONFIG_PCI */ dma_addr_t __phys_to_dma(struct device *dev, phys_addr_t paddr) { - struct octeon_dma_map_ops *ops = container_of(get_dma_ops(dev), - struct octeon_dma_map_ops, - dma_map_ops); - - return ops->phys_to_dma(dev, paddr); +#ifdef CONFIG_PCI + if (dev && dev_is_pci(dev)) + return octeon_pci_dma_ops->phys_to_dma(dev, paddr); +#endif + return paddr; } -EXPORT_SYMBOL(__phys_to_dma); phys_addr_t __dma_to_phys(struct device *dev, dma_addr_t daddr) { - struct octeon_dma_map_ops *ops = container_of(get_dma_ops(dev), - struct octeon_dma_map_ops, - dma_map_ops); - - return ops->dma_to_phys(dev, daddr); +#ifdef CONFIG_PCI + if (dev && dev_is_pci(dev)) + return octeon_pci_dma_ops->dma_to_phys(dev, daddr); +#endif + return daddr; } -EXPORT_SYMBOL(__dma_to_phys); - -static struct octeon_dma_map_ops octeon_linear_dma_map_ops = { - .dma_map_ops = { - .alloc = octeon_dma_alloc_coherent, - .free = swiotlb_free, - .map_page = octeon_dma_map_page, - .unmap_page = swiotlb_unmap_page, - .map_sg = octeon_dma_map_sg, - .unmap_sg = swiotlb_unmap_sg_attrs, - .sync_single_for_cpu = swiotlb_sync_single_for_cpu, - .sync_single_for_device = octeon_dma_sync_single_for_device, - .sync_sg_for_cpu = swiotlb_sync_sg_for_cpu, - .sync_sg_for_device = octeon_dma_sync_sg_for_device, - .mapping_error = swiotlb_dma_mapping_error, - .dma_supported = swiotlb_dma_supported - }, - .phys_to_dma = octeon_unity_phys_to_dma, - .dma_to_phys = octeon_unity_dma_to_phys -}; char *octeon_swiotlb; @@ -283,52 +248,4 @@ void __init plat_swiotlb_setup(void) if (swiotlb_init_with_tbl(octeon_swiotlb, swiotlb_nslabs, 1) == -ENOMEM) panic("Cannot allocate SWIOTLB buffer"); - - mips_dma_map_ops = &octeon_linear_dma_map_ops.dma_map_ops; } - -#ifdef CONFIG_PCI -static struct octeon_dma_map_ops _octeon_pci_dma_map_ops = { - .dma_map_ops = { - .alloc = octeon_dma_alloc_coherent, - .free = swiotlb_free, - .map_page = octeon_dma_map_page, - .unmap_page = swiotlb_unmap_page, - .map_sg = octeon_dma_map_sg, - .unmap_sg = swiotlb_unmap_sg_attrs, - .sync_single_for_cpu = swiotlb_sync_single_for_cpu, - .sync_single_for_device = octeon_dma_sync_single_for_device, - .sync_sg_for_cpu = swiotlb_sync_sg_for_cpu, - .sync_sg_for_device = octeon_dma_sync_sg_for_device, - .mapping_error = swiotlb_dma_mapping_error, - .dma_supported = swiotlb_dma_supported - }, -}; - -const struct dma_map_ops *octeon_pci_dma_map_ops; - -void __init octeon_pci_dma_init(void) -{ - switch (octeon_dma_bar_type) { - case OCTEON_DMA_BAR_TYPE_PCIE2: - _octeon_pci_dma_map_ops.phys_to_dma = octeon_gen2_phys_to_dma; - _octeon_pci_dma_map_ops.dma_to_phys = octeon_gen2_dma_to_phys; - break; - case OCTEON_DMA_BAR_TYPE_PCIE: - _octeon_pci_dma_map_ops.phys_to_dma = octeon_gen1_phys_to_dma; - _octeon_pci_dma_map_ops.dma_to_phys = octeon_gen1_dma_to_phys; - break; - case OCTEON_DMA_BAR_TYPE_BIG: - _octeon_pci_dma_map_ops.phys_to_dma = octeon_big_phys_to_dma; - _octeon_pci_dma_map_ops.dma_to_phys = octeon_big_dma_to_phys; - break; - case OCTEON_DMA_BAR_TYPE_SMALL: - _octeon_pci_dma_map_ops.phys_to_dma = octeon_small_phys_to_dma; - _octeon_pci_dma_map_ops.dma_to_phys = octeon_small_dma_to_phys; - break; - default: - BUG(); - } - octeon_pci_dma_map_ops = &_octeon_pci_dma_map_ops.dma_map_ops; -} -#endif /* CONFIG_PCI */ |