ADF_PF2VF_MSGTYPE_RESTARTING            = 0x01,
        ADF_PF2VF_MSGTYPE_VERSION_RESP          = 0x02,
        ADF_PF2VF_MSGTYPE_BLKMSG_RESP           = 0x03,
+       ADF_PF2VF_MSGTYPE_FATAL_ERROR           = 0x04,
+       ADF_PF2VF_MSGTYPE_RESTARTED             = 0x05,
 /* Values from 0x10 are Gen4 specific, message type is only 4 bits in Gen2 devices. */
        ADF_PF2VF_MSGTYPE_RP_RESET_RESP         = 0x10,
 };
        ADF_VF2PF_MSGTYPE_LARGE_BLOCK_REQ       = 0x07,
        ADF_VF2PF_MSGTYPE_MEDIUM_BLOCK_REQ      = 0x08,
        ADF_VF2PF_MSGTYPE_SMALL_BLOCK_REQ       = 0x09,
+       ADF_VF2PF_MSGTYPE_RESTARTING_COMPLETE   = 0x0a,
 /* Values from 0x10 are Gen4 specific, message type is only 4 bits in Gen2 devices. */
        ADF_VF2PF_MSGTYPE_RP_RESET              = 0x10,
 };
        ADF_PFVF_COMPAT_FAST_ACK                = 0x03,
        /* Ring to service mapping support for non-standard mappings */
        ADF_PFVF_COMPAT_RING_TO_SVC_MAP         = 0x04,
+       /* Fallback compat */
+       ADF_PFVF_COMPAT_FALLBACK                = 0x05,
        /* Reference to the latest version */
-       ADF_PFVF_COMPAT_THIS_VERSION            = 0x04,
+       ADF_PFVF_COMPAT_THIS_VERSION            = 0x05,
 };
 
 /* PF->VF Version Response */
 
 // SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0-only)
 /* Copyright(c) 2015 - 2021 Intel Corporation */
+#include <linux/delay.h>
 #include <linux/pci.h>
 #include "adf_accel_devices.h"
 #include "adf_pfvf_msg.h"
 #include "adf_pfvf_pf_msg.h"
 #include "adf_pfvf_pf_proto.h"
 
+#define ADF_PF_WAIT_RESTARTING_COMPLETE_DELAY  100
+#define ADF_VF_SHUTDOWN_RETRY                  100
+
 void adf_pf2vf_notify_restarting(struct adf_accel_dev *accel_dev)
 {
        struct adf_accel_vf_info *vf;
        struct pfvf_message msg = { .type = ADF_PF2VF_MSGTYPE_RESTARTING };
        int i, num_vfs = pci_num_vf(accel_to_pci_dev(accel_dev));
 
+       dev_dbg(&GET_DEV(accel_dev), "pf2vf notify restarting\n");
        for (i = 0, vf = accel_dev->pf.vf_info; i < num_vfs; i++, vf++) {
-               if (vf->init && adf_send_pf2vf_msg(accel_dev, i, msg))
+               vf->restarting = false;
+               if (!vf->init)
+                       continue;
+               if (adf_send_pf2vf_msg(accel_dev, i, msg))
                        dev_err(&GET_DEV(accel_dev),
                                "Failed to send restarting msg to VF%d\n", i);
+               else if (vf->vf_compat_ver >= ADF_PFVF_COMPAT_FALLBACK)
+                       vf->restarting = true;
+       }
+}
+
+void adf_pf2vf_wait_for_restarting_complete(struct adf_accel_dev *accel_dev)
+{
+       int num_vfs = pci_num_vf(accel_to_pci_dev(accel_dev));
+       int i, retries = ADF_VF_SHUTDOWN_RETRY;
+       struct adf_accel_vf_info *vf;
+       bool vf_running;
+
+       dev_dbg(&GET_DEV(accel_dev), "pf2vf wait for restarting complete\n");
+       do {
+               vf_running = false;
+               for (i = 0, vf = accel_dev->pf.vf_info; i < num_vfs; i++, vf++)
+                       if (vf->restarting)
+                               vf_running = true;
+               if (!vf_running)
+                       break;
+               msleep(ADF_PF_WAIT_RESTARTING_COMPLETE_DELAY);
+       } while (--retries);
+
+       if (vf_running)
+               dev_warn(&GET_DEV(accel_dev), "Some VFs are still running\n");
+}
+
+void adf_pf2vf_notify_restarted(struct adf_accel_dev *accel_dev)
+{
+       struct pfvf_message msg = { .type = ADF_PF2VF_MSGTYPE_RESTARTED };
+       int i, num_vfs = pci_num_vf(accel_to_pci_dev(accel_dev));
+       struct adf_accel_vf_info *vf;
+
+       dev_dbg(&GET_DEV(accel_dev), "pf2vf notify restarted\n");
+       for (i = 0, vf = accel_dev->pf.vf_info; i < num_vfs; i++, vf++) {
+               if (vf->init && vf->vf_compat_ver >= ADF_PFVF_COMPAT_FALLBACK &&
+                   adf_send_pf2vf_msg(accel_dev, i, msg))
+                       dev_err(&GET_DEV(accel_dev),
+                               "Failed to send restarted msg to VF%d\n", i);
+       }
+}
+
+void adf_pf2vf_notify_fatal_error(struct adf_accel_dev *accel_dev)
+{
+       struct pfvf_message msg = { .type = ADF_PF2VF_MSGTYPE_FATAL_ERROR };
+       int i, num_vfs = pci_num_vf(accel_to_pci_dev(accel_dev));
+       struct adf_accel_vf_info *vf;
+
+       dev_dbg(&GET_DEV(accel_dev), "pf2vf notify fatal error\n");
+       for (i = 0, vf = accel_dev->pf.vf_info; i < num_vfs; i++, vf++) {
+               if (vf->init && vf->vf_compat_ver >= ADF_PFVF_COMPAT_FALLBACK &&
+                   adf_send_pf2vf_msg(accel_dev, i, msg))
+                       dev_err(&GET_DEV(accel_dev),
+                               "Failed to send fatal error msg to VF%d\n", i);
        }
 }
 
 
 
 #include "adf_accel_devices.h"
 
+#if defined(CONFIG_PCI_IOV)
 void adf_pf2vf_notify_restarting(struct adf_accel_dev *accel_dev);
+void adf_pf2vf_wait_for_restarting_complete(struct adf_accel_dev *accel_dev);
+void adf_pf2vf_notify_restarted(struct adf_accel_dev *accel_dev);
+void adf_pf2vf_notify_fatal_error(struct adf_accel_dev *accel_dev);
+#else
+static inline void adf_pf2vf_notify_restarting(struct adf_accel_dev *accel_dev)
+{
+}
+
+static inline void adf_pf2vf_wait_for_restarting_complete(struct adf_accel_dev *accel_dev)
+{
+}
+
+static inline void adf_pf2vf_notify_restarted(struct adf_accel_dev *accel_dev)
+{
+}
+
+static inline void adf_pf2vf_notify_fatal_error(struct adf_accel_dev *accel_dev)
+{
+}
+#endif
 
 typedef int (*adf_pf2vf_blkmsg_provider)(struct adf_accel_dev *accel_dev,
                                         u8 *buffer, u8 compat);