From 6e69d6068cc2aa545544189a1ee4d2e1a32ad591 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 28 Aug 2007 14:25:32 -0700 Subject: [SPARC64]: Fix type and constant sizes wrt. sun4u IMAP/ICLR handling. Sometimes we were using 32-bit values and the top bits were getting inadvertantly chopped off. This will matter for the forthcoming Fire controller MSI support. Signed-off-by: David S. Miller --- arch/sparc64/kernel/irq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/sparc64/kernel/irq.c') diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c index 384abf410cf..51b8875a13a 100644 --- a/arch/sparc64/kernel/irq.c +++ b/arch/sparc64/kernel/irq.c @@ -308,7 +308,7 @@ static void sun4u_irq_disable(unsigned int virt_irq) if (likely(data)) { unsigned long imap = data->imap; - u32 tmp = upa_readq(imap); + unsigned long tmp = upa_readq(imap); tmp &= ~IMAP_VALID; upa_writeq(tmp, imap); -- cgit v1.2.3 From 5f92c329364c0bf2d3a356da5e8759fbe349f9d1 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 30 Aug 2007 22:27:28 -0700 Subject: [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 --- arch/sparc64/kernel/irq.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) (limited to 'arch/sparc64/kernel/irq.c') diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c index 51b8875a13a..23956096b3b 100644 --- a/arch/sparc64/kernel/irq.c +++ b/arch/sparc64/kernel/irq.c @@ -217,8 +217,27 @@ struct irq_handler_data { void (*pre_handler)(unsigned int, void *, void *); void *pre_handler_arg1; void *pre_handler_arg2; + + u32 msi; }; +void sparc64_set_msi(unsigned int virt_irq, u32 msi) +{ + struct irq_handler_data *data = get_irq_chip_data(virt_irq); + + if (data) + data->msi = msi; +} + +u32 sparc64_get_msi(unsigned int virt_irq) +{ + struct irq_handler_data *data = get_irq_chip_data(virt_irq); + + if (data) + return data->msi; + return 0xffffffff; +} + static inline struct ino_bucket *virt_irq_to_bucket(unsigned int virt_irq) { 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, break; } if (devino >= msi_end) - return 0; + return -ENOSPC; sysino = sun4v_devino_to_sysino(devhandle, devino); bucket = &ivector_table[sysino]; @@ -755,8 +774,8 @@ unsigned int sun4v_build_msi(u32 devhandle, unsigned int *virt_irq_p, data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC); if (unlikely(!data)) { - prom_printf("IRQ: kzalloc(irq_handler_data) failed.\n"); - prom_halt(); + virt_irq_free(*virt_irq_p); + return -ENOMEM; } set_irq_chip_data(bucket->virt_irq, data); -- cgit v1.2.3