real_dev = is_vlan_dev(dev) ? vlan_dev_real_dev(dev) : dev;
        uplink_dev = mlx5_eswitch_uplink_get_proto_dev(esw, REP_ETH);
-       uplink_upper = netdev_master_upper_dev_get(uplink_dev);
+
+       rcu_read_lock();
+       uplink_upper = netdev_master_upper_dev_get_rcu(uplink_dev);
+       /* mlx5_lag_is_sriov() is a blocking function which can't be called
+        * while holding rcu read lock. Take the net_device for correctness
+        * sake.
+        */
+       if (uplink_upper)
+               dev_hold(uplink_upper);
+       rcu_read_unlock();
+
        dst_is_lag_dev = (uplink_upper &&
                          netif_is_lag_master(uplink_upper) &&
                          real_dev == uplink_upper &&
                          mlx5_lag_is_sriov(priv->mdev));
+       if (uplink_upper)
+               dev_put(uplink_upper);
 
        /* if the egress device isn't on the same HW e-switch or
         * it's a LAG device, use the uplink
 
                        if (netdev_port_same_parent_id(priv->netdev, out_dev)) {
                                struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
                                struct net_device *uplink_dev = mlx5_eswitch_uplink_get_proto_dev(esw, REP_ETH);
-                               struct net_device *uplink_upper = netdev_master_upper_dev_get(uplink_dev);
+                               struct net_device *uplink_upper;
 
+                               rcu_read_lock();
+                               uplink_upper =
+                                       netdev_master_upper_dev_get_rcu(uplink_dev);
                                if (uplink_upper &&
                                    netif_is_lag_master(uplink_upper) &&
                                    uplink_upper == out_dev)
                                        out_dev = uplink_dev;
+                               rcu_read_unlock();
 
                                if (is_vlan_dev(out_dev)) {
                                        err = add_vlan_push_action(priv, attr,