[PATCH] drivers/net/amd8111e.c: fix NAPI interrupt in poll
This patch makes the netif_rx_complete() and rx_interrupt_enable atomic when exiting the poll() method, so to avoid interrupt in poll. It also fixes the rx interrupt check logic in interrupt handler. Signed-off-by: Liu Tao <liutao1980@gmail.com> Signed-off-by: Jeff Garzik <jgarzik@pobox.com>hifive-unleashed-5.1
parent
88d7bd8cb9
commit
dfa1b73ffb
|
@ -738,6 +738,7 @@ static int amd8111e_rx_poll(struct net_device *dev, int * budget)
|
||||||
short vtag;
|
short vtag;
|
||||||
#endif
|
#endif
|
||||||
int rx_pkt_limit = dev->quota;
|
int rx_pkt_limit = dev->quota;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
do{
|
do{
|
||||||
/* process receive packets until we use the quota*/
|
/* process receive packets until we use the quota*/
|
||||||
|
@ -841,18 +842,19 @@ static int amd8111e_rx_poll(struct net_device *dev, int * budget)
|
||||||
/* Receive descriptor is empty now */
|
/* Receive descriptor is empty now */
|
||||||
dev->quota -= num_rx_pkt;
|
dev->quota -= num_rx_pkt;
|
||||||
*budget -= num_rx_pkt;
|
*budget -= num_rx_pkt;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&lp->lock, flags);
|
||||||
netif_rx_complete(dev);
|
netif_rx_complete(dev);
|
||||||
/* enable receive interrupt */
|
|
||||||
writel(VAL0|RINTEN0, mmio + INTEN0);
|
writel(VAL0|RINTEN0, mmio + INTEN0);
|
||||||
writel(VAL2 | RDMD0, mmio + CMD0);
|
writel(VAL2 | RDMD0, mmio + CMD0);
|
||||||
|
spin_unlock_irqrestore(&lp->lock, flags);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
rx_not_empty:
|
rx_not_empty:
|
||||||
/* Do not call a netif_rx_complete */
|
/* Do not call a netif_rx_complete */
|
||||||
dev->quota -= num_rx_pkt;
|
dev->quota -= num_rx_pkt;
|
||||||
*budget -= num_rx_pkt;
|
*budget -= num_rx_pkt;
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
@ -1261,18 +1263,20 @@ static irqreturn_t amd8111e_interrupt(int irq, void *dev_id, struct pt_regs *reg
|
||||||
struct net_device * dev = (struct net_device *) dev_id;
|
struct net_device * dev = (struct net_device *) dev_id;
|
||||||
struct amd8111e_priv *lp = netdev_priv(dev);
|
struct amd8111e_priv *lp = netdev_priv(dev);
|
||||||
void __iomem *mmio = lp->mmio;
|
void __iomem *mmio = lp->mmio;
|
||||||
unsigned int intr0;
|
unsigned int intr0, intren0;
|
||||||
unsigned int handled = 1;
|
unsigned int handled = 1;
|
||||||
|
|
||||||
if(dev == NULL)
|
if(unlikely(dev == NULL))
|
||||||
return IRQ_NONE;
|
return IRQ_NONE;
|
||||||
|
|
||||||
if (regs) spin_lock (&lp->lock);
|
spin_lock(&lp->lock);
|
||||||
|
|
||||||
/* disabling interrupt */
|
/* disabling interrupt */
|
||||||
writel(INTREN, mmio + CMD0);
|
writel(INTREN, mmio + CMD0);
|
||||||
|
|
||||||
/* Read interrupt status */
|
/* Read interrupt status */
|
||||||
intr0 = readl(mmio + INT0);
|
intr0 = readl(mmio + INT0);
|
||||||
|
intren0 = readl(mmio + INTEN0);
|
||||||
|
|
||||||
/* Process all the INT event until INTR bit is clear. */
|
/* Process all the INT event until INTR bit is clear. */
|
||||||
|
|
||||||
|
@ -1293,11 +1297,11 @@ static irqreturn_t amd8111e_interrupt(int irq, void *dev_id, struct pt_regs *reg
|
||||||
/* Schedule a polling routine */
|
/* Schedule a polling routine */
|
||||||
__netif_rx_schedule(dev);
|
__netif_rx_schedule(dev);
|
||||||
}
|
}
|
||||||
else {
|
else if (intren0 & RINTEN0) {
|
||||||
printk("************Driver bug! \
|
printk("************Driver bug! \
|
||||||
interrupt while in poll\n");
|
interrupt while in poll\n");
|
||||||
/* Fix by disabling interrupts */
|
/* Fix by disable receive interrupts */
|
||||||
writel(RINT0, mmio + INT0);
|
writel(RINTEN0, mmio + INTEN0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
@ -1321,7 +1325,7 @@ static irqreturn_t amd8111e_interrupt(int irq, void *dev_id, struct pt_regs *reg
|
||||||
err_no_interrupt:
|
err_no_interrupt:
|
||||||
writel( VAL0 | INTREN,mmio + CMD0);
|
writel( VAL0 | INTREN,mmio + CMD0);
|
||||||
|
|
||||||
if (regs) spin_unlock(&lp->lock);
|
spin_unlock(&lp->lock);
|
||||||
|
|
||||||
return IRQ_RETVAL(handled);
|
return IRQ_RETVAL(handled);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue