#include <net/netevent.h>
 
 #include "en.h"
+#include "eswitch.h"
 #include "ipsec.h"
 #include "ipsec_rxtx.h"
 #include "en_rep.h"
        if (err)
                goto err_xfrm;
 
+       if (!mlx5_eswitch_block_ipsec(priv->mdev)) {
+               err = -EBUSY;
+               goto err_xfrm;
+       }
+
        /* check esn */
        if (x->props.flags & XFRM_STATE_ESN)
                mlx5e_ipsec_update_esn_state(sa_entry);
 
        err = mlx5_ipsec_create_work(sa_entry);
        if (err)
-               goto err_xfrm;
+               goto unblock_ipsec;
 
        err = mlx5e_ipsec_create_dwork(sa_entry);
        if (err)
        if (sa_entry->work)
                kfree(sa_entry->work->data);
        kfree(sa_entry->work);
+unblock_ipsec:
+       mlx5_eswitch_unblock_ipsec(priv->mdev);
 err_xfrm:
        kfree(sa_entry);
        NL_SET_ERR_MSG_WEAK_MOD(extack, "Device failed to offload this state");
 static void mlx5e_xfrm_free_state(struct xfrm_state *x)
 {
        struct mlx5e_ipsec_sa_entry *sa_entry = to_ipsec_sa_entry(x);
+       struct mlx5e_ipsec *ipsec = sa_entry->ipsec;
 
        if (x->xso.flags & XFRM_DEV_OFFLOAD_FLAG_ACQ)
                goto sa_entry_free;
        if (sa_entry->work)
                kfree(sa_entry->work->data);
        kfree(sa_entry->work);
+       mlx5_eswitch_unblock_ipsec(ipsec->mdev);
 sa_entry_free:
        kfree(sa_entry);
 }
        pol_entry->x = x;
        pol_entry->ipsec = priv->ipsec;
 
+       if (!mlx5_eswitch_block_ipsec(priv->mdev)) {
+               err = -EBUSY;
+               goto ipsec_busy;
+       }
+
        mlx5e_ipsec_build_accel_pol_attrs(pol_entry, &pol_entry->attrs);
        err = mlx5e_accel_ipsec_fs_add_pol(pol_entry);
        if (err)
        return 0;
 
 err_fs:
+       mlx5_eswitch_unblock_ipsec(priv->mdev);
+ipsec_busy:
        kfree(pol_entry);
        NL_SET_ERR_MSG_MOD(extack, "Device failed to offload this policy");
        return err;
        struct mlx5e_ipsec_pol_entry *pol_entry = to_ipsec_pol_entry(x);
 
        mlx5e_accel_ipsec_fs_del_pol(pol_entry);
+       mlx5_eswitch_unblock_ipsec(pol_entry->ipsec->mdev);
 }
 
 static void mlx5e_xfrm_free_policy(struct xfrm_policy *x)
 
 #include "devlink.h"
 #include "ecpf.h"
 #include "en/mod_hdr.h"
+#include "en_accel/ipsec.h"
 
 enum {
        MLX5_ACTION_NONE = 0,
        return mlx5_esw_allowed(esw) ? esw->dev : NULL;
 }
 EXPORT_SYMBOL(mlx5_eswitch_get_core_dev);
+
+bool mlx5_eswitch_block_ipsec(struct mlx5_core_dev *dev)
+{
+       struct mlx5_eswitch *esw = dev->priv.eswitch;
+
+       if (!mlx5_esw_allowed(esw))
+               return true;
+
+       mutex_lock(&esw->state_lock);
+       if (esw->enabled_ipsec_vf_count) {
+               mutex_unlock(&esw->state_lock);
+               return false;
+       }
+
+       dev->num_ipsec_offloads++;
+       mutex_unlock(&esw->state_lock);
+       return true;
+}
+
+void mlx5_eswitch_unblock_ipsec(struct mlx5_core_dev *dev)
+{
+       struct mlx5_eswitch *esw = dev->priv.eswitch;
+
+       if (!mlx5_esw_allowed(esw))
+               /* Failure means no eswitch => core dev is not a PF */
+               return;
+
+       mutex_lock(&esw->state_lock);
+       dev->num_ipsec_offloads--;
+       mutex_unlock(&esw->state_lock);
+}
 
        struct blocking_notifier_head n_head;
        struct xarray paired;
        struct mlx5_devcom_comp_dev *devcom;
+       u16 enabled_ipsec_vf_count;
 };
 
 void esw_offloads_disable(struct mlx5_eswitch *esw);
 
 int mlx5_eswitch_restore_ipsec_rule(struct mlx5_eswitch *esw, struct mlx5_flow_handle *rule,
                                    struct mlx5_esw_flow_attr *esw_attr, int attr_idx);
+bool mlx5_eswitch_block_ipsec(struct mlx5_core_dev *dev);
+void mlx5_eswitch_unblock_ipsec(struct mlx5_core_dev *dev);
 #else  /* CONFIG_MLX5_ESWITCH */
 /* eswitch API stubs */
 static inline int  mlx5_eswitch_init(struct mlx5_core_dev *dev) { return 0; }
 
 static inline int mlx5_eswitch_block_mode(struct mlx5_core_dev *dev) { return 0; }
 static inline void mlx5_eswitch_unblock_mode(struct mlx5_core_dev *dev) {}
+static inline bool mlx5_eswitch_block_ipsec(struct mlx5_core_dev *dev)
+{
+       return false;
+}
+
+static inline void mlx5_eswitch_unblock_ipsec(struct mlx5_core_dev *dev) {}
 #endif /* CONFIG_MLX5_ESWITCH */
 
 #endif /* __MLX5_ESWITCH_H__ */
 
        /* MACsec notifier chain to sync MACsec core and IB database */
        struct blocking_notifier_head macsec_nh;
 #endif
+       u64 num_ipsec_offloads;
 };
 
 struct mlx5_db {