#include "qed_vf.h"
 
 /* IOV ramrods */
-static int qed_sp_vf_start(struct qed_hwfn *p_hwfn,
-                          u32 concrete_vfid, u16 opaque_vfid)
+static int qed_sp_vf_start(struct qed_hwfn *p_hwfn, struct qed_vf_info *p_vf)
 {
        struct vf_start_ramrod_data *p_ramrod = NULL;
        struct qed_spq_entry *p_ent = NULL;
        struct qed_sp_init_data init_data;
        int rc = -EINVAL;
+       u8 fp_minor;
 
        /* Get SPQ entry */
        memset(&init_data, 0, sizeof(init_data));
        init_data.cid = qed_spq_get_cid(p_hwfn);
-       init_data.opaque_fid = opaque_vfid;
+       init_data.opaque_fid = p_vf->opaque_fid;
        init_data.comp_mode = QED_SPQ_MODE_EBLOCK;
 
        rc = qed_sp_init_request(p_hwfn, &p_ent,
 
        p_ramrod = &p_ent->ramrod.vf_start;
 
-       p_ramrod->vf_id = GET_FIELD(concrete_vfid, PXP_CONCRETE_FID_VFID);
-       p_ramrod->opaque_fid = cpu_to_le16(opaque_vfid);
+       p_ramrod->vf_id = GET_FIELD(p_vf->concrete_fid, PXP_CONCRETE_FID_VFID);
+       p_ramrod->opaque_fid = cpu_to_le16(p_vf->opaque_fid);
+
+       switch (p_hwfn->hw_info.personality) {
+       case QED_PCI_ETH:
+               p_ramrod->personality = PERSONALITY_ETH;
+               break;
+       case QED_PCI_ETH_ROCE:
+               p_ramrod->personality = PERSONALITY_RDMA_AND_ETH;
+               break;
+       default:
+               DP_NOTICE(p_hwfn, "Unknown VF personality %d\n",
+                         p_hwfn->hw_info.personality);
+               return -EINVAL;
+       }
+
+       fp_minor = p_vf->acquire.vfdev_info.eth_fp_hsi_minor;
+       if (fp_minor > ETH_HSI_VER_MINOR) {
+               DP_VERBOSE(p_hwfn,
+                          QED_MSG_IOV,
+                          "VF [%d] - Requested fp hsi %02x.%02x which is slightly newer than PF's %02x.%02x; Configuring PFs version\n",
+                          p_vf->abs_vf_id,
+                          ETH_HSI_VER_MAJOR,
+                          fp_minor, ETH_HSI_VER_MAJOR, ETH_HSI_VER_MINOR);
+               fp_minor = ETH_HSI_VER_MINOR;
+       }
 
-       p_ramrod->personality = PERSONALITY_ETH;
        p_ramrod->hsi_fp_ver.major_ver_arr[ETH_VER_KEY] = ETH_HSI_VER_MAJOR;
-       p_ramrod->hsi_fp_ver.minor_ver_arr[ETH_VER_KEY] = ETH_HSI_VER_MINOR;
+       p_ramrod->hsi_fp_ver.minor_ver_arr[ETH_VER_KEY] = fp_minor;
+
+       DP_VERBOSE(p_hwfn, QED_MSG_IOV,
+                  "VF[%d] - Starting using HSI %02x.%02x\n",
+                  p_vf->abs_vf_id, ETH_HSI_VER_MAJOR, fp_minor);
 
        return qed_spq_post(p_hwfn, p_ent, NULL);
 }
        /* unpretend */
        qed_fid_pretend(p_hwfn, p_ptt, (u16) p_hwfn->hw_info.concrete_fid);
 
-       if (vf->state != VF_STOPPED) {
-               DP_NOTICE(p_hwfn, "VF[%02x] is already started\n",
-                         vf->abs_vf_id);
-               return -EINVAL;
-       }
-
-       /* Start VF */
-       rc = qed_sp_vf_start(p_hwfn, vf->concrete_fid, vf->opaque_fid);
-       if (rc)
-               DP_NOTICE(p_hwfn, "Failed to start VF[%02x]\n", vf->abs_vf_id);
-
        vf->state = VF_FREE;
 
        return rc;
        struct qed_mcp_link_params params;
        struct qed_mcp_link_state link;
        struct qed_vf_info *vf = NULL;
-       int rc = 0;
 
        vf = qed_iov_get_vf_info(p_hwfn, rel_vf_id, true);
        if (!vf) {
        memcpy(&caps, qed_mcp_get_link_capabilities(p_hwfn), sizeof(caps));
        qed_iov_set_link(p_hwfn, rel_vf_id, ¶ms, &link, &caps);
 
-       if (vf->state != VF_STOPPED) {
-               /* Stopping the VF */
-               rc = qed_sp_vf_stop(p_hwfn, vf->concrete_fid, vf->opaque_fid);
-
-               if (rc != 0) {
-                       DP_ERR(p_hwfn, "qed_sp_vf_stop returned error %d\n",
-                              rc);
-                       return rc;
-               }
-
-               vf->state = VF_STOPPED;
-       }
+       /* Forget the VF's acquisition message */
+       memset(&vf->acquire, 0, sizeof(vf->acquire));
 
        /* disablng interrupts and resetting permission table was done during
         * vf-close, however, we could get here without going through vf_close
                p_vf->vf_queues[i].rxq_active = 0;
 
        memset(&p_vf->shadow_config, 0, sizeof(p_vf->shadow_config));
+       memset(&p_vf->acquire, 0, sizeof(p_vf->acquire));
        qed_iov_clean_vf(p_hwfn, p_vf->relative_vf_id);
 }
 
        struct pfvf_acquire_resp_tlv *resp = &mbx->reply_virt->acquire_resp;
        struct pf_vf_pfdev_info *pfdev_info = &resp->pfdev_info;
        struct vfpf_acquire_tlv *req = &mbx->req_virt->acquire;
-       u8 i, vfpf_status = PFVF_STATUS_SUCCESS;
+       u8 i, vfpf_status = PFVF_STATUS_NOT_SUPPORTED;
        struct pf_vf_resc *resc = &resp->resc;
+       int rc;
+
+       memset(resp, 0, sizeof(*resp));
 
        /* Validate FW compatibility */
-       if (req->vfdev_info.fw_major != FW_MAJOR_VERSION ||
-           req->vfdev_info.fw_minor != FW_MINOR_VERSION ||
-           req->vfdev_info.fw_revision != FW_REVISION_VERSION ||
-           req->vfdev_info.fw_engineering != FW_ENGINEERING_VERSION) {
+       if (req->vfdev_info.eth_fp_hsi_major != ETH_HSI_VER_MAJOR) {
                DP_INFO(p_hwfn,
-                       "VF[%d] is running an incompatible driver [VF needs FW %02x:%02x:%02x:%02x but Hypervisor is using %02x:%02x:%02x:%02x]\n",
+                       "VF[%d] needs fastpath HSI %02x.%02x, which is incompatible with loaded FW's faspath HSI %02x.%02x\n",
                        vf->abs_vf_id,
-                       req->vfdev_info.fw_major,
-                       req->vfdev_info.fw_minor,
-                       req->vfdev_info.fw_revision,
-                       req->vfdev_info.fw_engineering,
-                       FW_MAJOR_VERSION,
-                       FW_MINOR_VERSION,
-                       FW_REVISION_VERSION, FW_ENGINEERING_VERSION);
-               vfpf_status = PFVF_STATUS_NOT_SUPPORTED;
+                       req->vfdev_info.eth_fp_hsi_major,
+                       req->vfdev_info.eth_fp_hsi_minor,
+                       ETH_HSI_VER_MAJOR, ETH_HSI_VER_MINOR);
+
+               /* Write the PF version so that VF would know which version
+                * is supported.
+                */
+               pfdev_info->major_fp_hsi = ETH_HSI_VER_MAJOR;
+               pfdev_info->minor_fp_hsi = ETH_HSI_VER_MINOR;
+
                goto out;
        }
 
                DP_INFO(p_hwfn,
                        "VF[%d] is running an old driver that doesn't support 100g\n",
                        vf->abs_vf_id);
-               vfpf_status = PFVF_STATUS_NOT_SUPPORTED;
                goto out;
        }
 
-       memset(resp, 0, sizeof(*resp));
+       /* Store the acquire message */
+       memcpy(&vf->acquire, req, sizeof(vf->acquire));
 
        /* Fill in vf info stuff */
        vf->opaque_fid = req->vfdev_info.opaque_fid;
        pfdev_info->fw_minor = FW_MINOR_VERSION;
        pfdev_info->fw_rev = FW_REVISION_VERSION;
        pfdev_info->fw_eng = FW_ENGINEERING_VERSION;
+       pfdev_info->minor_fp_hsi = min_t(u8,
+                                        ETH_HSI_VER_MINOR,
+                                        req->vfdev_info.eth_fp_hsi_minor);
        pfdev_info->os_type = VFPF_ACQUIRE_OS_LINUX;
        qed_mcp_get_mfw_ver(p_hwfn, p_ptt, &pfdev_info->mfw_ver, NULL);
 
         */
        resc->num_mc_filters = req->resc_request.num_mc_filters;
 
+       /* Start the VF in FW */
+       rc = qed_sp_vf_start(p_hwfn, vf);
+       if (rc) {
+               DP_NOTICE(p_hwfn, "Failed to start VF[%02x]\n", vf->abs_vf_id);
+               vfpf_status = PFVF_STATUS_FAILURE;
+               goto out;
+       }
+
        /* Fill agreed size of bulletin board in response */
        resp->bulletin_size = vf->bulletin.size;
        qed_iov_post_vf_bulletin(p_hwfn, vf->relative_vf_id, p_ptt);
                                   struct qed_vf_info *p_vf)
 {
        u16 length = sizeof(struct pfvf_def_resp_tlv);
+       u8 status = PFVF_STATUS_SUCCESS;
+       int rc = 0;
 
        qed_iov_vf_cleanup(p_hwfn, p_vf);
 
+       if (p_vf->state != VF_STOPPED && p_vf->state != VF_FREE) {
+               /* Stopping the VF */
+               rc = qed_sp_vf_stop(p_hwfn, p_vf->concrete_fid,
+                                   p_vf->opaque_fid);
+
+               if (rc) {
+                       DP_ERR(p_hwfn, "qed_sp_vf_stop returned error %d\n",
+                              rc);
+                       status = PFVF_STATUS_FAILURE;
+               }
+
+               p_vf->state = VF_STOPPED;
+       }
+
        qed_iov_prepare_resp(p_hwfn, p_ptt, p_vf, CHANNEL_TLV_RELEASE,
-                            length, PFVF_STATUS_SUCCESS);
+                            length, status);
 }
 
 static int