diff options
author | Chris Metcalf <cmetcalf@tilera.com> | 2012-06-15 15:23:06 -0400 |
---|---|---|
committer | Chris Metcalf <cmetcalf@tilera.com> | 2012-07-18 16:40:17 -0400 |
commit | 41bb38fc5398ae878c799647f3c4b25374029afb (patch) | |
tree | 5d7e01bd4176db1241b801f83cf92f32231b8e8b /arch/tile/include/asm/pci.h | |
parent | eef015c8aa74451f848307fe5f65485070533bbb (diff) |
tile pci: enable IOMMU to support DMA for legacy devices
This change uses the TRIO IOMMU to map the PCI DMA space and physical
memory at different addresses. We also now use the dma_mapping_ops
to provide support for non-PCI DMA, PCIe DMA (64-bit) and legacy PCI
DMA (32-bit). We use the kernel's software I/O TLB framework
(i.e. bounce buffers) for the legacy 32-bit PCI device support since
there are a limited number of TLB entries in the IOMMU and it is
non-trivial to handle indexing, searching, matching, etc. For 32-bit
devices the performance impact of bounce buffers should not be a concern.
Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
Diffstat (limited to 'arch/tile/include/asm/pci.h')
-rw-r--r-- | arch/tile/include/asm/pci.h | 76 |
1 files changed, 67 insertions, 9 deletions
diff --git a/arch/tile/include/asm/pci.h b/arch/tile/include/asm/pci.h index 2c224c47d8a..553b7ff018c 100644 --- a/arch/tile/include/asm/pci.h +++ b/arch/tile/include/asm/pci.h @@ -15,6 +15,7 @@ #ifndef _ASM_TILE_PCI_H #define _ASM_TILE_PCI_H +#include <linux/dma-mapping.h> #include <linux/pci.h> #include <linux/numa.h> #include <asm-generic/pci_iomap.h> @@ -53,6 +54,16 @@ static inline void pci_iounmap(struct pci_dev *dev, void __iomem *addr) {} #define TILE_NUM_PCIE 2 +/* + * The hypervisor maps the entirety of CPA-space as bus addresses, so + * bus addresses are physical addresses. The networking and block + * device layers use this boolean for bounce buffer decisions. + */ +#define PCI_DMA_BUS_IS_PHYS 1 + +/* generic pci stuff */ +#include <asm-generic/pci.h> + #else #include <asm/page.h> @@ -85,7 +96,47 @@ static inline void pci_iounmap(struct pci_dev *dev, void __iomem *addr) {} /* * Each Mem-Map interrupt region occupies 4KB. */ -#define MEM_MAP_INTR_REGION_SIZE (1<< TRIO_MAP_MEM_LIM__ADDR_SHIFT) +#define MEM_MAP_INTR_REGION_SIZE (1 << TRIO_MAP_MEM_LIM__ADDR_SHIFT) + +/* + * Allocate the PCI BAR window right below 4GB. + */ +#define TILE_PCI_BAR_WINDOW_TOP (1ULL << 32) + +/* + * Allocate 1GB for the PCI BAR window. + */ +#define TILE_PCI_BAR_WINDOW_SIZE (1 << 30) + +/* + * This is the highest bus address targeting the host memory that + * can be generated by legacy PCI devices with 32-bit or less + * DMA capability, dictated by the BAR window size and location. + */ +#define TILE_PCI_MAX_DIRECT_DMA_ADDRESS \ + (TILE_PCI_BAR_WINDOW_TOP - TILE_PCI_BAR_WINDOW_SIZE - 1) + +/* + * We shift the PCI bus range for all the physical memory up by the whole PA + * range. The corresponding CPA of an incoming PCI request will be the PCI + * address minus TILE_PCI_MEM_MAP_BASE_OFFSET. This also implies + * that the 64-bit capable devices will be given DMA addresses as + * the CPA plus TILE_PCI_MEM_MAP_BASE_OFFSET. To support 32-bit + * devices, we create a separate map region that handles the low + * 4GB. + */ +#define TILE_PCI_MEM_MAP_BASE_OFFSET (1ULL << CHIP_PA_WIDTH()) + +/* + * End of the PCI memory resource. + */ +#define TILE_PCI_MEM_END \ + ((1ULL << CHIP_PA_WIDTH()) + TILE_PCI_BAR_WINDOW_TOP) + +/* + * Start of the PCI memory resource. + */ +#define TILE_PCI_MEM_START (TILE_PCI_MEM_END - TILE_PCI_BAR_WINDOW_SIZE) /* * Structure of a PCI controller (host bridge) on Gx. @@ -108,6 +159,8 @@ struct pci_controller { int index; /* PCI domain number */ struct pci_bus *root_bus; + uint64_t mem_offset; /* cpu->bus memory mapping offset. */ + int last_busno; struct pci_ops *ops; @@ -126,14 +179,22 @@ extern gxio_trio_context_t trio_contexts[TILEGX_NUM_TRIO]; extern void pci_iounmap(struct pci_dev *dev, void __iomem *); -#endif /* __tilegx__ */ +extern void +pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, + struct resource *res); + +extern void +pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res, + struct pci_bus_region *region); /* - * The hypervisor maps the entirety of CPA-space as bus addresses, so - * bus addresses are physical addresses. The networking and block - * device layers use this boolean for bounce buffer decisions. + * The PCI address space does not equal the physical memory address + * space (we have an IOMMU). The IDE and SCSI device layers use this + * boolean for bounce buffer decisions. */ -#define PCI_DMA_BUS_IS_PHYS 1 +#define PCI_DMA_BUS_IS_PHYS 0 + +#endif /* __tilegx__ */ int __init tile_pci_init(void); int __init pcibios_init(void); @@ -169,7 +230,4 @@ static inline int pcibios_assign_all_busses(void) /* implement the pci_ DMA API in terms of the generic device dma_ one */ #include <asm-generic/pci-dma-compat.h> -/* generic pci stuff */ -#include <asm-generic/pci.h> - #endif /* _ASM_TILE_PCI_H */ |