aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2007-01-28 14:56:37 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2007-02-07 18:50:08 -0500
commitf7feaca77d6ad6bcfcc88ac54e3188970448d6fe (patch)
tree3002076ed2b6ab497b3b90232ff11b08de2eca5d /arch
parent5b912c108c8b1fcecbfe13d6d9a183db97b682d3 (diff)
msi: Make MSI useable more architectures
The arch hooks arch_setup_msi_irq and arch_teardown_msi_irq are now responsible for allocating and freeing the linux irq in addition to setting up the the linux irq to work with the interrupt. arch_setup_msi_irq now takes a pci_device and a msi_desc and returns an irq. With this change in place this code should be useable by all platforms except those that won't let the OS touch the hardware like ppc RTAS. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Acked-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'arch')
-rw-r--r--arch/i386/kernel/io_apic.c17
-rw-r--r--arch/ia64/kernel/msi_ia64.c19
-rw-r--r--arch/ia64/sn/kernel/msi_sn.c20
-rw-r--r--arch/x86_64/kernel/io_apic.c17
4 files changed, 50 insertions, 23 deletions
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
index 6a3875f81a0a..5592fa6e1fa1 100644
--- a/arch/i386/kernel/io_apic.c
+++ b/arch/i386/kernel/io_apic.c
@@ -2606,25 +2606,32 @@ static struct irq_chip msi_chip = {
2606 .retrigger = ioapic_retrigger_irq, 2606 .retrigger = ioapic_retrigger_irq,
2607}; 2607};
2608 2608
2609int arch_setup_msi_irq(unsigned int irq, struct pci_dev *dev) 2609int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
2610{ 2610{
2611 struct msi_msg msg; 2611 struct msi_msg msg;
2612 int ret; 2612 int irq, ret;
2613 irq = create_irq();
2614 if (irq < 0)
2615 return irq;
2616
2617 set_irq_msi(irq, desc);
2613 ret = msi_compose_msg(dev, irq, &msg); 2618 ret = msi_compose_msg(dev, irq, &msg);
2614 if (ret < 0) 2619 if (ret < 0) {
2620 destroy_irq(irq);
2615 return ret; 2621 return ret;
2622 }
2616 2623
2617 write_msi_msg(irq, &msg); 2624 write_msi_msg(irq, &msg);
2618 2625
2619 set_irq_chip_and_handler_name(irq, &msi_chip, handle_edge_irq, 2626 set_irq_chip_and_handler_name(irq, &msi_chip, handle_edge_irq,
2620 "edge"); 2627 "edge");
2621 2628
2622 return 0; 2629 return irq;
2623} 2630}
2624 2631
2625void arch_teardown_msi_irq(unsigned int irq) 2632void arch_teardown_msi_irq(unsigned int irq)
2626{ 2633{
2627 return; 2634 destroy_irq(irq);
2628} 2635}
2629 2636
2630#endif /* CONFIG_PCI_MSI */ 2637#endif /* CONFIG_PCI_MSI */
diff --git a/arch/ia64/kernel/msi_ia64.c b/arch/ia64/kernel/msi_ia64.c
index 822e59a1b822..0d05450c91c4 100644
--- a/arch/ia64/kernel/msi_ia64.c
+++ b/arch/ia64/kernel/msi_ia64.c
@@ -64,12 +64,17 @@ static void ia64_set_msi_irq_affinity(unsigned int irq, cpumask_t cpu_mask)
64} 64}
65#endif /* CONFIG_SMP */ 65#endif /* CONFIG_SMP */
66 66
67int ia64_setup_msi_irq(unsigned int irq, struct pci_dev *pdev) 67int ia64_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
68{ 68{
69 struct msi_msg msg; 69 struct msi_msg msg;
70 unsigned long dest_phys_id; 70 unsigned long dest_phys_id;
71 unsigned int vector; 71 unsigned int irq, vector;
72 72
73 irq = create_irq();
74 if (irq < 0)
75 return irq;
76
77 set_irq_msi(irq, desc);
73 dest_phys_id = cpu_physical_id(first_cpu(cpu_online_map)); 78 dest_phys_id = cpu_physical_id(first_cpu(cpu_online_map));
74 vector = irq; 79 vector = irq;
75 80
@@ -89,12 +94,12 @@ int ia64_setup_msi_irq(unsigned int irq, struct pci_dev *pdev)
89 write_msi_msg(irq, &msg); 94 write_msi_msg(irq, &msg);
90 set_irq_chip_and_handler(irq, &ia64_msi_chip, handle_edge_irq); 95 set_irq_chip_and_handler(irq, &ia64_msi_chip, handle_edge_irq);
91 96
92 return 0; 97 return irq;
93} 98}
94 99
95void ia64_teardown_msi_irq(unsigned int irq) 100void ia64_teardown_msi_irq(unsigned int irq)
96{ 101{
97 return; /* no-op */ 102 destroy_irq(irq);
98} 103}
99 104
100static void ia64_ack_msi_irq(unsigned int irq) 105static void ia64_ack_msi_irq(unsigned int irq)
@@ -126,12 +131,12 @@ static struct irq_chip ia64_msi_chip = {
126}; 131};
127 132
128 133
129int arch_setup_msi_irq(unsigned int irq, struct pci_dev *pdev) 134int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
130{ 135{
131 if (platform_setup_msi_irq) 136 if (platform_setup_msi_irq)
132 return platform_setup_msi_irq(irq, pdev); 137 return platform_setup_msi_irq(pdev, desc);
133 138
134 return ia64_setup_msi_irq(irq, pdev); 139 return ia64_setup_msi_irq(pdev, desc);
135} 140}
136 141
137void arch_teardown_msi_irq(unsigned int irq) 142void arch_teardown_msi_irq(unsigned int irq)
diff --git a/arch/ia64/sn/kernel/msi_sn.c b/arch/ia64/sn/kernel/msi_sn.c
index 31fbb859b67e..ea3dc38d73fd 100644
--- a/arch/ia64/sn/kernel/msi_sn.c
+++ b/arch/ia64/sn/kernel/msi_sn.c
@@ -59,13 +59,12 @@ void sn_teardown_msi_irq(unsigned int irq)
59 sn_intr_free(nasid, widget, sn_irq_info); 59 sn_intr_free(nasid, widget, sn_irq_info);
60 sn_msi_info[irq].sn_irq_info = NULL; 60 sn_msi_info[irq].sn_irq_info = NULL;
61 61
62 return; 62 destroy_irq(irq);
63} 63}
64 64
65int sn_setup_msi_irq(unsigned int irq, struct pci_dev *pdev) 65int sn_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *entry)
66{ 66{
67 struct msi_msg msg; 67 struct msi_msg msg;
68 struct msi_desc *entry;
69 int widget; 68 int widget;
70 int status; 69 int status;
71 nasid_t nasid; 70 nasid_t nasid;
@@ -73,8 +72,8 @@ int sn_setup_msi_irq(unsigned int irq, struct pci_dev *pdev)
73 struct sn_irq_info *sn_irq_info; 72 struct sn_irq_info *sn_irq_info;
74 struct pcibus_bussoft *bussoft = SN_PCIDEV_BUSSOFT(pdev); 73 struct pcibus_bussoft *bussoft = SN_PCIDEV_BUSSOFT(pdev);
75 struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev); 74 struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
75 int irq;
76 76
77 entry = get_irq_msi(irq);
78 if (!entry->msi_attrib.is_64) 77 if (!entry->msi_attrib.is_64)
79 return -EINVAL; 78 return -EINVAL;
80 79
@@ -84,6 +83,11 @@ int sn_setup_msi_irq(unsigned int irq, struct pci_dev *pdev)
84 if (provider == NULL || provider->dma_map_consistent == NULL) 83 if (provider == NULL || provider->dma_map_consistent == NULL)
85 return -EINVAL; 84 return -EINVAL;
86 85
86 irq = create_irq();
87 if (irq < 0)
88 return irq;
89
90 set_irq_msi(irq, entry);
87 /* 91 /*
88 * Set up the vector plumbing. Let the prom (via sn_intr_alloc) 92 * Set up the vector plumbing. Let the prom (via sn_intr_alloc)
89 * decide which cpu to direct this msi at by default. 93 * decide which cpu to direct this msi at by default.
@@ -95,12 +99,15 @@ int sn_setup_msi_irq(unsigned int irq, struct pci_dev *pdev)
95 SWIN_WIDGETNUM(bussoft->bs_base); 99 SWIN_WIDGETNUM(bussoft->bs_base);
96 100
97 sn_irq_info = kzalloc(sizeof(struct sn_irq_info), GFP_KERNEL); 101 sn_irq_info = kzalloc(sizeof(struct sn_irq_info), GFP_KERNEL);
98 if (! sn_irq_info) 102 if (! sn_irq_info) {
103 destroy_irq(irq);
99 return -ENOMEM; 104 return -ENOMEM;
105 }
100 106
101 status = sn_intr_alloc(nasid, widget, sn_irq_info, irq, -1, -1); 107 status = sn_intr_alloc(nasid, widget, sn_irq_info, irq, -1, -1);
102 if (status) { 108 if (status) {
103 kfree(sn_irq_info); 109 kfree(sn_irq_info);
110 destroy_irq(irq);
104 return -ENOMEM; 111 return -ENOMEM;
105 } 112 }
106 113
@@ -121,6 +128,7 @@ int sn_setup_msi_irq(unsigned int irq, struct pci_dev *pdev)
121 if (! bus_addr) { 128 if (! bus_addr) {
122 sn_intr_free(nasid, widget, sn_irq_info); 129 sn_intr_free(nasid, widget, sn_irq_info);
123 kfree(sn_irq_info); 130 kfree(sn_irq_info);
131 destroy_irq(irq);
124 return -ENOMEM; 132 return -ENOMEM;
125 } 133 }
126 134
@@ -139,7 +147,7 @@ int sn_setup_msi_irq(unsigned int irq, struct pci_dev *pdev)
139 write_msi_msg(irq, &msg); 147 write_msi_msg(irq, &msg);
140 set_irq_chip_and_handler(irq, &sn_msi_chip, handle_edge_irq); 148 set_irq_chip_and_handler(irq, &sn_msi_chip, handle_edge_irq);
141 149
142 return 0; 150 return irq;
143} 151}
144 152
145#ifdef CONFIG_SMP 153#ifdef CONFIG_SMP
diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c
index d7bad90a5ad8..6be6730acb5c 100644
--- a/arch/x86_64/kernel/io_apic.c
+++ b/arch/x86_64/kernel/io_apic.c
@@ -1956,24 +1956,31 @@ static struct irq_chip msi_chip = {
1956 .retrigger = ioapic_retrigger_irq, 1956 .retrigger = ioapic_retrigger_irq,
1957}; 1957};
1958 1958
1959int arch_setup_msi_irq(unsigned int irq, struct pci_dev *dev) 1959int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
1960{ 1960{
1961 struct msi_msg msg; 1961 struct msi_msg msg;
1962 int ret; 1962 int irq, ret;
1963 irq = create_irq();
1964 if (irq < 0)
1965 return irq;
1966
1967 set_irq_msi(irq, desc);
1963 ret = msi_compose_msg(dev, irq, &msg); 1968 ret = msi_compose_msg(dev, irq, &msg);
1964 if (ret < 0) 1969 if (ret < 0) {
1970 destroy_irq(irq);
1965 return ret; 1971 return ret;
1972 }
1966 1973
1967 write_msi_msg(irq, &msg); 1974 write_msi_msg(irq, &msg);
1968 1975
1969 set_irq_chip_and_handler_name(irq, &msi_chip, handle_edge_irq, "edge"); 1976 set_irq_chip_and_handler_name(irq, &msi_chip, handle_edge_irq, "edge");
1970 1977
1971 return 0; 1978 return irq;
1972} 1979}
1973 1980
1974void arch_teardown_msi_irq(unsigned int irq) 1981void arch_teardown_msi_irq(unsigned int irq)
1975{ 1982{
1976 return; 1983 destroy_irq(irq);
1977} 1984}
1978 1985
1979#endif /* CONFIG_PCI_MSI */ 1986#endif /* CONFIG_PCI_MSI */