aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Duyck <aduyck@mirantis.com>2016-01-13 10:31:11 -0500
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2016-04-04 20:39:05 -0400
commit49763de0425560eed50a186428010189eae69372 (patch)
tree2d42d3f263695e4d5857962534e6caa22ea1e8cc
parentc7374b5a767cb6c7d9acbfc82656dc89afeae257 (diff)
ixgbe: Add support for generic Tx checksums
This patch adds support for generic Tx checksums to the ixgbe driver. It turns out this is actually pretty easy after going over the datasheet as we were doing a number of steps we didn't need to. In order to perform a Tx checksum for an L4 header we need to fill in the following fields in the Tx descriptor: MACLEN (maximum of 127), retrieved from: skb_network_offset() IPLEN (maximum of 511), retrieved from: skb_checksum_start_offset() - skb_network_offset() TUCMD.L4T indicates offset and if checksum or crc32c, based on: skb->csum_offset The added advantage to doing this is that we can support inner checksum offloads for tunnels and MPLS while still being able to transparently insert VLAN tags. I also took the opportunity to clean-up many of the feature flag configuration bits to make them a bit more consistent between drivers. Signed-off-by: Alexander Duyck <aduyck@mirantis.com> Tested-by: Andrew Bowers <andrewx.bowers@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_main.c162
1 files changed, 58 insertions, 104 deletions
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index bce5737b1a96..0f007d9a2a13 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -7202,103 +7202,61 @@ static int ixgbe_tso(struct ixgbe_ring *tx_ring,
7202 return 1; 7202 return 1;
7203} 7203}
7204 7204
7205static inline bool ixgbe_ipv6_csum_is_sctp(struct sk_buff *skb)
7206{
7207 unsigned int offset = 0;
7208
7209 ipv6_find_hdr(skb, &offset, IPPROTO_SCTP, NULL, NULL);
7210
7211 return offset == skb_checksum_start_offset(skb);
7212}
7213
7205static void ixgbe_tx_csum(struct ixgbe_ring *tx_ring, 7214static void ixgbe_tx_csum(struct ixgbe_ring *tx_ring,
7206 struct ixgbe_tx_buffer *first) 7215 struct ixgbe_tx_buffer *first)
7207{ 7216{
7208 struct sk_buff *skb = first->skb; 7217 struct sk_buff *skb = first->skb;
7209 u32 vlan_macip_lens = 0; 7218 u32 vlan_macip_lens = 0;
7210 u32 mss_l4len_idx = 0;
7211 u32 type_tucmd = 0; 7219 u32 type_tucmd = 0;
7212 7220
7213 if (skb->ip_summed != CHECKSUM_PARTIAL) { 7221 if (skb->ip_summed != CHECKSUM_PARTIAL) {
7214 if (!(first->tx_flags & IXGBE_TX_FLAGS_HW_VLAN) && 7222csum_failed:
7215 !(first->tx_flags & IXGBE_TX_FLAGS_CC)) 7223 if (!(first->tx_flags & (IXGBE_TX_FLAGS_HW_VLAN |
7224 IXGBE_TX_FLAGS_CC)))
7216 return; 7225 return;
7217 vlan_macip_lens = skb_network_offset(skb) << 7226 goto no_csum;
7218 IXGBE_ADVTXD_MACLEN_SHIFT; 7227 }
7219 } else {
7220 u8 l4_hdr = 0;
7221 union {
7222 struct iphdr *ipv4;
7223 struct ipv6hdr *ipv6;
7224 u8 *raw;
7225 } network_hdr;
7226 union {
7227 struct tcphdr *tcphdr;
7228 u8 *raw;
7229 } transport_hdr;
7230 __be16 frag_off;
7231
7232 if (skb->encapsulation) {
7233 network_hdr.raw = skb_inner_network_header(skb);
7234 transport_hdr.raw = skb_inner_transport_header(skb);
7235 vlan_macip_lens = skb_inner_network_offset(skb) <<
7236 IXGBE_ADVTXD_MACLEN_SHIFT;
7237 } else {
7238 network_hdr.raw = skb_network_header(skb);
7239 transport_hdr.raw = skb_transport_header(skb);
7240 vlan_macip_lens = skb_network_offset(skb) <<
7241 IXGBE_ADVTXD_MACLEN_SHIFT;
7242 }
7243 7228
7244 /* use first 4 bits to determine IP version */ 7229 switch (skb->csum_offset) {
7245 switch (network_hdr.ipv4->version) { 7230 case offsetof(struct tcphdr, check):
7246 case IPVERSION: 7231 type_tucmd = IXGBE_ADVTXD_TUCMD_L4T_TCP;
7247 vlan_macip_lens |= transport_hdr.raw - network_hdr.raw; 7232 /* fall through */
7248 type_tucmd |= IXGBE_ADVTXD_TUCMD_IPV4; 7233 case offsetof(struct udphdr, check):
7249 l4_hdr = network_hdr.ipv4->protocol; 7234 break;
7250 break; 7235 case offsetof(struct sctphdr, checksum):
7251 case 6: 7236 /* validate that this is actually an SCTP request */
7252 vlan_macip_lens |= transport_hdr.raw - network_hdr.raw; 7237 if (((first->protocol == htons(ETH_P_IP)) &&
7253 l4_hdr = network_hdr.ipv6->nexthdr; 7238 (ip_hdr(skb)->protocol == IPPROTO_SCTP)) ||
7254 if (likely((transport_hdr.raw - network_hdr.raw) == 7239 ((first->protocol == htons(ETH_P_IPV6)) &&
7255 sizeof(struct ipv6hdr))) 7240 ixgbe_ipv6_csum_is_sctp(skb))) {
7256 break; 7241 type_tucmd = IXGBE_ADVTXD_TUCMD_L4T_SCTP;
7257 ipv6_skip_exthdr(skb, network_hdr.raw - skb->data +
7258 sizeof(struct ipv6hdr),
7259 &l4_hdr, &frag_off);
7260 if (unlikely(frag_off))
7261 l4_hdr = NEXTHDR_FRAGMENT;
7262 break;
7263 default:
7264 break; 7242 break;
7265 } 7243 }
7266 7244 /* fall through */
7267 switch (l4_hdr) { 7245 default:
7268 case IPPROTO_TCP: 7246 skb_checksum_help(skb);
7269 type_tucmd |= IXGBE_ADVTXD_TUCMD_L4T_TCP; 7247 goto csum_failed;
7270 mss_l4len_idx = (transport_hdr.tcphdr->doff * 4) <<
7271 IXGBE_ADVTXD_L4LEN_SHIFT;
7272 break;
7273 case IPPROTO_SCTP:
7274 type_tucmd |= IXGBE_ADVTXD_TUCMD_L4T_SCTP;
7275 mss_l4len_idx = sizeof(struct sctphdr) <<
7276 IXGBE_ADVTXD_L4LEN_SHIFT;
7277 break;
7278 case IPPROTO_UDP:
7279 mss_l4len_idx = sizeof(struct udphdr) <<
7280 IXGBE_ADVTXD_L4LEN_SHIFT;
7281 break;
7282 default:
7283 if (unlikely(net_ratelimit())) {
7284 dev_warn(tx_ring->dev,
7285 "partial checksum, version=%d, l4 proto=%x\n",
7286 network_hdr.ipv4->version, l4_hdr);
7287 }
7288 skb_checksum_help(skb);
7289 goto no_csum;
7290 }
7291
7292 /* update TX checksum flag */
7293 first->tx_flags |= IXGBE_TX_FLAGS_CSUM;
7294 } 7248 }
7295 7249
7250 /* update TX checksum flag */
7251 first->tx_flags |= IXGBE_TX_FLAGS_CSUM;
7252 vlan_macip_lens = skb_checksum_start_offset(skb) -
7253 skb_network_offset(skb);
7296no_csum: 7254no_csum:
7297 /* vlan_macip_lens: MACLEN, VLAN tag */ 7255 /* vlan_macip_lens: MACLEN, VLAN tag */
7256 vlan_macip_lens |= skb_network_offset(skb) << IXGBE_ADVTXD_MACLEN_SHIFT;
7298 vlan_macip_lens |= first->tx_flags & IXGBE_TX_FLAGS_VLAN_MASK; 7257 vlan_macip_lens |= first->tx_flags & IXGBE_TX_FLAGS_VLAN_MASK;
7299 7258
7300 ixgbe_tx_ctxtdesc(tx_ring, vlan_macip_lens, 0, 7259 ixgbe_tx_ctxtdesc(tx_ring, vlan_macip_lens, 0, type_tucmd, 0);
7301 type_tucmd, mss_l4len_idx);
7302} 7260}
7303 7261
7304#define IXGBE_SET_FLAG(_input, _flag, _result) \ 7262#define IXGBE_SET_FLAG(_input, _flag, _result) \
@@ -9190,41 +9148,37 @@ skip_sriov:
9190 9148
9191#endif 9149#endif
9192 netdev->features = NETIF_F_SG | 9150 netdev->features = NETIF_F_SG |
9193 NETIF_F_IP_CSUM |
9194 NETIF_F_IPV6_CSUM |
9195 NETIF_F_HW_VLAN_CTAG_TX |
9196 NETIF_F_HW_VLAN_CTAG_RX |
9197 NETIF_F_TSO | 9151 NETIF_F_TSO |
9198 NETIF_F_TSO6 | 9152 NETIF_F_TSO6 |
9199 NETIF_F_RXHASH | 9153 NETIF_F_RXHASH |
9200 NETIF_F_RXCSUM; 9154 NETIF_F_RXCSUM |
9201 9155 NETIF_F_HW_CSUM |
9202 netdev->hw_features = netdev->features | NETIF_F_HW_L2FW_DOFFLOAD; 9156 NETIF_F_HW_VLAN_CTAG_TX |
9157 NETIF_F_HW_VLAN_CTAG_RX;
9203 9158
9204 switch (adapter->hw.mac.type) { 9159 if (hw->mac.type >= ixgbe_mac_82599EB)
9205 case ixgbe_mac_82599EB:
9206 case ixgbe_mac_X540:
9207 case ixgbe_mac_X550:
9208 case ixgbe_mac_X550EM_x:
9209 netdev->features |= NETIF_F_SCTP_CRC; 9160 netdev->features |= NETIF_F_SCTP_CRC;
9210 netdev->hw_features |= NETIF_F_SCTP_CRC | 9161
9211 NETIF_F_NTUPLE | 9162 /* copy netdev features into list of user selectable features */
9163 netdev->hw_features |= netdev->features;
9164 netdev->hw_features |= NETIF_F_RXALL |
9165 NETIF_F_HW_L2FW_DOFFLOAD;
9166
9167 if (hw->mac.type >= ixgbe_mac_82599EB)
9168 netdev->hw_features |= NETIF_F_NTUPLE |
9212 NETIF_F_HW_TC; 9169 NETIF_F_HW_TC;
9213 break;
9214 default:
9215 break;
9216 }
9217 9170
9218 netdev->hw_features |= NETIF_F_RXALL; 9171 /* set this bit last since it cannot be part of hw_features */
9219 netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER; 9172 netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
9220 9173
9221 netdev->vlan_features |= NETIF_F_TSO; 9174 netdev->vlan_features |= NETIF_F_SG |
9222 netdev->vlan_features |= NETIF_F_TSO6; 9175 NETIF_F_TSO |
9223 netdev->vlan_features |= NETIF_F_IP_CSUM; 9176 NETIF_F_TSO6 |
9224 netdev->vlan_features |= NETIF_F_IPV6_CSUM; 9177 NETIF_F_HW_CSUM |
9225 netdev->vlan_features |= NETIF_F_SG; 9178 NETIF_F_SCTP_CRC;
9226 9179
9227 netdev->hw_enc_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; 9180 netdev->mpls_features |= NETIF_F_HW_CSUM;
9181 netdev->hw_enc_features |= NETIF_F_HW_CSUM;
9228 9182
9229 netdev->priv_flags |= IFF_UNICAST_FLT; 9183 netdev->priv_flags |= IFF_UNICAST_FLT;
9230 netdev->priv_flags |= IFF_SUPP_NOFCS; 9184 netdev->priv_flags |= IFF_SUPP_NOFCS;