[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1359641187-17902-2-git-send-email-vipul@chelsio.com>
Date: Thu, 31 Jan 2013 19:36:27 +0530
From: Vipul Pandya <vipul@...lsio.com>
To: netdev@...r.kernel.org
Cc: davem@...emloft.net, divy@...lsio.com, dm@...lsio.com,
leedom@...lsio.com, abhishek@...lsio.com,
Vipul Pandya <vipul@...lsio.com>,
Jay Hernandez <jay@...lsio.com>
Subject: [PATCH net-next 2/2] cxgb4vf: Send Flush Work Request on a TX Queue
Send Flush Work Request on a TX Queue if it has unreclaimed TX Descriptors
and the last time anything was sent on the associated net device was more than
5 seconds in the past, issue a flush request on the TX Queue in order to get
any stranded skb's off the TX Queue.
Signed-off-by: Jay Hernandez <jay@...lsio.com>
Signed-off-by: Vipul Pandya <vipul@...lsio.com>
---
drivers/net/ethernet/chelsio/cxgb4vf/sge.c | 104 ++++++++++++++++++++++++---
1 files changed, 92 insertions(+), 12 deletions(-)
diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/sge.c b/drivers/net/ethernet/chelsio/cxgb4vf/sge.c
index 92170d5..be6ef40 100644
--- a/drivers/net/ethernet/chelsio/cxgb4vf/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb4vf/sge.c
@@ -1969,8 +1969,69 @@ static void sge_rx_timer_cb(unsigned long data)
mod_timer(&s->rx_timer, jiffies + RX_QCHECK_PERIOD);
}
-/**
- * sge_tx_timer_cb - perform periodic maintenance of SGE Tx queues
+/* send_flush_wr - send a Flush Work Request on a TX Queue
+ * @adapter: the adapter
+ * @txq: TX Queue to flush
+ *
+ * Send a Flush Work Request on the indicated TX Queue with a request to
+ * updated the Status Page of the TX Queue when the Flush Work Request
+ * is processed. This will allow us to determine when all of the
+ * preceeding TX Requests have been processed.
+ */
+static void send_flush_wr(struct adapter *adapter, struct sge_eth_txq *txq)
+{
+ int credits;
+ unsigned int ndesc;
+ struct fw_eq_flush_wr *fwr;
+ struct sk_buff *skb;
+ unsigned int len;
+
+ /* See if there's space in the TX Queue to fit the Flush Work Request.
+ * If not, we simply return.
+ */
+ len = sizeof(*fwr);
+ ndesc = DIV_ROUND_UP(len, sizeof(struct tx_desc));
+ credits = txq_avail(&txq->q) - ndesc;
+ if (unlikely(credits < 0))
+ return;
+
+ /* Allocate an skb to hold the Flush Work Request and initialize it
+ * with the flush request.
+ */
+ skb = alloc_skb(len, GFP_ATOMIC);
+ if (unlikely(!skb))
+ return;
+ fwr = (struct fw_eq_flush_wr *)__skb_put(skb, len);
+ memset(fwr, 0, sizeof(*fwr));
+
+ fwr->opcode = (__force __u8) htonl(FW_WR_OP(FW_EQ_FLUSH_WR));
+ fwr->equiq_to_len16 = cpu_to_be32(FW_WR_EQUEQ |
+ FW_WR_LEN16(len / 16));
+
+ /* If the Flush Work Request fills up the TX Queue to the point where
+ * we don't have enough room for a maximum sized TX Request, then
+ * we need to stop further TX Requests and request that the firmware
+ * notify us with an interrupt when it processes this request.
+ */
+ if (unlikely(credits < ETHTXQ_STOP_THRES)) {
+ txq_stop(txq);
+ fwr->equiq_to_len16 |= cpu_to_be32(FW_WR_EQUIQ);
+ }
+
+ /* Copy the Flush Work Request into the TX Queue and notify the
+ * hardware that we've given it some more to do ...
+ */
+ inline_tx_skb(skb, &txq->q, &txq->q.desc[txq->q.pidx]);
+ txq_advance(&txq->q, ndesc);
+ ring_tx_db(adapter, &txq->q, ndesc);
+
+ /* Free up the skb and return ...
+ */
+ kfree_skb(skb);
+ return;
+}
+
+/* sge_tx_timer_cb - perform periodic maintenance of SGE Tx queues
* @data: the adapter
*
* Runs periodically from a timer to perform maintenance of SGE TX queues.
@@ -1991,19 +2052,38 @@ static void sge_tx_timer_cb(unsigned long data)
do {
struct sge_eth_txq *txq = &s->ethtxq[i];
- if (reclaimable(&txq->q) && __netif_tx_trylock(txq->txq)) {
- int avail = reclaimable(&txq->q);
+ if (__netif_tx_trylock(txq->txq)) {
- if (avail > budget)
- avail = budget;
+ if (reclaimable(&txq->q)) {
+ int avail = reclaimable(&txq->q);
- free_tx_desc(adapter, &txq->q, avail, true);
- txq->q.in_use -= avail;
- __netif_tx_unlock(txq->txq);
+ if (avail > budget)
+ avail = budget;
+
+ free_tx_desc(adapter, &txq->q, avail, true);
+ txq->q.in_use -= avail;
- budget -= avail;
- if (!budget)
- break;
+ budget -= avail;
+ if (!budget) {
+ __netif_tx_unlock(txq->txq);
+ break;
+ }
+ }
+
+ /* If the TX Queue has unreclaimed TX Descriptors and
+ * the last time anything was sent on the associated
+ * net device was more than 5 seconds in the past,
+ * issue a flush request on the TX Queue in order to
+ * get any stranded skb's off the TX Queue.
+ */
+ if (txq->q.in_use > 0 &&
+ time_after(jiffies,
+ txq->txq->dev->trans_start + HZ * 5)) {
+ local_bh_disable();
+ send_flush_wr(adapter, txq);
+ local_bh_enable();
+ }
+ __netif_tx_unlock(txq->txq);
}
i++;
--
1.7.1
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists