aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel/irq.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2007-08-31 01:27:28 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-08-31 02:06:51 -0400
commit5f92c329364c0bf2d3a356da5e8759fbe349f9d1 (patch)
tree2bf27d77009229a26c371102655c5f81c7e68d1e /arch/sparc64/kernel/irq.c
parent6e69d6068cc2aa545544189a1ee4d2e1a32ad591 (diff)
[SPARC64]: Fix several bugs in MSI handling.
1) sun4{u,v}_build_msi() have improper return value handling. We should always return negative error codes, instead of using the magic value "0" which could in fact be a valid MSI number. 2) sun4{u,v}_build_msi() should return -ENOMEM instead of calling prom_prom() halt with kzalloc() of the interrupt data fails. 3) We 'remembered' the MSI number using a singleton in the struct device archdata area, this doesn't work for MSI-X which can cause multiple MSIs assosciated with one device. Delete that archdata member, and instead store the MSI number in the IRQ chip data area. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc64/kernel/irq.c')
-rw-r--r--arch/sparc64/kernel/irq.c25
1 files changed, 22 insertions, 3 deletions
diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c
index 51b8875a13a8..23956096b3bf 100644
--- a/arch/sparc64/kernel/irq.c
+++ b/arch/sparc64/kernel/irq.c
@@ -217,8 +217,27 @@ struct irq_handler_data {
217 void (*pre_handler)(unsigned int, void *, void *); 217 void (*pre_handler)(unsigned int, void *, void *);
218 void *pre_handler_arg1; 218 void *pre_handler_arg1;
219 void *pre_handler_arg2; 219 void *pre_handler_arg2;
220
221 u32 msi;
220}; 222};
221 223
224void sparc64_set_msi(unsigned int virt_irq, u32 msi)
225{
226 struct irq_handler_data *data = get_irq_chip_data(virt_irq);
227
228 if (data)
229 data->msi = msi;
230}
231
232u32 sparc64_get_msi(unsigned int virt_irq)
233{
234 struct irq_handler_data *data = get_irq_chip_data(virt_irq);
235
236 if (data)
237 return data->msi;
238 return 0xffffffff;
239}
240
222static inline struct ino_bucket *virt_irq_to_bucket(unsigned int virt_irq) 241static inline struct ino_bucket *virt_irq_to_bucket(unsigned int virt_irq)
223{ 242{
224 unsigned int real_irq = virt_to_real_irq(virt_irq); 243 unsigned int real_irq = virt_to_real_irq(virt_irq);
@@ -741,7 +760,7 @@ unsigned int sun4v_build_msi(u32 devhandle, unsigned int *virt_irq_p,
741 break; 760 break;
742 } 761 }
743 if (devino >= msi_end) 762 if (devino >= msi_end)
744 return 0; 763 return -ENOSPC;
745 764
746 sysino = sun4v_devino_to_sysino(devhandle, devino); 765 sysino = sun4v_devino_to_sysino(devhandle, devino);
747 bucket = &ivector_table[sysino]; 766 bucket = &ivector_table[sysino];
@@ -755,8 +774,8 @@ unsigned int sun4v_build_msi(u32 devhandle, unsigned int *virt_irq_p,
755 774
756 data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC); 775 data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC);
757 if (unlikely(!data)) { 776 if (unlikely(!data)) {
758 prom_printf("IRQ: kzalloc(irq_handler_data) failed.\n"); 777 virt_irq_free(*virt_irq_p);
759 prom_halt(); 778 return -ENOMEM;
760 } 779 }
761 set_irq_chip_data(bucket->virt_irq, data); 780 set_irq_chip_data(bucket->virt_irq, data);
762 781