aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWeidong Han <weidong.han@intel.com>2009-04-17 04:42:14 -0400
committerIngo Molnar <mingo@elte.hu>2009-04-19 04:21:43 -0400
commit937582382c71b75b29fbb92615629494e1a05ac0 (patch)
treee73af8d10d388fcc78d19534611db66233907a9e
parent5d0ae2db6deac4f15dac4f42f23bc56448fc8d4d (diff)
x86, intr-remap: enable interrupt remapping early
Currently, when x2apic is not enabled, interrupt remapping will be enabled in init_dmars(), where it is too late to remap ioapic interrupts, that is, ioapic interrupts are really in compatibility mode, not remappable mode. This patch always enables interrupt remapping before ioapic setup, it guarantees all interrupts will be remapped when interrupt remapping is enabled. Thus it doesn't need to set the compatibility interrupt bit. [ Impact: refactor intr-remap init sequence, enable fuller remap mode ] Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com> Signed-off-by: Weidong Han <weidong.han@intel.com> Acked-by: David Woodhouse <David.Woodhouse@intel.com> Cc: iommu@lists.linux-foundation.org Cc: allen.m.kay@intel.com Cc: fenghua.yu@intel.com LKML-Reference: <1239957736-6161-4-git-send-email-weidong.han@intel.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--arch/x86/include/asm/apic.h7
-rw-r--r--arch/x86/kernel/apic/apic.c76
-rw-r--r--drivers/pci/intel-iommu.c9
-rw-r--r--drivers/pci/intr_remapping.c28
-rw-r--r--include/linux/dmar.h1
5 files changed, 54 insertions, 67 deletions
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index d4cb7e590c06..fbdd65446c7a 100644
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -169,7 +169,6 @@ static inline u64 native_x2apic_icr_read(void)
169extern int x2apic, x2apic_phys; 169extern int x2apic, x2apic_phys;
170extern void check_x2apic(void); 170extern void check_x2apic(void);
171extern void enable_x2apic(void); 171extern void enable_x2apic(void);
172extern void enable_IR_x2apic(void);
173extern void x2apic_icr_write(u32 low, u32 id); 172extern void x2apic_icr_write(u32 low, u32 id);
174static inline int x2apic_enabled(void) 173static inline int x2apic_enabled(void)
175{ 174{
@@ -190,18 +189,18 @@ static inline void check_x2apic(void)
190static inline void enable_x2apic(void) 189static inline void enable_x2apic(void)
191{ 190{
192} 191}
193static inline void enable_IR_x2apic(void)
194{
195}
196static inline int x2apic_enabled(void) 192static inline int x2apic_enabled(void)
197{ 193{
198 return 0; 194 return 0;
199} 195}
200 196
201#define x2apic 0 197#define x2apic 0
198#define x2apic_preenabled 0
202 199
203#endif 200#endif
204 201
202extern void enable_IR_x2apic(void);
203
205extern int get_physical_broadcast(void); 204extern int get_physical_broadcast(void);
206 205
207extern void apic_disable(void); 206extern void apic_disable(void);
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index 83e47febcc89..0cf1eea750cc 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -141,6 +141,8 @@ static int x2apic_preenabled;
141static int disable_x2apic; 141static int disable_x2apic;
142static __init int setup_nox2apic(char *str) 142static __init int setup_nox2apic(char *str)
143{ 143{
144 if (x2apic_enabled())
145 panic("Bios already enabled x2apic, can't enforce nox2apic");
144 disable_x2apic = 1; 146 disable_x2apic = 1;
145 setup_clear_cpu_cap(X86_FEATURE_X2APIC); 147 setup_clear_cpu_cap(X86_FEATURE_X2APIC);
146 return 0; 148 return 0;
@@ -1345,6 +1347,7 @@ void enable_x2apic(void)
1345 wrmsr(MSR_IA32_APICBASE, msr | X2APIC_ENABLE, 0); 1347 wrmsr(MSR_IA32_APICBASE, msr | X2APIC_ENABLE, 0);
1346 } 1348 }
1347} 1349}
1350#endif /* CONFIG_X86_X2APIC */
1348 1351
1349void __init enable_IR_x2apic(void) 1352void __init enable_IR_x2apic(void)
1350{ 1353{
@@ -1353,32 +1356,21 @@ void __init enable_IR_x2apic(void)
1353 unsigned long flags; 1356 unsigned long flags;
1354 struct IO_APIC_route_entry **ioapic_entries = NULL; 1357 struct IO_APIC_route_entry **ioapic_entries = NULL;
1355 1358
1356 if (!cpu_has_x2apic) 1359 ret = dmar_table_init();
1357 return; 1360 if (ret) {
1358 1361 pr_debug("dmar_table_init() failed with %d:\n", ret);
1359 if (!x2apic_preenabled && disable_x2apic) { 1362 goto ir_failed;
1360 pr_info("Skipped enabling x2apic and Interrupt-remapping "
1361 "because of nox2apic\n");
1362 return;
1363 } 1363 }
1364 1364
1365 if (x2apic_preenabled && disable_x2apic) 1365 if (!intr_remapping_supported()) {
1366 panic("Bios already enabled x2apic, can't enforce nox2apic"); 1366 pr_debug("intr-remapping not supported\n");
1367 1367 goto ir_failed;
1368 if (!x2apic_preenabled && skip_ioapic_setup) {
1369 pr_info("Skipped enabling x2apic and Interrupt-remapping "
1370 "because of skipping io-apic setup\n");
1371 return;
1372 } 1368 }
1373 1369
1374 ret = dmar_table_init();
1375 if (ret) {
1376 pr_info("dmar_table_init() failed with %d:\n", ret);
1377 1370
1378 if (x2apic_preenabled) 1371 if (!x2apic_preenabled && skip_ioapic_setup) {
1379 panic("x2apic enabled by bios. But IR enabling failed"); 1372 pr_info("Skipped enabling intr-remap because of skipping "
1380 else 1373 "io-apic setup\n");
1381 pr_info("Not enabling x2apic,Intr-remapping\n");
1382 return; 1374 return;
1383 } 1375 }
1384 1376
@@ -1398,20 +1390,25 @@ void __init enable_IR_x2apic(void)
1398 mask_IO_APIC_setup(ioapic_entries); 1390 mask_IO_APIC_setup(ioapic_entries);
1399 mask_8259A(); 1391 mask_8259A();
1400 1392
1401 ret = enable_intr_remapping(EIM_32BIT_APIC_ID); 1393#ifdef CONFIG_X86_X2APIC
1402 1394 if (cpu_has_x2apic)
1403 if (ret && x2apic_preenabled) { 1395 ret = enable_intr_remapping(EIM_32BIT_APIC_ID);
1404 local_irq_restore(flags); 1396 else
1405 panic("x2apic enabled by bios. But IR enabling failed"); 1397#endif
1406 } 1398 ret = enable_intr_remapping(EIM_8BIT_APIC_ID);
1407 1399
1408 if (ret) 1400 if (ret)
1409 goto end_restore; 1401 goto end_restore;
1410 1402
1411 if (!x2apic) { 1403 pr_info("Enabled Interrupt-remapping\n");
1404
1405#ifdef CONFIG_X86_X2APIC
1406 if (cpu_has_x2apic && !x2apic) {
1412 x2apic = 1; 1407 x2apic = 1;
1413 enable_x2apic(); 1408 enable_x2apic();
1409 pr_info("Enabled x2apic\n");
1414 } 1410 }
1411#endif
1415 1412
1416end_restore: 1413end_restore:
1417 if (ret) 1414 if (ret)
@@ -1426,30 +1423,29 @@ end_restore:
1426 local_irq_restore(flags); 1423 local_irq_restore(flags);
1427 1424
1428end: 1425end:
1429 if (!ret) {
1430 if (!x2apic_preenabled)
1431 pr_info("Enabled x2apic and interrupt-remapping\n");
1432 else
1433 pr_info("Enabled Interrupt-remapping\n");
1434 } else
1435 pr_err("Failed to enable Interrupt-remapping and x2apic\n");
1436 if (ioapic_entries) 1426 if (ioapic_entries)
1437 free_ioapic_entries(ioapic_entries); 1427 free_ioapic_entries(ioapic_entries);
1428
1429 if (!ret)
1430 return;
1431
1432ir_failed:
1433 if (x2apic_preenabled)
1434 panic("x2apic enabled by bios. But IR enabling failed");
1435 else if (cpu_has_x2apic)
1436 pr_info("Not enabling x2apic,Intr-remapping\n");
1438#else 1437#else
1439 if (!cpu_has_x2apic) 1438 if (!cpu_has_x2apic)
1440 return; 1439 return;
1441 1440
1442 if (x2apic_preenabled) 1441 if (x2apic_preenabled)
1443 panic("x2apic enabled prior OS handover," 1442 panic("x2apic enabled prior OS handover,"
1444 " enable CONFIG_INTR_REMAP"); 1443 " enable CONFIG_X86_X2APIC, CONFIG_INTR_REMAP");
1445
1446 pr_info("Enable CONFIG_INTR_REMAP for enabling intr-remapping "
1447 " and x2apic\n");
1448#endif 1444#endif
1449 1445
1450 return; 1446 return;
1451} 1447}
1452#endif /* CONFIG_X86_X2APIC */ 1448
1453 1449
1454#ifdef CONFIG_X86_64 1450#ifdef CONFIG_X86_64
1455/* 1451/*
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c
index 001b328adf80..9ce8f0764bef 100644
--- a/drivers/pci/intel-iommu.c
+++ b/drivers/pci/intel-iommu.c
@@ -1968,15 +1968,6 @@ static int __init init_dmars(void)
1968 } 1968 }
1969 } 1969 }
1970 1970
1971#ifdef CONFIG_INTR_REMAP
1972 if (!intr_remapping_enabled) {
1973 ret = enable_intr_remapping(0);
1974 if (ret)
1975 printk(KERN_ERR
1976 "IOMMU: enable interrupt remapping failed\n");
1977 }
1978#endif
1979
1980 /* 1971 /*
1981 * For each rmrr 1972 * For each rmrr
1982 * for each dev attached to rmrr 1973 * for each dev attached to rmrr
diff --git a/drivers/pci/intr_remapping.c b/drivers/pci/intr_remapping.c
index f5e0ea724a6f..5c2142656e96 100644
--- a/drivers/pci/intr_remapping.c
+++ b/drivers/pci/intr_remapping.c
@@ -423,20 +423,6 @@ static void iommu_set_intr_remapping(struct intel_iommu *iommu, int mode)
423 readl, (sts & DMA_GSTS_IRTPS), sts); 423 readl, (sts & DMA_GSTS_IRTPS), sts);
424 spin_unlock_irqrestore(&iommu->register_lock, flags); 424 spin_unlock_irqrestore(&iommu->register_lock, flags);
425 425
426 if (mode == 0) {
427 spin_lock_irqsave(&iommu->register_lock, flags);
428
429 /* enable comaptiblity format interrupt pass through */
430 cmd = iommu->gcmd | DMA_GCMD_CFI;
431 iommu->gcmd |= DMA_GCMD_CFI;
432 writel(cmd, iommu->reg + DMAR_GCMD_REG);
433
434 IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
435 readl, (sts & DMA_GSTS_CFIS), sts);
436
437 spin_unlock_irqrestore(&iommu->register_lock, flags);
438 }
439
440 /* 426 /*
441 * global invalidation of interrupt entry cache before enabling 427 * global invalidation of interrupt entry cache before enabling
442 * interrupt-remapping. 428 * interrupt-remapping.
@@ -516,6 +502,20 @@ end:
516 spin_unlock_irqrestore(&iommu->register_lock, flags); 502 spin_unlock_irqrestore(&iommu->register_lock, flags);
517} 503}
518 504
505int __init intr_remapping_supported(void)
506{
507 struct dmar_drhd_unit *drhd;
508
509 for_each_drhd_unit(drhd) {
510 struct intel_iommu *iommu = drhd->iommu;
511
512 if (!ecap_ir_support(iommu->ecap))
513 return 0;
514 }
515
516 return 1;
517}
518
519int __init enable_intr_remapping(int eim) 519int __init enable_intr_remapping(int eim)
520{ 520{
521 struct dmar_drhd_unit *drhd; 521 struct dmar_drhd_unit *drhd;
diff --git a/include/linux/dmar.h b/include/linux/dmar.h
index e397dc342cda..06f592a7f73c 100644
--- a/include/linux/dmar.h
+++ b/include/linux/dmar.h
@@ -108,6 +108,7 @@ struct irte {
108}; 108};
109#ifdef CONFIG_INTR_REMAP 109#ifdef CONFIG_INTR_REMAP
110extern int intr_remapping_enabled; 110extern int intr_remapping_enabled;
111extern int intr_remapping_supported(void);
111extern int enable_intr_remapping(int); 112extern int enable_intr_remapping(int);
112extern void disable_intr_remapping(void); 113extern void disable_intr_remapping(void);
113extern int reenable_intr_remapping(int); 114extern int reenable_intr_remapping(int);