Commit a90ee89e authored by Richard Henderson's avatar Richard Henderson Committed by Linus Torvalds

[PATCH] Alpha: generic dma mapping

From: Ivan Kokshaysky <ink@jurassic.park.msu.ru>

 - big functions moved out of line;
 - handle dev == NULL case, which apparently means the isa device.

As before, this is needed for Jensen. This also makes the isa sound
drivers working again with recent kernels.
parent 7ef56c66
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/tty.h> #include <linux/tty.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/console.h> #include <asm/console.h>
...@@ -136,7 +137,9 @@ EXPORT_SYMBOL(pci_dac_dma_supported); ...@@ -136,7 +137,9 @@ EXPORT_SYMBOL(pci_dac_dma_supported);
EXPORT_SYMBOL(pci_dac_page_to_dma); EXPORT_SYMBOL(pci_dac_page_to_dma);
EXPORT_SYMBOL(pci_dac_dma_to_page); EXPORT_SYMBOL(pci_dac_dma_to_page);
EXPORT_SYMBOL(pci_dac_dma_to_offset); EXPORT_SYMBOL(pci_dac_dma_to_offset);
EXPORT_SYMBOL(alpha_gendev_to_pci);
#endif #endif
EXPORT_SYMBOL(dma_set_mask);
EXPORT_SYMBOL(dump_thread); EXPORT_SYMBOL(dump_thread);
EXPORT_SYMBOL(dump_elf_thread); EXPORT_SYMBOL(dump_elf_thread);
......
...@@ -7,8 +7,10 @@ ...@@ -7,8 +7,10 @@
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/bootmem.h> #include <linux/bootmem.h>
#include <linux/mm.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/dma-mapping.h>
#include "proto.h" #include "proto.h"
...@@ -101,41 +103,100 @@ sys_pciconfig_write(unsigned long bus, unsigned long dfn, ...@@ -101,41 +103,100 @@ sys_pciconfig_write(unsigned long bus, unsigned long dfn,
else else
return -ENODEV; return -ENODEV;
} }
/* stubs for the routines in pci_iommu.c */
/* Stubs for the routines in pci_iommu.c: */
void * void *
pci_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_addrp) pci_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_addrp)
{ {
return NULL; return NULL;
} }
void void
pci_free_consistent(struct pci_dev *pdev, size_t size, void *cpu_addr, pci_free_consistent(struct pci_dev *pdev, size_t size, void *cpu_addr,
dma_addr_t dma_addr) dma_addr_t dma_addr)
{ {
} }
dma_addr_t dma_addr_t
pci_map_single(struct pci_dev *pdev, void *cpu_addr, size_t size, pci_map_single(struct pci_dev *pdev, void *cpu_addr, size_t size,
int direction) int direction)
{ {
return (dma_addr_t) 0; return (dma_addr_t) 0;
} }
void void
pci_unmap_single(struct pci_dev *pdev, dma_addr_t dma_addr, size_t size, pci_unmap_single(struct pci_dev *pdev, dma_addr_t dma_addr, size_t size,
int direction) int direction)
{ {
} }
int int
pci_map_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents, pci_map_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents,
int direction) int direction)
{ {
return 0; return 0;
} }
void void
pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents, pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents,
int direction) int direction)
{ {
} }
int int
pci_dma_supported(struct pci_dev *hwdev, dma_addr_t mask) pci_dma_supported(struct pci_dev *hwdev, dma_addr_t mask)
{ {
return 0; return 0;
} }
/* Generic DMA mapping functions: */
void *
dma_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, int gfp)
{
void *ret;
if (!dev || *dev->dma_mask >= 0xffffffffUL)
gfp &= ~GFP_DMA;
ret = (void *)__get_free_pages(gfp, get_order(size));
if (ret) {
memset(ret, 0, size);
*dma_handle = virt_to_bus(ret);
}
return ret;
}
EXPORT_SYMBOL(dma_alloc_coherent);
int
dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
enum dma_data_direction direction)
{
int i;
for (i = 0; i < nents; i++ ) {
void *va;
BUG_ON(!sg[i].page);
va = page_address(sg[i].page) + sg[i].offset;
sg_dma_address(sg + i) = (dma_addr_t)virt_to_bus(va);
sg_dma_len(sg + i) = sg[i].length;
}
return nents;
}
EXPORT_SYMBOL(dma_map_sg);
int
dma_set_mask(struct device *dev, u64 mask)
{
if (!dev->dma_mask || !dma_supported(dev, mask))
return -EIO;
*dev->dma_mask = mask;
return 0;
}
...@@ -930,3 +930,42 @@ pci_dac_dma_to_offset(struct pci_dev *pdev, dma64_addr_t dma_addr) ...@@ -930,3 +930,42 @@ pci_dac_dma_to_offset(struct pci_dev *pdev, dma64_addr_t dma_addr)
{ {
return (dma_addr & ~PAGE_MASK); return (dma_addr & ~PAGE_MASK);
} }
/* Helper for generic DMA-mapping functions. */
struct pci_dev *
alpha_gendev_to_pci(struct device *dev)
{
if (dev && dev->bus == &pci_bus_type)
return to_pci_dev(dev);
/* Assume that non-PCI devices asking for DMA are either ISA or EISA,
BUG() otherwise. */
BUG_ON(!isa_bridge);
/* Assume non-busmaster ISA DMA when dma_mask is not set (the ISA
bridge is bus master then). */
if (!dev || !dev->dma_mask || !*dev->dma_mask)
return isa_bridge;
/* For EISA bus masters, return isa_bridge (it might have smaller
dma_mask due to wiring limitations). */
if (*dev->dma_mask >= isa_bridge->dma_mask)
return isa_bridge;
/* This assumes ISA bus master with dma_mask 0xffffff. */
return NULL;
}
int
dma_set_mask(struct device *dev, u64 mask)
{
if (!dev->dma_mask ||
!pci_dma_supported(alpha_gendev_to_pci(dev), mask))
return -EIO;
*dev->dma_mask = mask;
return 0;
}
...@@ -20,6 +20,6 @@ ...@@ -20,6 +20,6 @@
#define L1_CACHE_ALIGN(x) (((x)+(L1_CACHE_BYTES-1))&~(L1_CACHE_BYTES-1)) #define L1_CACHE_ALIGN(x) (((x)+(L1_CACHE_BYTES-1))&~(L1_CACHE_BYTES-1))
#define SMP_CACHE_BYTES L1_CACHE_BYTES #define SMP_CACHE_BYTES L1_CACHE_BYTES
#define L1_CACHE_SHIFT_MAX 6 /* largest L1 which this arch supports */ #define L1_CACHE_SHIFT_MAX L1_CACHE_SHIFT
#endif #endif
#include <asm-generic/dma-mapping.h> #ifndef _ALPHA_DMA_MAPPING_H
#define _ALPHA_DMA_MAPPING_H
#include <linux/config.h>
#ifdef CONFIG_PCI
#include <linux/pci.h>
#define dma_map_single(dev, va, size, dir) \
pci_map_single(alpha_gendev_to_pci(dev), va, size, dir)
#define dma_unmap_single(dev, addr, size, dir) \
pci_unmap_single(alpha_gendev_to_pci(dev), addr, size, dir)
#define dma_alloc_coherent(dev, size, addr, gfp) \
pci_alloc_consistent(alpha_gendev_to_pci(dev), size, addr)
#define dma_free_coherent(dev, size, va, addr) \
pci_free_consistent(alpha_gendev_to_pci(dev), size, va, addr)
#define dma_map_page(dev, page, off, size, dir) \
pci_map_single(alpha_gendev_to_pci(dev), page, off, size, dir)
#define dma_unmap_page(dev, addr, size, dir) \
pci_unmap_page(alpha_gendev_to_pci(dev), addr, size, dir)
#define dma_map_sg(dev, sg, nents, dir) \
pci_map_sg(alpha_gendev_to_pci(dev), sg, nents, dir)
#define dma_unmap_sg(dev, sg, nents, dir) \
pci_unmap_sg(alpha_gendev_to_pci(dev), sg, nents, dir)
#define dma_supported(dev, mask) \
pci_dma_supported(alpha_gendev_to_pci(dev), mask)
#else /* no PCI - no IOMMU. */
void *dma_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, int gfp);
int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
enum dma_data_direction direction);
#define dma_free_coherent(dev, size, va, addr) \
free_pages((unsigned long)va, get_order(size))
#define dma_supported(dev, mask) (mask < 0x00ffffffUL ? 0 : 1)
#define dma_map_single(dev, va, size, dir) virt_to_phys(va)
#define dma_map_page(dev, page, off, size, dir) (page_to_pa(page) + off)
#define dma_unmap_single(dev, addr, size, dir) do { } while (0)
#define dma_unmap_page(dev, addr, size, dir) do { } while (0)
#define dma_unmap_sg(dev, sg, nents, dir) do { } while (0)
#endif /* !CONFIG_PCI */
#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
#define dma_is_consistent(dev) (1)
int dma_set_mask(struct device *dev, u64 mask);
#define dma_sync_single_for_cpu(dev, addr, size, dir) do { } while (0)
#define dma_sync_single_for_device(dev, addr, size, dir) do { } while (0)
#define dma_sync_single_range(dev, addr, off, size, dir) do { } while (0)
#define dma_sync_sg_for_cpu(dev, sg, nents, dir) do { } while (0)
#define dma_sync_sg_for_device(dev, sg, nents, dir) do { } while (0)
#define dma_cache_sync(va, size, dir) do { } while (0)
#define dma_get_cache_alignment() L1_CACHE_BYTES
#endif /* _ALPHA_DMA_MAPPING_H */
...@@ -246,6 +246,8 @@ pcibios_add_platform_entries(struct pci_dev *dev) ...@@ -246,6 +246,8 @@ pcibios_add_platform_entries(struct pci_dev *dev)
{ {
} }
struct pci_dev *alpha_gendev_to_pci(struct device *dev);
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
/* Values for the `which' argument to sys_pciconfig_iobase. */ /* Values for the `which' argument to sys_pciconfig_iobase. */
......
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