diff options
-rw-r--r-- | drivers/net/forcedeth.c | 18 |
1 files changed, 12 insertions, 6 deletions
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 7c0f0ccbbb2..ae6cf7827e5 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -210,7 +210,7 @@ enum { * NVREG_POLL_DEFAULT=97 would result in an interval length of 1 ms */ NvRegPollingInterval = 0x00c, -#define NVREG_POLL_DEFAULT_THROUGHPUT 970 +#define NVREG_POLL_DEFAULT_THROUGHPUT 970 /* backup tx cleanup if loop max reached */ #define NVREG_POLL_DEFAULT_CPU 13 NvRegMSIMap0 = 0x020, NvRegMSIMap1 = 0x024, @@ -1859,14 +1859,15 @@ static void nv_tx_done(struct net_device *dev) } } -static void nv_tx_done_optimized(struct net_device *dev) +static void nv_tx_done_optimized(struct net_device *dev, int limit) { struct fe_priv *np = netdev_priv(dev); u32 flags; struct ring_desc_ex* orig_get_tx = np->get_tx.ex; while ((np->get_tx.ex != np->put_tx.ex) && - !((flags = le32_to_cpu(np->get_tx.ex->flaglen)) & NV_TX_VALID)) { + !((flags = le32_to_cpu(np->get_tx.ex->flaglen)) & NV_TX_VALID) && + (limit-- > 0)) { dprintk(KERN_DEBUG "%s: nv_tx_done_optimized: flags 0x%x.\n", dev->name, flags); @@ -1973,7 +1974,7 @@ static void nv_tx_timeout(struct net_device *dev) if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) nv_tx_done(dev); else - nv_tx_done_optimized(dev); + nv_tx_done_optimized(dev, np->tx_ring_size); /* 3) if there are dead entries: clear everything */ if (np->get_tx_ctx != np->put_tx_ctx) { @@ -2899,7 +2900,7 @@ static irqreturn_t nv_nic_irq_optimized(int foo, void *data) break; spin_lock(&np->lock); - nv_tx_done_optimized(dev); + nv_tx_done_optimized(dev, TX_WORK_PER_LOOP); spin_unlock(&np->lock); #ifdef CONFIG_FORCEDETH_NAPI @@ -3006,7 +3007,7 @@ static irqreturn_t nv_nic_irq_tx(int foo, void *data) break; spin_lock_irqsave(&np->lock, flags); - nv_tx_done_optimized(dev); + nv_tx_done_optimized(dev, TX_WORK_PER_LOOP); spin_unlock_irqrestore(&np->lock, flags); if (unlikely(events & (NVREG_IRQ_TX_ERR))) { @@ -3163,6 +3164,11 @@ static irqreturn_t nv_nic_irq_other(int foo, void *data) if (!(events & np->irqmask)) break; + /* check tx in case we reached max loop limit in tx isr */ + spin_lock_irqsave(&np->lock, flags); + nv_tx_done_optimized(dev, TX_WORK_PER_LOOP); + spin_unlock_irqrestore(&np->lock, flags); + if (events & NVREG_IRQ_LINK) { spin_lock_irqsave(&np->lock, flags); nv_link_irq(dev); |