Skip to content

Commit

Permalink
Pull vtd-iommu into release branch
Browse files Browse the repository at this point in the history
Conflicts:
	arch/ia64/kernel/acpi.c
  • Loading branch information
Tony Luck committed Oct 17, 2008
2 parents 22ca532 + 62fdd76 commit fe39316
Show file tree
Hide file tree
Showing 23 changed files with 620 additions and 13 deletions.
17 changes: 17 additions & 0 deletions arch/ia64/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -145,13 +145,15 @@ config IA64_GENERIC
select NUMA
select ACPI_NUMA
select SWIOTLB
select PCI_MSI
help
This selects the system type of your hardware. A "generic" kernel
will run on any supported IA-64 system. However, if you configure
a kernel for your specific system, it will be faster and smaller.

generic For any supported IA-64 system
DIG-compliant For DIG ("Developer's Interface Guide") compliant systems
DIG+Intel+IOMMU For DIG systems with Intel IOMMU
HP-zx1/sx1000 For HP systems
HP-zx1/sx1000+swiotlb For HP systems with (broken) DMA-constrained devices.
SGI-SN2 For SGI Altix systems
Expand All @@ -165,6 +167,11 @@ config IA64_DIG
bool "DIG-compliant"
select SWIOTLB

config IA64_DIG_VTD
bool "DIG+Intel+IOMMU"
select DMAR
select PCI_MSI

config IA64_HP_ZX1
bool "HP-zx1/sx1000"
help
Expand Down Expand Up @@ -614,6 +621,16 @@ source "drivers/pci/hotplug/Kconfig"

source "drivers/pcmcia/Kconfig"

config DMAR
bool "Support for DMA Remapping Devices (EXPERIMENTAL)"
depends on IA64_GENERIC && ACPI && EXPERIMENTAL
help
DMA remapping (DMAR) devices support enables independent address
translations for Direct Memory Access (DMA) from devices.
These DMA remapping devices are reported via ACPI tables
and include PCI device scope covered by these DMA
remapping devices.

endmenu

endif
Expand Down
1 change: 1 addition & 0 deletions arch/ia64/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ libs-y += arch/ia64/lib/
core-y += arch/ia64/kernel/ arch/ia64/mm/
core-$(CONFIG_IA32_SUPPORT) += arch/ia64/ia32/
core-$(CONFIG_IA64_DIG) += arch/ia64/dig/
core-$(CONFIG_IA64_DIG_VTD) += arch/ia64/dig/
core-$(CONFIG_IA64_GENERIC) += arch/ia64/dig/
core-$(CONFIG_IA64_HP_ZX1) += arch/ia64/dig/
core-$(CONFIG_IA64_HP_ZX1_SWIOTLB) += arch/ia64/dig/
Expand Down
2 changes: 2 additions & 0 deletions arch/ia64/configs/generic_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,8 @@ CONFIG_DMIID=y
CONFIG_BINFMT_ELF=y
CONFIG_BINFMT_MISC=m

# CONFIG_DMAR is not set

#
# Power management and ACPI
#
Expand Down
2 changes: 2 additions & 0 deletions arch/ia64/configs/tiger_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,8 @@ CONFIG_DMIID=y
CONFIG_BINFMT_ELF=y
CONFIG_BINFMT_MISC=m

# CONFIG_DMAR is not set

#
# Power management and ACPI
#
Expand Down
5 changes: 5 additions & 0 deletions arch/ia64/dig/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,9 @@
#

obj-y := setup.o
ifeq ($(CONFIG_DMAR), y)
obj-$(CONFIG_IA64_GENERIC) += machvec.o machvec_vtd.o dig_vtd_iommu.o
else
obj-$(CONFIG_IA64_GENERIC) += machvec.o
endif
obj-$(CONFIG_IA64_DIG_VTD) += dig_vtd_iommu.o
59 changes: 59 additions & 0 deletions arch/ia64/dig/dig_vtd_iommu.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/intel-iommu.h>

void *
vtd_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
gfp_t flags)
{
return intel_alloc_coherent(dev, size, dma_handle, flags);
}
EXPORT_SYMBOL_GPL(vtd_alloc_coherent);

void
vtd_free_coherent(struct device *dev, size_t size, void *vaddr,
dma_addr_t dma_handle)
{
intel_free_coherent(dev, size, vaddr, dma_handle);
}
EXPORT_SYMBOL_GPL(vtd_free_coherent);

dma_addr_t
vtd_map_single_attrs(struct device *dev, void *addr, size_t size,
int dir, struct dma_attrs *attrs)
{
return intel_map_single(dev, (phys_addr_t)addr, size, dir);
}
EXPORT_SYMBOL_GPL(vtd_map_single_attrs);

void
vtd_unmap_single_attrs(struct device *dev, dma_addr_t iova, size_t size,
int dir, struct dma_attrs *attrs)
{
intel_unmap_single(dev, iova, size, dir);
}
EXPORT_SYMBOL_GPL(vtd_unmap_single_attrs);

int
vtd_map_sg_attrs(struct device *dev, struct scatterlist *sglist, int nents,
int dir, struct dma_attrs *attrs)
{
return intel_map_sg(dev, sglist, nents, dir);
}
EXPORT_SYMBOL_GPL(vtd_map_sg_attrs);

void
vtd_unmap_sg_attrs(struct device *dev, struct scatterlist *sglist,
int nents, int dir, struct dma_attrs *attrs)
{
intel_unmap_sg(dev, sglist, nents, dir);
}
EXPORT_SYMBOL_GPL(vtd_unmap_sg_attrs);

int
vtd_dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
{
return 0;
}
EXPORT_SYMBOL_GPL(vtd_dma_mapping_error);
3 changes: 3 additions & 0 deletions arch/ia64/dig/machvec_vtd.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#define MACHVEC_PLATFORM_NAME dig_vtd
#define MACHVEC_PLATFORM_HEADER <asm/machvec_dig_vtd.h>
#include <asm/machvec_init.h>
2 changes: 2 additions & 0 deletions arch/ia64/include/asm/cacheflush.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ do { \
#define flush_dcache_mmap_unlock(mapping) do { } while (0)

extern void flush_icache_range (unsigned long start, unsigned long end);
extern void clflush_cache_range(void *addr, int size);


#define flush_icache_user_range(vma, page, user_addr, len) \
do { \
Expand Down
3 changes: 3 additions & 0 deletions arch/ia64/include/asm/device.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ struct dev_archdata {
#ifdef CONFIG_ACPI
void *acpi_handle;
#endif
#ifdef CONFIG_DMAR
void *iommu; /* hook for IOMMU specific extension */
#endif
};

#endif /* _ASM_IA64_DEVICE_H */
50 changes: 50 additions & 0 deletions arch/ia64/include/asm/dma-mapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,49 @@
*/
#include <asm/machvec.h>
#include <linux/scatterlist.h>
#include <asm/swiotlb.h>

struct dma_mapping_ops {
int (*mapping_error)(struct device *dev,
dma_addr_t dma_addr);
void* (*alloc_coherent)(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t gfp);
void (*free_coherent)(struct device *dev, size_t size,
void *vaddr, dma_addr_t dma_handle);
dma_addr_t (*map_single)(struct device *hwdev, unsigned long ptr,
size_t size, int direction);
void (*unmap_single)(struct device *dev, dma_addr_t addr,
size_t size, int direction);
void (*sync_single_for_cpu)(struct device *hwdev,
dma_addr_t dma_handle, size_t size,
int direction);
void (*sync_single_for_device)(struct device *hwdev,
dma_addr_t dma_handle, size_t size,
int direction);
void (*sync_single_range_for_cpu)(struct device *hwdev,
dma_addr_t dma_handle, unsigned long offset,
size_t size, int direction);
void (*sync_single_range_for_device)(struct device *hwdev,
dma_addr_t dma_handle, unsigned long offset,
size_t size, int direction);
void (*sync_sg_for_cpu)(struct device *hwdev,
struct scatterlist *sg, int nelems,
int direction);
void (*sync_sg_for_device)(struct device *hwdev,
struct scatterlist *sg, int nelems,
int direction);
int (*map_sg)(struct device *hwdev, struct scatterlist *sg,
int nents, int direction);
void (*unmap_sg)(struct device *hwdev,
struct scatterlist *sg, int nents,
int direction);
int (*dma_supported_op)(struct device *hwdev, u64 mask);
int is_phys;
};

extern struct dma_mapping_ops *dma_ops;
extern struct ia64_machine_vector ia64_mv;
extern void set_iommu_machvec(void);

#define dma_alloc_coherent(dev, size, handle, gfp) \
platform_dma_alloc_coherent(dev, size, handle, (gfp) | GFP_DMA)
Expand Down Expand Up @@ -96,4 +139,11 @@ dma_cache_sync (struct device *dev, void *vaddr, size_t size,

#define dma_is_consistent(d, h) (1) /* all we do is coherent memory... */

static inline struct dma_mapping_ops *get_dma_ops(struct device *dev)
{
return dma_ops;
}



#endif /* _ASM_IA64_DMA_MAPPING_H */
16 changes: 16 additions & 0 deletions arch/ia64/include/asm/iommu.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#ifndef _ASM_IA64_IOMMU_H
#define _ASM_IA64_IOMMU_H 1

#define cpu_has_x2apic 0
/* 10 seconds */
#define DMAR_OPERATION_TIMEOUT (((cycles_t) local_cpu_data->itc_freq)*10)

extern void pci_iommu_shutdown(void);
extern void no_iommu_init(void);
extern int force_iommu, no_iommu;
extern int iommu_detected;
extern void iommu_dma_init(void);
extern void machvec_init(const char *name);
extern int forbid_dac;

#endif
2 changes: 2 additions & 0 deletions arch/ia64/include/asm/machvec.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@ extern void machvec_tlb_migrate_finish (struct mm_struct *);
# include <asm/machvec_hpsim.h>
# elif defined (CONFIG_IA64_DIG)
# include <asm/machvec_dig.h>
# elif defined(CONFIG_IA64_DIG_VTD)
# include <asm/machvec_dig_vtd.h>
# elif defined (CONFIG_IA64_HP_ZX1)
# include <asm/machvec_hpzx1.h>
# elif defined (CONFIG_IA64_HP_ZX1_SWIOTLB)
Expand Down
38 changes: 38 additions & 0 deletions arch/ia64/include/asm/machvec_dig_vtd.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#ifndef _ASM_IA64_MACHVEC_DIG_VTD_h
#define _ASM_IA64_MACHVEC_DIG_VTD_h

extern ia64_mv_setup_t dig_setup;
extern ia64_mv_dma_alloc_coherent vtd_alloc_coherent;
extern ia64_mv_dma_free_coherent vtd_free_coherent;
extern ia64_mv_dma_map_single_attrs vtd_map_single_attrs;
extern ia64_mv_dma_unmap_single_attrs vtd_unmap_single_attrs;
extern ia64_mv_dma_map_sg_attrs vtd_map_sg_attrs;
extern ia64_mv_dma_unmap_sg_attrs vtd_unmap_sg_attrs;
extern ia64_mv_dma_supported iommu_dma_supported;
extern ia64_mv_dma_mapping_error vtd_dma_mapping_error;
extern ia64_mv_dma_init pci_iommu_alloc;

/*
* This stuff has dual use!
*
* For a generic kernel, the macros are used to initialize the
* platform's machvec structure. When compiling a non-generic kernel,
* the macros are used directly.
*/
#define platform_name "dig_vtd"
#define platform_setup dig_setup
#define platform_dma_init pci_iommu_alloc
#define platform_dma_alloc_coherent vtd_alloc_coherent
#define platform_dma_free_coherent vtd_free_coherent
#define platform_dma_map_single_attrs vtd_map_single_attrs
#define platform_dma_unmap_single_attrs vtd_unmap_single_attrs
#define platform_dma_map_sg_attrs vtd_map_sg_attrs
#define platform_dma_unmap_sg_attrs vtd_unmap_sg_attrs
#define platform_dma_sync_single_for_cpu machvec_dma_sync_single
#define platform_dma_sync_sg_for_cpu machvec_dma_sync_sg
#define platform_dma_sync_single_for_device machvec_dma_sync_single
#define platform_dma_sync_sg_for_device machvec_dma_sync_sg
#define platform_dma_supported iommu_dma_supported
#define platform_dma_mapping_error vtd_dma_mapping_error

#endif /* _ASM_IA64_MACHVEC_DIG_VTD_h */
1 change: 1 addition & 0 deletions arch/ia64/include/asm/machvec_init.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include <asm/iommu.h>
#include <asm/machvec.h>

extern ia64_mv_send_ipi_t ia64_send_ipi;
Expand Down
3 changes: 3 additions & 0 deletions arch/ia64/include/asm/pci.h
Original file line number Diff line number Diff line change
Expand Up @@ -164,4 +164,7 @@ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
return channel ? isa_irq_to_vector(15) : isa_irq_to_vector(14);
}

#ifdef CONFIG_DMAR
extern void pci_iommu_alloc(void);
#endif
#endif /* _ASM_IA64_PCI_H */
56 changes: 56 additions & 0 deletions arch/ia64/include/asm/swiotlb.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#ifndef ASM_IA64__SWIOTLB_H
#define ASM_IA64__SWIOTLB_H

#include <linux/dma-mapping.h>

/* SWIOTLB interface */

extern dma_addr_t swiotlb_map_single(struct device *hwdev, void *ptr,
size_t size, int dir);
extern void *swiotlb_alloc_coherent(struct device *hwdev, size_t size,
dma_addr_t *dma_handle, gfp_t flags);
extern void swiotlb_unmap_single(struct device *hwdev, dma_addr_t dev_addr,
size_t size, int dir);
extern void swiotlb_sync_single_for_cpu(struct device *hwdev,
dma_addr_t dev_addr,
size_t size, int dir);
extern void swiotlb_sync_single_for_device(struct device *hwdev,
dma_addr_t dev_addr,
size_t size, int dir);
extern void swiotlb_sync_single_range_for_cpu(struct device *hwdev,
dma_addr_t dev_addr,
unsigned long offset,
size_t size, int dir);
extern void swiotlb_sync_single_range_for_device(struct device *hwdev,
dma_addr_t dev_addr,
unsigned long offset,
size_t size, int dir);
extern void swiotlb_sync_sg_for_cpu(struct device *hwdev,
struct scatterlist *sg, int nelems,
int dir);
extern void swiotlb_sync_sg_for_device(struct device *hwdev,
struct scatterlist *sg, int nelems,
int dir);
extern int swiotlb_map_sg(struct device *hwdev, struct scatterlist *sg,
int nents, int direction);
extern void swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sg,
int nents, int direction);
extern int swiotlb_dma_mapping_error(struct device *hwdev, dma_addr_t dma_addr);
extern void swiotlb_free_coherent(struct device *hwdev, size_t size,
void *vaddr, dma_addr_t dma_handle);
extern int swiotlb_dma_supported(struct device *hwdev, u64 mask);
extern void swiotlb_init(void);

extern int swiotlb_force;

#ifdef CONFIG_SWIOTLB
extern int swiotlb;
extern void pci_swiotlb_init(void);
#else
#define swiotlb 0
static inline void pci_swiotlb_init(void)
{
}
#endif

#endif /* ASM_IA64__SWIOTLB_H */
4 changes: 4 additions & 0 deletions arch/ia64/kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ obj-$(CONFIG_IA64_ESI) += esi.o
ifneq ($(CONFIG_IA64_ESI),)
obj-y += esi_stub.o # must be in kernel proper
endif
obj-$(CONFIG_DMAR) += pci-dma.o
ifeq ($(CONFIG_DMAR), y)
obj-$(CONFIG_SWIOTLB) += pci-swiotlb.o
endif

# The gate DSO image is built using a special linker script.
targets += gate.so gate-syms.o
Expand Down
Loading

0 comments on commit fe39316

Please sign in to comment.