diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-09-01 18:20:51 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-09-01 18:20:51 -0400 |
commit | 43af9872f52abfed5523b8346d98a5e283b38163 (patch) | |
tree | f50f52c5dfc47ed06972d10a20f01feeff7300d9 /arch/x86/lguest | |
parent | 17e6b00ac422b49d44a0b8d98402a211f726282d (diff) | |
parent | a47d4576cd1c58157a2d8cfffa93aa7ca375eede (diff) |
Merge branch 'x86-apic-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 apic updates from Thomas Gleixner:
"This udpate contains:
- rework the irq vector array to store a pointer to the irq
descriptor instead of the irq number to avoid a lookup of the irq
descriptor in the irq entry path
- lguest interrupt handling cleanups
- conversion of the local apic timer to the new clockevent callbacks
- preparatory changes for the irq argument removal of interrupt flow
handlers"
* 'x86-apic-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
x86/irq: Do not dereference irq descriptor before checking it
tools/lguest: Clean up include dir
tools/lguest: Fix redefinition of struct virtio_pci_cfg_cap
x86/irq: Store irq descriptor in vector array
genirq: Provide irq_desc_has_action
x86/irq: Get rid of an indentation level
x86/irq: Rename VECTOR_UNDEFINED to VECTOR_UNUSED
x86/irq: Replace numeric constant
x86/irq: Protect smp_cleanup_move
x86/lguest: Do not setup unused irq vectors
x86/lguest: Clean up lguest_setup_irq
x86/apic: Drop local_irq_save/restore in timer callbacks
x86/apic: Migrate apic timer to new set_state interface
x86/irq: Use access helper irq_data_get_affinity_mask()
x86/irq: Use accessor irq_data_get_irq_handler_data()
x86/irq: Use accessor irq_data_get_node()
Diffstat (limited to 'arch/x86/lguest')
-rw-r--r-- | arch/x86/lguest/boot.c | 67 |
1 files changed, 37 insertions, 30 deletions
diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c index 433e5a7dd37f..161804de124a 100644 --- a/arch/x86/lguest/boot.c +++ b/arch/x86/lguest/boot.c | |||
@@ -835,16 +835,46 @@ static struct irq_chip lguest_irq_controller = { | |||
835 | .irq_unmask = enable_lguest_irq, | 835 | .irq_unmask = enable_lguest_irq, |
836 | }; | 836 | }; |
837 | 837 | ||
838 | /* | ||
839 | * Interrupt descriptors are allocated as-needed, but low-numbered ones are | ||
840 | * reserved by the generic x86 code. So we ignore irq_alloc_desc_at if it | ||
841 | * tells us the irq is already used: other errors (ie. ENOMEM) we take | ||
842 | * seriously. | ||
843 | */ | ||
844 | static int lguest_setup_irq(unsigned int irq) | ||
845 | { | ||
846 | struct irq_desc *desc; | ||
847 | int err; | ||
848 | |||
849 | /* Returns -ve error or vector number. */ | ||
850 | err = irq_alloc_desc_at(irq, 0); | ||
851 | if (err < 0 && err != -EEXIST) | ||
852 | return err; | ||
853 | |||
854 | /* | ||
855 | * Tell the Linux infrastructure that the interrupt is | ||
856 | * controlled by our level-based lguest interrupt controller. | ||
857 | */ | ||
858 | irq_set_chip_and_handler_name(irq, &lguest_irq_controller, | ||
859 | handle_level_irq, "level"); | ||
860 | |||
861 | /* Some systems map "vectors" to interrupts weirdly. Not us! */ | ||
862 | desc = irq_to_desc(irq); | ||
863 | __this_cpu_write(vector_irq[FIRST_EXTERNAL_VECTOR + irq], desc); | ||
864 | return 0; | ||
865 | } | ||
866 | |||
838 | static int lguest_enable_irq(struct pci_dev *dev) | 867 | static int lguest_enable_irq(struct pci_dev *dev) |
839 | { | 868 | { |
869 | int err; | ||
840 | u8 line = 0; | 870 | u8 line = 0; |
841 | 871 | ||
842 | /* We literally use the PCI interrupt line as the irq number. */ | 872 | /* We literally use the PCI interrupt line as the irq number. */ |
843 | pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &line); | 873 | pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &line); |
844 | irq_set_chip_and_handler_name(line, &lguest_irq_controller, | 874 | err = lguest_setup_irq(line); |
845 | handle_level_irq, "level"); | 875 | if (!err) |
846 | dev->irq = line; | 876 | dev->irq = line; |
847 | return 0; | 877 | return err; |
848 | } | 878 | } |
849 | 879 | ||
850 | /* We don't do hotplug PCI, so this shouldn't be called. */ | 880 | /* We don't do hotplug PCI, so this shouldn't be called. */ |
@@ -855,17 +885,13 @@ static void lguest_disable_irq(struct pci_dev *dev) | |||
855 | 885 | ||
856 | /* | 886 | /* |
857 | * This sets up the Interrupt Descriptor Table (IDT) entry for each hardware | 887 | * This sets up the Interrupt Descriptor Table (IDT) entry for each hardware |
858 | * interrupt (except 128, which is used for system calls), and then tells the | 888 | * interrupt (except 128, which is used for system calls). |
859 | * Linux infrastructure that each interrupt is controlled by our level-based | ||
860 | * lguest interrupt controller. | ||
861 | */ | 889 | */ |
862 | static void __init lguest_init_IRQ(void) | 890 | static void __init lguest_init_IRQ(void) |
863 | { | 891 | { |
864 | unsigned int i; | 892 | unsigned int i; |
865 | 893 | ||
866 | for (i = FIRST_EXTERNAL_VECTOR; i < FIRST_SYSTEM_VECTOR; i++) { | 894 | for (i = FIRST_EXTERNAL_VECTOR; i < FIRST_SYSTEM_VECTOR; i++) { |
867 | /* Some systems map "vectors" to interrupts weirdly. Not us! */ | ||
868 | __this_cpu_write(vector_irq[i], i - FIRST_EXTERNAL_VECTOR); | ||
869 | if (i != IA32_SYSCALL_VECTOR) | 895 | if (i != IA32_SYSCALL_VECTOR) |
870 | set_intr_gate(i, irq_entries_start + | 896 | set_intr_gate(i, irq_entries_start + |
871 | 8 * (i - FIRST_EXTERNAL_VECTOR)); | 897 | 8 * (i - FIRST_EXTERNAL_VECTOR)); |
@@ -879,26 +905,6 @@ static void __init lguest_init_IRQ(void) | |||
879 | } | 905 | } |
880 | 906 | ||
881 | /* | 907 | /* |
882 | * Interrupt descriptors are allocated as-needed, but low-numbered ones are | ||
883 | * reserved by the generic x86 code. So we ignore irq_alloc_desc_at if it | ||
884 | * tells us the irq is already used: other errors (ie. ENOMEM) we take | ||
885 | * seriously. | ||
886 | */ | ||
887 | int lguest_setup_irq(unsigned int irq) | ||
888 | { | ||
889 | int err; | ||
890 | |||
891 | /* Returns -ve error or vector number. */ | ||
892 | err = irq_alloc_desc_at(irq, 0); | ||
893 | if (err < 0 && err != -EEXIST) | ||
894 | return err; | ||
895 | |||
896 | irq_set_chip_and_handler_name(irq, &lguest_irq_controller, | ||
897 | handle_level_irq, "level"); | ||
898 | return 0; | ||
899 | } | ||
900 | |||
901 | /* | ||
902 | * Time. | 908 | * Time. |
903 | * | 909 | * |
904 | * It would be far better for everyone if the Guest had its own clock, but | 910 | * It would be far better for everyone if the Guest had its own clock, but |
@@ -1028,7 +1034,8 @@ static void lguest_time_irq(unsigned int irq, struct irq_desc *desc) | |||
1028 | static void lguest_time_init(void) | 1034 | static void lguest_time_init(void) |
1029 | { | 1035 | { |
1030 | /* Set up the timer interrupt (0) to go to our simple timer routine */ | 1036 | /* Set up the timer interrupt (0) to go to our simple timer routine */ |
1031 | lguest_setup_irq(0); | 1037 | if (lguest_setup_irq(0) != 0) |
1038 | panic("Could not set up timer irq"); | ||
1032 | irq_set_handler(0, lguest_time_irq); | 1039 | irq_set_handler(0, lguest_time_irq); |
1033 | 1040 | ||
1034 | clocksource_register_hz(&lguest_clock, NSEC_PER_SEC); | 1041 | clocksource_register_hz(&lguest_clock, NSEC_PER_SEC); |