Thread (5 messages) 5 messages, 3 authors, 2013-11-29

Re: [PATCH] net: 8139cp: fix a BUG_ON triggered by wrong bytes_compl

From: Yang Yingliang <hidden>
Date: 2013-11-27 06:05:30

On 2013/11/27 12:35, Eric Dumazet wrote:
On Wed, 2013-11-27 at 12:07 +0800, Yang Yingliang wrote:
quoted
Using iperf to send packets(GSO mode is on), a bug is triggered:
quoted
When a skb has frags, bytes_compl plus skb->len nr_frags times in cp_tx().
It's not the correct value(actually, it should plus skb->len once) and it
will trigger the BUG_ON(bytes_compl > num_queued - dql->num_completed).Use
txd->opts1 which stores the real length of a frag in cp_start_xmit() to
calculate bytes_compl.
pkts_compl also has a wrong value, fix it too.

It's introduced by commit 871f0d4c("8139cp: enable bql").

Signed-off-by: Yang Yingliang <redacted>
---
 drivers/net/ethernet/realtek/8139cp.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c
index f2a2128..3b837f0 100644
--- a/drivers/net/ethernet/realtek/8139cp.c
+++ b/drivers/net/ethernet/realtek/8139cp.c
@@ -664,7 +664,7 @@ static void cp_tx (struct cp_private *cp)
 	while (tx_tail != tx_head) {
 		struct cp_desc *txd = cp->tx_ring + tx_tail;
 		struct sk_buff *skb;
-		u32 status;
+		u32 status, flags;
 
 		rmb();
 		status = le32_to_cpu(txd->opts1);
@@ -678,8 +678,10 @@ static void cp_tx (struct cp_private *cp)
 				 le32_to_cpu(txd->opts1) & 0xffff,
 				 PCI_DMA_TODEVICE);
 
-		bytes_compl += skb->len;
-		pkts_compl++;
+		flags = le32_to_cpu(txd->opts1);
Why not using 'status' here, its the same value.
quoted
+		bytes_compl += (flags & 0xffff);
+		if (flags & FirstFrag)
+			pkts_compl++;
 
 		if (status & LastFrag) {
 			if (status & (TxError | TxFIFOUnder)) {
I dont know, this seems a bit convoluted and dangerous, as
cp_start_xmit() did :

netdev_sent_queue(dev, skb->len);
I tried to let pkts_compl equals sum of every frags' length.
Your way looks more simpler. I'll post an updated version of
the patch as you suggested.

Thanks!
quoted hunk ↗ jump to hunk
So I would just use :
diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c
index f2a2128165dd..4a935a966e28 100644
--- a/drivers/net/ethernet/realtek/8139cp.c
+++ b/drivers/net/ethernet/realtek/8139cp.c
@@ -678,8 +678,6 @@ static void cp_tx (struct cp_private *cp)
 				 le32_to_cpu(txd->opts1) & 0xffff,
 				 PCI_DMA_TODEVICE);
 
-		bytes_compl += skb->len;
-		pkts_compl++;
 
 		if (status & LastFrag) {
 			if (status & (TxError | TxFIFOUnder)) {
@@ -702,6 +700,8 @@ static void cp_tx (struct cp_private *cp)
 				netif_dbg(cp, tx_done, cp->dev,
 					  "tx done, slot %d\n", tx_tail);
 			}
+			bytes_compl += skb->len;
+			pkts_compl++;
 			dev_kfree_skb_irq(skb);
 		}
 


.
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help