On 8/26/2024 10:39 AM, Paul Greenwalt wrote:
E830 supports generic receive and HW_CSUM transmit checksumming.

Generic receive checksum support is provided by hardware calculating the
checksum over the whole packet and providing it to the driver in the Rx
flex descriptor. Then the driver assigns the checksum to skb-->csum and
sets skb->ip_summed to CHECKSUM_COMPLETE.

E830 HW_CSUM transmit checksum does not support TCP Segmentation Offload
(TSO) inner packet modification, so TSO and HW_CSUM are mutually exclusive.
Therefore NETIF_F_HW_CSUM hardware feature support is indicated but is not
enabled by default. Instead, IP checksum and TSO are the defaults.
Enforcement of mutual exclusivity of TSO and HW_CSUM is done in
ice_fix_features(). Mutual exclusivity of IP checksum and HW_CSUM is
handled by netdev_fix_features().

When NETIF_F_HW_CSUM is requested the provide skb->csum_start and
skb->csum_offset are passed to hardware in the Tx context descriptor
generic checksum (GCS) parameters. Hardware calculates the 1's complement
from skb->csum_start to the end of the packet, and inserts the result in
the packet at skb->csum_offset.

Co-developed-by: Alice Michael <[email protected]>
Signed-off-by: Alice Michael <[email protected]>
Co-developed-by: Eric Joyner <[email protected]>
Signed-off-by: Eric Joyner <[email protected]>
Signed-off-by: Paul Greenwalt <[email protected]>
---
  drivers/net/ethernet/intel/ice/ice.h          |  1 +
  .../net/ethernet/intel/ice/ice_hw_autogen.h   |  1 +
  .../net/ethernet/intel/ice/ice_lan_tx_rx.h    |  8 +++--
  drivers/net/ethernet/intel/ice/ice_lib.c      |  9 +++++
  drivers/net/ethernet/intel/ice/ice_main.c     | 30 +++++++++++++++++
  drivers/net/ethernet/intel/ice/ice_txrx.c     | 26 ++++++++++++++-
  drivers/net/ethernet/intel/ice/ice_txrx.h     |  2 ++
  drivers/net/ethernet/intel/ice/ice_txrx_lib.c | 33 +++++++++++++++++++
  8 files changed, 107 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/intel/ice/ice.h 
b/drivers/net/ethernet/intel/ice/ice.h
index caaa10157909..70e2cf8825cc 100644
--- a/drivers/net/ethernet/intel/ice/ice.h
+++ b/drivers/net/ethernet/intel/ice/ice.h
@@ -205,6 +205,7 @@ enum ice_feature {
        ICE_F_SMA_CTRL,
        ICE_F_CGU,
        ICE_F_GNSS,
+       ICE_F_GCS,
        ICE_F_ROCE_LAG,
        ICE_F_SRIOV_LAG,
        ICE_F_MAX
diff --git a/drivers/net/ethernet/intel/ice/ice_hw_autogen.h 
b/drivers/net/ethernet/intel/ice/ice_hw_autogen.h
index 91cbae1eec89..3128806e1cc6 100644
--- a/drivers/net/ethernet/intel/ice/ice_hw_autogen.h
+++ b/drivers/net/ethernet/intel/ice/ice_hw_autogen.h
@@ -110,6 +110,7 @@
  #define PRTDCB_TUP2TC                         0x001D26C0
  #define GL_PREEXT_L2_PMASK0(_i)                       (0x0020F0FC + ((_i) * 
4))
  #define GL_PREEXT_L2_PMASK1(_i)                       (0x0020F108 + ((_i) * 
4))
+#define GL_RDPU_CNTRL                          0x00052054
  #define GLFLXP_RXDID_FLAGS(_i, _j)              (0x0045D000 + ((_i) * 4 + 
(_j) * 256))
  #define GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_S       0
  #define GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_M       ICE_M(0x3F, 0)
diff --git a/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h 
b/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h
index 611577ebc29d..759a7c6f72bd 100644
--- a/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h
+++ b/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h
@@ -229,7 +229,7 @@ struct ice_32b_rx_flex_desc_nic {
        __le16 status_error1;
        u8 flexi_flags2;
        u8 ts_low;
-       __le16 l2tag2_1st;
+       __le16 raw_csum;
        __le16 l2tag2_2nd;
/* Qword 3 */
@@ -500,10 +500,14 @@ enum ice_tx_desc_len_fields {
  struct ice_tx_ctx_desc {
        __le32 tunneling_params;
        __le16 l2tag2;
-       __le16 rsvd;
+       __le16 gcs;
        __le64 qw1;
  };
+#define ICE_TX_GCS_DESC_START 0 /* 8 BITS */
+#define ICE_TX_GCS_DESC_OFFSET 8       /* 4 BITS */
+#define ICE_TX_GCS_DESC_TYPE   12      /* 3 BITS */
+
  #define ICE_TXD_CTX_QW1_CMD_S 4
  #define ICE_TXD_CTX_QW1_CMD_M (0x7FUL << ICE_TXD_CTX_QW1_CMD_S)
diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c
index f559e60992fa..118ac34f89e9 100644
--- a/drivers/net/ethernet/intel/ice/ice_lib.c
+++ b/drivers/net/ethernet/intel/ice/ice_lib.c
@@ -1380,6 +1380,9 @@ static int ice_vsi_alloc_rings(struct ice_vsi *vsi)
                        ring->flags |= ICE_TX_FLAGS_RING_VLAN_L2TAG2;
                else
                        ring->flags |= ICE_TX_FLAGS_RING_VLAN_L2TAG1;
+
+               if (ice_is_feature_supported(pf, ICE_F_GCS))
+                       ring->flags |= ICE_TXRX_FLAGS_GCS_ENA;
                WRITE_ONCE(vsi->tx_rings[i], ring);
        }
@@ -1399,6 +1402,9 @@ static int ice_vsi_alloc_rings(struct ice_vsi *vsi)
                ring->dev = dev;
                ring->count = vsi->num_rx_desc;
                ring->cached_phctime = pf->ptp.cached_phc_time;
+
+               if (ice_is_feature_supported(pf, ICE_F_GCS))
+                       ring->flags |= ICE_TXRX_FLAGS_GCS_ENA;
                WRITE_ONCE(vsi->rx_rings[i], ring);
        }
@@ -3896,6 +3902,9 @@ void ice_init_feature_support(struct ice_pf *pf)
        default:
                break;
        }
+
+       if (pf->hw.mac_type == ICE_MAC_E830)
+               ice_set_feature_support(pf, ICE_F_GCS);
  }
/**
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c 
b/drivers/net/ethernet/intel/ice/ice_main.c
index 6f97ed471fe9..67e32ac962df 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -3678,6 +3678,12 @@ static void ice_set_netdev_features(struct net_device 
*netdev)
         */
        netdev->hw_features |= NETIF_F_RXFCS;
+ /* Mutual exclusivity for TSO and GCS is enforced by the
+        * ice_fix_features() ndo callback.
+        */
+       if (ice_is_feature_supported(pf, ICE_F_GCS))
+               netdev->hw_features |= NETIF_F_HW_CSUM;
+
        netif_set_tso_max_size(netdev, ICE_MAX_TSO_SIZE);
  }
@@ -6237,6 +6243,7 @@ ice_fix_features(struct net_device *netdev, netdev_features_t features)
        struct ice_netdev_priv *np = netdev_priv(netdev);
        netdev_features_t req_vlan_fltr, cur_vlan_fltr;
        bool cur_ctag, cur_stag, req_ctag, req_stag;
+       netdev_features_t changed;
cur_vlan_fltr = netdev->features & NETIF_VLAN_FILTERING_FEATURES;
        cur_ctag = cur_vlan_fltr & NETIF_F_HW_VLAN_CTAG_FILTER;
@@ -6285,6 +6292,29 @@ ice_fix_features(struct net_device *netdev, 
netdev_features_t features)
                features &= ~NETIF_VLAN_STRIPPING_FEATURES;
        }
+ if (!ice_is_feature_supported(np->vsi->back, ICE_F_GCS) ||
+           !(features & NETIF_F_HW_CSUM))
+               return features;

This prevents adding any other feature checks below this in the future. Seems like we should rework this into the feature being checked so that we don't have this restriction.

+
+       changed = netdev->features ^ features;

Scope of this could be reduced, but I guess the depends on what the re-work looks like.

+
+       /* HW checksum feature is supported and set, so enforce mutual
+        * exclusivity of TSO and GCS.
+        */
+       if (features & NETIF_F_ALL_TSO) {
+               if (changed & NETIF_F_HW_CSUM && changed & NETIF_F_ALL_TSO) {
+                       netdev_warn(netdev, "Dropping TSO and HW checksum. TSO and 
HW checksum are mutually exclusive.\n");
+                       features &= ~NETIF_F_HW_CSUM;
+                       features &= ~((features & changed) & NETIF_F_ALL_TSO);
+               } else if (changed & NETIF_F_HW_CSUM) {
+                       netdev_warn(netdev, "Dropping HW checksum. TSO and HW 
checksum are mutually exclusive.\n");
+                       features &= ~NETIF_F_HW_CSUM;
+               } else {
+                       netdev_warn(netdev, "Dropping TSO. TSO and HW checksum are 
mutually exclusive.\n");
+                       features &= ~NETIF_F_ALL_TSO;
+               }
+       }
+
        return features;
  }
diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.c b/drivers/net/ethernet/intel/ice/ice_txrx.c
index 8d25b6981269..bfcce1eab243 100644
--- a/drivers/net/ethernet/intel/ice/ice_txrx.c
+++ b/drivers/net/ethernet/intel/ice/ice_txrx.c
@@ -1792,6 +1792,7 @@ ice_tx_map(struct ice_tx_ring *tx_ring, struct ice_tx_buf 
*first,
  static
  int ice_tx_csum(struct ice_tx_buf *first, struct ice_tx_offload_params *off)
  {
+       const struct ice_tx_ring *tx_ring = off->tx_ring;
        u32 l4_len = 0, l3_len = 0, l2_len = 0;
        struct sk_buff *skb = first->skb;
        union {
@@ -1941,6 +1942,29 @@ int ice_tx_csum(struct ice_tx_buf *first, struct 
ice_tx_offload_params *off)
        l3_len = l4.hdr - ip.hdr;
        offset |= (l3_len / 4) << ICE_TX_DESC_LEN_IPLEN_S;
+#define TX_GCS_ENABLED 1

This should probably go with the other GCS defines.

+       if (tx_ring->netdev->features & NETIF_F_HW_CSUM &&
+           tx_ring->flags & ICE_TXRX_FLAGS_GCS_ENA &&
+           !(first->tx_flags & ICE_TX_FLAGS_TSO) &&
+           !skb_csum_is_sctp(skb)) {
+               /* Set GCS */
+               u16 gcs_params = ((skb->csum_start - skb->mac_header) / 2) <<
+                                ICE_TX_GCS_DESC_START;

Missing newline here.

+               gcs_params |= (skb->csum_offset / 2) << ICE_TX_GCS_DESC_OFFSET;
+               /* Type is 1 for 16-bit TCP/UDP checksums w/ pseudo */
+               gcs_params |= TX_GCS_ENABLED << ICE_TX_GCS_DESC_TYPE
Could we define TX_GCS_ENABLED to have the proper bit set? I don't see ICE_TX_GCS_DESC_TYPE used anywhere else so it'd eliminate the need for it.

+
+               /* Unlike legacy HW checksums, GCS requires a context
+                * descriptor.
+                */
+               off->cd_qw1 |= (u64)(ICE_TX_DESC_DTYPE_CTX);

Are these latter parentheses needed?

+               off->cd_gcs_params = gcs_params;
+               /* Fill out CSO info in data descriptors */
+               off->td_offset |= offset;
+               off->td_cmd |= cmd;
+               return 1;
+       }
+
        /* Enable L4 checksum offloads */
        switch (l4_proto) {
        case IPPROTO_TCP:
@@ -2422,7 +2446,7 @@ ice_xmit_frame_ring(struct sk_buff *skb, struct 
ice_tx_ring *tx_ring)
                /* setup context descriptor */
                cdesc->tunneling_params = cpu_to_le32(offload.cd_tunnel_params);
                cdesc->l2tag2 = cpu_to_le16(offload.cd_l2tag2);
-               cdesc->rsvd = cpu_to_le16(0);
+               cdesc->gcs = cpu_to_le16(offload.cd_gcs_params);
                cdesc->qw1 = cpu_to_le64(offload.cd_qw1);
        }
diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.h b/drivers/net/ethernet/intel/ice/ice_txrx.h
index feba314a3fe4..11b6af7a7414 100644
--- a/drivers/net/ethernet/intel/ice/ice_txrx.h
+++ b/drivers/net/ethernet/intel/ice/ice_txrx.h
@@ -193,6 +193,7 @@ struct ice_tx_offload_params {
        u32 td_l2tag1;
        u32 cd_tunnel_params;
        u16 cd_l2tag2;
+       u16 cd_gcs_params;
        u8 header_len;
  };
@@ -366,6 +367,7 @@ struct ice_rx_ring {
  #define ICE_RX_FLAGS_RING_BUILD_SKB   BIT(1)
  #define ICE_RX_FLAGS_CRC_STRIP_DIS    BIT(2)
  #define ICE_RX_FLAGS_MULTIDEV         BIT(3)
+#define ICE_TXRX_FLAGS_GCS_ENA         BIT(4)

The RX flags [1] and TX flags [2] are seperate, please keep them seperated and define them individually.

Thanks,
Tony

[1] https://elixir.bootlin.com/linux/v6.10.6/source/drivers/net/ethernet/intel/ice/ice_txrx.h#L366 [2] https://elixir.bootlin.com/linux/v6.10.6/source/drivers/net/ethernet/intel/ice/ice_txrx.h#L404

Reply via email to