[parisc-linux-cvs] multi-diva change

Paul Bame bame@fc.hp.com
Tue, 14 Jan 2003 13:17:50 -0700


Index: drivers/char/serial.c
===================================================================
RCS file: /var/cvs/linux/drivers/char/serial.c,v
retrieving revision 1.41
diff -u -r1.41 serial.c
--- drivers/char/serial.c	13 Jan 2003 15:41:06 -0000	1.41
+++ drivers/char/serial.c	14 Jan 2003 20:11:52 -0000
@@ -268,7 +268,7 @@
 #ifdef CONFIG_SERIAL_SHARE_IRQ
 #define HP_DIVA_CHECKTIME (1*HZ)
 static struct timer_list hp_diva_timer;
-static int hp_diva_irq = -1;
+static int hp_diva_count = 0;
 #endif /* CONFIG_SERIAL_SHARE_IRQ */
 
 /* serial subtype definitions */
@@ -807,6 +807,19 @@
 }
 
 #ifdef CONFIG_SERIAL_SHARE_IRQ
+static inline int is_hp_diva_info(struct async_struct *info) 
+{
+    struct pci_dev *dev = info->state->dev;
+    return (dev && dev->vendor == PCI_VENDOR_ID_HP &&
+		dev->device == PCI_DEVICE_ID_HP_SAS);
+}
+
+static inline int is_hp_diva_irq(int irq)
+{
+    struct async_struct *info = IRQ_ports[irq];
+    return (info && is_hp_diva_info(info));
+}
+
 /*
  * It is possible to "use up" transmit empty interrupts in some
  * cases with HP Diva cards.  Figure out if there _should_ be a
@@ -817,7 +830,7 @@
 {
 	int iir = serial_in(info, UART_IIR);
 
-	if (irq == hp_diva_irq &&
+	if (is_hp_diva_info(info) &&
 		(iir & UART_IIR_NO_INT) != 0 &&
 		(info->IER & UART_IER_THRI) != 0 &&
 		(info->xmit.head != info->xmit.tail || info->x_char) &&
@@ -1123,7 +1136,7 @@
 #ifdef CONFIG_SERIAL_SHARE_IRQ
 			if (info->next_port) {
 				do {
-					if (i != hp_diva_irq) {
+					if (!is_hp_diva_info(info)) {
 						serial_out(info, UART_IER, 0);
 						info->IER |= UART_IER_THRI;
 						serial_out(info, UART_IER, info->IER);
@@ -1169,15 +1182,16 @@
 static void hp_diva_check(unsigned long dummy)
 {
 	static unsigned long last_strobe;
-	struct async_struct *info;
 	unsigned long flags;
+	int i;
 
 	if (time_after_eq(jiffies, last_strobe + HP_DIVA_CHECKTIME)) {
-		info = IRQ_ports[hp_diva_irq];
-		if (info) {
-			save_flags(flags); cli();
-			rs_interrupt(hp_diva_irq, NULL, NULL);
-			restore_flags(flags);
+		for (i = 0; i < NR_IRQS; i++) {
+			if (is_hp_diva_irq(i)) {
+			    save_flags(flags); cli();
+			    rs_interrupt(i, NULL, NULL);
+			    restore_flags(flags);
+			}
 		}
 	}
 	last_strobe = jiffies;
@@ -4325,7 +4339,7 @@
 	if (!enable)
 		return 0;
 
-	hp_diva_irq = dev->irq;
+	hp_diva_count++;
 
 	switch (dev->subsystem_device) {
 	case 0x1049: /* Prelude Diva 1 */
@@ -5800,7 +5814,7 @@
 	/* printk("Unloading %s: version %s\n", serial_name, serial_version); */
 	del_timer_sync(&serial_timer);
 #ifdef CONFIG_SERIAL_SHARE_IRQ
-	if (hp_diva_irq != -1)
+	if (hp_diva_count > 0)
 		del_timer_sync(&hp_diva_timer);
 #endif /* CONFIG_SERIAL_SHARE_IRQ */
 	save_flags(flags); cli();