Skip to content

Commit

Permalink
Merge branch 'x86-iommu-for-linus' of git://git.kernel.org/pub/scm/li…
Browse files Browse the repository at this point in the history
…nux/kernel/git/tip/linux-2.6-tip

* 'x86-iommu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
  x86, iommu: Update header comments with appropriate naming
  ia64, iommu: Add a dummy iommu_table.h file in IA64.
  x86, iommu: Fix IOMMU_INIT alignment rules
  x86, doc: Adding comments about .iommu_table and its neighbors.
  x86, iommu: Utilize the IOMMU_INIT macros functionality.
  x86, VT-d: Make Intel VT-d IOMMU use IOMMU_INIT_* macros.
  x86, GART/AMD-VI: Make AMD GART and IOMMU use IOMMU_INIT_* macros.
  x86, calgary: Make Calgary IOMMU use IOMMU_INIT_* macros.
  x86, xen-swiotlb: Make Xen-SWIOTLB use IOMMU_INIT_* macros.
  x86, swiotlb: Make SWIOTLB use IOMMU_INIT_* macros.
  x86, swiotlb: Simplify SWIOTLB pci_swiotlb_detect routine.
  x86, iommu: Add proper dependency sort routine (and sanity check).
  x86, iommu: Make all IOMMU's detection routines return a value.
  x86, iommu: Add IOMMU_INIT macros, .iommu_table section, and iommu_table_entry structure
  • Loading branch information
Linus Torvalds committed Oct 21, 2010
2 parents 4a60cfa + 6e96366 commit 157b6ce
Show file tree
Hide file tree
Showing 18 changed files with 344 additions and 57 deletions.
6 changes: 6 additions & 0 deletions arch/ia64/include/asm/iommu_table.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#ifndef _ASM_IA64_IOMMU_TABLE_H
#define _ASM_IA64_IOMMU_TABLE_H

#define IOMMU_INIT_POST(_detect)

#endif /* _ASM_IA64_IOMMU_TABLE_H */
4 changes: 2 additions & 2 deletions arch/x86/include/asm/amd_iommu.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@

#ifdef CONFIG_AMD_IOMMU

extern void amd_iommu_detect(void);
extern int amd_iommu_detect(void);

#else

static inline void amd_iommu_detect(void) { }
static inline int amd_iommu_detect(void) { return -ENODEV; }

#endif

Expand Down
4 changes: 2 additions & 2 deletions arch/x86/include/asm/calgary.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,9 @@ struct cal_chipset_ops {
extern int use_calgary;

#ifdef CONFIG_CALGARY_IOMMU
extern void detect_calgary(void);
extern int detect_calgary(void);
#else
static inline void detect_calgary(void) { return; }
static inline int detect_calgary(void) { return -ENODEV; }
#endif

#endif /* _ASM_X86_CALGARY_H */
5 changes: 3 additions & 2 deletions arch/x86/include/asm/gart.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ extern int gart_iommu_aperture_disabled;
extern void early_gart_iommu_check(void);
extern int gart_iommu_init(void);
extern void __init gart_parse_options(char *);
extern void gart_iommu_hole_init(void);
extern int gart_iommu_hole_init(void);

#else
#define gart_iommu_aperture 0
Expand All @@ -50,8 +50,9 @@ static inline void early_gart_iommu_check(void)
static inline void gart_parse_options(char *options)
{
}
static inline void gart_iommu_hole_init(void)
static inline int gart_iommu_hole_init(void)
{
return -ENODEV;
}
#endif

Expand Down
100 changes: 100 additions & 0 deletions arch/x86/include/asm/iommu_table.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
#ifndef _ASM_X86_IOMMU_TABLE_H
#define _ASM_X86_IOMMU_TABLE_H

#include <asm/swiotlb.h>

/*
* History lesson:
* The execution chain of IOMMUs in 2.6.36 looks as so:
*
* [xen-swiotlb]
* |
* +----[swiotlb *]--+
* / | \
* / | \
* [GART] [Calgary] [Intel VT-d]
* /
* /
* [AMD-Vi]
*
* *: if SWIOTLB detected 'iommu=soft'/'swiotlb=force' it would skip
* over the rest of IOMMUs and unconditionally initialize the SWIOTLB.
* Also it would surreptitiously initialize set the swiotlb=1 if there were
* more than 4GB and if the user did not pass in 'iommu=off'. The swiotlb
* flag would be turned off by all IOMMUs except the Calgary one.
*
* The IOMMU_INIT* macros allow a similar tree (or more complex if desired)
* to be built by defining who we depend on.
*
* And all that needs to be done is to use one of the macros in the IOMMU
* and the pci-dma.c will take care of the rest.
*/

struct iommu_table_entry {
initcall_t detect;
initcall_t depend;
void (*early_init)(void); /* No memory allocate available. */
void (*late_init)(void); /* Yes, can allocate memory. */
#define IOMMU_FINISH_IF_DETECTED (1<<0)
#define IOMMU_DETECTED (1<<1)
int flags;
};
/*
* Macro fills out an entry in the .iommu_table that is equivalent
* to the fields that 'struct iommu_table_entry' has. The entries
* that are put in the .iommu_table section are not put in any order
* hence during boot-time we will have to resort them based on
* dependency. */


#define __IOMMU_INIT(_detect, _depend, _early_init, _late_init, _finish)\
static const struct iommu_table_entry const \
__iommu_entry_##_detect __used \
__attribute__ ((unused, __section__(".iommu_table"), \
aligned((sizeof(void *))))) \
= {_detect, _depend, _early_init, _late_init, \
_finish ? IOMMU_FINISH_IF_DETECTED : 0}
/*
* The simplest IOMMU definition. Provide the detection routine
* and it will be run after the SWIOTLB and the other IOMMUs
* that utilize this macro. If the IOMMU is detected (ie, the
* detect routine returns a positive value), the other IOMMUs
* are also checked. You can use IOMMU_INIT_POST_FINISH if you prefer
* to stop detecting the other IOMMUs after yours has been detected.
*/
#define IOMMU_INIT_POST(_detect) \
__IOMMU_INIT(_detect, pci_swiotlb_detect_4gb, 0, 0, 0)

#define IOMMU_INIT_POST_FINISH(detect) \
__IOMMU_INIT(_detect, pci_swiotlb_detect_4gb, 0, 0, 1)

/*
* A more sophisticated version of IOMMU_INIT. This variant requires:
* a). A detection routine function.
* b). The name of the detection routine we depend on to get called
* before us.
* c). The init routine which gets called if the detection routine
* returns a positive value from the pci_iommu_alloc. This means
* no presence of a memory allocator.
* d). Similar to the 'init', except that this gets called from pci_iommu_init
* where we do have a memory allocator.
*
* The standard vs the _FINISH differs in that the _FINISH variant will
* continue detecting other IOMMUs in the call list after the
* the detection routine returns a positive number. The _FINISH will
* stop the execution chain. Both will still call the 'init' and
* 'late_init' functions if they are set.
*/
#define IOMMU_INIT_FINISH(_detect, _depend, _init, _late_init) \
__IOMMU_INIT(_detect, _depend, _init, _late_init, 1)

#define IOMMU_INIT(_detect, _depend, _init, _late_init) \
__IOMMU_INIT(_detect, _depend, _init, _late_init, 0)

void sort_iommu_table(struct iommu_table_entry *start,
struct iommu_table_entry *finish);

void check_iommu_entries(struct iommu_table_entry *start,
struct iommu_table_entry *finish);

#endif /* _ASM_X86_IOMMU_TABLE_H */
13 changes: 11 additions & 2 deletions arch/x86/include/asm/swiotlb.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,26 @@

#ifdef CONFIG_SWIOTLB
extern int swiotlb;
extern int __init pci_swiotlb_detect(void);
extern int __init pci_swiotlb_detect_override(void);
extern int __init pci_swiotlb_detect_4gb(void);
extern void __init pci_swiotlb_init(void);
extern void __init pci_swiotlb_late_init(void);
#else
#define swiotlb 0
static inline int pci_swiotlb_detect(void)
static inline int pci_swiotlb_detect_override(void)
{
return 0;
}
static inline int pci_swiotlb_detect_4gb(void)
{
return 0;
}
static inline void pci_swiotlb_init(void)
{
}
static inline void pci_swiotlb_late_init(void)
{
}
#endif

static inline void dma_mark_clean(void *addr, size_t size) {}
Expand Down
1 change: 1 addition & 0 deletions arch/x86/kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ obj-y += bootflag.o e820.o
obj-y += pci-dma.o quirks.o i8237.o topology.o kdebugfs.o
obj-y += alternative.o i8253.o pci-nommu.o hw_breakpoint.o
obj-y += tsc.o io_delay.o rtc.o
obj-y += pci-iommu_table.o

obj-$(CONFIG_X86_TRAMPOLINE) += trampoline.o
obj-y += process.o
Expand Down
15 changes: 11 additions & 4 deletions arch/x86/kernel/amd_iommu_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
#include <asm/iommu.h>
#include <asm/gart.h>
#include <asm/x86_init.h>

#include <asm/iommu_table.h>
/*
* definitions for the ACPI scanning code
*/
Expand Down Expand Up @@ -1499,13 +1499,13 @@ static int __init early_amd_iommu_detect(struct acpi_table_header *table)
return 0;
}

void __init amd_iommu_detect(void)
int __init amd_iommu_detect(void)
{
if (no_iommu || (iommu_detected && !gart_iommu_aperture))
return;
return -ENODEV;

if (amd_iommu_disabled)
return;
return -ENODEV;

if (acpi_table_parse("IVRS", early_amd_iommu_detect) == 0) {
iommu_detected = 1;
Expand All @@ -1514,7 +1514,9 @@ void __init amd_iommu_detect(void)

/* Make sure ACS will be enabled */
pci_request_acs();
return 1;
}
return -ENODEV;
}

/****************************************************************************
Expand Down Expand Up @@ -1545,3 +1547,8 @@ static int __init parse_amd_iommu_options(char *str)

__setup("amd_iommu_dump", parse_amd_iommu_dump);
__setup("amd_iommu=", parse_amd_iommu_options);

IOMMU_INIT_FINISH(amd_iommu_detect,
gart_iommu_hole_init,
0,
0);
11 changes: 7 additions & 4 deletions arch/x86/kernel/aperture_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,7 @@ void __init early_gart_iommu_check(void)

static int __initdata printed_gart_size_msg;

void __init gart_iommu_hole_init(void)
int __init gart_iommu_hole_init(void)
{
u32 agp_aper_base = 0, agp_aper_order = 0;
u32 aper_size, aper_alloc = 0, aper_order = 0, last_aper_order = 0;
Expand All @@ -381,7 +381,7 @@ void __init gart_iommu_hole_init(void)

if (gart_iommu_aperture_disabled || !fix_aperture ||
!early_pci_allowed())
return;
return -ENODEV;

printk(KERN_INFO "Checking aperture...\n");

Expand Down Expand Up @@ -463,8 +463,9 @@ void __init gart_iommu_hole_init(void)
unsigned long n = (32 * 1024 * 1024) << last_aper_order;

insert_aperture_resource((u32)last_aper_base, n);
return 1;
}
return;
return 0;
}

if (!fallback_aper_force) {
Expand Down Expand Up @@ -500,7 +501,7 @@ void __init gart_iommu_hole_init(void)
panic("Not enough memory for aperture");
}
} else {
return;
return 0;
}

/* Fix up the north bridges */
Expand All @@ -526,4 +527,6 @@ void __init gart_iommu_hole_init(void)
}

set_up_gart_resume(aper_order, aper_alloc);

return 1;
}
18 changes: 11 additions & 7 deletions arch/x86/kernel/pci-calgary_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
#include <asm/rio.h>
#include <asm/bios_ebda.h>
#include <asm/x86_init.h>
#include <asm/iommu_table.h>

#ifdef CONFIG_CALGARY_IOMMU_ENABLED_BY_DEFAULT
int use_calgary __read_mostly = 1;
Expand Down Expand Up @@ -1364,7 +1365,7 @@ static int __init calgary_iommu_init(void)
return 0;
}

void __init detect_calgary(void)
int __init detect_calgary(void)
{
int bus;
void *tbl;
Expand All @@ -1378,13 +1379,13 @@ void __init detect_calgary(void)
* another HW IOMMU already, bail out.
*/
if (no_iommu || iommu_detected)
return;
return -ENODEV;

if (!use_calgary)
return;
return -ENODEV;

if (!early_pci_allowed())
return;
return -ENODEV;

printk(KERN_DEBUG "Calgary: detecting Calgary via BIOS EBDA area\n");

Expand All @@ -1410,13 +1411,13 @@ void __init detect_calgary(void)
if (!rio_table_hdr) {
printk(KERN_DEBUG "Calgary: Unable to locate Rio Grande table "
"in EBDA - bailing!\n");
return;
return -ENODEV;
}

ret = build_detail_arrays();
if (ret) {
printk(KERN_DEBUG "Calgary: build_detail_arrays ret %d\n", ret);
return;
return -ENOMEM;
}

specified_table_size = determine_tce_table_size((is_kdump_kernel() ?
Expand Down Expand Up @@ -1464,7 +1465,7 @@ void __init detect_calgary(void)

x86_init.iommu.iommu_init = calgary_iommu_init;
}
return;
return calgary_found;

cleanup:
for (--bus; bus >= 0; --bus) {
Expand All @@ -1473,6 +1474,7 @@ void __init detect_calgary(void)
if (info->tce_space)
free_tce_table(info->tce_space);
}
return -ENOMEM;
}

static int __init calgary_parse_options(char *p)
Expand Down Expand Up @@ -1594,3 +1596,5 @@ static int __init calgary_fixup_tce_spaces(void)
* and before device_initcall.
*/
rootfs_initcall(calgary_fixup_tce_spaces);

IOMMU_INIT_POST(detect_calgary);
Loading

0 comments on commit 157b6ce

Please sign in to comment.