|
| 1 | +ice: Add E830 checksum offload support |
| 2 | + |
| 3 | +jira LE-4694 |
| 4 | +Rebuild_History Non-Buildable kernel-6.12.0-55.43.1.el10_0 |
| 5 | +commit-author Paul Greenwalt <paul.greenwalt@intel.com> |
| 6 | +commit 905d1a220e8db4aaf0ccc5cb9f733ac2e5989386 |
| 7 | +Empty-Commit: Cherry-Pick Conflicts during history rebuild. |
| 8 | +Will be included in final tarball splat. Ref for failed cherry-pick at: |
| 9 | +ciq/ciq_backports/kernel-6.12.0-55.43.1.el10_0/905d1a22.failed |
| 10 | + |
| 11 | +E830 supports raw receive and generic transmit checksum offloads. |
| 12 | + |
| 13 | +Raw receive checksum support is provided by hardware calculating the |
| 14 | +checksum over the whole packet, regardless of type. The calculated |
| 15 | +checksum is provided to driver in the Rx flex descriptor. Then the driver |
| 16 | +assigns the checksum to skb->csum and sets skb->ip_summed to |
| 17 | +CHECKSUM_COMPLETE. |
| 18 | + |
| 19 | +Generic transmit checksum support is provided by hardware calculating the |
| 20 | +checksum given two offsets: the start offset to begin checksum calculation, |
| 21 | +and the offset to insert the calculated checksum in the packet. Support is |
| 22 | +advertised to the stack using NETIF_F_HW_CSUM feature. |
| 23 | + |
| 24 | +E830 has the following limitations when both generic transmit checksum |
| 25 | +offload and TCP Segmentation Offload (TSO) are enabled: |
| 26 | + |
| 27 | +1. Inner packet header modification is not supported. This restriction |
| 28 | + includes the inability to alter TCP flags, such as the push flag. As a |
| 29 | + result, this limitation can impact the receiver's ability to coalesce |
| 30 | + packets, potentially degrading network throughput. |
| 31 | +2. The Maximum Segment Size (MSS) is limited to 1023 bytes, which prevents |
| 32 | + support of Maximum Transmission Unit (MTU) greater than 1063 bytes. |
| 33 | + |
| 34 | +Therefore NETIF_F_HW_CSUM and NETIF_F_ALL_TSO features are mutually |
| 35 | +exclusive. NETIF_F_HW_CSUM hardware feature support is indicated but is not |
| 36 | +enabled by default. Instead, IP checksums and NETIF_F_ALL_TSO are the |
| 37 | +defaults. Enforcement of mutual exclusivity of NETIF_F_HW_CSUM and |
| 38 | +NETIF_F_ALL_TSO is done in ice_set_features(). Mutual exclusivity |
| 39 | +of IP checksums and NETIF_F_HW_CSUM is handled by netdev_fix_features(). |
| 40 | + |
| 41 | +When NETIF_F_HW_CSUM is requested the provided skb->csum_start and |
| 42 | +skb->csum_offset are passed to hardware in the Tx context descriptor |
| 43 | +generic checksum (GCS) parameters. Hardware calculates the 1's complement |
| 44 | +from skb->csum_start to the end of the packet, and inserts the result in |
| 45 | +the packet at skb->csum_offset. |
| 46 | + |
| 47 | +Co-developed-by: Alice Michael <alice.michael@intel.com> |
| 48 | + Signed-off-by: Alice Michael <alice.michael@intel.com> |
| 49 | +Co-developed-by: Eric Joyner <eric.joyner@intel.com> |
| 50 | + Signed-off-by: Eric Joyner <eric.joyner@intel.com> |
| 51 | + Signed-off-by: Paul Greenwalt <paul.greenwalt@intel.com> |
| 52 | + Reviewed-by: Simon Horman <horms@kernel.org> |
| 53 | + Tested-by: Rinitha S <sx.rinitha@intel.com> (A Contingent worker at Intel) |
| 54 | + Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com> |
| 55 | +Link: https://patch.msgid.link/20250310174502.3708121-2-anthony.l.nguyen@intel.com |
| 56 | + Signed-off-by: Paolo Abeni <pabeni@redhat.com> |
| 57 | + |
| 58 | +(cherry picked from commit 905d1a220e8db4aaf0ccc5cb9f733ac2e5989386) |
| 59 | + Signed-off-by: Jonathan Maple <jmaple@ciq.com> |
| 60 | + |
| 61 | +# Conflicts: |
| 62 | +# drivers/net/ethernet/intel/ice/ice_main.c |
| 63 | +diff --cc drivers/net/ethernet/intel/ice/ice_main.c |
| 64 | +index ed612b2a3064,049edeb60104..000000000000 |
| 65 | +--- a/drivers/net/ethernet/intel/ice/ice_main.c |
| 66 | ++++ b/drivers/net/ethernet/intel/ice/ice_main.c |
| 67 | +@@@ -3663,6 -3631,15 +3663,18 @@@ void ice_set_netdev_features(struct net |
| 68 | + */ |
| 69 | + netdev->hw_features |= NETIF_F_RXFCS; |
| 70 | + |
| 71 | +++<<<<<<< HEAD |
| 72 | +++======= |
| 73 | ++ /* Allow core to manage IRQs affinity */ |
| 74 | ++ netif_set_affinity_auto(netdev); |
| 75 | ++ |
| 76 | ++ /* Mutual exclusivity for TSO and GCS is enforced by the set features |
| 77 | ++ * ndo callback. |
| 78 | ++ */ |
| 79 | ++ if (ice_is_feature_supported(pf, ICE_F_GCS)) |
| 80 | ++ netdev->hw_features |= NETIF_F_HW_CSUM; |
| 81 | ++ |
| 82 | +++>>>>>>> 905d1a220e8d (ice: Add E830 checksum offload support) |
| 83 | + netif_set_tso_max_size(netdev, ICE_MAX_TSO_SIZE); |
| 84 | + } |
| 85 | + |
| 86 | +diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h |
| 87 | +index c9104b13e1d2..7200d6042590 100644 |
| 88 | +--- a/drivers/net/ethernet/intel/ice/ice.h |
| 89 | ++++ b/drivers/net/ethernet/intel/ice/ice.h |
| 90 | +@@ -201,6 +201,7 @@ enum ice_feature { |
| 91 | + ICE_F_SMA_CTRL, |
| 92 | + ICE_F_CGU, |
| 93 | + ICE_F_GNSS, |
| 94 | ++ ICE_F_GCS, |
| 95 | + ICE_F_ROCE_LAG, |
| 96 | + ICE_F_SRIOV_LAG, |
| 97 | + ICE_F_MBX_LIMIT, |
| 98 | +diff --git a/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h b/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h |
| 99 | +index 1479b45738af..77ba26538b07 100644 |
| 100 | +--- a/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h |
| 101 | ++++ b/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h |
| 102 | +@@ -229,7 +229,7 @@ struct ice_32b_rx_flex_desc_nic { |
| 103 | + __le16 status_error1; |
| 104 | + u8 flexi_flags2; |
| 105 | + u8 ts_low; |
| 106 | +- __le16 l2tag2_1st; |
| 107 | ++ __le16 raw_csum; |
| 108 | + __le16 l2tag2_2nd; |
| 109 | + |
| 110 | + /* Qword 3 */ |
| 111 | +@@ -478,10 +478,15 @@ enum ice_tx_desc_len_fields { |
| 112 | + struct ice_tx_ctx_desc { |
| 113 | + __le32 tunneling_params; |
| 114 | + __le16 l2tag2; |
| 115 | +- __le16 rsvd; |
| 116 | ++ __le16 gcs; |
| 117 | + __le64 qw1; |
| 118 | + }; |
| 119 | + |
| 120 | ++#define ICE_TX_GCS_DESC_START_M GENMASK(7, 0) |
| 121 | ++#define ICE_TX_GCS_DESC_OFFSET_M GENMASK(11, 8) |
| 122 | ++#define ICE_TX_GCS_DESC_TYPE_M GENMASK(14, 12) |
| 123 | ++#define ICE_TX_GCS_DESC_CSUM_PSH 1 |
| 124 | ++ |
| 125 | + #define ICE_TXD_CTX_QW1_CMD_S 4 |
| 126 | + #define ICE_TXD_CTX_QW1_CMD_M (0x7FUL << ICE_TXD_CTX_QW1_CMD_S) |
| 127 | + |
| 128 | +diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c |
| 129 | +index fb7508180d5e..fcad806a3c90 100644 |
| 130 | +--- a/drivers/net/ethernet/intel/ice/ice_lib.c |
| 131 | ++++ b/drivers/net/ethernet/intel/ice/ice_lib.c |
| 132 | +@@ -1431,6 +1431,10 @@ static int ice_vsi_alloc_rings(struct ice_vsi *vsi) |
| 133 | + ring->dev = dev; |
| 134 | + ring->count = vsi->num_rx_desc; |
| 135 | + ring->cached_phctime = pf->ptp.cached_phc_time; |
| 136 | ++ |
| 137 | ++ if (ice_is_feature_supported(pf, ICE_F_GCS)) |
| 138 | ++ ring->flags |= ICE_RX_FLAGS_RING_GCS; |
| 139 | ++ |
| 140 | + WRITE_ONCE(vsi->rx_rings[i], ring); |
| 141 | + } |
| 142 | + |
| 143 | +@@ -3891,8 +3895,10 @@ void ice_init_feature_support(struct ice_pf *pf) |
| 144 | + break; |
| 145 | + } |
| 146 | + |
| 147 | +- if (pf->hw.mac_type == ICE_MAC_E830) |
| 148 | ++ if (pf->hw.mac_type == ICE_MAC_E830) { |
| 149 | + ice_set_feature_support(pf, ICE_F_MBX_LIMIT); |
| 150 | ++ ice_set_feature_support(pf, ICE_F_GCS); |
| 151 | ++ } |
| 152 | + } |
| 153 | + |
| 154 | + /** |
| 155 | +* Unmerged path drivers/net/ethernet/intel/ice/ice_main.c |
| 156 | +diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.c b/drivers/net/ethernet/intel/ice/ice_txrx.c |
| 157 | +index f522dd42093a..c7c91c5b5f71 100644 |
| 158 | +--- a/drivers/net/ethernet/intel/ice/ice_txrx.c |
| 159 | ++++ b/drivers/net/ethernet/intel/ice/ice_txrx.c |
| 160 | +@@ -1809,6 +1809,7 @@ ice_tx_map(struct ice_tx_ring *tx_ring, struct ice_tx_buf *first, |
| 161 | + static |
| 162 | + int ice_tx_csum(struct ice_tx_buf *first, struct ice_tx_offload_params *off) |
| 163 | + { |
| 164 | ++ const struct ice_tx_ring *tx_ring = off->tx_ring; |
| 165 | + u32 l4_len = 0, l3_len = 0, l2_len = 0; |
| 166 | + struct sk_buff *skb = first->skb; |
| 167 | + union { |
| 168 | +@@ -1958,6 +1959,30 @@ int ice_tx_csum(struct ice_tx_buf *first, struct ice_tx_offload_params *off) |
| 169 | + l3_len = l4.hdr - ip.hdr; |
| 170 | + offset |= (l3_len / 4) << ICE_TX_DESC_LEN_IPLEN_S; |
| 171 | + |
| 172 | ++ if ((tx_ring->netdev->features & NETIF_F_HW_CSUM) && |
| 173 | ++ !(first->tx_flags & ICE_TX_FLAGS_TSO) && |
| 174 | ++ !skb_csum_is_sctp(skb)) { |
| 175 | ++ /* Set GCS */ |
| 176 | ++ u16 csum_start = (skb->csum_start - skb->mac_header) / 2; |
| 177 | ++ u16 csum_offset = skb->csum_offset / 2; |
| 178 | ++ u16 gcs_params; |
| 179 | ++ |
| 180 | ++ gcs_params = FIELD_PREP(ICE_TX_GCS_DESC_START_M, csum_start) | |
| 181 | ++ FIELD_PREP(ICE_TX_GCS_DESC_OFFSET_M, csum_offset) | |
| 182 | ++ FIELD_PREP(ICE_TX_GCS_DESC_TYPE_M, |
| 183 | ++ ICE_TX_GCS_DESC_CSUM_PSH); |
| 184 | ++ |
| 185 | ++ /* Unlike legacy HW checksums, GCS requires a context |
| 186 | ++ * descriptor. |
| 187 | ++ */ |
| 188 | ++ off->cd_qw1 |= ICE_TX_DESC_DTYPE_CTX; |
| 189 | ++ off->cd_gcs_params = gcs_params; |
| 190 | ++ /* Fill out CSO info in data descriptors */ |
| 191 | ++ off->td_offset |= offset; |
| 192 | ++ off->td_cmd |= cmd; |
| 193 | ++ return 1; |
| 194 | ++ } |
| 195 | ++ |
| 196 | + /* Enable L4 checksum offloads */ |
| 197 | + switch (l4_proto) { |
| 198 | + case IPPROTO_TCP: |
| 199 | +@@ -2441,7 +2466,7 @@ ice_xmit_frame_ring(struct sk_buff *skb, struct ice_tx_ring *tx_ring) |
| 200 | + /* setup context descriptor */ |
| 201 | + cdesc->tunneling_params = cpu_to_le32(offload.cd_tunnel_params); |
| 202 | + cdesc->l2tag2 = cpu_to_le16(offload.cd_l2tag2); |
| 203 | +- cdesc->rsvd = cpu_to_le16(0); |
| 204 | ++ cdesc->gcs = cpu_to_le16(offload.cd_gcs_params); |
| 205 | + cdesc->qw1 = cpu_to_le64(offload.cd_qw1); |
| 206 | + } |
| 207 | + |
| 208 | +diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.h b/drivers/net/ethernet/intel/ice/ice_txrx.h |
| 209 | +index 806bce701df3..a4b1e9514632 100644 |
| 210 | +--- a/drivers/net/ethernet/intel/ice/ice_txrx.h |
| 211 | ++++ b/drivers/net/ethernet/intel/ice/ice_txrx.h |
| 212 | +@@ -193,6 +193,7 @@ struct ice_tx_offload_params { |
| 213 | + u32 td_l2tag1; |
| 214 | + u32 cd_tunnel_params; |
| 215 | + u16 cd_l2tag2; |
| 216 | ++ u16 cd_gcs_params; |
| 217 | + u8 header_len; |
| 218 | + }; |
| 219 | + |
| 220 | +@@ -366,6 +367,7 @@ struct ice_rx_ring { |
| 221 | + #define ICE_RX_FLAGS_RING_BUILD_SKB BIT(1) |
| 222 | + #define ICE_RX_FLAGS_CRC_STRIP_DIS BIT(2) |
| 223 | + #define ICE_RX_FLAGS_MULTIDEV BIT(3) |
| 224 | ++#define ICE_RX_FLAGS_RING_GCS BIT(4) |
| 225 | + u8 flags; |
| 226 | + /* CL5 - 5th cacheline starts here */ |
| 227 | + struct xdp_rxq_info xdp_rxq; |
| 228 | +diff --git a/drivers/net/ethernet/intel/ice/ice_txrx_lib.c b/drivers/net/ethernet/intel/ice/ice_txrx_lib.c |
| 229 | +index 2719f0e20933..45cfaabc41cb 100644 |
| 230 | +--- a/drivers/net/ethernet/intel/ice/ice_txrx_lib.c |
| 231 | ++++ b/drivers/net/ethernet/intel/ice/ice_txrx_lib.c |
| 232 | +@@ -80,6 +80,23 @@ ice_rx_hash_to_skb(const struct ice_rx_ring *rx_ring, |
| 233 | + libeth_rx_pt_set_hash(skb, hash, decoded); |
| 234 | + } |
| 235 | + |
| 236 | ++/** |
| 237 | ++ * ice_rx_gcs - Set generic checksum in skb |
| 238 | ++ * @skb: skb currently being received and modified |
| 239 | ++ * @rx_desc: receive descriptor |
| 240 | ++ */ |
| 241 | ++static void ice_rx_gcs(struct sk_buff *skb, |
| 242 | ++ const union ice_32b_rx_flex_desc *rx_desc) |
| 243 | ++{ |
| 244 | ++ const struct ice_32b_rx_flex_desc_nic *desc; |
| 245 | ++ u16 csum; |
| 246 | ++ |
| 247 | ++ desc = (struct ice_32b_rx_flex_desc_nic *)rx_desc; |
| 248 | ++ skb->ip_summed = CHECKSUM_COMPLETE; |
| 249 | ++ csum = (__force u16)desc->raw_csum; |
| 250 | ++ skb->csum = csum_unfold((__force __sum16)swab16(csum)); |
| 251 | ++} |
| 252 | ++ |
| 253 | + /** |
| 254 | + * ice_rx_csum - Indicate in skb if checksum is good |
| 255 | + * @ring: the ring we care about |
| 256 | +@@ -107,6 +124,15 @@ ice_rx_csum(struct ice_rx_ring *ring, struct sk_buff *skb, |
| 257 | + rx_status0 = le16_to_cpu(rx_desc->wb.status_error0); |
| 258 | + rx_status1 = le16_to_cpu(rx_desc->wb.status_error1); |
| 259 | + |
| 260 | ++ if ((ring->flags & ICE_RX_FLAGS_RING_GCS) && |
| 261 | ++ rx_desc->wb.rxdid == ICE_RXDID_FLEX_NIC && |
| 262 | ++ (decoded.inner_prot == LIBETH_RX_PT_INNER_TCP || |
| 263 | ++ decoded.inner_prot == LIBETH_RX_PT_INNER_UDP || |
| 264 | ++ decoded.inner_prot == LIBETH_RX_PT_INNER_ICMP)) { |
| 265 | ++ ice_rx_gcs(skb, rx_desc); |
| 266 | ++ return; |
| 267 | ++ } |
| 268 | ++ |
| 269 | + /* check if HW has decoded the packet and checksum */ |
| 270 | + if (!(rx_status0 & BIT(ICE_RX_FLEX_DESC_STATUS0_L3L4P_S))) |
| 271 | + return; |
0 commit comments