| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: intr.c,v 1.69 2010/11/24 14:56:18 cegger Exp $ */ | | 1 | /* $NetBSD: intr.c,v 1.70 2011/01/22 14:01:27 tsutsui Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 2007, 2008, 2009 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 2007, 2008, 2009 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Andrew Doran. | | 8 | * by Andrew Doran. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
| @@ -123,27 +123,27 @@ | | | @@ -123,27 +123,27 @@ |
123 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | | 123 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
124 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 124 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
125 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 125 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
126 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 126 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
127 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 127 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
128 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 128 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
129 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 129 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
130 | * SUCH DAMAGE. | | 130 | * SUCH DAMAGE. |
131 | * | | 131 | * |
132 | * @(#)isa.c 7.2 (Berkeley) 5/13/91 | | 132 | * @(#)isa.c 7.2 (Berkeley) 5/13/91 |
133 | */ | | 133 | */ |
134 | | | 134 | |
135 | #include <sys/cdefs.h> | | 135 | #include <sys/cdefs.h> |
136 | __KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.69 2010/11/24 14:56:18 cegger Exp $"); | | 136 | __KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.70 2011/01/22 14:01:27 tsutsui Exp $"); |
137 | | | 137 | |
138 | #include "opt_intrdebug.h" | | 138 | #include "opt_intrdebug.h" |
139 | #include "opt_multiprocessor.h" | | 139 | #include "opt_multiprocessor.h" |
140 | #include "opt_acpi.h" | | 140 | #include "opt_acpi.h" |
141 | | | 141 | |
142 | #include <sys/param.h> | | 142 | #include <sys/param.h> |
143 | #include <sys/systm.h> | | 143 | #include <sys/systm.h> |
144 | #include <sys/kernel.h> | | 144 | #include <sys/kernel.h> |
145 | #include <sys/syslog.h> | | 145 | #include <sys/syslog.h> |
146 | #include <sys/device.h> | | 146 | #include <sys/device.h> |
147 | #include <sys/kmem.h> | | 147 | #include <sys/kmem.h> |
148 | #include <sys/proc.h> | | 148 | #include <sys/proc.h> |
149 | #include <sys/errno.h> | | 149 | #include <sys/errno.h> |
| @@ -684,86 +684,87 @@ intr_establish(int legacy_irq, struct pi | | | @@ -684,86 +684,87 @@ intr_establish(int legacy_irq, struct pi |
684 | int (*handler)(void *), void *arg, bool known_mpsafe) | | 684 | int (*handler)(void *), void *arg, bool known_mpsafe) |
685 | { | | 685 | { |
686 | struct intrhand **p, *q, *ih; | | 686 | struct intrhand **p, *q, *ih; |
687 | struct cpu_info *ci; | | 687 | struct cpu_info *ci; |
688 | int slot, error, idt_vec; | | 688 | int slot, error, idt_vec; |
689 | struct intrsource *source; | | 689 | struct intrsource *source; |
690 | #ifdef MULTIPROCESSOR | | 690 | #ifdef MULTIPROCESSOR |
691 | bool mpsafe = (known_mpsafe || level != IPL_VM); | | 691 | bool mpsafe = (known_mpsafe || level != IPL_VM); |
692 | #endif /* MULTIPROCESSOR */ | | 692 | #endif /* MULTIPROCESSOR */ |
693 | uint64_t where; | | 693 | uint64_t where; |
694 | | | 694 | |
695 | #ifdef DIAGNOSTIC | | 695 | #ifdef DIAGNOSTIC |
696 | if (legacy_irq != -1 && (legacy_irq < 0 || legacy_irq > 15)) | | 696 | if (legacy_irq != -1 && (legacy_irq < 0 || legacy_irq > 15)) |
697 | panic("intr_establish: bad legacy IRQ value"); | | 697 | panic("%s: bad legacy IRQ value", __func__); |
698 | | | 698 | |
699 | if (legacy_irq == -1 && pic == &i8259_pic) | | 699 | if (legacy_irq == -1 && pic == &i8259_pic) |
700 | panic("intr_establish: non-legacy IRQ on i8259"); | | 700 | panic("intr_establish: non-legacy IRQ on i8259"); |
701 | #endif | | 701 | #endif |
702 | | | 702 | |
703 | ih = kmem_alloc(sizeof(*ih), KM_SLEEP); | | 703 | ih = kmem_alloc(sizeof(*ih), KM_SLEEP); |
704 | if (ih == NULL) { | | 704 | if (ih == NULL) { |
705 | printf("intr_establish: can't allocate handler info\n"); | | 705 | printf("%s: can't allocate handler info\n", __func__); |
706 | return NULL; | | 706 | return NULL; |
707 | } | | 707 | } |
708 | | | 708 | |
709 | mutex_enter(&cpu_lock); | | 709 | mutex_enter(&cpu_lock); |
710 | error = intr_allocate_slot(pic, pin, level, &ci, &slot, &idt_vec); | | 710 | error = intr_allocate_slot(pic, pin, level, &ci, &slot, &idt_vec); |
711 | if (error != 0) { | | 711 | if (error != 0) { |
712 | mutex_exit(&cpu_lock); | | 712 | mutex_exit(&cpu_lock); |
713 | kmem_free(ih, sizeof(*ih)); | | 713 | kmem_free(ih, sizeof(*ih)); |
714 | printf("failed to allocate interrupt slot for PIC %s pin %d\n", | | 714 | printf("failed to allocate interrupt slot for PIC %s pin %d\n", |
715 | pic->pic_name, pin); | | 715 | pic->pic_name, pin); |
716 | return NULL; | | 716 | return NULL; |
717 | } | | 717 | } |
718 | | | 718 | |
719 | source = ci->ci_isources[slot]; | | 719 | source = ci->ci_isources[slot]; |
720 | | | 720 | |
721 | if (source->is_handlers != NULL && | | 721 | if (source->is_handlers != NULL && |
722 | source->is_pic->pic_type != pic->pic_type) { | | 722 | source->is_pic->pic_type != pic->pic_type) { |
723 | mutex_exit(&cpu_lock); | | 723 | mutex_exit(&cpu_lock); |
724 | kmem_free(ih, sizeof(*ih)); | | 724 | kmem_free(ih, sizeof(*ih)); |
725 | printf("intr_establish: can't share intr source between " | | 725 | printf("%s: can't share intr source between " |
726 | "different PIC types (legacy_irq %d pin %d slot %d)\n", | | 726 | "different PIC types (legacy_irq %d pin %d slot %d)\n", |
727 | legacy_irq, pin, slot); | | 727 | __func__, legacy_irq, pin, slot); |
728 | return NULL; | | 728 | return NULL; |
729 | } | | 729 | } |
730 | | | 730 | |
731 | source->is_pin = pin; | | 731 | source->is_pin = pin; |
732 | source->is_pic = pic; | | 732 | source->is_pic = pic; |
733 | | | 733 | |
734 | switch (source->is_type) { | | 734 | switch (source->is_type) { |
735 | case IST_NONE: | | 735 | case IST_NONE: |
736 | source->is_type = type; | | 736 | source->is_type = type; |
737 | break; | | 737 | break; |
738 | case IST_EDGE: | | 738 | case IST_EDGE: |
739 | case IST_LEVEL: | | 739 | case IST_LEVEL: |
740 | if (source->is_type == type) | | 740 | if (source->is_type == type) |
741 | break; | | 741 | break; |
742 | /* FALLTHROUGH */ | | 742 | /* FALLTHROUGH */ |
743 | case IST_PULSE: | | 743 | case IST_PULSE: |
744 | if (type != IST_NONE) { | | 744 | if (type != IST_NONE) { |
745 | mutex_exit(&cpu_lock); | | 745 | mutex_exit(&cpu_lock); |
746 | kmem_free(ih, sizeof(*ih)); | | 746 | kmem_free(ih, sizeof(*ih)); |
747 | intr_source_free(ci, slot, pic, idt_vec); | | 747 | intr_source_free(ci, slot, pic, idt_vec); |
748 | printf("intr_establish: pic %s pin %d: can't share " | | 748 | printf("%s: pic %s pin %d: can't share " |
749 | "type %d with %d\n", pic->pic_name, pin, | | 749 | "type %d with %d\n", |
| | | 750 | __func__, pic->pic_name, pin, |
750 | source->is_type, type); | | 751 | source->is_type, type); |
751 | return NULL; | | 752 | return NULL; |
752 | } | | 753 | } |
753 | break; | | 754 | break; |
754 | default: | | 755 | default: |
755 | panic("intr_establish: bad intr type %d for pic %s pin %d\n", | | 756 | panic("%s: bad intr type %d for pic %s pin %d\n", |
756 | source->is_type, pic->pic_name, pin); | | 757 | __func__, source->is_type, pic->pic_name, pin); |
757 | /* NOTREACHED */ | | 758 | /* NOTREACHED */ |
758 | } | | 759 | } |
759 | | | 760 | |
760 | /* | | 761 | /* |
761 | * We're now committed. Mask the interrupt in hardware and | | 762 | * We're now committed. Mask the interrupt in hardware and |
762 | * count it for load distribution. | | 763 | * count it for load distribution. |
763 | */ | | 764 | */ |
764 | (*pic->pic_hwmask)(pic, pin); | | 765 | (*pic->pic_hwmask)(pic, pin); |
765 | (ci->ci_nintrhand)++; | | 766 | (ci->ci_nintrhand)++; |
766 | | | 767 | |
767 | /* | | 768 | /* |
768 | * Figure out where to put the handler. | | 769 | * Figure out where to put the handler. |
769 | * This is O(N^2), but we want to preserve the order, and N is | | 770 | * This is O(N^2), but we want to preserve the order, and N is |
| @@ -849,27 +850,27 @@ intr_disestablish_xcall(void *arg1, void | | | @@ -849,27 +850,27 @@ intr_disestablish_xcall(void *arg1, void |
849 | idtvec = source->is_idtvec; | | 850 | idtvec = source->is_idtvec; |
850 | | | 851 | |
851 | (*pic->pic_hwmask)(pic, ih->ih_pin); | | 852 | (*pic->pic_hwmask)(pic, ih->ih_pin); |
852 | atomic_and_32(&ci->ci_ipending, ~(1 << ih->ih_slot)); | | 853 | atomic_and_32(&ci->ci_ipending, ~(1 << ih->ih_slot)); |
853 | | | 854 | |
854 | /* | | 855 | /* |
855 | * Remove the handler from the chain. | | 856 | * Remove the handler from the chain. |
856 | */ | | 857 | */ |
857 | for (p = &source->is_handlers; (q = *p) != NULL && q != ih; | | 858 | for (p = &source->is_handlers; (q = *p) != NULL && q != ih; |
858 | p = &q->ih_next) | | 859 | p = &q->ih_next) |
859 | ; | | 860 | ; |
860 | if (q == NULL) { | | 861 | if (q == NULL) { |
861 | x86_write_psl(psl); | | 862 | x86_write_psl(psl); |
862 | panic("intr_disestablish: handler not registered"); | | 863 | panic("%s: handler not registered", __func__); |
863 | /* NOTREACHED */ | | 864 | /* NOTREACHED */ |
864 | } | | 865 | } |
865 | | | 866 | |
866 | *p = q->ih_next; | | 867 | *p = q->ih_next; |
867 | | | 868 | |
868 | intr_calculatemasks(ci); | | 869 | intr_calculatemasks(ci); |
869 | (*pic->pic_delroute)(pic, ci, ih->ih_pin, idtvec, source->is_type); | | 870 | (*pic->pic_delroute)(pic, ci, ih->ih_pin, idtvec, source->is_type); |
870 | (*pic->pic_hwunmask)(pic, ih->ih_pin); | | 871 | (*pic->pic_hwunmask)(pic, ih->ih_pin); |
871 | | | 872 | |
872 | /* Re-enable interrupts. */ | | 873 | /* Re-enable interrupts. */ |
873 | x86_write_psl(psl); | | 874 | x86_write_psl(psl); |
874 | | | 875 | |
875 | /* If the source is free we can drop it now. */ | | 876 | /* If the source is free we can drop it now. */ |
| @@ -909,27 +910,27 @@ intr_disestablish(struct intrhand *ih) | | | @@ -909,27 +910,27 @@ intr_disestablish(struct intrhand *ih) |
909 | mutex_exit(&cpu_lock); | | 910 | mutex_exit(&cpu_lock); |
910 | kmem_free(ih, sizeof(*ih)); | | 911 | kmem_free(ih, sizeof(*ih)); |
911 | } | | 912 | } |
912 | | | 913 | |
913 | const char * | | 914 | const char * |
914 | intr_string(int ih) | | 915 | intr_string(int ih) |
915 | { | | 916 | { |
916 | static char irqstr[64]; | | 917 | static char irqstr[64]; |
917 | #if NIOAPIC > 0 | | 918 | #if NIOAPIC > 0 |
918 | struct ioapic_softc *pic; | | 919 | struct ioapic_softc *pic; |
919 | #endif | | 920 | #endif |
920 | | | 921 | |
921 | if (ih == 0) | | 922 | if (ih == 0) |
922 | panic("pci_intr_string: bogus handle 0x%x", ih); | | 923 | panic("%s: bogus handle 0x%x", __func__, ih); |
923 | | | 924 | |
924 | | | 925 | |
925 | #if NIOAPIC > 0 | | 926 | #if NIOAPIC > 0 |
926 | if (ih & APIC_INT_VIA_APIC) { | | 927 | if (ih & APIC_INT_VIA_APIC) { |
927 | pic = ioapic_find(APIC_IRQ_APIC(ih)); | | 928 | pic = ioapic_find(APIC_IRQ_APIC(ih)); |
928 | if (pic != NULL) { | | 929 | if (pic != NULL) { |
929 | snprintf(irqstr, sizeof(irqstr), "%s pin %d", | | 930 | snprintf(irqstr, sizeof(irqstr), "%s pin %d", |
930 | device_xname(pic->sc_dev), APIC_IRQ_PIN(ih)); | | 931 | device_xname(pic->sc_dev), APIC_IRQ_PIN(ih)); |
931 | } else { | | 932 | } else { |
932 | snprintf(irqstr, sizeof(irqstr), | | 933 | snprintf(irqstr, sizeof(irqstr), |
933 | "apic %d int %d (irq %d)", | | 934 | "apic %d int %d (irq %d)", |
934 | APIC_IRQ_APIC(ih), | | 935 | APIC_IRQ_APIC(ih), |
935 | APIC_IRQ_PIN(ih), | | 936 | APIC_IRQ_PIN(ih), |