Commit a998d65b authored by Jeff Garzik's avatar Jeff Garzik Committed by Linus Torvalds

[PATCH] Fix oopses in fealnx driver TX path

In both uniprocessor and SMP, the fealnx driver's TX-submit path can 
race against the interrupt handler, with disastrous results.  Add the
lock that needed to be there all along, to fix this.

There's another problem in the RX path, that will be sent as a separate 
patch, as soon as we get that patch 100% nailed down, and acceptable for
a Release Candidate.
parent d8b8beb4
...@@ -1303,14 +1303,15 @@ static void init_ring(struct net_device *dev) ...@@ -1303,14 +1303,15 @@ static void init_ring(struct net_device *dev)
/* for the last tx descriptor */ /* for the last tx descriptor */
np->tx_ring[i - 1].next_desc = np->tx_ring_dma; np->tx_ring[i - 1].next_desc = np->tx_ring_dma;
np->tx_ring[i - 1].next_desc_logical = &np->tx_ring[0]; np->tx_ring[i - 1].next_desc_logical = &np->tx_ring[0];
return;
} }
static int start_tx(struct sk_buff *skb, struct net_device *dev) static int start_tx(struct sk_buff *skb, struct net_device *dev)
{ {
struct netdev_private *np = dev->priv; struct netdev_private *np = dev->priv;
unsigned long flags;
spin_lock_irqsave(&np->lock, flags);
np->cur_tx_copy->skbuff = skb; np->cur_tx_copy->skbuff = skb;
...@@ -1377,6 +1378,7 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev) ...@@ -1377,6 +1378,7 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev)
writel(0, dev->base_addr + TXPDR); writel(0, dev->base_addr + TXPDR);
dev->trans_start = jiffies; dev->trans_start = jiffies;
spin_unlock_irqrestore(&np->lock, flags);
return 0; return 0;
} }
...@@ -1423,6 +1425,8 @@ static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs ...@@ -1423,6 +1425,8 @@ static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs
unsigned int num_tx = 0; unsigned int num_tx = 0;
int handled = 0; int handled = 0;
spin_lock(&np->lock);
writel(0, dev->base_addr + IMR); writel(0, dev->base_addr + IMR);
ioaddr = dev->base_addr; ioaddr = dev->base_addr;
...@@ -1565,6 +1569,8 @@ static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs ...@@ -1565,6 +1569,8 @@ static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs
writel(np->imrvalue, ioaddr + IMR); writel(np->imrvalue, ioaddr + IMR);
spin_unlock(&np->lock);
return IRQ_RETVAL(handled); return IRQ_RETVAL(handled);
} }
......
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