+static void
+sfc_ef100_tx_qdesc_tso_create(const struct rte_mbuf *m,
+ uint16_t nb_header_descs,
+ uint16_t nb_payload_descs,
+ size_t header_len, size_t payload_len,
+ size_t outer_iph_off, size_t outer_udph_off,
+ size_t iph_off, size_t tcph_off,
+ efx_oword_t *tx_desc)
+{
+ efx_oword_t tx_desc_extra_fields;
+ int ed_outer_udp_len = (outer_udph_off != 0) ? 1 : 0;
+ int ed_outer_ip_len = (outer_iph_off != 0) ? 1 : 0;
+ int ed_outer_ip_id = (outer_iph_off != 0) ?
+ ESE_GZ_TX_DESC_IP4_ID_INC_MOD16 : 0;
+ /*
+ * If no tunnel encapsulation is present, then the ED_INNER
+ * fields should be used.
+ */
+ int ed_inner_ip_id = ESE_GZ_TX_DESC_IP4_ID_INC_MOD16;
+ uint8_t inner_l3 = sfc_ef100_tx_qdesc_cso_inner_l3(
+ m->ol_flags & PKT_TX_TUNNEL_MASK);
+
+ EFX_POPULATE_OWORD_10(*tx_desc,
+ ESF_GZ_TX_TSO_MSS, m->tso_segsz,
+ ESF_GZ_TX_TSO_HDR_NUM_SEGS, nb_header_descs,
+ ESF_GZ_TX_TSO_PAYLOAD_NUM_SEGS, nb_payload_descs,
+ ESF_GZ_TX_TSO_ED_OUTER_IP4_ID, ed_outer_ip_id,
+ ESF_GZ_TX_TSO_ED_INNER_IP4_ID, ed_inner_ip_id,
+ ESF_GZ_TX_TSO_ED_OUTER_IP_LEN, ed_outer_ip_len,
+ ESF_GZ_TX_TSO_ED_INNER_IP_LEN, 1,
+ ESF_GZ_TX_TSO_ED_OUTER_UDP_LEN, ed_outer_udp_len,
+ ESF_GZ_TX_TSO_HDR_LEN_W, header_len >> 1,
+ ESF_GZ_TX_TSO_PAYLOAD_LEN, payload_len);
+
+ EFX_POPULATE_OWORD_9(tx_desc_extra_fields,
+ /*
+ * Outer offsets are required for outer IPv4 ID
+ * and length edits in the case of tunnel TSO.
+ */
+ ESF_GZ_TX_TSO_OUTER_L3_OFF_W, outer_iph_off >> 1,
+ ESF_GZ_TX_TSO_OUTER_L4_OFF_W, outer_udph_off >> 1,
+ /*
+ * Inner offsets are required for inner IPv4 ID
+ * and IP length edits and partial checksum
+ * offload in the case of tunnel TSO.
+ */
+ ESF_GZ_TX_TSO_INNER_L3_OFF_W, iph_off >> 1,
+ ESF_GZ_TX_TSO_INNER_L4_OFF_W, tcph_off >> 1,
+ ESF_GZ_TX_TSO_CSO_INNER_L4,
+ inner_l3 != ESE_GZ_TX_DESC_CS_INNER_L3_OFF,
+ ESF_GZ_TX_TSO_CSO_INNER_L3, inner_l3,
+ /*
+ * Use outer full checksum offloads which do
+ * not require any extra information.
+ */
+ ESF_GZ_TX_TSO_CSO_OUTER_L3, 1,
+ ESF_GZ_TX_TSO_CSO_OUTER_L4, 1,
+ ESF_GZ_TX_DESC_TYPE, ESE_GZ_TX_DESC_TYPE_TSO);
+
+ EFX_OR_OWORD(*tx_desc, tx_desc_extra_fields);
+
+ if (m->ol_flags & PKT_TX_VLAN_PKT) {
+ EFX_POPULATE_OWORD_2(tx_desc_extra_fields,
+ ESF_GZ_TX_TSO_VLAN_INSERT_EN, 1,
+ ESF_GZ_TX_TSO_VLAN_INSERT_TCI, m->vlan_tci);
+
+ EFX_OR_OWORD(*tx_desc, tx_desc_extra_fields);
+ }
+}
+