irq fixes for wavelan_cs/netwave_cs
Subsystems (2)
PATCH 1/1 irq fixes for wavelan_cs/netwave_cs
Hi,
This patch for 2.5.68-bk11 will fix the irq handler of someobsolete wireless drivers (wavelan, wavelan_cs and netwave_cs) plus assorted fixes. All those drivers have been tested on a SMP box.
Have fun... Jean
drivers/net/wireless/netwave_cs.c renamed from drivers/net/wireless-badirq/netwave_cs.c +6 -4
@@ -227,7 +227,7 @@ static int netwave_start_xmit( struct skstatic int netwave_rx (struct net_device *dev);/* Interrupt routines */ -static void netwave_interrupt (int irq,void *dev_id,struct pt_regs *regs); +static irqreturn_t netwave_interrupt (int irq,void *dev_id,struct pt_regs *regs);static void netwave_watchdog (struct net_device *);/* Statistics */
@@ -1456,7 +1456,7 @@ static int netwave_start_xmit(struct sk_* ready to transmit another packet. * 3. A command has completed execution. */ -static void netwave_interrupt (int irq,void * dev_id,struct pt_regs *regs) { +static irqreturn_t netwave_interrupt (int irq,void * dev_id,struct pt_regs *regs) {ioaddr_t iobase;u_char *ramBase;struct net_device *dev = (struct net_device *)dev_id;
@@ -1465,7 +1465,7 @@ static void netwave_interrupt(int irq, vint i;if (!netif_device_present (dev)) -return ; +return IRQ_NONE ; iobase = dev->base_addr; ramBase = priv->ramBase;
@@ -1476,7 +1476,7 @@ static void netwave_interrupt(int irq, vwait_WOC (iobase);if (!(inb (iobase+NETWAVE_REG_CCSR ) &0x02 )) -break ;/* None of the interrupt sources asserted */ +break ;/* None of the interrupt sources asserted (normal exit) */ status =inb (iobase +NETWAVE_REG_ASR );
@@ -1569,6 +1569,8 @@ static void netwave_interrupt(int irq, v} */ } +/* Handled if we looped at least one time - Jean II */ +return IRQ_RETVAL (i); }/* netwave_interrupt */ /*
drivers/net/wireless/wavelan.c renamed from drivers/net/wireless-badirq/wavelan.c +11 -10
@@ -2884,10 +2884,6 @@ static inline int wv_packet_write(device length);#endif -/* Do we need some padding? */ -if (clen <ETH_ZLEN ) - clen =ETH_ZLEN ; -spin_lock_irqsave (&lp->spinlock, flags);/* Check nothing bad has happened */
@@ -3008,12 +3004,6 @@ static int wavelan_packet_xmit(struct sk (unsigned) skb);#endif -if (skb->len <ETH_ZLEN ) { - skb =skb_padto (skb,ETH_ZLEN ); -if (skb ==NULL ) -return 0 ; - } -/* * Block a timer-based transmit from overlapping. * In other words, prevent reentering this routine.
@@ -3035,6 +3025,17 @@ static int wavelan_packet_xmit(struct skif (skb->next)printk (KERN_INFO "skb has next\n" );#endif + +/* Do we need some padding? */ +/* Note : on wireless the propagation time is in the order of 1us, +* and we don't have the Ethernet specific requirement of beeing +* able to detect collisions, therefore in theory we don't really +* need to pad. Jean II */ +if (skb->len <ETH_ZLEN ) { + skb =skb_padto (skb,ETH_ZLEN ); +if (skb ==NULL ) +return 0 ; + }/* Write packet on the card */ if (wv_packet_write (dev, skb->data, skb->len))
drivers/net/wireless/wavelan_cs.c renamed from drivers/net/wireless-badirq/wavelan_cs.c +31 -6
@@ -3581,10 +3581,6 @@ wv_packet_write(device * dev,spin_lock_irqsave (&lp->spinlock, flags); -/* Check if we need some padding */ -if (clen <ETH_ZLEN ) - clen =ETH_ZLEN ; -/* Write the length of data buffer followed by the buffer */ outb (xmtdata_base &0xff ,PIORL (base));outb (((xmtdata_base >>8 ) &PIORH_MASK ) |PIORH_SEL_TX ,PIORH (base));
@@ -3664,6 +3660,17 @@ wavelan_packet_xmit(struct sk_buff * skbprintk (KERN_INFO "skb has next\n" );#endif +/* Check if we need some padding */ +/* Note : on wireless the propagation time is in the order of 1us, +* and we don't have the Ethernet specific requirement of beeing +* able to detect collisions, therefore in theory we don't really +* need to pad. Jean II */ +if (skb->len <ETH_ZLEN ) { + skb =skb_padto (skb,ETH_ZLEN ); +if (skb ==NULL ) +return 0 ; + } +wv_packet_write (dev, skb->data, skb->len);dev_kfree_skb (skb);
@@ -4644,7 +4651,7 @@ wv_flush_stale_links(void)* ready to transmit another packet. * 3. A command has completed execution. */ -static void +static irqreturn_t wavelan_interrupt (int irq,void * dev_id,struct pt_regs * regs)
@@ -4661,7 +4668,7 @@ wavelan_interrupt(int irq,printk (KERN_WARNING "wavelan_interrupt(): irq %d for unknown device.\n" , irq);#endif -return ; +return IRQ_NONE ; }#ifdef DEBUG_INTERRUPT_TRACE
@@ -4883,6 +4890,24 @@ wavelan_interrupt(int irq,#ifdef DEBUG_INTERRUPT_TRACE printk (KERN_DEBUG "%s: <-wavelan_interrupt()\n" , dev->name);#endif + +/* We always return IRQ_HANDLED, because we will receive empty +* interrupts under normal operations. Anyway, it doesn't matter +* as we are dealing with an ISA interrupt that can't be shared. +* +* Explanation : under heavy receive, the following happens : +* ->wavelan_interrupt() +* (status0 & SR0_INTERRUPT) != 0 +* ->wv_packet_rcv() +* (status0 & SR0_INTERRUPT) != 0 +* ->wv_packet_rcv() +* (status0 & SR0_INTERRUPT) == 0 // i.e. no more event +* <-wavelan_interrupt() +* ->wavelan_interrupt() +* (status0 & SR0_INTERRUPT) == 0 // i.e. empty interrupt +* <-wavelan_interrupt() +* Jean II */ +return IRQ_HANDLED ; }/* wv_interrupt */ /*------------------------------------------------------------------*/
drivers/net/wireless/wavelan_cs.p.h renamed from drivers/net/wireless-badirq/wavelan_cs.p.h +1 -6
@@ -686,11 +686,6 @@ void wv_roam_init(struct net_device *devvoid wv_roam_cleanup (struct net_device *dev);#endif /* WAVELAN_ROAMING */ -/* ----------------------- MISC SUBROUTINES ------------------------ */ -static void -cs_error (client_handle_t ,/* Report error to cardmgr */ -int , -int );/* ----------------- MODEM MANAGEMENT SUBROUTINES ----------------- */ static inline u_char /* data */ hasr_read (u_long );/* Read the host interface : base address */
@@ -791,7 +786,7 @@ static voidwv_pcmcia_release (u_long),/* Remove a device */ wv_flush_stale_links (void);/* "detach" all possible devices */ /* ---------------------- INTERRUPT HANDLING ---------------------- */ -static void +static irqreturn_t wavelan_interrupt (int ,/* Interrupt handler */ void *,struct pt_regs *);