Commit 529f1f65 authored by Alexander Duyck's avatar Alexander Duyck Committed by Jeff Kirsher

i40e/i40evf: Add exception handling for Tx checksum

Add exception handling to the Tx checksum path so that we can handle cases
of TSO where the frame is bad, or Tx checksum where we didn't recognize a
protocol

Drop I40E_TX_FLAGS_CSUM as it is unused, move the CHECKSUM_PARTIAL check
into the function itself so that we can decrease indent.
Signed-off-by: default avatarAlexander Duyck <aduyck@mirantis.com>
Tested-by: default avatarAndrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent 475b4205
...@@ -2387,10 +2387,10 @@ static int i40e_tsyn(struct i40e_ring *tx_ring, struct sk_buff *skb, ...@@ -2387,10 +2387,10 @@ static int i40e_tsyn(struct i40e_ring *tx_ring, struct sk_buff *skb,
* @tx_ring: Tx descriptor ring * @tx_ring: Tx descriptor ring
* @cd_tunneling: ptr to context desc bits * @cd_tunneling: ptr to context desc bits
**/ **/
static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags, static int i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
u32 *td_cmd, u32 *td_offset, u32 *td_cmd, u32 *td_offset,
struct i40e_ring *tx_ring, struct i40e_ring *tx_ring,
u32 *cd_tunneling) u32 *cd_tunneling)
{ {
union { union {
struct iphdr *v4; struct iphdr *v4;
...@@ -2407,6 +2407,9 @@ static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags, ...@@ -2407,6 +2407,9 @@ static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
__be16 frag_off; __be16 frag_off;
u8 l4_proto = 0; u8 l4_proto = 0;
if (skb->ip_summed != CHECKSUM_PARTIAL)
return 0;
ip.hdr = skb_network_header(skb); ip.hdr = skb_network_header(skb);
l4.hdr = skb_transport_header(skb); l4.hdr = skb_transport_header(skb);
...@@ -2449,7 +2452,11 @@ static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags, ...@@ -2449,7 +2452,11 @@ static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
*tx_flags |= I40E_TX_FLAGS_UDP_TUNNEL; *tx_flags |= I40E_TX_FLAGS_UDP_TUNNEL;
break; break;
default: default:
return; if (*tx_flags & I40E_TX_FLAGS_TSO)
return -1;
skb_checksum_help(skb);
return 0;
} }
/* compute tunnel header size */ /* compute tunnel header size */
...@@ -2513,11 +2520,16 @@ static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags, ...@@ -2513,11 +2520,16 @@ static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
I40E_TX_DESC_LENGTH_L4_FC_LEN_SHIFT; I40E_TX_DESC_LENGTH_L4_FC_LEN_SHIFT;
break; break;
default: default:
break; if (*tx_flags & I40E_TX_FLAGS_TSO)
return -1;
skb_checksum_help(skb);
return 0;
} }
*td_cmd |= cmd; *td_cmd |= cmd;
*td_offset |= offset; *td_offset |= offset;
return 1;
} }
/** /**
...@@ -2954,12 +2966,10 @@ static netdev_tx_t i40e_xmit_frame_ring(struct sk_buff *skb, ...@@ -2954,12 +2966,10 @@ static netdev_tx_t i40e_xmit_frame_ring(struct sk_buff *skb,
td_cmd |= I40E_TX_DESC_CMD_ICRC; td_cmd |= I40E_TX_DESC_CMD_ICRC;
/* Always offload the checksum, since it's in the data descriptor */ /* Always offload the checksum, since it's in the data descriptor */
if (skb->ip_summed == CHECKSUM_PARTIAL) { tso = i40e_tx_enable_csum(skb, &tx_flags, &td_cmd, &td_offset,
tx_flags |= I40E_TX_FLAGS_CSUM; tx_ring, &cd_tunneling);
if (tso < 0)
i40e_tx_enable_csum(skb, &tx_flags, &td_cmd, &td_offset, goto out_drop;
tx_ring, &cd_tunneling);
}
i40e_create_tx_ctx(tx_ring, cd_type_cmd_tso_mss, i40e_create_tx_ctx(tx_ring, cd_type_cmd_tso_mss,
cd_tunneling, cd_l2tag2); cd_tunneling, cd_l2tag2);
......
...@@ -153,7 +153,6 @@ enum i40e_dyn_idx_t { ...@@ -153,7 +153,6 @@ enum i40e_dyn_idx_t {
#define DESC_NEEDED (MAX_SKB_FRAGS + 4) #define DESC_NEEDED (MAX_SKB_FRAGS + 4)
#define I40E_MIN_DESC_PENDING 4 #define I40E_MIN_DESC_PENDING 4
#define I40E_TX_FLAGS_CSUM BIT(0)
#define I40E_TX_FLAGS_HW_VLAN BIT(1) #define I40E_TX_FLAGS_HW_VLAN BIT(1)
#define I40E_TX_FLAGS_SW_VLAN BIT(2) #define I40E_TX_FLAGS_SW_VLAN BIT(2)
#define I40E_TX_FLAGS_TSO BIT(3) #define I40E_TX_FLAGS_TSO BIT(3)
......
...@@ -1602,12 +1602,13 @@ static int i40e_tso(struct i40e_ring *tx_ring, struct sk_buff *skb, ...@@ -1602,12 +1602,13 @@ static int i40e_tso(struct i40e_ring *tx_ring, struct sk_buff *skb,
* @tx_flags: pointer to Tx flags currently set * @tx_flags: pointer to Tx flags currently set
* @td_cmd: Tx descriptor command bits to set * @td_cmd: Tx descriptor command bits to set
* @td_offset: Tx descriptor header offsets to set * @td_offset: Tx descriptor header offsets to set
* @tx_ring: Tx descriptor ring
* @cd_tunneling: ptr to context desc bits * @cd_tunneling: ptr to context desc bits
**/ **/
static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags, static int i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
u32 *td_cmd, u32 *td_offset, u32 *td_cmd, u32 *td_offset,
struct i40e_ring *tx_ring, struct i40e_ring *tx_ring,
u32 *cd_tunneling) u32 *cd_tunneling)
{ {
union { union {
struct iphdr *v4; struct iphdr *v4;
...@@ -1624,6 +1625,9 @@ static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags, ...@@ -1624,6 +1625,9 @@ static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
__be16 frag_off; __be16 frag_off;
u8 l4_proto = 0; u8 l4_proto = 0;
if (skb->ip_summed != CHECKSUM_PARTIAL)
return 0;
ip.hdr = skb_network_header(skb); ip.hdr = skb_network_header(skb);
l4.hdr = skb_transport_header(skb); l4.hdr = skb_transport_header(skb);
...@@ -1666,7 +1670,11 @@ static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags, ...@@ -1666,7 +1670,11 @@ static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
*tx_flags |= I40E_TX_FLAGS_VXLAN_TUNNEL; *tx_flags |= I40E_TX_FLAGS_VXLAN_TUNNEL;
break; break;
default: default:
return; if (*tx_flags & I40E_TX_FLAGS_TSO)
return -1;
skb_checksum_help(skb);
return 0;
} }
/* compute tunnel header size */ /* compute tunnel header size */
...@@ -1730,11 +1738,16 @@ static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags, ...@@ -1730,11 +1738,16 @@ static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
I40E_TX_DESC_LENGTH_L4_FC_LEN_SHIFT; I40E_TX_DESC_LENGTH_L4_FC_LEN_SHIFT;
break; break;
default: default:
break; if (*tx_flags & I40E_TX_FLAGS_TSO)
return -1;
skb_checksum_help(skb);
return 0;
} }
*td_cmd |= cmd; *td_cmd |= cmd;
*td_offset |= offset; *td_offset |= offset;
return 1;
} }
/** /**
...@@ -2150,12 +2163,10 @@ static netdev_tx_t i40e_xmit_frame_ring(struct sk_buff *skb, ...@@ -2150,12 +2163,10 @@ static netdev_tx_t i40e_xmit_frame_ring(struct sk_buff *skb,
td_cmd |= I40E_TX_DESC_CMD_ICRC; td_cmd |= I40E_TX_DESC_CMD_ICRC;
/* Always offload the checksum, since it's in the data descriptor */ /* Always offload the checksum, since it's in the data descriptor */
if (skb->ip_summed == CHECKSUM_PARTIAL) { tso = i40e_tx_enable_csum(skb, &tx_flags, &td_cmd, &td_offset,
tx_flags |= I40E_TX_FLAGS_CSUM; tx_ring, &cd_tunneling);
if (tso < 0)
i40e_tx_enable_csum(skb, &tx_flags, &td_cmd, &td_offset, goto out_drop;
tx_ring, &cd_tunneling);
}
i40e_create_tx_ctx(tx_ring, cd_type_cmd_tso_mss, i40e_create_tx_ctx(tx_ring, cd_type_cmd_tso_mss,
cd_tunneling, cd_l2tag2); cd_tunneling, cd_l2tag2);
......
...@@ -153,7 +153,6 @@ enum i40e_dyn_idx_t { ...@@ -153,7 +153,6 @@ enum i40e_dyn_idx_t {
#define DESC_NEEDED (MAX_SKB_FRAGS + 4) #define DESC_NEEDED (MAX_SKB_FRAGS + 4)
#define I40E_MIN_DESC_PENDING 4 #define I40E_MIN_DESC_PENDING 4
#define I40E_TX_FLAGS_CSUM BIT(0)
#define I40E_TX_FLAGS_HW_VLAN BIT(1) #define I40E_TX_FLAGS_HW_VLAN BIT(1)
#define I40E_TX_FLAGS_SW_VLAN BIT(2) #define I40E_TX_FLAGS_SW_VLAN BIT(2)
#define I40E_TX_FLAGS_TSO BIT(3) #define I40E_TX_FLAGS_TSO BIT(3)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment