diff options
-rw-r--r-- | arch/x86/include/asm/apic.h | 7 | ||||
-rw-r--r-- | arch/x86/kernel/apic/apic.c | 76 | ||||
-rw-r--r-- | drivers/pci/intel-iommu.c | 9 | ||||
-rw-r--r-- | drivers/pci/intr_remapping.c | 28 | ||||
-rw-r--r-- | include/linux/dmar.h | 1 |
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) | |||
169 | extern int x2apic, x2apic_phys; | 169 | extern int x2apic, x2apic_phys; |
170 | extern void check_x2apic(void); | 170 | extern void check_x2apic(void); |
171 | extern void enable_x2apic(void); | 171 | extern void enable_x2apic(void); |
172 | extern void enable_IR_x2apic(void); | ||
173 | extern void x2apic_icr_write(u32 low, u32 id); | 172 | extern void x2apic_icr_write(u32 low, u32 id); |
174 | static inline int x2apic_enabled(void) | 173 | static inline int x2apic_enabled(void) |
175 | { | 174 | { |
@@ -190,18 +189,18 @@ static inline void check_x2apic(void) | |||
190 | static inline void enable_x2apic(void) | 189 | static inline void enable_x2apic(void) |
191 | { | 190 | { |
192 | } | 191 | } |
193 | static inline void enable_IR_x2apic(void) | ||
194 | { | ||
195 | } | ||
196 | static inline int x2apic_enabled(void) | 192 | static 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 | ||
202 | extern void enable_IR_x2apic(void); | ||
203 | |||
205 | extern int get_physical_broadcast(void); | 204 | extern int get_physical_broadcast(void); |
206 | 205 | ||
207 | extern void apic_disable(void); | 206 | extern 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; | |||
141 | static int disable_x2apic; | 141 | static int disable_x2apic; |
142 | static __init int setup_nox2apic(char *str) | 142 | static __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 | ||
1349 | void __init enable_IR_x2apic(void) | 1352 | void __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 | ||
1416 | end_restore: | 1413 | end_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 | ||
1428 | end: | 1425 | end: |
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 | |||
1432 | ir_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 | ||
505 | int __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 | |||
519 | int __init enable_intr_remapping(int eim) | 519 | int __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 |
110 | extern int intr_remapping_enabled; | 110 | extern int intr_remapping_enabled; |
111 | extern int intr_remapping_supported(void); | ||
111 | extern int enable_intr_remapping(int); | 112 | extern int enable_intr_remapping(int); |
112 | extern void disable_intr_remapping(void); | 113 | extern void disable_intr_remapping(void); |
113 | extern int reenable_intr_remapping(int); | 114 | extern int reenable_intr_remapping(int); |