]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
ice: do switchdev slow-path Rx using PF VSI
authorMichal Swiatkowski <michal.swiatkowski@linux.intel.com>
Fri, 1 Mar 2024 11:54:13 +0000 (12:54 +0100)
committerTony Nguyen <anthony.l.nguyen@intel.com>
Mon, 25 Mar 2024 20:08:47 +0000 (13:08 -0700)
Add an ICE_RX_FLAG_MULTIDEV flag to Rx ring.

If it is set try to find correct port representor. Do it based on
src_vsi value stored in flex descriptor. Ids of representor pointers
stored in xarray are equal to corresponding src_vsi value. Thanks to
that we can directly get correct representor if we have src_vsi value.

Set multidev flag during ring configuration.

If the mode is switchdev, change the ring descriptor to the one that
contains src_vsi value.

PF netdev should be reconfigured, do it by calling ice_down() and
ice_up() if the netdev was up before configuring switchdev.

Reviewed-by: Marcin Szycik <marcin.szycik@linux.intel.com>
Signed-off-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
Tested-by: Sujai Buvaneswaran <sujai.buvaneswaran@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
drivers/net/ethernet/intel/ice/ice_base.c
drivers/net/ethernet/intel/ice/ice_eswitch.c
drivers/net/ethernet/intel/ice/ice_eswitch.h
drivers/net/ethernet/intel/ice/ice_txrx.h
drivers/net/ethernet/intel/ice/ice_txrx_lib.c

index 8ffae7fe894f6d4ecee1fb3f6bc50e7552e00000..662fc395edcca89f4a8da2ed4796dfcf917b80db 100644 (file)
@@ -452,6 +452,14 @@ static int ice_setup_rx_ctx(struct ice_rx_ring *ring)
        /* Rx queue threshold in units of 64 */
        rlan_ctx.lrxqthresh = 1;
 
+       /* PF acts as uplink for switchdev; set flex descriptor with src_vsi
+        * metadata and flags to allow redirecting to PR netdev
+        */
+       if (ice_is_eswitch_mode_switchdev(vsi->back)) {
+               ring->flags |= ICE_RX_FLAGS_MULTIDEV;
+               rxdid = ICE_RXDID_FLEX_NIC_2;
+       }
+
        /* Enable Flexible Descriptors in the queue context which
         * allows this driver to select a specific receive descriptor format
         * increasing context priority to pick up profile ID; default is 0x01;
index 5eba8dec9f9497b688d8efcca751b73ae64eb57e..86a6d58ad3ec96785d8740be6c73a2ac54130003 100644 (file)
@@ -21,8 +21,13 @@ static int ice_eswitch_setup_env(struct ice_pf *pf)
 {
        struct ice_vsi *uplink_vsi = pf->eswitch.uplink_vsi;
        struct net_device *netdev = uplink_vsi->netdev;
+       bool if_running = netif_running(netdev);
        struct ice_vsi_vlan_ops *vlan_ops;
 
+       if (if_running && !test_and_set_bit(ICE_VSI_DOWN, uplink_vsi->state))
+               if (ice_down(uplink_vsi))
+                       return -ENODEV;
+
        ice_remove_vsi_fltr(&pf->hw, uplink_vsi->idx);
 
        netif_addr_lock_bh(netdev);
@@ -51,8 +56,13 @@ static int ice_eswitch_setup_env(struct ice_pf *pf)
        if (ice_vsi_update_local_lb(uplink_vsi, true))
                goto err_override_local_lb;
 
+       if (if_running && ice_up(uplink_vsi))
+               goto err_up;
+
        return 0;
 
+err_up:
+       ice_vsi_update_local_lb(uplink_vsi, false);
 err_override_local_lb:
        ice_vsi_update_security(uplink_vsi, ice_vsi_ctx_clear_allow_override);
 err_override_uplink:
@@ -69,6 +79,9 @@ err_vlan_zero:
        ice_fltr_add_mac_and_broadcast(uplink_vsi,
                                       uplink_vsi->port_info->mac.perm_addr,
                                       ICE_FWD_TO_VSI);
+       if (if_running)
+               ice_up(uplink_vsi);
+
        return -ENODEV;
 }
 
@@ -493,3 +506,26 @@ void ice_eswitch_rebuild(struct ice_pf *pf)
        xa_for_each(&pf->eswitch.reprs, id, repr)
                ice_eswitch_detach(pf, repr->vf);
 }
+
+/**
+ * ice_eswitch_get_target - get netdev based on src_vsi from descriptor
+ * @rx_ring: ring used to receive the packet
+ * @rx_desc: descriptor used to get src_vsi value
+ *
+ * Get src_vsi value from descriptor and load correct representor. If it isn't
+ * found return rx_ring->netdev.
+ */
+struct net_device *ice_eswitch_get_target(struct ice_rx_ring *rx_ring,
+                                         union ice_32b_rx_flex_desc *rx_desc)
+{
+       struct ice_eswitch *eswitch = &rx_ring->vsi->back->eswitch;
+       struct ice_32b_rx_flex_desc_nic_2 *desc;
+       struct ice_repr *repr;
+
+       desc = (struct ice_32b_rx_flex_desc_nic_2 *)rx_desc;
+       repr = xa_load(&eswitch->reprs, le16_to_cpu(desc->src_vsi));
+       if (!repr)
+               return rx_ring->netdev;
+
+       return repr->netdev;
+}
index baad685074714642a0dd8cd1d6392365a3d7e2d4..e2e5c0c75e7d46ffb2070e0c57df9f04a1a3980b 100644 (file)
@@ -26,6 +26,8 @@ void ice_eswitch_set_target_vsi(struct sk_buff *skb,
                                struct ice_tx_offload_params *off);
 netdev_tx_t
 ice_eswitch_port_start_xmit(struct sk_buff *skb, struct net_device *netdev);
+struct net_device *ice_eswitch_get_target(struct ice_rx_ring *rx_ring,
+                                         union ice_32b_rx_flex_desc *rx_desc);
 #else /* CONFIG_ICE_SWITCHDEV */
 static inline void ice_eswitch_detach(struct ice_pf *pf, struct ice_vf *vf) { }
 
@@ -76,5 +78,12 @@ ice_eswitch_port_start_xmit(struct sk_buff *skb, struct net_device *netdev)
 {
        return NETDEV_TX_BUSY;
 }
+
+static inline struct net_device *
+ice_eswitch_get_target(struct ice_rx_ring *rx_ring,
+                      union ice_32b_rx_flex_desc *rx_desc)
+{
+       return rx_ring->netdev;
+}
 #endif /* CONFIG_ICE_SWITCHDEV */
 #endif /* _ICE_ESWITCH_H_ */
index af955b0e5dc5caeb3ce6ca3f9671772763270f52..feba314a3fe4413973a422a27f6c45caeaaf6639 100644 (file)
@@ -365,6 +365,7 @@ struct ice_rx_ring {
        u8 ptp_rx;
 #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)
        u8 flags;
        /* CL5 - 5th cacheline starts here */
        struct xdp_rxq_info xdp_rxq;
index f8f1d2bdc1be92b5bbfd1e3dd907d7c0d141dfbc..676c00e1554c36de59f981c2a0fc9896cc714417 100644 (file)
@@ -236,7 +236,14 @@ ice_process_skb_fields(struct ice_rx_ring *rx_ring,
        ice_rx_hash_to_skb(rx_ring, rx_desc, skb, ptype);
 
        /* modifies the skb - consumes the enet header */
-       skb->protocol = eth_type_trans(skb, rx_ring->netdev);
+       if (unlikely(rx_ring->flags & ICE_RX_FLAGS_MULTIDEV)) {
+               struct net_device *netdev = ice_eswitch_get_target(rx_ring,
+                                                                  rx_desc);
+
+               skb->protocol = eth_type_trans(skb, netdev);
+       } else {
+               skb->protocol = eth_type_trans(skb, rx_ring->netdev);
+       }
 
        ice_rx_csum(rx_ring, skb, rx_desc, ptype);