enic: Simplify RX handler function
authorJohn Daley <johndale@cisco.com>
Wed, 5 Feb 2025 23:54:14 +0000 (15:54 -0800)
committerJakub Kicinski <kuba@kernel.org>
Fri, 7 Feb 2025 01:17:01 +0000 (17:17 -0800)
Split up RX handler functions in preparation for moving
to a page pool based implementation.

No functional changes.

Co-developed-by: Nelson Escobar <neescoba@cisco.com>
Signed-off-by: Nelson Escobar <neescoba@cisco.com>
Co-developed-by: Satish Kharat <satishkh@cisco.com>
Signed-off-by: Satish Kharat <satishkh@cisco.com>
Signed-off-by: John Daley <johndale@cisco.com>
Link: https://patch.msgid.link/20250205235416.25410-3-johndale@cisco.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/cisco/enic/enic_rq.c

index e5b2f581c05551dd5bd0e3e64d1c710630073528..48aa385aa8313be61b9a27b163143415243b79ce 100644 (file)
@@ -50,6 +50,94 @@ int enic_rq_service(struct vnic_dev *vdev, struct cq_desc *cq_desc, u8 type,
        return 0;
 }
 
+static void enic_rq_set_skb_flags(struct vnic_rq *vrq, u8 type, u32 rss_hash,
+                                 u8 rss_type, u8 fcoe, u8 fcoe_fc_crc_ok,
+                                 u8 vlan_stripped, u8 csum_not_calc,
+                                 u8 tcp_udp_csum_ok, u8 ipv6, u8 ipv4_csum_ok,
+                                 u16 vlan_tci, struct sk_buff *skb)
+{
+       struct enic *enic = vnic_dev_priv(vrq->vdev);
+       struct net_device *netdev = enic->netdev;
+       struct enic_rq_stats *rqstats =  &enic->rq[vrq->index].stats;
+       bool outer_csum_ok = true, encap = false;
+
+       if ((netdev->features & NETIF_F_RXHASH) && rss_hash && type == 3) {
+               switch (rss_type) {
+               case CQ_ENET_RQ_DESC_RSS_TYPE_TCP_IPv4:
+               case CQ_ENET_RQ_DESC_RSS_TYPE_TCP_IPv6:
+               case CQ_ENET_RQ_DESC_RSS_TYPE_TCP_IPv6_EX:
+                       skb_set_hash(skb, rss_hash, PKT_HASH_TYPE_L4);
+                       rqstats->l4_rss_hash++;
+                       break;
+               case CQ_ENET_RQ_DESC_RSS_TYPE_IPv4:
+               case CQ_ENET_RQ_DESC_RSS_TYPE_IPv6:
+               case CQ_ENET_RQ_DESC_RSS_TYPE_IPv6_EX:
+                       skb_set_hash(skb, rss_hash, PKT_HASH_TYPE_L3);
+                       rqstats->l3_rss_hash++;
+                       break;
+               }
+       }
+       if (enic->vxlan.vxlan_udp_port_number) {
+               switch (enic->vxlan.patch_level) {
+               case 0:
+                       if (fcoe) {
+                               encap = true;
+                               outer_csum_ok = fcoe_fc_crc_ok;
+                       }
+                       break;
+               case 2:
+                       if (type == 7 && (rss_hash & BIT(0))) {
+                               encap = true;
+                               outer_csum_ok = (rss_hash & BIT(1)) &&
+                                               (rss_hash & BIT(2));
+                       }
+                       break;
+               }
+       }
+
+       /* Hardware does not provide whole packet checksum. It only
+        * provides pseudo checksum. Since hw validates the packet
+        * checksum but not provide us the checksum value. use
+        * CHECSUM_UNNECESSARY.
+        *
+        * In case of encap pkt tcp_udp_csum_ok/tcp_udp_csum_ok is
+        * inner csum_ok. outer_csum_ok is set by hw when outer udp
+        * csum is correct or is zero.
+        */
+       if ((netdev->features & NETIF_F_RXCSUM) && !csum_not_calc &&
+           tcp_udp_csum_ok && outer_csum_ok && (ipv4_csum_ok || ipv6)) {
+               skb->ip_summed = CHECKSUM_UNNECESSARY;
+               skb->csum_level = encap;
+               if (encap)
+                       rqstats->csum_unnecessary_encap++;
+               else
+                       rqstats->csum_unnecessary++;
+       }
+
+       if (vlan_stripped) {
+               __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_tci);
+               rqstats->vlan_stripped++;
+       }
+}
+
+static bool enic_rq_pkt_error(struct vnic_rq *vrq, u8 packet_error, u8 fcs_ok,
+                             u16 bytes_written)
+{
+       struct enic *enic = vnic_dev_priv(vrq->vdev);
+       struct enic_rq_stats *rqstats = &enic->rq[vrq->index].stats;
+
+       if (packet_error) {
+               if (!fcs_ok) {
+                       if (bytes_written > 0)
+                               rqstats->bad_fcs++;
+                       else if (bytes_written == 0)
+                               rqstats->pkt_truncated++;
+               }
+               return true;
+       }
+       return false;
+}
+
 int enic_rq_alloc_buf(struct vnic_rq *rq)
 {
        struct enic *enic = vnic_dev_priv(rq->vdev);
@@ -113,7 +201,6 @@ void enic_rq_indicate_buf(struct vnic_rq *rq, struct cq_desc *cq_desc,
        u8 packet_error;
        u16 q_number, completed_index, bytes_written, vlan_tci, checksum;
        u32 rss_hash;
-       bool outer_csum_ok = true, encap = false;
 
        rqstats->packets++;
        if (skipped) {
@@ -132,14 +219,7 @@ void enic_rq_indicate_buf(struct vnic_rq *rq, struct cq_desc *cq_desc,
                            &tcp, &ipv4_csum_ok, &ipv6, &ipv4, &ipv4_fragment,
                            &fcs_ok);
 
-       if (packet_error) {
-               if (!fcs_ok) {
-                       if (bytes_written > 0)
-                               rqstats->bad_fcs++;
-                       else if (bytes_written == 0)
-                               rqstats->pkt_truncated++;
-               }
-
+       if (enic_rq_pkt_error(rq, packet_error, fcs_ok, bytes_written)) {
                dma_unmap_single(&enic->pdev->dev, buf->dma_addr, buf->len,
                                 DMA_FROM_DEVICE);
                dev_kfree_skb_any(skb);
@@ -162,66 +242,10 @@ void enic_rq_indicate_buf(struct vnic_rq *rq, struct cq_desc *cq_desc,
                skb_put(skb, bytes_written);
                skb->protocol = eth_type_trans(skb, netdev);
                skb_record_rx_queue(skb, q_number);
-               if ((netdev->features & NETIF_F_RXHASH) && rss_hash &&
-                   type == 3) {
-                       switch (rss_type) {
-                       case CQ_ENET_RQ_DESC_RSS_TYPE_TCP_IPv4:
-                       case CQ_ENET_RQ_DESC_RSS_TYPE_TCP_IPv6:
-                       case CQ_ENET_RQ_DESC_RSS_TYPE_TCP_IPv6_EX:
-                               skb_set_hash(skb, rss_hash, PKT_HASH_TYPE_L4);
-                               rqstats->l4_rss_hash++;
-                               break;
-                       case CQ_ENET_RQ_DESC_RSS_TYPE_IPv4:
-                       case CQ_ENET_RQ_DESC_RSS_TYPE_IPv6:
-                       case CQ_ENET_RQ_DESC_RSS_TYPE_IPv6_EX:
-                               skb_set_hash(skb, rss_hash, PKT_HASH_TYPE_L3);
-                               rqstats->l3_rss_hash++;
-                               break;
-                       }
-               }
-               if (enic->vxlan.vxlan_udp_port_number) {
-                       switch (enic->vxlan.patch_level) {
-                       case 0:
-                               if (fcoe) {
-                                       encap = true;
-                                       outer_csum_ok = fcoe_fc_crc_ok;
-                               }
-                               break;
-                       case 2:
-                               if (type == 7 &&
-                                   (rss_hash & BIT(0))) {
-                                       encap = true;
-                                       outer_csum_ok = (rss_hash & BIT(1)) &&
-                                                       (rss_hash & BIT(2));
-                               }
-                               break;
-                       }
-               }
-
-               /* Hardware does not provide whole packet checksum. It only
-                * provides pseudo checksum. Since hw validates the packet
-                * checksum but not provide us the checksum value. use
-                * CHECSUM_UNNECESSARY.
-                *
-                * In case of encap pkt tcp_udp_csum_ok/tcp_udp_csum_ok is
-                * inner csum_ok. outer_csum_ok is set by hw when outer udp
-                * csum is correct or is zero.
-                */
-               if ((netdev->features & NETIF_F_RXCSUM) && !csum_not_calc &&
-                   tcp_udp_csum_ok && outer_csum_ok &&
-                   (ipv4_csum_ok || ipv6)) {
-                       skb->ip_summed = CHECKSUM_UNNECESSARY;
-                       skb->csum_level = encap;
-                       if (encap)
-                               rqstats->csum_unnecessary_encap++;
-                       else
-                               rqstats->csum_unnecessary++;
-               }
-
-               if (vlan_stripped) {
-                       __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_tci);
-                       rqstats->vlan_stripped++;
-               }
+               enic_rq_set_skb_flags(rq, type, rss_hash, rss_type, fcoe,
+                                     fcoe_fc_crc_ok, vlan_stripped,
+                                     csum_not_calc, tcp_udp_csum_ok, ipv6,
+                                     ipv4_csum_ok, vlan_tci, skb);
                skb_mark_napi_id(skb, &enic->napi[rq->index]);
                if (!(netdev->features & NETIF_F_GRO))
                        netif_receive_skb(skb);