diff options
author | Liu Tao <liutao1980@gmail.com> | 2005-05-12 19:40:38 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-05-12 19:40:38 -0400 |
commit | dfa1b73ffb414b64dc0452260132a090eb25bf52 (patch) | |
tree | d01ca6357ecdeb874bcf8ff3ea9a2131afd41862 /drivers/net/amd8111e.c | |
parent | 88d7bd8cb9eb8d64bf7997600b0d64f7834047c5 (diff) |
[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>
Diffstat (limited to 'drivers/net/amd8111e.c')
-rwxr-xr-x | drivers/net/amd8111e.c | 24 |
1 files changed, 14 insertions, 10 deletions
diff --git a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c index f2e937abf7b4..b7dd7260cafb 100755 --- a/drivers/net/amd8111e.c +++ b/drivers/net/amd8111e.c | |||
@@ -738,6 +738,7 @@ static int amd8111e_rx_poll(struct net_device *dev, int * budget) | |||
738 | short vtag; | 738 | short vtag; |
739 | #endif | 739 | #endif |
740 | int rx_pkt_limit = dev->quota; | 740 | int rx_pkt_limit = dev->quota; |
741 | unsigned long flags; | ||
741 | 742 | ||
742 | do{ | 743 | do{ |
743 | /* process receive packets until we use the quota*/ | 744 | /* process receive packets until we use the quota*/ |
@@ -841,18 +842,19 @@ static int amd8111e_rx_poll(struct net_device *dev, int * budget) | |||
841 | /* Receive descriptor is empty now */ | 842 | /* Receive descriptor is empty now */ |
842 | dev->quota -= num_rx_pkt; | 843 | dev->quota -= num_rx_pkt; |
843 | *budget -= num_rx_pkt; | 844 | *budget -= num_rx_pkt; |
845 | |||
846 | spin_lock_irqsave(&lp->lock, flags); | ||
844 | netif_rx_complete(dev); | 847 | netif_rx_complete(dev); |
845 | /* enable receive interrupt */ | ||
846 | writel(VAL0|RINTEN0, mmio + INTEN0); | 848 | writel(VAL0|RINTEN0, mmio + INTEN0); |
847 | writel(VAL2 | RDMD0, mmio + CMD0); | 849 | writel(VAL2 | RDMD0, mmio + CMD0); |
850 | spin_unlock_irqrestore(&lp->lock, flags); | ||
848 | return 0; | 851 | return 0; |
852 | |||
849 | rx_not_empty: | 853 | rx_not_empty: |
850 | /* Do not call a netif_rx_complete */ | 854 | /* Do not call a netif_rx_complete */ |
851 | dev->quota -= num_rx_pkt; | 855 | dev->quota -= num_rx_pkt; |
852 | *budget -= num_rx_pkt; | 856 | *budget -= num_rx_pkt; |
853 | return 1; | 857 | return 1; |
854 | |||
855 | |||
856 | } | 858 | } |
857 | 859 | ||
858 | #else | 860 | #else |
@@ -1261,18 +1263,20 @@ static irqreturn_t amd8111e_interrupt(int irq, void *dev_id, struct pt_regs *reg | |||
1261 | struct net_device * dev = (struct net_device *) dev_id; | 1263 | struct net_device * dev = (struct net_device *) dev_id; |
1262 | struct amd8111e_priv *lp = netdev_priv(dev); | 1264 | struct amd8111e_priv *lp = netdev_priv(dev); |
1263 | void __iomem *mmio = lp->mmio; | 1265 | void __iomem *mmio = lp->mmio; |
1264 | unsigned int intr0; | 1266 | unsigned int intr0, intren0; |
1265 | unsigned int handled = 1; | 1267 | unsigned int handled = 1; |
1266 | 1268 | ||
1267 | if(dev == NULL) | 1269 | if(unlikely(dev == NULL)) |
1268 | return IRQ_NONE; | 1270 | return IRQ_NONE; |
1269 | 1271 | ||
1270 | if (regs) spin_lock (&lp->lock); | 1272 | spin_lock(&lp->lock); |
1273 | |||
1271 | /* disabling interrupt */ | 1274 | /* disabling interrupt */ |
1272 | writel(INTREN, mmio + CMD0); | 1275 | writel(INTREN, mmio + CMD0); |
1273 | 1276 | ||
1274 | /* Read interrupt status */ | 1277 | /* Read interrupt status */ |
1275 | intr0 = readl(mmio + INT0); | 1278 | intr0 = readl(mmio + INT0); |
1279 | intren0 = readl(mmio + INTEN0); | ||
1276 | 1280 | ||
1277 | /* Process all the INT event until INTR bit is clear. */ | 1281 | /* Process all the INT event until INTR bit is clear. */ |
1278 | 1282 | ||
@@ -1293,11 +1297,11 @@ static irqreturn_t amd8111e_interrupt(int irq, void *dev_id, struct pt_regs *reg | |||
1293 | /* Schedule a polling routine */ | 1297 | /* Schedule a polling routine */ |
1294 | __netif_rx_schedule(dev); | 1298 | __netif_rx_schedule(dev); |
1295 | } | 1299 | } |
1296 | else { | 1300 | else if (intren0 & RINTEN0) { |
1297 | printk("************Driver bug! \ | 1301 | printk("************Driver bug! \ |
1298 | interrupt while in poll\n"); | 1302 | interrupt while in poll\n"); |
1299 | /* Fix by disabling interrupts */ | 1303 | /* Fix by disable receive interrupts */ |
1300 | writel(RINT0, mmio + INT0); | 1304 | writel(RINTEN0, mmio + INTEN0); |
1301 | } | 1305 | } |
1302 | } | 1306 | } |
1303 | #else | 1307 | #else |
@@ -1321,7 +1325,7 @@ static irqreturn_t amd8111e_interrupt(int irq, void *dev_id, struct pt_regs *reg | |||
1321 | err_no_interrupt: | 1325 | err_no_interrupt: |
1322 | writel( VAL0 | INTREN,mmio + CMD0); | 1326 | writel( VAL0 | INTREN,mmio + CMD0); |
1323 | 1327 | ||
1324 | if (regs) spin_unlock(&lp->lock); | 1328 | spin_unlock(&lp->lock); |
1325 | 1329 | ||
1326 | return IRQ_RETVAL(handled); | 1330 | return IRQ_RETVAL(handled); |
1327 | } | 1331 | } |