ChangeSet 1.2076, 2005/03/12 09:14:51-08:00, [EMAIL PROTECTED]
[PATCH] PA-RISC GSC interrupt fixes
Two problems occurred with the recent switch to virtual interrupt
numbers.
The first is that two devices (eg Lasi PS/2 mouse and keyboard) can
share the same physical interrupt and should therefore share the same
virtual interrupt rather than have a new one assigned to them. Fix this
by initialising the global_irq array to NO_IRQ, then checking the array
before assigning a new one.
The second is that some GSC devices (eg HIL and EISA) can have
two interrupts; one for normal interrupts and the other for NMI or
high-priority. To fix this, I introduced an auxiliary IRQ to the
parisc_device and fill it in in Asp and Wax.
Signed-off-by: Matthew Wilcox <[EMAIL PROTECTED]>
Signed-off-by: Linus Torvalds <[EMAIL PROTECTED]>
drivers/input/serio/hp_sdc.c | 9 ++++-----
drivers/parisc/asp.c | 8 ++++++++
drivers/parisc/gsc.c | 18 ++++++++++++++----
drivers/parisc/wax.c | 26 ++++++++++++++------------
include/asm-parisc/parisc-device.h | 1 +
5 files changed, 41 insertions(+), 21 deletions(-)
diff -Nru a/drivers/input/serio/hp_sdc.c b/drivers/input/serio/hp_sdc.c
--- a/drivers/input/serio/hp_sdc.c 2005-03-12 21:42:44 -08:00
+++ b/drivers/input/serio/hp_sdc.c 2005-03-12 21:42:44 -08:00
@@ -874,11 +874,10 @@
hp_sdc.dev = d;
hp_sdc.irq = d->irq;
- /* TODO: Is NMI == IRQ - 1 all cases, or is there a way to query? */
- hp_sdc.nmi = d->irq - 1;
- hp_sdc.base_io = (unsigned long) d->hpa;
- hp_sdc.data_io = (unsigned long) d->hpa + 0x800;
- hp_sdc.status_io = (unsigned long) d->hpa + 0x801;
+ hp_sdc.nmi = d->aux_irq;
+ hp_sdc.base_io = d->hpa;
+ hp_sdc.data_io = d->hpa + 0x800;
+ hp_sdc.status_io = d->hpa + 0x801;
return hp_sdc_init();
}
diff -Nru a/drivers/parisc/asp.c b/drivers/parisc/asp.c
--- a/drivers/parisc/asp.c 2005-03-12 21:42:44 -08:00
+++ b/drivers/parisc/asp.c 2005-03-12 21:42:44 -08:00
@@ -53,6 +53,14 @@
}
gsc_asic_assign_irq(ctrl, irq, &dev->irq);
+
+ switch (dev->id.sversion) {
+ case 0x73: irq = 2; break; /* i8042 High-priority */
+ case 0x76: irq = 0; break; /* EISA BA */
+ default: return; /* Other */
+ }
+
+ gsc_asic_assign_irq(ctrl, irq, &dev->aux_irq);
}
/* There are two register ranges we're interested in. Interrupt /
diff -Nru a/drivers/parisc/gsc.c b/drivers/parisc/gsc.c
--- a/drivers/parisc/gsc.c 2005-03-12 21:42:44 -08:00
+++ b/drivers/parisc/gsc.c 2005-03-12 21:42:44 -08:00
@@ -171,12 +171,16 @@
void gsc_asic_assign_irq(struct gsc_asic *asic, int local_irq, int *irqp)
{
- int irq = gsc_assign_irq(&gsc_asic_interrupt_type, asic);
- if (irq == NO_IRQ)
- return;
+ int irq = asic->global_irq[local_irq];
+
+ if (irq <= 0) {
+ irq = gsc_assign_irq(&gsc_asic_interrupt_type, asic);
+ if (irq == NO_IRQ)
+ return;
+ asic->global_irq[local_irq] = irq;
+ }
*irqp = irq;
- asic->global_irq[local_irq] = irq;
}
void gsc_fixup_irqs(struct parisc_device *parent, void *ctrl,
@@ -198,8 +202,14 @@
int gsc_common_setup(struct parisc_device *parent, struct gsc_asic *gsc_asic)
{
struct resource *res;
+ int i;
gsc_asic->gsc = parent;
+
+ /* Initialise local irq -> global irq mapping */
+ for (i = 0; i < 32; i++) {
+ gsc_asic->global_irq[i] = NO_IRQ;
+ }
/* allocate resource region */
res = request_mem_region(gsc_asic->hpa, 0x100000, gsc_asic->name);
diff -Nru a/drivers/parisc/wax.c b/drivers/parisc/wax.c
--- a/drivers/parisc/wax.c 2005-03-12 21:42:44 -08:00
+++ b/drivers/parisc/wax.c 2005-03-12 21:42:44 -08:00
@@ -25,20 +25,27 @@
#include "gsc.h"
#define WAX_GSC_IRQ 7 /* Hardcoded Interrupt for GSC */
-#define WAX_GSC_NMI_IRQ 29
static void wax_choose_irq(struct parisc_device *dev, void *ctrl)
{
int irq;
switch (dev->id.sversion) {
- case 0x73: irq = 1; break; /* HIL */
- case 0x8c: irq = 6; break; /* RS232 */
- case 0x90: irq = 10; break; /* WAX EISA BA */
+ case 0x73: irq = 1; break; /* i8042 General */
+ case 0x8c: irq = 6; break; /* Serial */
+ case 0x90: irq = 10; break; /* EISA */
default: return; /* Unknown */
}
gsc_asic_assign_irq(ctrl, irq, &dev->irq);
+
+ switch (dev->id.sversion) {
+ case 0x73: irq = 2; break; /* i8042 High-priority */
+ case 0x90: irq = 0; break; /* EISA NMI */
+ default: return; /* No secondary IRQ */
+ }
+
+ gsc_asic_assign_irq(ctrl, irq, &dev->aux_irq);
}
static void __init
@@ -46,7 +53,7 @@
{
unsigned long base = wax->hpa;
- /* Stop WAX barking for a bit */
+ /* Wax-off */
gsc_writel(0x00000000, base+OFFSET_IMR);
/* clear pending interrupts */
@@ -59,11 +66,6 @@
/* Resets */
// gsc_writel(0xFFFFFFFF, base+0x1000); /* HIL */
// gsc_writel(0xFFFFFFFF, base+0x2000); /* RS232-B on Wax */
-
- /* Ok we hit it on the head with a hammer, our Dog is now
- ** comatose and muzzled. Devices will now unmask WAX
- ** interrupts as they are registered as irq's in the WAX range.
- */
}
int __init
@@ -78,7 +80,7 @@
if (!wax)
return -ENOMEM;
- wax->name = "Wax";
+ wax->name = "wax";
wax->hpa = dev->hpa;
wax->version = 0; /* gsc_readb(wax->hpa+WAX_VER); */
@@ -132,7 +134,7 @@
MODULE_DEVICE_TABLE(parisc, wax_tbl);
struct parisc_driver wax_driver = {
- .name = "Wax",
+ .name = "wax",
.id_table = wax_tbl,
.probe = wax_init_chip,
};
diff -Nru a/include/asm-parisc/parisc-device.h
b/include/asm-parisc/parisc-device.h
--- a/include/asm-parisc/parisc-device.h 2005-03-12 21:42:44 -08:00
+++ b/include/asm-parisc/parisc-device.h 2005-03-12 21:42:44 -08:00
@@ -6,6 +6,7 @@
struct parisc_driver *driver; /* Driver for this device */
char name[80]; /* The hardware description */
int irq;
+ int aux_irq; /* Some devices have a second IRQ */
char hw_path; /* The module number on this bus */
unsigned int num_addrs; /* some devices have additional address
ranges. */
-
To unsubscribe from this list: send the line "unsubscribe bk-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at http://vger.kernel.org/majordomo-info.html