12d04eef92
This patch completely refactors DMA operations for 64 bits powerpc. 32 bits is untouched for now. We use the new dev_archdata structure to add the dma operations pointer and associated data to struct device. While at it, we also add the OF node pointer and numa node. In the future, we might want to look into merging that with pci_dn as well. The old vio, pci-iommu and pci-direct DMA ops are gone. They are now replaced by a set of generic iommu and direct DMA ops (non PCI specific) that can be used by bus types. The toplevel implementation is now inline. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Paul Mackerras <paulus@samba.org>
114 lines
4.0 KiB
C
114 lines
4.0 KiB
C
/*
|
|
* Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation
|
|
* Rewrite, cleanup:
|
|
* Copyright (C) 2004 Olof Johansson <olof@lixom.net>, IBM Corporation
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
#ifndef _ASM_IOMMU_H
|
|
#define _ASM_IOMMU_H
|
|
#ifdef __KERNEL__
|
|
|
|
#include <linux/compiler.h>
|
|
#include <linux/spinlock.h>
|
|
#include <linux/device.h>
|
|
#include <linux/dma-mapping.h>
|
|
#include <asm/types.h>
|
|
#include <asm/bitops.h>
|
|
|
|
#define IOMMU_PAGE_SHIFT 12
|
|
#define IOMMU_PAGE_SIZE (ASM_CONST(1) << IOMMU_PAGE_SHIFT)
|
|
#define IOMMU_PAGE_MASK (~((1 << IOMMU_PAGE_SHIFT) - 1))
|
|
#define IOMMU_PAGE_ALIGN(addr) _ALIGN_UP(addr, IOMMU_PAGE_SIZE)
|
|
|
|
#ifndef __ASSEMBLY__
|
|
|
|
/* Pure 2^n version of get_order */
|
|
static __inline__ __attribute_const__ int get_iommu_order(unsigned long size)
|
|
{
|
|
return __ilog2((size - 1) >> IOMMU_PAGE_SHIFT) + 1;
|
|
}
|
|
|
|
#endif /* __ASSEMBLY__ */
|
|
|
|
|
|
/*
|
|
* IOMAP_MAX_ORDER defines the largest contiguous block
|
|
* of dma space we can get. IOMAP_MAX_ORDER = 13
|
|
* allows up to 2**12 pages (4096 * 4096) = 16 MB
|
|
*/
|
|
#define IOMAP_MAX_ORDER 13
|
|
|
|
struct iommu_table {
|
|
unsigned long it_busno; /* Bus number this table belongs to */
|
|
unsigned long it_size; /* Size of iommu table in entries */
|
|
unsigned long it_offset; /* Offset into global table */
|
|
unsigned long it_base; /* mapped address of tce table */
|
|
unsigned long it_index; /* which iommu table this is */
|
|
unsigned long it_type; /* type: PCI or Virtual Bus */
|
|
unsigned long it_blocksize; /* Entries in each block (cacheline) */
|
|
unsigned long it_hint; /* Hint for next alloc */
|
|
unsigned long it_largehint; /* Hint for large allocs */
|
|
unsigned long it_halfpoint; /* Breaking point for small/large allocs */
|
|
spinlock_t it_lock; /* Protects it_map */
|
|
unsigned long *it_map; /* A simple allocation bitmap for now */
|
|
};
|
|
|
|
struct scatterlist;
|
|
struct device_node;
|
|
|
|
/* Frees table for an individual device node */
|
|
extern void iommu_free_table(struct device_node *dn);
|
|
|
|
/* Initializes an iommu_table based in values set in the passed-in
|
|
* structure
|
|
*/
|
|
extern struct iommu_table *iommu_init_table(struct iommu_table * tbl,
|
|
int nid);
|
|
|
|
extern int iommu_map_sg(struct iommu_table *tbl, struct scatterlist *sglist,
|
|
int nelems, unsigned long mask,
|
|
enum dma_data_direction direction);
|
|
extern void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist,
|
|
int nelems, enum dma_data_direction direction);
|
|
|
|
extern void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size,
|
|
dma_addr_t *dma_handle, unsigned long mask,
|
|
gfp_t flag, int node);
|
|
extern void iommu_free_coherent(struct iommu_table *tbl, size_t size,
|
|
void *vaddr, dma_addr_t dma_handle);
|
|
extern dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr,
|
|
size_t size, unsigned long mask,
|
|
enum dma_data_direction direction);
|
|
extern void iommu_unmap_single(struct iommu_table *tbl, dma_addr_t dma_handle,
|
|
size_t size, enum dma_data_direction direction);
|
|
|
|
extern void iommu_init_early_pSeries(void);
|
|
extern void iommu_init_early_iSeries(void);
|
|
extern void iommu_init_early_dart(void);
|
|
|
|
#ifdef CONFIG_PCI
|
|
extern void pci_iommu_init(void);
|
|
extern void pci_direct_iommu_init(void);
|
|
#else
|
|
static inline void pci_iommu_init(void) { }
|
|
#endif
|
|
|
|
extern void alloc_dart_table(void);
|
|
|
|
#endif /* __KERNEL__ */
|
|
#endif /* _ASM_IOMMU_H */
|