mirror of
https://github.com/torvalds/linux.git
synced 2024-11-27 22:51:35 +00:00
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>
This commit is contained in:
commit
8ece853d12
@ -285,7 +285,11 @@ typedef union efx_oword {
|
||||
field10, value10, \
|
||||
field11, value11, \
|
||||
field12, value12, \
|
||||
field13, value13) \
|
||||
field13, value13, \
|
||||
field14, value14, \
|
||||
field15, value15, \
|
||||
field16, value16, \
|
||||
field17, value17) \
|
||||
(EFX_INSERT_FIELD_NATIVE((min), (max), field1, (value1)) | \
|
||||
EFX_INSERT_FIELD_NATIVE((min), (max), field2, (value2)) | \
|
||||
EFX_INSERT_FIELD_NATIVE((min), (max), field3, (value3)) | \
|
||||
@ -298,7 +302,11 @@ typedef union efx_oword {
|
||||
EFX_INSERT_FIELD_NATIVE((min), (max), field10, (value10)) | \
|
||||
EFX_INSERT_FIELD_NATIVE((min), (max), field11, (value11)) | \
|
||||
EFX_INSERT_FIELD_NATIVE((min), (max), field12, (value12)) | \
|
||||
EFX_INSERT_FIELD_NATIVE((min), (max), field13, (value13)))
|
||||
EFX_INSERT_FIELD_NATIVE((min), (max), field13, (value13)) | \
|
||||
EFX_INSERT_FIELD_NATIVE((min), (max), field14, (value14)) | \
|
||||
EFX_INSERT_FIELD_NATIVE((min), (max), field15, (value15)) | \
|
||||
EFX_INSERT_FIELD_NATIVE((min), (max), field16, (value16)) | \
|
||||
EFX_INSERT_FIELD_NATIVE((min), (max), field17, (value17)))
|
||||
|
||||
#define EFX_INSERT_FIELDS64(...) \
|
||||
cpu_to_le64(EFX_INSERT_FIELDS_NATIVE(__VA_ARGS__))
|
||||
@ -340,7 +348,15 @@ typedef union efx_oword {
|
||||
#endif
|
||||
|
||||
/* Populate an octword field with various numbers of arguments */
|
||||
#define EFX_POPULATE_OWORD_13 EFX_POPULATE_OWORD
|
||||
#define EFX_POPULATE_OWORD_17 EFX_POPULATE_OWORD
|
||||
#define EFX_POPULATE_OWORD_16(oword, ...) \
|
||||
EFX_POPULATE_OWORD_17(oword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
|
||||
#define EFX_POPULATE_OWORD_15(oword, ...) \
|
||||
EFX_POPULATE_OWORD_16(oword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
|
||||
#define EFX_POPULATE_OWORD_14(oword, ...) \
|
||||
EFX_POPULATE_OWORD_15(oword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
|
||||
#define EFX_POPULATE_OWORD_13(oword, ...) \
|
||||
EFX_POPULATE_OWORD_14(oword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
|
||||
#define EFX_POPULATE_OWORD_12(oword, ...) \
|
||||
EFX_POPULATE_OWORD_13(oword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
|
||||
#define EFX_POPULATE_OWORD_11(oword, ...) \
|
||||
@ -375,7 +391,15 @@ typedef union efx_oword {
|
||||
EFX_DWORD_3, 0xffffffff)
|
||||
|
||||
/* Populate a quadword field with various numbers of arguments */
|
||||
#define EFX_POPULATE_QWORD_13 EFX_POPULATE_QWORD
|
||||
#define EFX_POPULATE_QWORD_17 EFX_POPULATE_QWORD
|
||||
#define EFX_POPULATE_QWORD_16(qword, ...) \
|
||||
EFX_POPULATE_QWORD_17(qword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
|
||||
#define EFX_POPULATE_QWORD_15(qword, ...) \
|
||||
EFX_POPULATE_QWORD_16(qword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
|
||||
#define EFX_POPULATE_QWORD_14(qword, ...) \
|
||||
EFX_POPULATE_QWORD_15(qword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
|
||||
#define EFX_POPULATE_QWORD_13(qword, ...) \
|
||||
EFX_POPULATE_QWORD_14(qword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
|
||||
#define EFX_POPULATE_QWORD_12(qword, ...) \
|
||||
EFX_POPULATE_QWORD_13(qword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
|
||||
#define EFX_POPULATE_QWORD_11(qword, ...) \
|
||||
@ -408,7 +432,15 @@ typedef union efx_oword {
|
||||
EFX_DWORD_1, 0xffffffff)
|
||||
|
||||
/* Populate a dword field with various numbers of arguments */
|
||||
#define EFX_POPULATE_DWORD_13 EFX_POPULATE_DWORD
|
||||
#define EFX_POPULATE_DWORD_17 EFX_POPULATE_DWORD
|
||||
#define EFX_POPULATE_DWORD_16(dword, ...) \
|
||||
EFX_POPULATE_DWORD_17(dword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
|
||||
#define EFX_POPULATE_DWORD_15(dword, ...) \
|
||||
EFX_POPULATE_DWORD_16(dword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
|
||||
#define EFX_POPULATE_DWORD_14(dword, ...) \
|
||||
EFX_POPULATE_DWORD_15(dword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
|
||||
#define EFX_POPULATE_DWORD_13(dword, ...) \
|
||||
EFX_POPULATE_DWORD_14(dword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
|
||||
#define EFX_POPULATE_DWORD_12(dword, ...) \
|
||||
EFX_POPULATE_DWORD_13(dword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
|
||||
#define EFX_POPULATE_DWORD_11(dword, ...) \
|
||||
|
@ -182,8 +182,16 @@ static int efx_ef100_init_datapath_caps(struct efx_nic *efx)
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (efx_ef100_has_cap(nic_data->datapath_caps2, TX_TSO_V3))
|
||||
efx->net_dev->features |= NETIF_F_TSO | NETIF_F_TSO6;
|
||||
if (efx_ef100_has_cap(nic_data->datapath_caps2, TX_TSO_V3)) {
|
||||
struct net_device *net_dev = efx->net_dev;
|
||||
netdev_features_t tso = NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_GSO_PARTIAL |
|
||||
NETIF_F_GSO_UDP_TUNNEL | NETIF_F_GSO_UDP_TUNNEL_CSUM;
|
||||
|
||||
net_dev->features |= tso;
|
||||
net_dev->hw_features |= tso;
|
||||
net_dev->hw_enc_features |= tso;
|
||||
net_dev->gso_partial_features |= NETIF_F_GSO_UDP_TUNNEL | NETIF_F_GSO_UDP_TUNNEL_CSUM;
|
||||
}
|
||||
efx->num_mac_stats = MCDI_WORD(outbuf,
|
||||
GET_CAPABILITIES_V4_OUT_MAC_STATS_NUM_STATS);
|
||||
netif_dbg(efx, probe, efx->net_dev,
|
||||
@ -686,7 +694,7 @@ static unsigned int ef100_check_caps(const struct efx_nic *efx,
|
||||
#define EF100_OFFLOAD_FEATURES (NETIF_F_HW_CSUM | NETIF_F_RXCSUM | \
|
||||
NETIF_F_HIGHDMA | NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_NTUPLE | \
|
||||
NETIF_F_RXHASH | NETIF_F_RXFCS | NETIF_F_TSO_ECN | NETIF_F_RXALL | \
|
||||
NETIF_F_TSO_MANGLEID | NETIF_F_HW_VLAN_CTAG_TX)
|
||||
NETIF_F_HW_VLAN_CTAG_TX)
|
||||
|
||||
const struct efx_nic_type ef100_pf_nic_type = {
|
||||
.revision = EFX_REV_EF100,
|
||||
@ -1101,6 +1109,9 @@ static int ef100_probe_main(struct efx_nic *efx)
|
||||
nic_data->efx = efx;
|
||||
net_dev->features |= efx->type->offload_features;
|
||||
net_dev->hw_features |= efx->type->offload_features;
|
||||
net_dev->hw_enc_features |= efx->type->offload_features;
|
||||
net_dev->vlan_features |= NETIF_F_HW_CSUM | NETIF_F_SG |
|
||||
NETIF_F_HIGHDMA | NETIF_F_ALL_TSO;
|
||||
|
||||
/* Populate design-parameter defaults */
|
||||
nic_data->tso_max_hdr_len = ESE_EF100_DP_GZ_TSO_MAX_HDR_LEN_DEFAULT;
|
||||
|
@ -54,8 +54,6 @@ static bool ef100_tx_can_tso(struct efx_tx_queue *tx_queue, struct sk_buff *skb)
|
||||
struct efx_nic *efx = tx_queue->efx;
|
||||
struct ef100_nic_data *nic_data;
|
||||
struct efx_tx_buffer *buffer;
|
||||
struct tcphdr *tcphdr;
|
||||
struct iphdr *iphdr;
|
||||
size_t header_len;
|
||||
u32 mss;
|
||||
|
||||
@ -98,20 +96,6 @@ static bool ef100_tx_can_tso(struct efx_tx_queue *tx_queue, struct sk_buff *skb)
|
||||
buffer->unmap_len = 0;
|
||||
buffer->skb = skb;
|
||||
++tx_queue->insert_count;
|
||||
|
||||
/* Adjust the TCP checksum to exclude the total length, since we set
|
||||
* ED_INNER_IP_LEN in the descriptor.
|
||||
*/
|
||||
tcphdr = tcp_hdr(skb);
|
||||
if (skb_is_gso_v6(skb)) {
|
||||
tcphdr->check = ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
|
||||
&ipv6_hdr(skb)->daddr,
|
||||
0, IPPROTO_TCP, 0);
|
||||
} else {
|
||||
iphdr = ip_hdr(skb);
|
||||
tcphdr->check = ~csum_tcpudp_magic(iphdr->saddr, iphdr->daddr,
|
||||
0, IPPROTO_TCP, 0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -203,23 +187,42 @@ static void ef100_make_tso_desc(struct efx_nic *efx,
|
||||
struct efx_tx_buffer *buffer, efx_oword_t *txd,
|
||||
unsigned int segment_count)
|
||||
{
|
||||
u32 mangleid = (efx->net_dev->features & NETIF_F_TSO_MANGLEID) ||
|
||||
skb_shinfo(skb)->gso_type & SKB_GSO_TCP_FIXEDID ?
|
||||
ESE_GZ_TX_DESC_IP4_ID_NO_OP :
|
||||
ESE_GZ_TX_DESC_IP4_ID_INC_MOD16;
|
||||
u16 vlan_enable = efx->net_dev->features & NETIF_F_HW_VLAN_CTAG_TX ?
|
||||
skb_vlan_tag_present(skb) : 0;
|
||||
bool gso_partial = skb_shinfo(skb)->gso_type & SKB_GSO_PARTIAL;
|
||||
unsigned int len, ip_offset, tcp_offset, payload_segs;
|
||||
u32 mangleid = ESE_GZ_TX_DESC_IP4_ID_INC_MOD16;
|
||||
unsigned int outer_ip_offset, outer_l4_offset;
|
||||
u16 vlan_tci = skb_vlan_tag_get(skb);
|
||||
u32 mss = skb_shinfo(skb)->gso_size;
|
||||
bool encap = skb->encapsulation;
|
||||
u16 vlan_enable = 0;
|
||||
struct tcphdr *tcp;
|
||||
u32 paylen;
|
||||
|
||||
if (skb_shinfo(skb)->gso_type & SKB_GSO_TCP_FIXEDID)
|
||||
mangleid = ESE_GZ_TX_DESC_IP4_ID_NO_OP;
|
||||
if (efx->net_dev->features & NETIF_F_HW_VLAN_CTAG_TX)
|
||||
vlan_enable = skb_vlan_tag_present(skb);
|
||||
|
||||
len = skb->len - buffer->len;
|
||||
/* We use 1 for the TSO descriptor and 1 for the header */
|
||||
payload_segs = segment_count - 2;
|
||||
if (encap) {
|
||||
outer_ip_offset = skb_network_offset(skb);
|
||||
outer_l4_offset = skb_transport_offset(skb);
|
||||
ip_offset = skb_inner_network_offset(skb);
|
||||
tcp_offset = skb_inner_transport_offset(skb);
|
||||
} else {
|
||||
ip_offset = skb_network_offset(skb);
|
||||
tcp_offset = skb_transport_offset(skb);
|
||||
outer_ip_offset = outer_l4_offset = 0;
|
||||
}
|
||||
|
||||
EFX_POPULATE_OWORD_13(*txd,
|
||||
/* subtract TCP payload length from inner checksum */
|
||||
tcp = (void *)skb->data + tcp_offset;
|
||||
paylen = skb->len - tcp_offset;
|
||||
csum_replace_by_diff(&tcp->check, (__force __wsum)htonl(paylen));
|
||||
|
||||
EFX_POPULATE_OWORD_17(*txd,
|
||||
ESF_GZ_TX_DESC_TYPE, ESE_GZ_TX_DESC_TYPE_TSO,
|
||||
ESF_GZ_TX_TSO_MSS, mss,
|
||||
ESF_GZ_TX_TSO_HDR_NUM_SEGS, 1,
|
||||
@ -231,6 +234,11 @@ static void ef100_make_tso_desc(struct efx_nic *efx,
|
||||
ESF_GZ_TX_TSO_INNER_L4_OFF_W, tcp_offset >> 1,
|
||||
ESF_GZ_TX_TSO_ED_INNER_IP4_ID, mangleid,
|
||||
ESF_GZ_TX_TSO_ED_INNER_IP_LEN, 1,
|
||||
ESF_GZ_TX_TSO_OUTER_L3_OFF_W, outer_ip_offset >> 1,
|
||||
ESF_GZ_TX_TSO_OUTER_L4_OFF_W, outer_l4_offset >> 1,
|
||||
ESF_GZ_TX_TSO_ED_OUTER_UDP_LEN, encap && !gso_partial,
|
||||
ESF_GZ_TX_TSO_ED_OUTER_IP4_ID, encap ? mangleid :
|
||||
ESE_GZ_TX_DESC_IP4_ID_NO_OP,
|
||||
ESF_GZ_TX_TSO_VLAN_INSERT_EN, vlan_enable,
|
||||
ESF_GZ_TX_TSO_VLAN_INSERT_TCI, vlan_tci
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user