diff mbox

[4/7] 8139cp: Fix TSO/scatter-gather descriptor setup

Message ID 1442844165.7367.14.camel@infradead.org
State Not Applicable, archived
Delegated to: David Miller
Headers show

Commit Message

David Woodhouse Sept. 21, 2015, 2:02 p.m. UTC
From: David Woodhouse <David.Woodhouse@intel.com>

When sending a TSO frame in multiple buffers, we were neglecting to set
the first descriptor up in TSO mode.

Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
---
 drivers/net/ethernet/realtek/8139cp.c | 23 +++++++++++------------
 1 file changed, 11 insertions(+), 12 deletions(-)

Comments

Francois Romieu Sept. 21, 2015, 9:01 p.m. UTC | #1
David Woodhouse <dwmw2@infradead.org> :
[...]
> diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c
> index 058f835..07621b5 100644
> --- a/drivers/net/ethernet/realtek/8139cp.c
> +++ b/drivers/net/ethernet/realtek/8139cp.c
[...]
> @@ -865,20 +864,20 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb,
>  		txd->addr = cpu_to_le64(first_mapping);
>  		wmb();
>  
> -		if (skb->ip_summed == CHECKSUM_PARTIAL) {
> +		ctrl = first_eor | first_len | FirstFrag | DescOwn;
> +		if (mss)
> +			ctrl |= LargeSend |
> +				((mss & MSSMask) << MSSShift);

			ctrl |= LargeSend | ((mss & MSSMask) << MSSShift);

> +		else if (skb->ip_summed == CHECKSUM_PARTIAL) {
>  			if (ip->protocol == IPPROTO_TCP)
> -				txd->opts1 = cpu_to_le32(first_eor | first_len |
> -							 FirstFrag | DescOwn |
> -							 IPCS | TCPCS);
> +				ctrl |= IPCS | TCPCS;
>  			else if (ip->protocol == IPPROTO_UDP)
> -				txd->opts1 = cpu_to_le32(first_eor | first_len |
> -							 FirstFrag | DescOwn |
> -							 IPCS | UDPCS);
> +				ctrl |= IPCS | UDPCS;
>  			else
>  				BUG();

Can you pile a patch to replace BUG with WARN_ON_ONCE(1) ?
David Woodhouse Sept. 21, 2015, 9:06 p.m. UTC | #2
On Mon, 2015-09-21 at 23:01 +0200, Francois Romieu wrote:
> Can you pile a patch to replace BUG with WARN_ON_ONCE(1) ?

OK. I can probably contrive a userspace program using AF_PACKET and
PACKET_VNET_HDR to trigger it, too¹ :)
diff mbox

Patch

diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c
index 058f835..07621b5 100644
--- a/drivers/net/ethernet/realtek/8139cp.c
+++ b/drivers/net/ethernet/realtek/8139cp.c
@@ -797,7 +797,7 @@  static netdev_tx_t cp_start_xmit (struct sk_buff *skb,
 			  entry, skb->len);
 	} else {
 		struct cp_desc *txd;
-		u32 first_len, first_eor;
+		u32 first_len, first_eor, ctrl;
 		dma_addr_t first_mapping;
 		int frag, first_entry = entry;
 		const struct iphdr *ip = ip_hdr(skb);
@@ -817,7 +817,6 @@  static netdev_tx_t cp_start_xmit (struct sk_buff *skb,
 		for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) {
 			const skb_frag_t *this_frag = &skb_shinfo(skb)->frags[frag];
 			u32 len;
-			u32 ctrl;
 			dma_addr_t mapping;
 
 			entry = NEXT_TX(entry);
@@ -865,20 +864,20 @@  static netdev_tx_t cp_start_xmit (struct sk_buff *skb,
 		txd->addr = cpu_to_le64(first_mapping);
 		wmb();
 
-		if (skb->ip_summed == CHECKSUM_PARTIAL) {
+		ctrl = first_eor | first_len | FirstFrag | DescOwn;
+		if (mss)
+			ctrl |= LargeSend |
+				((mss & MSSMask) << MSSShift);
+		else if (skb->ip_summed == CHECKSUM_PARTIAL) {
 			if (ip->protocol == IPPROTO_TCP)
-				txd->opts1 = cpu_to_le32(first_eor | first_len |
-							 FirstFrag | DescOwn |
-							 IPCS | TCPCS);
+				ctrl |= IPCS | TCPCS;
 			else if (ip->protocol == IPPROTO_UDP)
-				txd->opts1 = cpu_to_le32(first_eor | first_len |
-							 FirstFrag | DescOwn |
-							 IPCS | UDPCS);
+				ctrl |= IPCS | UDPCS;
 			else
 				BUG();
-		} else
-			txd->opts1 = cpu_to_le32(first_eor | first_len |
-						 FirstFrag | DescOwn);
+		}
+
+		txd->opts1 = cpu_to_le32(ctrl);
 		wmb();
 
 		netif_dbg(cp, tx_queued, cp->dev, "tx queued, slots %d-%d, skblen %d\n",