Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'sfc-ef100-tso-enhancements'

Edward Cree says:

====================
sfc: EF100 TSO enhancements

Support TSO over encapsulation (with GSO_PARTIAL), and over VLANs
(which the code already handled but we didn't advertise). Also
correct our handling of IPID mangling.

I couldn't find documentation of exactly what shaped SKBs we can
get given, so patch #2 is slightly guesswork, but when I tested
TSO over both underlay and (VxLAN) overlay, the checksums came
out correctly, so at least in those cases the edits we're making
must be the right ones.
Similarly, I'm not 100% sure I've correctly understood how FIXEDID
and MANGLEID are supposed to work in patch #3.
====================

Link: https://lore.kernel.org/r/6e1ea05f-faeb-18df-91ef-572445691d89@solarflare.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+84 -33
+37 -5
drivers/net/ethernet/sfc/bitfield.h
··· 285 285 field10, value10, \ 286 286 field11, value11, \ 287 287 field12, value12, \ 288 - field13, value13) \ 288 + field13, value13, \ 289 + field14, value14, \ 290 + field15, value15, \ 291 + field16, value16, \ 292 + field17, value17) \ 289 293 (EFX_INSERT_FIELD_NATIVE((min), (max), field1, (value1)) | \ 290 294 EFX_INSERT_FIELD_NATIVE((min), (max), field2, (value2)) | \ 291 295 EFX_INSERT_FIELD_NATIVE((min), (max), field3, (value3)) | \ ··· 302 298 EFX_INSERT_FIELD_NATIVE((min), (max), field10, (value10)) | \ 303 299 EFX_INSERT_FIELD_NATIVE((min), (max), field11, (value11)) | \ 304 300 EFX_INSERT_FIELD_NATIVE((min), (max), field12, (value12)) | \ 305 - EFX_INSERT_FIELD_NATIVE((min), (max), field13, (value13))) 301 + EFX_INSERT_FIELD_NATIVE((min), (max), field13, (value13)) | \ 302 + EFX_INSERT_FIELD_NATIVE((min), (max), field14, (value14)) | \ 303 + EFX_INSERT_FIELD_NATIVE((min), (max), field15, (value15)) | \ 304 + EFX_INSERT_FIELD_NATIVE((min), (max), field16, (value16)) | \ 305 + EFX_INSERT_FIELD_NATIVE((min), (max), field17, (value17))) 306 306 307 307 #define EFX_INSERT_FIELDS64(...) \ 308 308 cpu_to_le64(EFX_INSERT_FIELDS_NATIVE(__VA_ARGS__)) ··· 348 340 #endif 349 341 350 342 /* Populate an octword field with various numbers of arguments */ 351 - #define EFX_POPULATE_OWORD_13 EFX_POPULATE_OWORD 343 + #define EFX_POPULATE_OWORD_17 EFX_POPULATE_OWORD 344 + #define EFX_POPULATE_OWORD_16(oword, ...) \ 345 + EFX_POPULATE_OWORD_17(oword, EFX_DUMMY_FIELD, 0, __VA_ARGS__) 346 + #define EFX_POPULATE_OWORD_15(oword, ...) \ 347 + EFX_POPULATE_OWORD_16(oword, EFX_DUMMY_FIELD, 0, __VA_ARGS__) 348 + #define EFX_POPULATE_OWORD_14(oword, ...) \ 349 + EFX_POPULATE_OWORD_15(oword, EFX_DUMMY_FIELD, 0, __VA_ARGS__) 350 + #define EFX_POPULATE_OWORD_13(oword, ...) \ 351 + EFX_POPULATE_OWORD_14(oword, EFX_DUMMY_FIELD, 0, __VA_ARGS__) 352 352 #define EFX_POPULATE_OWORD_12(oword, ...) \ 353 353 EFX_POPULATE_OWORD_13(oword, EFX_DUMMY_FIELD, 0, __VA_ARGS__) 354 354 #define EFX_POPULATE_OWORD_11(oword, ...) \ ··· 391 375 EFX_DWORD_3, 0xffffffff) 392 376 393 377 /* Populate a quadword field with various numbers of arguments */ 394 - #define EFX_POPULATE_QWORD_13 EFX_POPULATE_QWORD 378 + #define EFX_POPULATE_QWORD_17 EFX_POPULATE_QWORD 379 + #define EFX_POPULATE_QWORD_16(qword, ...) \ 380 + EFX_POPULATE_QWORD_17(qword, EFX_DUMMY_FIELD, 0, __VA_ARGS__) 381 + #define EFX_POPULATE_QWORD_15(qword, ...) \ 382 + EFX_POPULATE_QWORD_16(qword, EFX_DUMMY_FIELD, 0, __VA_ARGS__) 383 + #define EFX_POPULATE_QWORD_14(qword, ...) \ 384 + EFX_POPULATE_QWORD_15(qword, EFX_DUMMY_FIELD, 0, __VA_ARGS__) 385 + #define EFX_POPULATE_QWORD_13(qword, ...) \ 386 + EFX_POPULATE_QWORD_14(qword, EFX_DUMMY_FIELD, 0, __VA_ARGS__) 395 387 #define EFX_POPULATE_QWORD_12(qword, ...) \ 396 388 EFX_POPULATE_QWORD_13(qword, EFX_DUMMY_FIELD, 0, __VA_ARGS__) 397 389 #define EFX_POPULATE_QWORD_11(qword, ...) \ ··· 432 408 EFX_DWORD_1, 0xffffffff) 433 409 434 410 /* Populate a dword field with various numbers of arguments */ 435 - #define EFX_POPULATE_DWORD_13 EFX_POPULATE_DWORD 411 + #define EFX_POPULATE_DWORD_17 EFX_POPULATE_DWORD 412 + #define EFX_POPULATE_DWORD_16(dword, ...) \ 413 + EFX_POPULATE_DWORD_17(dword, EFX_DUMMY_FIELD, 0, __VA_ARGS__) 414 + #define EFX_POPULATE_DWORD_15(dword, ...) \ 415 + EFX_POPULATE_DWORD_16(dword, EFX_DUMMY_FIELD, 0, __VA_ARGS__) 416 + #define EFX_POPULATE_DWORD_14(dword, ...) \ 417 + EFX_POPULATE_DWORD_15(dword, EFX_DUMMY_FIELD, 0, __VA_ARGS__) 418 + #define EFX_POPULATE_DWORD_13(dword, ...) \ 419 + EFX_POPULATE_DWORD_14(dword, EFX_DUMMY_FIELD, 0, __VA_ARGS__) 436 420 #define EFX_POPULATE_DWORD_12(dword, ...) \ 437 421 EFX_POPULATE_DWORD_13(dword, EFX_DUMMY_FIELD, 0, __VA_ARGS__) 438 422 #define EFX_POPULATE_DWORD_11(dword, ...) \
+14 -3
drivers/net/ethernet/sfc/ef100_nic.c
··· 182 182 if (rc) 183 183 return rc; 184 184 185 - if (efx_ef100_has_cap(nic_data->datapath_caps2, TX_TSO_V3)) 186 - efx->net_dev->features |= NETIF_F_TSO | NETIF_F_TSO6; 185 + if (efx_ef100_has_cap(nic_data->datapath_caps2, TX_TSO_V3)) { 186 + struct net_device *net_dev = efx->net_dev; 187 + netdev_features_t tso = NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_GSO_PARTIAL | 188 + NETIF_F_GSO_UDP_TUNNEL | NETIF_F_GSO_UDP_TUNNEL_CSUM; 189 + 190 + net_dev->features |= tso; 191 + net_dev->hw_features |= tso; 192 + net_dev->hw_enc_features |= tso; 193 + net_dev->gso_partial_features |= NETIF_F_GSO_UDP_TUNNEL | NETIF_F_GSO_UDP_TUNNEL_CSUM; 194 + } 187 195 efx->num_mac_stats = MCDI_WORD(outbuf, 188 196 GET_CAPABILITIES_V4_OUT_MAC_STATS_NUM_STATS); 189 197 netif_dbg(efx, probe, efx->net_dev, ··· 694 686 #define EF100_OFFLOAD_FEATURES (NETIF_F_HW_CSUM | NETIF_F_RXCSUM | \ 695 687 NETIF_F_HIGHDMA | NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_NTUPLE | \ 696 688 NETIF_F_RXHASH | NETIF_F_RXFCS | NETIF_F_TSO_ECN | NETIF_F_RXALL | \ 697 - NETIF_F_TSO_MANGLEID | NETIF_F_HW_VLAN_CTAG_TX) 689 + NETIF_F_HW_VLAN_CTAG_TX) 698 690 699 691 const struct efx_nic_type ef100_pf_nic_type = { 700 692 .revision = EFX_REV_EF100, ··· 1109 1101 nic_data->efx = efx; 1110 1102 net_dev->features |= efx->type->offload_features; 1111 1103 net_dev->hw_features |= efx->type->offload_features; 1104 + net_dev->hw_enc_features |= efx->type->offload_features; 1105 + net_dev->vlan_features |= NETIF_F_HW_CSUM | NETIF_F_SG | 1106 + NETIF_F_HIGHDMA | NETIF_F_ALL_TSO; 1112 1107 1113 1108 /* Populate design-parameter defaults */ 1114 1109 nic_data->tso_max_hdr_len = ESE_EF100_DP_GZ_TSO_MAX_HDR_LEN_DEFAULT;
+33 -25
drivers/net/ethernet/sfc/ef100_tx.c
··· 54 54 struct efx_nic *efx = tx_queue->efx; 55 55 struct ef100_nic_data *nic_data; 56 56 struct efx_tx_buffer *buffer; 57 - struct tcphdr *tcphdr; 58 - struct iphdr *iphdr; 59 57 size_t header_len; 60 58 u32 mss; 61 59 ··· 96 98 buffer->unmap_len = 0; 97 99 buffer->skb = skb; 98 100 ++tx_queue->insert_count; 99 - 100 - /* Adjust the TCP checksum to exclude the total length, since we set 101 - * ED_INNER_IP_LEN in the descriptor. 102 - */ 103 - tcphdr = tcp_hdr(skb); 104 - if (skb_is_gso_v6(skb)) { 105 - tcphdr->check = ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr, 106 - &ipv6_hdr(skb)->daddr, 107 - 0, IPPROTO_TCP, 0); 108 - } else { 109 - iphdr = ip_hdr(skb); 110 - tcphdr->check = ~csum_tcpudp_magic(iphdr->saddr, iphdr->daddr, 111 - 0, IPPROTO_TCP, 0); 112 - } 113 101 return true; 114 102 } 115 103 ··· 187 203 struct efx_tx_buffer *buffer, efx_oword_t *txd, 188 204 unsigned int segment_count) 189 205 { 190 - u32 mangleid = (efx->net_dev->features & NETIF_F_TSO_MANGLEID) || 191 - skb_shinfo(skb)->gso_type & SKB_GSO_TCP_FIXEDID ? 192 - ESE_GZ_TX_DESC_IP4_ID_NO_OP : 193 - ESE_GZ_TX_DESC_IP4_ID_INC_MOD16; 194 - u16 vlan_enable = efx->net_dev->features & NETIF_F_HW_VLAN_CTAG_TX ? 195 - skb_vlan_tag_present(skb) : 0; 206 + bool gso_partial = skb_shinfo(skb)->gso_type & SKB_GSO_PARTIAL; 196 207 unsigned int len, ip_offset, tcp_offset, payload_segs; 208 + u32 mangleid = ESE_GZ_TX_DESC_IP4_ID_INC_MOD16; 209 + unsigned int outer_ip_offset, outer_l4_offset; 197 210 u16 vlan_tci = skb_vlan_tag_get(skb); 198 211 u32 mss = skb_shinfo(skb)->gso_size; 212 + bool encap = skb->encapsulation; 213 + u16 vlan_enable = 0; 214 + struct tcphdr *tcp; 215 + u32 paylen; 216 + 217 + if (skb_shinfo(skb)->gso_type & SKB_GSO_TCP_FIXEDID) 218 + mangleid = ESE_GZ_TX_DESC_IP4_ID_NO_OP; 219 + if (efx->net_dev->features & NETIF_F_HW_VLAN_CTAG_TX) 220 + vlan_enable = skb_vlan_tag_present(skb); 199 221 200 222 len = skb->len - buffer->len; 201 223 /* We use 1 for the TSO descriptor and 1 for the header */ 202 224 payload_segs = segment_count - 2; 203 - ip_offset = skb_network_offset(skb); 204 - tcp_offset = skb_transport_offset(skb); 225 + if (encap) { 226 + outer_ip_offset = skb_network_offset(skb); 227 + outer_l4_offset = skb_transport_offset(skb); 228 + ip_offset = skb_inner_network_offset(skb); 229 + tcp_offset = skb_inner_transport_offset(skb); 230 + } else { 231 + ip_offset = skb_network_offset(skb); 232 + tcp_offset = skb_transport_offset(skb); 233 + outer_ip_offset = outer_l4_offset = 0; 234 + } 205 235 206 - EFX_POPULATE_OWORD_13(*txd, 236 + /* subtract TCP payload length from inner checksum */ 237 + tcp = (void *)skb->data + tcp_offset; 238 + paylen = skb->len - tcp_offset; 239 + csum_replace_by_diff(&tcp->check, (__force __wsum)htonl(paylen)); 240 + 241 + EFX_POPULATE_OWORD_17(*txd, 207 242 ESF_GZ_TX_DESC_TYPE, ESE_GZ_TX_DESC_TYPE_TSO, 208 243 ESF_GZ_TX_TSO_MSS, mss, 209 244 ESF_GZ_TX_TSO_HDR_NUM_SEGS, 1, ··· 234 231 ESF_GZ_TX_TSO_INNER_L4_OFF_W, tcp_offset >> 1, 235 232 ESF_GZ_TX_TSO_ED_INNER_IP4_ID, mangleid, 236 233 ESF_GZ_TX_TSO_ED_INNER_IP_LEN, 1, 234 + ESF_GZ_TX_TSO_OUTER_L3_OFF_W, outer_ip_offset >> 1, 235 + ESF_GZ_TX_TSO_OUTER_L4_OFF_W, outer_l4_offset >> 1, 236 + ESF_GZ_TX_TSO_ED_OUTER_UDP_LEN, encap && !gso_partial, 237 + ESF_GZ_TX_TSO_ED_OUTER_IP4_ID, encap ? mangleid : 238 + ESE_GZ_TX_DESC_IP4_ID_NO_OP, 237 239 ESF_GZ_TX_TSO_VLAN_INSERT_EN, vlan_enable, 238 240 ESF_GZ_TX_TSO_VLAN_INSERT_TCI, vlan_tci 239 241 );