Skip to content

Commit

Permalink
Merge git://git.infradead.org/iommu-2.6
Browse files Browse the repository at this point in the history
* git://git.infradead.org/iommu-2.6:
  drivers/pci/intr_remapping.c: include acpi.h
  intel-iommu: Fix oops in device_to_iommu() when devices not found.
  intel-iommu: Handle PCI domains appropriately.
  intel-iommu: Fix device-to-iommu mapping for PCI-PCI bridges.
  x2apic/intr-remap: decouple interrupt remapping from x2apic
  x86, dmar: check if it's initialized before disable queue invalidation
  intel-iommu: set compatibility format interrupt
  Intel IOMMU Suspend/Resume Support - Interrupt Remapping
  Intel IOMMU Suspend/Resume Support - Queued Invalidation
  Intel IOMMU Suspend/Resume Support - DMAR
  intel-iommu: Add for_each_iommu() and for_each_active_iommu() macros
  • Loading branch information
Linus Torvalds committed Apr 6, 2009
2 parents 8e320d0 + 46f06b7 commit ffa009c
Show file tree
Hide file tree
Showing 10 changed files with 539 additions and 105 deletions.
2 changes: 1 addition & 1 deletion arch/x86/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,7 @@ config SMP
config X86_X2APIC
bool "Support x2apic"
depends on X86_LOCAL_APIC && X86_64
select INTR_REMAP
---help---
This enables x2apic support on CPUs that have this feature.

Expand Down Expand Up @@ -1881,7 +1882,6 @@ config DMAR_FLOPPY_WA
config INTR_REMAP
bool "Support for Interrupt Remapping (EXPERIMENTAL)"
depends on X86_64 && X86_IO_APIC && PCI_MSI && ACPI && EXPERIMENTAL
select X86_X2APIC
---help---
Supports Interrupt remapping for IO-APIC and MSI devices.
To use x2apic mode in the CPU's which support x2APIC enhancements or
Expand Down
3 changes: 3 additions & 0 deletions arch/x86/include/asm/apic.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,9 @@ extern u32 native_safe_apic_wait_icr_idle(void);
extern void native_apic_icr_write(u32 low, u32 id);
extern u64 native_apic_icr_read(void);

#define EIM_8BIT_APIC_ID 0
#define EIM_32BIT_APIC_ID 1

#ifdef CONFIG_X86_X2APIC
/*
* Make previous memory operations globally visible before
Expand Down
11 changes: 7 additions & 4 deletions arch/x86/include/asm/io_apic.h
Original file line number Diff line number Diff line change
Expand Up @@ -162,10 +162,13 @@ extern int (*ioapic_renumber_irq)(int ioapic, int irq);
extern void ioapic_init_mappings(void);

#ifdef CONFIG_X86_64
extern int save_IO_APIC_setup(void);
extern void mask_IO_APIC_setup(void);
extern void restore_IO_APIC_setup(void);
extern void reinit_intr_remapped_IO_APIC(int);
extern struct IO_APIC_route_entry **alloc_ioapic_entries(void);
extern void free_ioapic_entries(struct IO_APIC_route_entry **ioapic_entries);
extern int save_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries);
extern void mask_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries);
extern int restore_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries);
extern void reinit_intr_remapped_IO_APIC(int intr_remapping,
struct IO_APIC_route_entry **ioapic_entries);
#endif

extern void probe_nr_irqs_gsi(void);
Expand Down
70 changes: 62 additions & 8 deletions arch/x86/kernel/apic/apic.c
Original file line number Diff line number Diff line change
Expand Up @@ -1304,6 +1304,7 @@ void __init enable_IR_x2apic(void)
#ifdef CONFIG_INTR_REMAP
int ret;
unsigned long flags;
struct IO_APIC_route_entry **ioapic_entries = NULL;

if (!cpu_has_x2apic)
return;
Expand Down Expand Up @@ -1334,17 +1335,23 @@ void __init enable_IR_x2apic(void)
return;
}

ret = save_IO_APIC_setup();
ioapic_entries = alloc_ioapic_entries();
if (!ioapic_entries) {
pr_info("Allocate ioapic_entries failed: %d\n", ret);
goto end;
}

ret = save_IO_APIC_setup(ioapic_entries);
if (ret) {
pr_info("Saving IO-APIC state failed: %d\n", ret);
goto end;
}

local_irq_save(flags);
mask_IO_APIC_setup();
mask_IO_APIC_setup(ioapic_entries);
mask_8259A();

ret = enable_intr_remapping(1);
ret = enable_intr_remapping(EIM_32BIT_APIC_ID);

if (ret && x2apic_preenabled) {
local_irq_restore(flags);
Expand All @@ -1364,9 +1371,9 @@ void __init enable_IR_x2apic(void)
/*
* IR enabling failed
*/
restore_IO_APIC_setup();
restore_IO_APIC_setup(ioapic_entries);
else
reinit_intr_remapped_IO_APIC(x2apic_preenabled);
reinit_intr_remapped_IO_APIC(x2apic_preenabled, ioapic_entries);

unmask_8259A();
local_irq_restore(flags);
Expand All @@ -1379,6 +1386,8 @@ void __init enable_IR_x2apic(void)
pr_info("Enabled Interrupt-remapping\n");
} else
pr_err("Failed to enable Interrupt-remapping and x2apic\n");
if (ioapic_entries)
free_ioapic_entries(ioapic_entries);
#else
if (!cpu_has_x2apic)
return;
Expand Down Expand Up @@ -1954,6 +1963,10 @@ static int lapic_suspend(struct sys_device *dev, pm_message_t state)

local_irq_save(flags);
disable_local_APIC();
#ifdef CONFIG_INTR_REMAP
if (intr_remapping_enabled)
disable_intr_remapping();
#endif
local_irq_restore(flags);
return 0;
}
Expand All @@ -1964,15 +1977,41 @@ static int lapic_resume(struct sys_device *dev)
unsigned long flags;
int maxlvt;

#ifdef CONFIG_INTR_REMAP
int ret;
struct IO_APIC_route_entry **ioapic_entries = NULL;

if (!apic_pm_state.active)
return 0;

maxlvt = lapic_get_maxlvt();

local_irq_save(flags);
if (x2apic) {
ioapic_entries = alloc_ioapic_entries();
if (!ioapic_entries) {
WARN(1, "Alloc ioapic_entries in lapic resume failed.");
return -ENOMEM;
}

ret = save_IO_APIC_setup(ioapic_entries);
if (ret) {
WARN(1, "Saving IO-APIC state failed: %d\n", ret);
free_ioapic_entries(ioapic_entries);
return ret;
}

mask_IO_APIC_setup(ioapic_entries);
mask_8259A();
enable_x2apic();
}
#else
if (!apic_pm_state.active)
return 0;

local_irq_save(flags);
if (x2apic)
enable_x2apic();
#endif

else {
/*
* Make sure the APICBASE points to the right address
Expand All @@ -1986,6 +2025,7 @@ static int lapic_resume(struct sys_device *dev)
wrmsr(MSR_IA32_APICBASE, l, h);
}

maxlvt = lapic_get_maxlvt();
apic_write(APIC_LVTERR, ERROR_APIC_VECTOR | APIC_LVT_MASKED);
apic_write(APIC_ID, apic_pm_state.apic_id);
apic_write(APIC_DFR, apic_pm_state.apic_dfr);
Expand All @@ -2009,8 +2049,20 @@ static int lapic_resume(struct sys_device *dev)
apic_write(APIC_ESR, 0);
apic_read(APIC_ESR);

#ifdef CONFIG_INTR_REMAP
if (intr_remapping_enabled)
reenable_intr_remapping(EIM_32BIT_APIC_ID);

if (x2apic) {
unmask_8259A();
restore_IO_APIC_setup(ioapic_entries);
free_ioapic_entries(ioapic_entries);
}
#endif

local_irq_restore(flags);


return 0;
}

Expand Down Expand Up @@ -2048,7 +2100,9 @@ static int __init init_lapic_sysfs(void)
error = sysdev_register(&device_lapic);
return error;
}
device_initcall(init_lapic_sysfs);

/* local apic needs to resume before other devices access its registers. */
core_initcall(init_lapic_sysfs);

#else /* CONFIG_PM */

Expand Down
Loading

0 comments on commit ffa009c

Please sign in to comment.