diff options
author | David S. Miller <davem@sunset.davemloft.net> | 2006-10-29 19:32:31 -0500 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-10-30 22:33:33 -0500 |
commit | 9001f2850ff92b52d7654379e7b7feb72f78f161 (patch) | |
tree | 2482fa3e7653f633dad7b0e864ade020d390d719 /arch/sparc64 | |
parent | a7aacdf9ea45bf6139cfd750e558a3dcbc6f16c3 (diff) |
[SPARC64]: Fix Tomatillo/Schizo IRQ handling.
The code in schizo_irq_trans_init() should set irq_data->sync_reg
to the location of the SYNC register if this is Tomatillo, and set
it to zero otherwise. But that is not what it is doing.
As a result, non-Tomatillo systems were trying to access a
non-existent register resulting in bus errors at the first
PCI interrupt.
Thanks to Roland Stigge for the bug report.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc64')
-rw-r--r-- | arch/sparc64/kernel/prom.c | 21 |
1 files changed, 17 insertions, 4 deletions
diff --git a/arch/sparc64/kernel/prom.c b/arch/sparc64/kernel/prom.c index c60efb3cb22e..0917c24c4f08 100644 --- a/arch/sparc64/kernel/prom.c +++ b/arch/sparc64/kernel/prom.c | |||
@@ -793,7 +793,7 @@ static unsigned int schizo_irq_build(struct device_node *dp, | |||
793 | return virt_irq; | 793 | return virt_irq; |
794 | } | 794 | } |
795 | 795 | ||
796 | static void schizo_irq_trans_init(struct device_node *dp) | 796 | static void __schizo_irq_trans_init(struct device_node *dp, int is_tomatillo) |
797 | { | 797 | { |
798 | struct linux_prom64_registers *regs; | 798 | struct linux_prom64_registers *regs; |
799 | struct schizo_irq_data *irq_data; | 799 | struct schizo_irq_data *irq_data; |
@@ -807,11 +807,24 @@ static void schizo_irq_trans_init(struct device_node *dp) | |||
807 | dp->irq_trans->data = irq_data; | 807 | dp->irq_trans->data = irq_data; |
808 | 808 | ||
809 | irq_data->pbm_regs = regs[0].phys_addr; | 809 | irq_data->pbm_regs = regs[0].phys_addr; |
810 | irq_data->sync_reg = regs[3].phys_addr + 0x1a18UL; | 810 | if (is_tomatillo) |
811 | irq_data->sync_reg = regs[3].phys_addr + 0x1a18UL; | ||
812 | else | ||
813 | irq_data->sync_reg = 0UL; | ||
811 | irq_data->portid = of_getintprop_default(dp, "portid", 0); | 814 | irq_data->portid = of_getintprop_default(dp, "portid", 0); |
812 | irq_data->chip_version = of_getintprop_default(dp, "version#", 0); | 815 | irq_data->chip_version = of_getintprop_default(dp, "version#", 0); |
813 | } | 816 | } |
814 | 817 | ||
818 | static void schizo_irq_trans_init(struct device_node *dp) | ||
819 | { | ||
820 | __schizo_irq_trans_init(dp, 0); | ||
821 | } | ||
822 | |||
823 | static void tomatillo_irq_trans_init(struct device_node *dp) | ||
824 | { | ||
825 | __schizo_irq_trans_init(dp, 1); | ||
826 | } | ||
827 | |||
815 | static unsigned int pci_sun4v_irq_build(struct device_node *dp, | 828 | static unsigned int pci_sun4v_irq_build(struct device_node *dp, |
816 | unsigned int devino, | 829 | unsigned int devino, |
817 | void *_data) | 830 | void *_data) |
@@ -1050,8 +1063,8 @@ static struct irq_trans pci_irq_trans_table[] = { | |||
1050 | { "pci108e,8001", schizo_irq_trans_init }, | 1063 | { "pci108e,8001", schizo_irq_trans_init }, |
1051 | { "SUNW,schizo+", schizo_irq_trans_init }, | 1064 | { "SUNW,schizo+", schizo_irq_trans_init }, |
1052 | { "pci108e,8002", schizo_irq_trans_init }, | 1065 | { "pci108e,8002", schizo_irq_trans_init }, |
1053 | { "SUNW,tomatillo", schizo_irq_trans_init }, | 1066 | { "SUNW,tomatillo", tomatillo_irq_trans_init }, |
1054 | { "pci108e,a801", schizo_irq_trans_init }, | 1067 | { "pci108e,a801", tomatillo_irq_trans_init }, |
1055 | { "SUNW,sun4v-pci", pci_sun4v_irq_trans_init }, | 1068 | { "SUNW,sun4v-pci", pci_sun4v_irq_trans_init }, |
1056 | }; | 1069 | }; |
1057 | #endif | 1070 | #endif |