summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorDivy Le Ray <divy@chelsio.com>2007-02-24 16:44:12 -0800
committerJeff Garzik <jeff@garzik.org>2007-02-27 04:27:12 -0500
commitbae73f44472921008f8d0982344c53ae231445a1 (patch)
tree11d1fe507ac8e179803c9468791952c9c217f66b /drivers
parent99d7cf30b99a8b7863090d8a510d6a4d9ad082cf (diff)
downloadlinux-bae73f44472921008f8d0982344c53ae231445a1.tar.gz
cxgb3 - Recovery from HW starvation of response queue entries.
Improve the traffic recovery after the HW ran out of response queue entries. Signed-off-by: Divy Le Ray <divy@chelsio.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/cxgb3/adapter.h2
-rw-r--r--drivers/net/cxgb3/sge.c15
2 files changed, 16 insertions, 1 deletions
diff --git a/drivers/net/cxgb3/adapter.h b/drivers/net/cxgb3/adapter.h
index 5c97a64451ce..01b99b901434 100644
--- a/drivers/net/cxgb3/adapter.h
+++ b/drivers/net/cxgb3/adapter.h
@@ -121,6 +121,8 @@ struct sge_rspq { /* state for an SGE response queue */
unsigned long empty; /* # of times queue ran out of credits */
unsigned long nomem; /* # of responses deferred due to no mem */
unsigned long unhandled_irqs; /* # of spurious intrs */
+ unsigned long starved;
+ unsigned long restarted;
};
struct tx_desc;
diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c
index 822a598c0db1..4ff0ab60c6c7 100644
--- a/drivers/net/cxgb3/sge.c
+++ b/drivers/net/cxgb3/sge.c
@@ -2376,13 +2376,26 @@ static void sge_timer_cb(unsigned long data)
spin_unlock(&qs->txq[TXQ_OFLD].lock);
}
lock = (adap->flags & USING_MSIX) ? &qs->rspq.lock :
- &adap->sge.qs[0].rspq.lock;
+ &adap->sge.qs[0].rspq.lock;
if (spin_trylock_irq(lock)) {
if (!napi_is_scheduled(qs->netdev)) {
+ u32 status = t3_read_reg(adap, A_SG_RSPQ_FL_STATUS);
+
if (qs->fl[0].credits < qs->fl[0].size)
__refill_fl(adap, &qs->fl[0]);
if (qs->fl[1].credits < qs->fl[1].size)
__refill_fl(adap, &qs->fl[1]);
+
+ if (status & (1 << qs->rspq.cntxt_id)) {
+ qs->rspq.starved++;
+ if (qs->rspq.credits) {
+ refill_rspq(adap, &qs->rspq, 1);
+ qs->rspq.credits--;
+ qs->rspq.restarted++;
+ t3_write_reg(adap, A_SG_RSPQ_FL_STATUS,
+ 1 << qs->rspq.cntxt_id);
+ }
+ }
}
spin_unlock_irq(lock);
}