return NULL;
 }
 
+/**
+ * ice_get_netdev_priv_vsi - return VSI associated with netdev priv.
+ * @np: private netdev structure
+ */
+static inline struct ice_vsi *ice_get_netdev_priv_vsi(struct ice_netdev_priv *np)
+{
+       /* In case of port representor return source port VSI. */
+       if (np->repr)
+               return np->repr->src_vsi;
+       else
+               return np->vsi;
+}
+
 /**
  * ice_get_ctrl_vsi - Get the control VSI
  * @pf: PF instance
 int ice_vsi_open_ctrl(struct ice_vsi *vsi);
 int ice_vsi_open(struct ice_vsi *vsi);
 void ice_set_ethtool_ops(struct net_device *netdev);
+void ice_set_ethtool_repr_ops(struct net_device *netdev);
 void ice_set_ethtool_safe_mode_ops(struct net_device *netdev);
 u16 ice_get_avail_txq_count(struct ice_pf *pf);
 u16 ice_get_avail_rxq_count(struct ice_pf *pf);
 
                                vsi->idx);
                        continue;
                }
+               /* no need to proceed with remaining cfg if it is switchdev
+                * VSI
+                */
+               if (vsi->type == ICE_VSI_SWITCHDEV_CTRL)
+                       continue;
 
                ice_vsi_map_rings_to_vectors(vsi);
                if (vsi->type == ICE_VSI_PF)
 
 #define ICE_PRIV_FLAG_ARRAY_SIZE       ARRAY_SIZE(ice_gstrings_priv_flags)
 
 static void
-ice_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
+__ice_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo,
+                 struct ice_vsi *vsi)
 {
-       struct ice_netdev_priv *np = netdev_priv(netdev);
-       struct ice_vsi *vsi = np->vsi;
        struct ice_pf *pf = vsi->back;
        struct ice_hw *hw = &pf->hw;
        struct ice_orom_info *orom;
        drvinfo->n_priv_flags = ICE_PRIV_FLAG_ARRAY_SIZE;
 }
 
+static void
+ice_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
+{
+       struct ice_netdev_priv *np = netdev_priv(netdev);
+
+       __ice_get_drvinfo(netdev, drvinfo, np->vsi);
+}
+
+static void
+ice_repr_get_drvinfo(struct net_device *netdev,
+                    struct ethtool_drvinfo *drvinfo)
+{
+       struct ice_repr *repr = ice_netdev_to_repr(netdev);
+
+       if (ice_check_vf_ready_for_cfg(repr->vf))
+               return;
+
+       __ice_get_drvinfo(netdev, drvinfo, repr->src_vsi);
+}
+
 static int ice_get_regs_len(struct net_device __always_unused *netdev)
 {
        return sizeof(ice_regs_dump_list);
 static void ice_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
 {
        struct ice_netdev_priv *np = netdev_priv(netdev);
-       struct ice_vsi *vsi = np->vsi;
+       struct ice_vsi *vsi = ice_get_netdev_priv_vsi(np);
        unsigned int i;
        u8 *p = data;
 
                        ethtool_sprintf(&p,
                                        ice_gstrings_vsi_stats[i].stat_string);
 
+               if (ice_is_port_repr_netdev(netdev))
+                       return;
+
                ice_for_each_alloc_txq(vsi, i) {
                        ethtool_sprintf(&p, "tx_queue_%u_packets", i);
                        ethtool_sprintf(&p, "tx_queue_%u_bytes", i);
                 * order of strings will suffer from race conditions and are
                 * not safe.
                 */
+               if (ice_is_port_repr_netdev(netdev))
+                       return ICE_VSI_STATS_LEN;
+
                return ICE_ALL_STATS_LEN(netdev);
        case ETH_SS_TEST:
                return ICE_TEST_LEN;
                      struct ethtool_stats __always_unused *stats, u64 *data)
 {
        struct ice_netdev_priv *np = netdev_priv(netdev);
-       struct ice_vsi *vsi = np->vsi;
+       struct ice_vsi *vsi = ice_get_netdev_priv_vsi(np);
        struct ice_pf *pf = vsi->back;
        struct ice_ring *ring;
        unsigned int j;
                             sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
        }
 
+       if (ice_is_port_repr_netdev(netdev))
+               return;
+
        /* populate per queue stats */
        rcu_read_lock();
 
        netdev->ethtool_ops = &ice_ethtool_safe_mode_ops;
 }
 
+static const struct ethtool_ops ice_ethtool_repr_ops = {
+       .get_drvinfo            = ice_repr_get_drvinfo,
+       .get_link               = ethtool_op_get_link,
+       .get_strings            = ice_get_strings,
+       .get_ethtool_stats      = ice_get_ethtool_stats,
+       .get_sset_count         = ice_get_sset_count,
+};
+
+/**
+ * ice_set_ethtool_repr_ops - setup VF's port representor ethtool ops
+ * @netdev: network interface device structure
+ */
+void ice_set_ethtool_repr_ops(struct net_device *netdev)
+{
+       netdev->ethtool_ops = &ice_ethtool_repr_ops;
+}
+
 /**
  * ice_set_ethtool_ops - setup netdev ethtool ops
  * @netdev: network interface device structure
 
        return 0;
 }
 
+/**
+ * ice_repr_get_stats64 - get VF stats for VFPR use
+ * @netdev: pointer to port representor netdev
+ * @stats: pointer to struct where stats can be stored
+ */
+static void
+ice_repr_get_stats64(struct net_device *netdev, struct rtnl_link_stats64 *stats)
+{
+       struct ice_netdev_priv *np = netdev_priv(netdev);
+       struct ice_eth_stats *eth_stats;
+       struct ice_vsi *vsi;
+
+       if (ice_is_vf_disabled(np->repr->vf))
+               return;
+       vsi = np->repr->src_vsi;
+
+       ice_update_vsi_stats(vsi);
+       eth_stats = &vsi->eth_stats;
+
+       stats->tx_packets = eth_stats->tx_unicast + eth_stats->tx_broadcast +
+                           eth_stats->tx_multicast;
+       stats->rx_packets = eth_stats->rx_unicast + eth_stats->rx_broadcast +
+                           eth_stats->rx_multicast;
+       stats->tx_bytes = eth_stats->tx_bytes;
+       stats->rx_bytes = eth_stats->rx_bytes;
+       stats->multicast = eth_stats->rx_multicast;
+       stats->tx_errors = eth_stats->tx_errors;
+       stats->tx_dropped = eth_stats->tx_discards;
+       stats->rx_dropped = eth_stats->rx_discards;
+}
+
 /**
  * ice_netdev_to_repr - Get port representor for given netdevice
  * @netdev: pointer to port representor netdev
 
 static const struct net_device_ops ice_repr_netdev_ops = {
        .ndo_get_phys_port_name = ice_repr_get_phys_port_name,
+       .ndo_get_stats64 = ice_repr_get_stats64,
        .ndo_open = ice_repr_open,
        .ndo_stop = ice_repr_stop,
        .ndo_start_xmit = ice_eswitch_port_start_xmit,
 {
        eth_hw_addr_random(netdev);
        netdev->netdev_ops = &ice_repr_netdev_ops;
+       ice_set_ethtool_repr_ops(netdev);
 
        netif_carrier_off(netdev);
        netif_tx_stop_all_queues(netdev);
 
  *
  * Returns true if the PF or VF is disabled, false otherwise.
  */
-static bool ice_is_vf_disabled(struct ice_vf *vf)
+bool ice_is_vf_disabled(struct ice_vf *vf)
 {
        struct ice_pf *pf = vf->pf;
 
  * disabled, and initialized so it can be configured and/or queried by a host
  * administrator.
  */
-static int ice_check_vf_ready_for_cfg(struct ice_vf *vf)
+int ice_check_vf_ready_for_cfg(struct ice_vf *vf)
 {
        struct ice_pf *pf;
 
 
 
 int ice_set_vf_link_state(struct net_device *netdev, int vf_id, int link_state);
 
+int ice_check_vf_ready_for_cfg(struct ice_vf *vf);
+
+bool ice_is_vf_disabled(struct ice_vf *vf);
+
 int ice_set_vf_spoofchk(struct net_device *netdev, int vf_id, bool ena);
 
 int ice_calc_vf_reg_idx(struct ice_vf *vf, struct ice_q_vector *q_vector);
 static inline void ice_print_vf_rx_mdd_event(struct ice_vf *vf) { }
 static inline void ice_restore_all_vfs_msi_state(struct pci_dev *pdev) { }
 
+static inline int ice_check_vf_ready_for_cfg(struct ice_vf *vf)
+{
+       return -EOPNOTSUPP;
+}
+
+static inline bool ice_is_vf_disabled(struct ice_vf *vf)
+{
+       return true;
+}
+
 static inline struct ice_vsi *ice_get_vf_vsi(struct ice_vf *vf)
 {
        return NULL;