lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date:	Thu, 31 Jan 2013 19:36:26 +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 1/2] cxgb4: 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/cxgb4/sge.c      |  112 +++++++++++++++++++++++--
 drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h |    8 ++
 2 files changed, 113 insertions(+), 7 deletions(-)

diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c
index fe9a2ea..d6cfdd5 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c
@@ -1994,6 +1994,81 @@ static void sge_rx_timer_cb(unsigned long data)
 	mod_timer(&s->rx_timer, jiffies + RX_QCHECK_PERIOD);
 }
 
+/*	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)) {
+		eth_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.
+ *	It performs two tasks:
+ *
+ *	a) Restarts offload Tx queues stopped due to I/O MMU mapping errors.
+ *
+ *	b) Reclaims completed Tx packets for the Ethernet queues.  Normally
+ *	packets are cleaned up by new Tx packets, this timer cleans up packets
+ *	when no new packets are being submitted.  This is essential for pktgen,
+ *	at least.
+ */
 static void sge_tx_timer_cb(unsigned long data)
 {
 	unsigned long m;
@@ -2015,26 +2090,49 @@ static void sge_tx_timer_cb(unsigned long data)
 	do {
 		struct sge_eth_txq *q = &s->ethtxq[i];
 
-		if (q->q.in_use &&
-		    time_after_eq(jiffies, q->txq->trans_start + HZ / 100) &&
-		    __netif_tx_trylock(q->txq)) {
-			int avail = reclaimable(&q->q);
+		if (__netif_tx_trylock(q->txq)) {
 
-			if (avail) {
+			if (reclaimable(&q->q)) {
+				int avail = reclaimable(&q->q);
 				if (avail > budget)
 					avail = budget;
 
 				free_tx_desc(adap, &q->q, avail, true);
 				q->q.in_use -= avail;
+
 				budget -= avail;
+				if (!budget) {
+					__netif_tx_unlock(q->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 (q->q.in_use > 0 &&
+			    time_after(jiffies,
+				       q->txq->dev->trans_start + HZ * 5)) {
+				local_bh_disable();
+				send_flush_wr(adap, q);
+				local_bh_enable();
 			}
 			__netif_tx_unlock(q->txq);
 		}
 
-		if (++i >= s->ethqsets)
+		i++;
+		if (i >= s->ethqsets)
 			i = 0;
-	} while (budget && i != s->ethtxq_rover);
+	} while (i != s->ethtxq_rover);
 	s->ethtxq_rover = i;
+
+	/* If we found too many reclaimable packets schedule a timer in the
+	 * near future to continue where we left off.  Otherwise the next timer
+	 * will be at its normal interval.
+	 */
 	mod_timer(&s->tx_timer, jiffies + (budget ? TX_QCHECK_PERIOD : 2));
 }
 
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
index a0dcccd..db31bd6 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
@@ -85,6 +85,7 @@ enum fw_wr_opcodes {
 	FW_ULPTX_WR                    = 0x04,
 	FW_TP_WR                       = 0x05,
 	FW_ETH_TX_PKT_WR               = 0x08,
+	FW_EQ_FLUSH_WR                 = 0x1b,
 	FW_OFLD_CONNECTION_WR          = 0x2f,
 	FW_FLOWC_WR                    = 0x0a,
 	FW_OFLD_TX_DATA_WR             = 0x0b,
@@ -416,6 +417,13 @@ struct fw_eth_tx_pkt_wr {
 	__be64 r3;
 };
 
+struct fw_eq_flush_wr {
+	__u8   opcode;
+	__u8   r1[3];
+	__be32 equiq_to_len16;
+	__be64 r3;
+};
+
 struct fw_ofld_connection_wr {
 	__be32 op_compl;
 	__be32 len16_pkd;
-- 
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