diff options
author | Suresh Siddha <suresh.b.siddha@intel.com> | 2011-05-18 19:31:33 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2011-05-20 07:40:52 -0400 |
commit | 31dce14a3269843f98ce1bc37d0c91b22f1991ee (patch) | |
tree | 66a02547580d22cc31648fd27169940b50c01ce4 /arch/x86 | |
parent | 4c79185cdb1425fb74241d0be772ff1a9913091a (diff) |
x86, ioapic: Use ioapic_saved_data while enabling intr-remapping
Code flow for enabling interrupt-remapping was
allocating/freeing buffers for saving/restoring io-apic RTE's.
ioapic suspend/resume code uses boot time allocated
ioapic_saved_data that is a perfect match for reuse here.
This will remove the unnecessary allocation/free of the
temporary buffers during suspend/resume of interrupt-remapping
enabled platforms aswell as paving the way for further code
consolidation.
Tested-by: Daniel J Blueman <daniel.blueman@gmail.com>
Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>
Link: http://lkml.kernel.org/r/20110518233157.574469296@sbsiddha-MOBL3.sc.intel.com
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/include/asm/io_apic.h | 20 | ||||
-rw-r--r-- | arch/x86/kernel/apic/apic.c | 48 | ||||
-rw-r--r-- | arch/x86/kernel/apic/io_apic.c | 80 |
3 files changed, 37 insertions, 111 deletions
diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h index a97a240f67f3..f46984e45094 100644 --- a/arch/x86/include/asm/io_apic.h +++ b/arch/x86/include/asm/io_apic.h | |||
@@ -152,11 +152,9 @@ extern void ioapic_insert_resources(void); | |||
152 | 152 | ||
153 | int io_apic_setup_irq_pin_once(unsigned int irq, int node, struct io_apic_irq_attr *attr); | 153 | int io_apic_setup_irq_pin_once(unsigned int irq, int node, struct io_apic_irq_attr *attr); |
154 | 154 | ||
155 | extern struct IO_APIC_route_entry **alloc_ioapic_entries(void); | 155 | extern int save_ioapic_entries(void); |
156 | extern void free_ioapic_entries(struct IO_APIC_route_entry **ioapic_entries); | 156 | extern void mask_ioapic_entries(void); |
157 | extern int save_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries); | 157 | extern int restore_ioapic_entries(void); |
158 | extern void mask_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries); | ||
159 | extern int restore_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries); | ||
160 | 158 | ||
161 | extern int get_nr_irqs_gsi(void); | 159 | extern int get_nr_irqs_gsi(void); |
162 | 160 | ||
@@ -192,19 +190,13 @@ struct io_apic_irq_attr; | |||
192 | static inline int io_apic_set_pci_routing(struct device *dev, int irq, | 190 | static inline int io_apic_set_pci_routing(struct device *dev, int irq, |
193 | struct io_apic_irq_attr *irq_attr) { return 0; } | 191 | struct io_apic_irq_attr *irq_attr) { return 0; } |
194 | 192 | ||
195 | static inline struct IO_APIC_route_entry **alloc_ioapic_entries(void) | 193 | static inline int save_ioapic_entries(void) |
196 | { | ||
197 | return NULL; | ||
198 | } | ||
199 | |||
200 | static inline void free_ioapic_entries(struct IO_APIC_route_entry **ent) { } | ||
201 | static inline int save_IO_APIC_setup(struct IO_APIC_route_entry **ent) | ||
202 | { | 194 | { |
203 | return -ENOMEM; | 195 | return -ENOMEM; |
204 | } | 196 | } |
205 | 197 | ||
206 | static inline void mask_IO_APIC_setup(struct IO_APIC_route_entry **ent) { } | 198 | static inline void mask_ioapic_entries(void) { } |
207 | static inline int restore_IO_APIC_setup(struct IO_APIC_route_entry **ent) | 199 | static inline int restore_ioapic_entries(void) |
208 | { | 200 | { |
209 | return -ENOMEM; | 201 | return -ENOMEM; |
210 | } | 202 | } |
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index f92a8e5d1e21..b961af86bfea 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c | |||
@@ -1461,7 +1461,6 @@ int __init enable_IR(void) | |||
1461 | void __init enable_IR_x2apic(void) | 1461 | void __init enable_IR_x2apic(void) |
1462 | { | 1462 | { |
1463 | unsigned long flags; | 1463 | unsigned long flags; |
1464 | struct IO_APIC_route_entry **ioapic_entries; | ||
1465 | int ret, x2apic_enabled = 0; | 1464 | int ret, x2apic_enabled = 0; |
1466 | int dmar_table_init_ret; | 1465 | int dmar_table_init_ret; |
1467 | 1466 | ||
@@ -1469,13 +1468,7 @@ void __init enable_IR_x2apic(void) | |||
1469 | if (dmar_table_init_ret && !x2apic_supported()) | 1468 | if (dmar_table_init_ret && !x2apic_supported()) |
1470 | return; | 1469 | return; |
1471 | 1470 | ||
1472 | ioapic_entries = alloc_ioapic_entries(); | 1471 | ret = save_ioapic_entries(); |
1473 | if (!ioapic_entries) { | ||
1474 | pr_err("Allocate ioapic_entries failed\n"); | ||
1475 | goto out; | ||
1476 | } | ||
1477 | |||
1478 | ret = save_IO_APIC_setup(ioapic_entries); | ||
1479 | if (ret) { | 1472 | if (ret) { |
1480 | pr_info("Saving IO-APIC state failed: %d\n", ret); | 1473 | pr_info("Saving IO-APIC state failed: %d\n", ret); |
1481 | goto out; | 1474 | goto out; |
@@ -1483,7 +1476,7 @@ void __init enable_IR_x2apic(void) | |||
1483 | 1476 | ||
1484 | local_irq_save(flags); | 1477 | local_irq_save(flags); |
1485 | legacy_pic->mask_all(); | 1478 | legacy_pic->mask_all(); |
1486 | mask_IO_APIC_setup(ioapic_entries); | 1479 | mask_ioapic_entries(); |
1487 | 1480 | ||
1488 | if (dmar_table_init_ret) | 1481 | if (dmar_table_init_ret) |
1489 | ret = 0; | 1482 | ret = 0; |
@@ -1514,14 +1507,11 @@ void __init enable_IR_x2apic(void) | |||
1514 | 1507 | ||
1515 | nox2apic: | 1508 | nox2apic: |
1516 | if (!ret) /* IR enabling failed */ | 1509 | if (!ret) /* IR enabling failed */ |
1517 | restore_IO_APIC_setup(ioapic_entries); | 1510 | restore_ioapic_entries(); |
1518 | legacy_pic->restore_mask(); | 1511 | legacy_pic->restore_mask(); |
1519 | local_irq_restore(flags); | 1512 | local_irq_restore(flags); |
1520 | 1513 | ||
1521 | out: | 1514 | out: |
1522 | if (ioapic_entries) | ||
1523 | free_ioapic_entries(ioapic_entries); | ||
1524 | |||
1525 | if (x2apic_enabled) | 1515 | if (x2apic_enabled) |
1526 | return; | 1516 | return; |
1527 | 1517 | ||
@@ -2095,28 +2085,20 @@ static void lapic_resume(void) | |||
2095 | { | 2085 | { |
2096 | unsigned int l, h; | 2086 | unsigned int l, h; |
2097 | unsigned long flags; | 2087 | unsigned long flags; |
2098 | int maxlvt, ret; | 2088 | int maxlvt; |
2099 | struct IO_APIC_route_entry **ioapic_entries = NULL; | ||
2100 | 2089 | ||
2101 | if (!apic_pm_state.active) | 2090 | if (!apic_pm_state.active) |
2102 | return; | 2091 | return; |
2103 | 2092 | ||
2104 | local_irq_save(flags); | 2093 | local_irq_save(flags); |
2105 | if (intr_remapping_enabled) { | 2094 | if (intr_remapping_enabled) { |
2106 | ioapic_entries = alloc_ioapic_entries(); | 2095 | /* |
2107 | if (!ioapic_entries) { | 2096 | * IO-APIC and PIC have their own resume routines. |
2108 | WARN(1, "Alloc ioapic_entries in lapic resume failed."); | 2097 | * We just mask them here to make sure the interrupt |
2109 | goto restore; | 2098 | * subsystem is completely quiet while we enable x2apic |
2110 | } | 2099 | * and interrupt-remapping. |
2111 | 2100 | */ | |
2112 | ret = save_IO_APIC_setup(ioapic_entries); | 2101 | mask_ioapic_entries(); |
2113 | if (ret) { | ||
2114 | WARN(1, "Saving IO-APIC state failed: %d\n", ret); | ||
2115 | free_ioapic_entries(ioapic_entries); | ||
2116 | goto restore; | ||
2117 | } | ||
2118 | |||
2119 | mask_IO_APIC_setup(ioapic_entries); | ||
2120 | legacy_pic->mask_all(); | 2102 | legacy_pic->mask_all(); |
2121 | } | 2103 | } |
2122 | 2104 | ||
@@ -2159,13 +2141,9 @@ static void lapic_resume(void) | |||
2159 | apic_write(APIC_ESR, 0); | 2141 | apic_write(APIC_ESR, 0); |
2160 | apic_read(APIC_ESR); | 2142 | apic_read(APIC_ESR); |
2161 | 2143 | ||
2162 | if (intr_remapping_enabled) { | 2144 | if (intr_remapping_enabled) |
2163 | reenable_intr_remapping(x2apic_mode); | 2145 | reenable_intr_remapping(x2apic_mode); |
2164 | legacy_pic->restore_mask(); | 2146 | |
2165 | restore_IO_APIC_setup(ioapic_entries); | ||
2166 | free_ioapic_entries(ioapic_entries); | ||
2167 | } | ||
2168 | restore: | ||
2169 | local_irq_restore(flags); | 2147 | local_irq_restore(flags); |
2170 | } | 2148 | } |
2171 | 2149 | ||
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 8e771d32ada1..08b794d07a52 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c | |||
@@ -101,7 +101,7 @@ int mp_irq_entries; | |||
101 | static int nr_irqs_gsi = NR_IRQS_LEGACY; | 101 | static int nr_irqs_gsi = NR_IRQS_LEGACY; |
102 | 102 | ||
103 | /* | 103 | /* |
104 | * Saved I/O APIC state during suspend/resume. | 104 | * Saved I/O APIC state during suspend/resume, or while enabling intr-remap. |
105 | */ | 105 | */ |
106 | static struct IO_APIC_route_entry *ioapic_saved_data[MAX_IO_APICS]; | 106 | static struct IO_APIC_route_entry *ioapic_saved_data[MAX_IO_APICS]; |
107 | 107 | ||
@@ -628,74 +628,43 @@ static int __init ioapic_pirq_setup(char *str) | |||
628 | __setup("pirq=", ioapic_pirq_setup); | 628 | __setup("pirq=", ioapic_pirq_setup); |
629 | #endif /* CONFIG_X86_32 */ | 629 | #endif /* CONFIG_X86_32 */ |
630 | 630 | ||
631 | struct IO_APIC_route_entry **alloc_ioapic_entries(void) | ||
632 | { | ||
633 | int apic; | ||
634 | struct IO_APIC_route_entry **ioapic_entries; | ||
635 | |||
636 | ioapic_entries = kzalloc(sizeof(*ioapic_entries) * nr_ioapics, | ||
637 | GFP_ATOMIC); | ||
638 | if (!ioapic_entries) | ||
639 | return 0; | ||
640 | |||
641 | for (apic = 0; apic < nr_ioapics; apic++) { | ||
642 | ioapic_entries[apic] = | ||
643 | kzalloc(sizeof(struct IO_APIC_route_entry) * | ||
644 | nr_ioapic_registers[apic], GFP_ATOMIC); | ||
645 | if (!ioapic_entries[apic]) | ||
646 | goto nomem; | ||
647 | } | ||
648 | |||
649 | return ioapic_entries; | ||
650 | |||
651 | nomem: | ||
652 | while (--apic >= 0) | ||
653 | kfree(ioapic_entries[apic]); | ||
654 | kfree(ioapic_entries); | ||
655 | |||
656 | return 0; | ||
657 | } | ||
658 | |||
659 | /* | 631 | /* |
660 | * Saves all the IO-APIC RTE's | 632 | * Saves all the IO-APIC RTE's |
661 | */ | 633 | */ |
662 | int save_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries) | 634 | int save_ioapic_entries(void) |
663 | { | 635 | { |
664 | int apic, pin; | 636 | int apic, pin; |
665 | 637 | int err = 0; | |
666 | if (!ioapic_entries) | ||
667 | return -ENOMEM; | ||
668 | 638 | ||
669 | for (apic = 0; apic < nr_ioapics; apic++) { | 639 | for (apic = 0; apic < nr_ioapics; apic++) { |
670 | if (!ioapic_entries[apic]) | 640 | if (!ioapic_saved_data[apic]) { |
671 | return -ENOMEM; | 641 | err = -ENOMEM; |
642 | continue; | ||
643 | } | ||
672 | 644 | ||
673 | for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) | 645 | for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) |
674 | ioapic_entries[apic][pin] = | 646 | ioapic_saved_data[apic][pin] = |
675 | ioapic_read_entry(apic, pin); | 647 | ioapic_read_entry(apic, pin); |
676 | } | 648 | } |
677 | 649 | ||
678 | return 0; | 650 | return err; |
679 | } | 651 | } |
680 | 652 | ||
681 | /* | 653 | /* |
682 | * Mask all IO APIC entries. | 654 | * Mask all IO APIC entries. |
683 | */ | 655 | */ |
684 | void mask_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries) | 656 | void mask_ioapic_entries(void) |
685 | { | 657 | { |
686 | int apic, pin; | 658 | int apic, pin; |
687 | 659 | ||
688 | if (!ioapic_entries) | ||
689 | return; | ||
690 | |||
691 | for (apic = 0; apic < nr_ioapics; apic++) { | 660 | for (apic = 0; apic < nr_ioapics; apic++) { |
692 | if (!ioapic_entries[apic]) | 661 | if (!ioapic_saved_data[apic]) |
693 | break; | 662 | continue; |
694 | 663 | ||
695 | for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) { | 664 | for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) { |
696 | struct IO_APIC_route_entry entry; | 665 | struct IO_APIC_route_entry entry; |
697 | 666 | ||
698 | entry = ioapic_entries[apic][pin]; | 667 | entry = ioapic_saved_data[apic][pin]; |
699 | if (!entry.mask) { | 668 | if (!entry.mask) { |
700 | entry.mask = 1; | 669 | entry.mask = 1; |
701 | ioapic_write_entry(apic, pin, entry); | 670 | ioapic_write_entry(apic, pin, entry); |
@@ -705,36 +674,23 @@ void mask_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries) | |||
705 | } | 674 | } |
706 | 675 | ||
707 | /* | 676 | /* |
708 | * Restore IO APIC entries which was saved in ioapic_entries. | 677 | * Restore IO APIC entries which was saved in ioapic_saved_data |
709 | */ | 678 | */ |
710 | int restore_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries) | 679 | int restore_ioapic_entries(void) |
711 | { | 680 | { |
712 | int apic, pin; | 681 | int apic, pin; |
713 | 682 | ||
714 | if (!ioapic_entries) | ||
715 | return -ENOMEM; | ||
716 | |||
717 | for (apic = 0; apic < nr_ioapics; apic++) { | 683 | for (apic = 0; apic < nr_ioapics; apic++) { |
718 | if (!ioapic_entries[apic]) | 684 | if (!ioapic_saved_data[apic]) |
719 | return -ENOMEM; | 685 | continue; |
720 | 686 | ||
721 | for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) | 687 | for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) |
722 | ioapic_write_entry(apic, pin, | 688 | ioapic_write_entry(apic, pin, |
723 | ioapic_entries[apic][pin]); | 689 | ioapic_saved_data[apic][pin]); |
724 | } | 690 | } |
725 | return 0; | 691 | return 0; |
726 | } | 692 | } |
727 | 693 | ||
728 | void free_ioapic_entries(struct IO_APIC_route_entry **ioapic_entries) | ||
729 | { | ||
730 | int apic; | ||
731 | |||
732 | for (apic = 0; apic < nr_ioapics; apic++) | ||
733 | kfree(ioapic_entries[apic]); | ||
734 | |||
735 | kfree(ioapic_entries); | ||
736 | } | ||
737 | |||
738 | /* | 694 | /* |
739 | * Find the IRQ entry number of a certain pin. | 695 | * Find the IRQ entry number of a certain pin. |
740 | */ | 696 | */ |