Commit 5e556524 authored by Jean Tourrilhes's avatar Jean Tourrilhes Committed by Linus Torvalds

[PATCH] irq fixes for wavelan_cs/netwave_cs

        This patch for 2.5.68-bk11 will fix the irq handler of some
obsolete wireless drivers (wavelan, wavelan_cs and netwave_cs) plus
assorted fixes. All those drivers have been tested on a SMP box.
parent 9808d508
...@@ -227,7 +227,7 @@ static int netwave_start_xmit( struct sk_buff *skb, struct net_device *dev); ...@@ -227,7 +227,7 @@ static int netwave_start_xmit( struct sk_buff *skb, struct net_device *dev);
static int netwave_rx( struct net_device *dev); static int netwave_rx( struct net_device *dev);
/* Interrupt routines */ /* 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 *); static void netwave_watchdog(struct net_device *);
/* Statistics */ /* Statistics */
...@@ -1456,7 +1456,7 @@ static int netwave_start_xmit(struct sk_buff *skb, struct net_device *dev) { ...@@ -1456,7 +1456,7 @@ static int netwave_start_xmit(struct sk_buff *skb, struct net_device *dev) {
* ready to transmit another packet. * ready to transmit another packet.
* 3. A command has completed execution. * 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; ioaddr_t iobase;
u_char *ramBase; u_char *ramBase;
struct net_device *dev = (struct net_device *)dev_id; struct net_device *dev = (struct net_device *)dev_id;
...@@ -1465,7 +1465,7 @@ static void netwave_interrupt(int irq, void* dev_id, struct pt_regs *regs) { ...@@ -1465,7 +1465,7 @@ static void netwave_interrupt(int irq, void* dev_id, struct pt_regs *regs) {
int i; int i;
if (!netif_device_present(dev)) if (!netif_device_present(dev))
return; return IRQ_NONE;
iobase = dev->base_addr; iobase = dev->base_addr;
ramBase = priv->ramBase; ramBase = priv->ramBase;
...@@ -1476,7 +1476,7 @@ static void netwave_interrupt(int irq, void* dev_id, struct pt_regs *regs) { ...@@ -1476,7 +1476,7 @@ static void netwave_interrupt(int irq, void* dev_id, struct pt_regs *regs) {
wait_WOC(iobase); wait_WOC(iobase);
if (!(inb(iobase+NETWAVE_REG_CCSR) & 0x02)) 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); status = inb(iobase + NETWAVE_REG_ASR);
...@@ -1569,6 +1569,8 @@ static void netwave_interrupt(int irq, void* dev_id, struct pt_regs *regs) { ...@@ -1569,6 +1569,8 @@ static void netwave_interrupt(int irq, void* dev_id, struct pt_regs *regs) {
} }
*/ */
} }
/* Handled if we looped at least one time - Jean II */
return IRQ_RETVAL(i);
} /* netwave_interrupt */ } /* netwave_interrupt */
/* /*
......
...@@ -2884,10 +2884,6 @@ static inline int wv_packet_write(device * dev, void *buf, short length) ...@@ -2884,10 +2884,6 @@ static inline int wv_packet_write(device * dev, void *buf, short length)
length); length);
#endif #endif
/* Do we need some padding? */
if (clen < ETH_ZLEN)
clen = ETH_ZLEN;
spin_lock_irqsave(&lp->spinlock, flags); spin_lock_irqsave(&lp->spinlock, flags);
/* Check nothing bad has happened */ /* Check nothing bad has happened */
...@@ -3008,12 +3004,6 @@ static int wavelan_packet_xmit(struct sk_buff *skb, device * dev) ...@@ -3008,12 +3004,6 @@ static int wavelan_packet_xmit(struct sk_buff *skb, device * dev)
(unsigned) skb); (unsigned) skb);
#endif #endif
if (skb->len < ETH_ZLEN) {
skb = skb_padto(skb, ETH_ZLEN);
if (skb == NULL)
return 0;
}
/* /*
* Block a timer-based transmit from overlapping. * Block a timer-based transmit from overlapping.
* In other words, prevent reentering this routine. * In other words, prevent reentering this routine.
...@@ -3036,6 +3026,17 @@ static int wavelan_packet_xmit(struct sk_buff *skb, device * dev) ...@@ -3036,6 +3026,17 @@ static int wavelan_packet_xmit(struct sk_buff *skb, device * dev)
printk(KERN_INFO "skb has next\n"); printk(KERN_INFO "skb has next\n");
#endif #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 */ /* Write packet on the card */
if(wv_packet_write(dev, skb->data, skb->len)) if(wv_packet_write(dev, skb->data, skb->len))
return 1; /* We failed */ return 1; /* We failed */
......
...@@ -3581,10 +3581,6 @@ wv_packet_write(device * dev, ...@@ -3581,10 +3581,6 @@ wv_packet_write(device * dev,
spin_lock_irqsave(&lp->spinlock, flags); 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 */ /* Write the length of data buffer followed by the buffer */
outb(xmtdata_base & 0xff, PIORL(base)); outb(xmtdata_base & 0xff, PIORL(base));
outb(((xmtdata_base >> 8) & PIORH_MASK) | PIORH_SEL_TX, PIORH(base)); outb(((xmtdata_base >> 8) & PIORH_MASK) | PIORH_SEL_TX, PIORH(base));
...@@ -3664,6 +3660,17 @@ wavelan_packet_xmit(struct sk_buff * skb, ...@@ -3664,6 +3660,17 @@ wavelan_packet_xmit(struct sk_buff * skb,
printk(KERN_INFO "skb has next\n"); printk(KERN_INFO "skb has next\n");
#endif #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); wv_packet_write(dev, skb->data, skb->len);
dev_kfree_skb(skb); dev_kfree_skb(skb);
...@@ -4644,7 +4651,7 @@ wv_flush_stale_links(void) ...@@ -4644,7 +4651,7 @@ wv_flush_stale_links(void)
* ready to transmit another packet. * ready to transmit another packet.
* 3. A command has completed execution. * 3. A command has completed execution.
*/ */
static void static irqreturn_t
wavelan_interrupt(int irq, wavelan_interrupt(int irq,
void * dev_id, void * dev_id,
struct pt_regs * regs) struct pt_regs * regs)
...@@ -4661,7 +4668,7 @@ wavelan_interrupt(int irq, ...@@ -4661,7 +4668,7 @@ wavelan_interrupt(int irq,
printk(KERN_WARNING "wavelan_interrupt(): irq %d for unknown device.\n", printk(KERN_WARNING "wavelan_interrupt(): irq %d for unknown device.\n",
irq); irq);
#endif #endif
return; return IRQ_NONE;
} }
#ifdef DEBUG_INTERRUPT_TRACE #ifdef DEBUG_INTERRUPT_TRACE
...@@ -4883,6 +4890,24 @@ wavelan_interrupt(int irq, ...@@ -4883,6 +4890,24 @@ wavelan_interrupt(int irq,
#ifdef DEBUG_INTERRUPT_TRACE #ifdef DEBUG_INTERRUPT_TRACE
printk(KERN_DEBUG "%s: <-wavelan_interrupt()\n", dev->name); printk(KERN_DEBUG "%s: <-wavelan_interrupt()\n", dev->name);
#endif #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 */ } /* wv_interrupt */
/*------------------------------------------------------------------*/ /*------------------------------------------------------------------*/
......
...@@ -686,11 +686,6 @@ void wv_roam_init(struct net_device *dev); ...@@ -686,11 +686,6 @@ void wv_roam_init(struct net_device *dev);
void wv_roam_cleanup(struct net_device *dev); void wv_roam_cleanup(struct net_device *dev);
#endif /* WAVELAN_ROAMING */ #endif /* WAVELAN_ROAMING */
/* ----------------------- MISC SUBROUTINES ------------------------ */
static void
cs_error(client_handle_t, /* Report error to cardmgr */
int,
int);
/* ----------------- MODEM MANAGEMENT SUBROUTINES ----------------- */ /* ----------------- MODEM MANAGEMENT SUBROUTINES ----------------- */
static inline u_char /* data */ static inline u_char /* data */
hasr_read(u_long); /* Read the host interface : base address */ hasr_read(u_long); /* Read the host interface : base address */
...@@ -791,7 +786,7 @@ static void ...@@ -791,7 +786,7 @@ static void
wv_pcmcia_release(u_long), /* Remove a device */ wv_pcmcia_release(u_long), /* Remove a device */
wv_flush_stale_links(void); /* "detach" all possible devices */ wv_flush_stale_links(void); /* "detach" all possible devices */
/* ---------------------- INTERRUPT HANDLING ---------------------- */ /* ---------------------- INTERRUPT HANDLING ---------------------- */
static void static irqreturn_t
wavelan_interrupt(int, /* Interrupt handler */ wavelan_interrupt(int, /* Interrupt handler */
void *, void *,
struct pt_regs *); struct pt_regs *);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment