aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/apic/apic.c
diff options
context:
space:
mode:
authorFenghua Yu <fenghua.yu@intel.com>2009-03-27 17:22:44 -0400
committerDavid Woodhouse <David.Woodhouse@intel.com>2009-04-03 16:45:59 -0400
commitb24696bc55f66fecc30715e003f10fc2555a9271 (patch)
tree3ef565bf041a06106a73d0b27ccc256845ef5644 /arch/x86/kernel/apic/apic.c
parenteb4a52bc660ea835482c582eaaf4893742cbd160 (diff)
Intel IOMMU Suspend/Resume Support - Interrupt Remapping
This patch enables suspend/resume for interrupt remapping. During suspend, interrupt remapping is disabled. When resume, interrupt remapping is enabled again. Signed-off-by: Fenghua Yu <fenghua.yu@intel.com> Acked-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'arch/x86/kernel/apic/apic.c')
-rw-r--r--arch/x86/kernel/apic/apic.c70
1 files changed, 62 insertions, 8 deletions
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index 85eb8e100818..098ec84b8c00 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -1304,6 +1304,7 @@ void __init enable_IR_x2apic(void)
1304#ifdef CONFIG_INTR_REMAP 1304#ifdef CONFIG_INTR_REMAP
1305 int ret; 1305 int ret;
1306 unsigned long flags; 1306 unsigned long flags;
1307 struct IO_APIC_route_entry **ioapic_entries = NULL;
1307 1308
1308 if (!cpu_has_x2apic) 1309 if (!cpu_has_x2apic)
1309 return; 1310 return;
@@ -1334,17 +1335,23 @@ void __init enable_IR_x2apic(void)
1334 return; 1335 return;
1335 } 1336 }
1336 1337
1337 ret = save_IO_APIC_setup(); 1338 ioapic_entries = alloc_ioapic_entries();
1339 if (!ioapic_entries) {
1340 pr_info("Allocate ioapic_entries failed: %d\n", ret);
1341 goto end;
1342 }
1343
1344 ret = save_IO_APIC_setup(ioapic_entries);
1338 if (ret) { 1345 if (ret) {
1339 pr_info("Saving IO-APIC state failed: %d\n", ret); 1346 pr_info("Saving IO-APIC state failed: %d\n", ret);
1340 goto end; 1347 goto end;
1341 } 1348 }
1342 1349
1343 local_irq_save(flags); 1350 local_irq_save(flags);
1344 mask_IO_APIC_setup(); 1351 mask_IO_APIC_setup(ioapic_entries);
1345 mask_8259A(); 1352 mask_8259A();
1346 1353
1347 ret = enable_intr_remapping(1); 1354 ret = enable_intr_remapping(EIM_32BIT_APIC_ID);
1348 1355
1349 if (ret && x2apic_preenabled) { 1356 if (ret && x2apic_preenabled) {
1350 local_irq_restore(flags); 1357 local_irq_restore(flags);
@@ -1364,9 +1371,9 @@ end_restore:
1364 /* 1371 /*
1365 * IR enabling failed 1372 * IR enabling failed
1366 */ 1373 */
1367 restore_IO_APIC_setup(); 1374 restore_IO_APIC_setup(ioapic_entries);
1368 else 1375 else
1369 reinit_intr_remapped_IO_APIC(x2apic_preenabled); 1376 reinit_intr_remapped_IO_APIC(x2apic_preenabled, ioapic_entries);
1370 1377
1371 unmask_8259A(); 1378 unmask_8259A();
1372 local_irq_restore(flags); 1379 local_irq_restore(flags);
@@ -1379,6 +1386,8 @@ end:
1379 pr_info("Enabled Interrupt-remapping\n"); 1386 pr_info("Enabled Interrupt-remapping\n");
1380 } else 1387 } else
1381 pr_err("Failed to enable Interrupt-remapping and x2apic\n"); 1388 pr_err("Failed to enable Interrupt-remapping and x2apic\n");
1389 if (ioapic_entries)
1390 free_ioapic_entries(ioapic_entries);
1382#else 1391#else
1383 if (!cpu_has_x2apic) 1392 if (!cpu_has_x2apic)
1384 return; 1393 return;
@@ -1954,6 +1963,10 @@ static int lapic_suspend(struct sys_device *dev, pm_message_t state)
1954 1963
1955 local_irq_save(flags); 1964 local_irq_save(flags);
1956 disable_local_APIC(); 1965 disable_local_APIC();
1966#ifdef CONFIG_INTR_REMAP
1967 if (intr_remapping_enabled)
1968 disable_intr_remapping();
1969#endif
1957 local_irq_restore(flags); 1970 local_irq_restore(flags);
1958 return 0; 1971 return 0;
1959} 1972}
@@ -1964,15 +1977,41 @@ static int lapic_resume(struct sys_device *dev)
1964 unsigned long flags; 1977 unsigned long flags;
1965 int maxlvt; 1978 int maxlvt;
1966 1979
1980#ifdef CONFIG_INTR_REMAP
1981 int ret;
1982 struct IO_APIC_route_entry **ioapic_entries = NULL;
1983
1967 if (!apic_pm_state.active) 1984 if (!apic_pm_state.active)
1968 return 0; 1985 return 0;
1969 1986
1970 maxlvt = lapic_get_maxlvt();
1971
1972 local_irq_save(flags); 1987 local_irq_save(flags);
1988 if (x2apic) {
1989 ioapic_entries = alloc_ioapic_entries();
1990 if (!ioapic_entries) {
1991 WARN(1, "Alloc ioapic_entries in lapic resume failed.");
1992 return -ENOMEM;
1993 }
1994
1995 ret = save_IO_APIC_setup(ioapic_entries);
1996 if (ret) {
1997 WARN(1, "Saving IO-APIC state failed: %d\n", ret);
1998 free_ioapic_entries(ioapic_entries);
1999 return ret;
2000 }
2001
2002 mask_IO_APIC_setup(ioapic_entries);
2003 mask_8259A();
2004 enable_x2apic();
2005 }
2006#else
2007 if (!apic_pm_state.active)
2008 return 0;
1973 2009
2010 local_irq_save(flags);
1974 if (x2apic) 2011 if (x2apic)
1975 enable_x2apic(); 2012 enable_x2apic();
2013#endif
2014
1976 else { 2015 else {
1977 /* 2016 /*
1978 * Make sure the APICBASE points to the right address 2017 * Make sure the APICBASE points to the right address
@@ -1986,6 +2025,7 @@ static int lapic_resume(struct sys_device *dev)
1986 wrmsr(MSR_IA32_APICBASE, l, h); 2025 wrmsr(MSR_IA32_APICBASE, l, h);
1987 } 2026 }
1988 2027
2028 maxlvt = lapic_get_maxlvt();
1989 apic_write(APIC_LVTERR, ERROR_APIC_VECTOR | APIC_LVT_MASKED); 2029 apic_write(APIC_LVTERR, ERROR_APIC_VECTOR | APIC_LVT_MASKED);
1990 apic_write(APIC_ID, apic_pm_state.apic_id); 2030 apic_write(APIC_ID, apic_pm_state.apic_id);
1991 apic_write(APIC_DFR, apic_pm_state.apic_dfr); 2031 apic_write(APIC_DFR, apic_pm_state.apic_dfr);
@@ -2009,8 +2049,20 @@ static int lapic_resume(struct sys_device *dev)
2009 apic_write(APIC_ESR, 0); 2049 apic_write(APIC_ESR, 0);
2010 apic_read(APIC_ESR); 2050 apic_read(APIC_ESR);
2011 2051
2052#ifdef CONFIG_INTR_REMAP
2053 if (intr_remapping_enabled)
2054 reenable_intr_remapping(EIM_32BIT_APIC_ID);
2055
2056 if (x2apic) {
2057 unmask_8259A();
2058 restore_IO_APIC_setup(ioapic_entries);
2059 free_ioapic_entries(ioapic_entries);
2060 }
2061#endif
2062
2012 local_irq_restore(flags); 2063 local_irq_restore(flags);
2013 2064
2065
2014 return 0; 2066 return 0;
2015} 2067}
2016 2068
@@ -2048,7 +2100,9 @@ static int __init init_lapic_sysfs(void)
2048 error = sysdev_register(&device_lapic); 2100 error = sysdev_register(&device_lapic);
2049 return error; 2101 return error;
2050} 2102}
2051device_initcall(init_lapic_sysfs); 2103
2104/* local apic needs to resume before other devices access its registers. */
2105core_initcall(init_lapic_sysfs);
2052 2106
2053#else /* CONFIG_PM */ 2107#else /* CONFIG_PM */
2054 2108