net/qede/base: use function pointers for spq async callback
[dpdk.git] / drivers / net / qede / base / ecore_sriov.c
index 7ac533e..2b8e24c 100644 (file)
 #include "ecore_init_fw_funcs.h"
 #include "ecore_sp_commands.h"
 
+static enum _ecore_status_t ecore_sriov_eqe_event(struct ecore_hwfn *p_hwfn,
+                                                 u8 opcode,
+                                                 __le16 echo,
+                                                 union event_ring_data *data,
+                                                 u8 fw_return_code);
+
 const char *ecore_channel_tlvs_string[] = {
        "CHANNEL_TLV_NONE",     /* ends tlv sequence */
        "CHANNEL_TLV_ACQUIRE",
@@ -54,11 +60,11 @@ const char *ecore_channel_tlvs_string[] = {
        "CHANNEL_TLV_UPDATE_TUNN_PARAM",
        "CHANNEL_TLV_COALESCE_UPDATE",
        "CHANNEL_TLV_QID",
+       "CHANNEL_TLV_COALESCE_READ",
        "CHANNEL_TLV_MAX"
 };
 
-static u8 ecore_vf_calculate_legacy(struct ecore_hwfn *p_hwfn,
-                                   struct ecore_vf_info *p_vf)
+static u8 ecore_vf_calculate_legacy(struct ecore_vf_info *p_vf)
 {
        u8 legacy = 0;
 
@@ -210,9 +216,7 @@ struct ecore_vf_info *ecore_iov_get_vf_info(struct ecore_hwfn *p_hwfn,
 }
 
 static struct ecore_queue_cid *
-ecore_iov_get_vf_rx_queue_cid(struct ecore_hwfn *p_hwfn,
-                             struct ecore_vf_info *p_vf,
-                             struct ecore_vf_queue *p_queue)
+ecore_iov_get_vf_rx_queue_cid(struct ecore_vf_queue *p_queue)
 {
        int i;
 
@@ -231,8 +235,7 @@ enum ecore_iov_validate_q_mode {
        ECORE_IOV_VALIDATE_Q_DISABLE,
 };
 
-static bool ecore_iov_validate_queue_mode(struct ecore_hwfn *p_hwfn,
-                                         struct ecore_vf_info *p_vf,
+static bool ecore_iov_validate_queue_mode(struct ecore_vf_info *p_vf,
                                          u16 qid,
                                          enum ecore_iov_validate_q_mode mode,
                                          bool b_is_tx)
@@ -274,8 +277,7 @@ static bool ecore_iov_validate_rxq(struct ecore_hwfn *p_hwfn,
                return false;
        }
 
-       return ecore_iov_validate_queue_mode(p_hwfn, p_vf, rx_qid,
-                                            mode, false);
+       return ecore_iov_validate_queue_mode(p_vf, rx_qid, mode, false);
 }
 
 static bool ecore_iov_validate_txq(struct ecore_hwfn *p_hwfn,
@@ -291,8 +293,7 @@ static bool ecore_iov_validate_txq(struct ecore_hwfn *p_hwfn,
                return false;
        }
 
-       return ecore_iov_validate_queue_mode(p_hwfn, p_vf, tx_qid,
-                                            mode, true);
+       return ecore_iov_validate_queue_mode(p_vf, tx_qid, mode, true);
 }
 
 static bool ecore_iov_validate_sb(struct ecore_hwfn *p_hwfn,
@@ -314,13 +315,12 @@ static bool ecore_iov_validate_sb(struct ecore_hwfn *p_hwfn,
 }
 
 /* Is there at least 1 queue open? */
-static bool ecore_iov_validate_active_rxq(struct ecore_hwfn *p_hwfn,
-                                         struct ecore_vf_info *p_vf)
+static bool ecore_iov_validate_active_rxq(struct ecore_vf_info *p_vf)
 {
        u8 i;
 
        for (i = 0; i < p_vf->num_rxqs; i++)
-               if (ecore_iov_validate_queue_mode(p_hwfn, p_vf, i,
+               if (ecore_iov_validate_queue_mode(p_vf, i,
                                                  ECORE_IOV_VALIDATE_Q_ENABLE,
                                                  false))
                        return true;
@@ -328,13 +328,12 @@ static bool ecore_iov_validate_active_rxq(struct ecore_hwfn *p_hwfn,
        return false;
 }
 
-static bool ecore_iov_validate_active_txq(struct ecore_hwfn *p_hwfn,
-                                         struct ecore_vf_info *p_vf)
+static bool ecore_iov_validate_active_txq(struct ecore_vf_info *p_vf)
 {
        u8 i;
 
        for (i = 0; i < p_vf->num_txqs; i++)
-               if (ecore_iov_validate_queue_mode(p_hwfn, p_vf, i,
+               if (ecore_iov_validate_queue_mode(p_vf, i,
                                                  ECORE_IOV_VALIDATE_Q_ENABLE,
                                                  true))
                        return true;
@@ -598,6 +597,9 @@ enum _ecore_status_t ecore_iov_alloc(struct ecore_hwfn *p_hwfn)
 
        p_hwfn->pf_iov_info = p_sriov;
 
+       ecore_spq_register_async_cb(p_hwfn, PROTOCOLID_COMMON,
+                                   ecore_sriov_eqe_event);
+
        return ecore_iov_allocate_vfdb(p_hwfn);
 }
 
@@ -611,6 +613,8 @@ void ecore_iov_setup(struct ecore_hwfn *p_hwfn)
 
 void ecore_iov_free(struct ecore_hwfn *p_hwfn)
 {
+       ecore_spq_unregister_async_cb(p_hwfn, PROTOCOLID_COMMON);
+
        if (IS_PF_SRIOV_ALLOC(p_hwfn)) {
                ecore_iov_free_vfdb(p_hwfn);
                OSAL_FREE(p_hwfn->p_dev, p_hwfn->pf_iov_info);
@@ -818,12 +822,48 @@ static void ecore_iov_vf_igu_set_int(struct ecore_hwfn *p_hwfn,
        ecore_fid_pretend(p_hwfn, p_ptt, (u16)p_hwfn->hw_info.concrete_fid);
 }
 
+static enum _ecore_status_t
+ecore_iov_enable_vf_access_msix(struct ecore_hwfn *p_hwfn,
+                               struct ecore_ptt *p_ptt,
+                               u8 abs_vf_id,
+                               u8 num_sbs)
+{
+       u8 current_max = 0;
+       int i;
+
+       /* If client overrides this, don't do anything */
+       if (p_hwfn->p_dev->b_dont_override_vf_msix)
+               return ECORE_SUCCESS;
+
+       /* For AH onward, configuration is per-PF. Find maximum of all
+        * the currently enabled child VFs, and set the number to be that.
+        */
+       if (!ECORE_IS_BB(p_hwfn->p_dev)) {
+               ecore_for_each_vf(p_hwfn, i) {
+                       struct ecore_vf_info *p_vf;
+
+                       p_vf  = ecore_iov_get_vf_info(p_hwfn, (u16)i, true);
+                       if (!p_vf)
+                               continue;
+
+                       current_max = OSAL_MAX_T(u8, current_max,
+                                                p_vf->num_sbs);
+               }
+       }
+
+       if (num_sbs > current_max)
+               return ecore_mcp_config_vf_msix(p_hwfn, p_ptt,
+                                               abs_vf_id, num_sbs);
+
+       return ECORE_SUCCESS;
+}
+
 static enum _ecore_status_t
 ecore_iov_enable_vf_access(struct ecore_hwfn *p_hwfn,
                           struct ecore_ptt *p_ptt, struct ecore_vf_info *vf)
 {
        u32 igu_vf_conf = IGU_VF_CONF_FUNC_EN;
-       enum _ecore_status_t rc;
+       enum _ecore_status_t rc = ECORE_SUCCESS;
 
        if (vf->to_disable)
                return ECORE_SUCCESS;
@@ -839,9 +879,8 @@ ecore_iov_enable_vf_access(struct ecore_hwfn *p_hwfn,
 
        /* It's possible VF was previously considered malicious */
        vf->b_malicious = false;
-
-       rc = ecore_mcp_config_vf_msix(p_hwfn, p_ptt,
-                                     vf->abs_vf_id, vf->num_sbs);
+       rc = ecore_iov_enable_vf_access_msix(p_hwfn, p_ptt,
+                                            vf->abs_vf_id, vf->num_sbs);
        if (rc != ECORE_SUCCESS)
                return rc;
 
@@ -1267,8 +1306,7 @@ static void ecore_iov_unlock_vf_pf_channel(struct ecore_hwfn *p_hwfn,
 }
 
 /* place a given tlv on the tlv buffer, continuing current tlv list */
-void *ecore_add_tlv(struct ecore_hwfn *p_hwfn,
-                   u8 **offset, u16 type, u16 length)
+void *ecore_add_tlv(u8 **offset, u16 type, u16 length)
 {
        struct channel_tlv *tl = (struct channel_tlv *)*offset;
 
@@ -1324,7 +1362,12 @@ void ecore_dp_tlv_list(struct ecore_hwfn *p_hwfn, void *tlvs_list)
 static void ecore_iov_send_response(struct ecore_hwfn *p_hwfn,
                                    struct ecore_ptt *p_ptt,
                                    struct ecore_vf_info *p_vf,
-                                   u16 length, u8 status)
+#ifdef CONFIG_ECORE_SW_CHANNEL
+                                   u16 length,
+#else
+                                   u16 OSAL_UNUSED length,
+#endif
+                                   u8 status)
 {
        struct ecore_iov_vf_mbx *mbx = &p_vf->vf_mbx;
        struct ecore_dmae_params params;
@@ -1361,10 +1404,11 @@ static void ecore_iov_send_response(struct ecore_hwfn *p_hwfn,
        REG_WR(p_hwfn,
               GTT_BAR0_MAP_REG_USDM_RAM +
               USTORM_VF_PF_CHANNEL_READY_OFFSET(eng_vf_id), 1);
+
+       OSAL_IOV_PF_RESP_TYPE(p_hwfn, p_vf->relative_vf_id, status);
 }
 
-static u16 ecore_iov_vport_to_tlv(struct ecore_hwfn *p_hwfn,
-                                 enum ecore_iov_vport_update_flag flag)
+static u16 ecore_iov_vport_to_tlv(enum ecore_iov_vport_update_flag flag)
 {
        switch (flag) {
        case ECORE_IOV_VP_UPDATE_ACTIVATE:
@@ -1402,15 +1446,15 @@ static u16 ecore_iov_prep_vp_update_resp_tlvs(struct ecore_hwfn *p_hwfn,
        size = sizeof(struct pfvf_def_resp_tlv);
        total_len = size;
 
-       ecore_add_tlv(p_hwfn, &p_mbx->offset, CHANNEL_TLV_VPORT_UPDATE, size);
+       ecore_add_tlv(&p_mbx->offset, CHANNEL_TLV_VPORT_UPDATE, size);
 
        /* Prepare response for all extended tlvs if they are found by PF */
        for (i = 0; i < ECORE_IOV_VP_UPDATE_MAX; i++) {
                if (!(tlvs_mask & (1 << i)))
                        continue;
 
-               resp = ecore_add_tlv(p_hwfn, &p_mbx->offset,
-                                    ecore_iov_vport_to_tlv(p_hwfn, i), size);
+               resp = ecore_add_tlv(&p_mbx->offset, ecore_iov_vport_to_tlv(i),
+                                    size);
 
                if (tlvs_accepted & (1 << i))
                        resp->hdr.status = status;
@@ -1420,12 +1464,13 @@ static u16 ecore_iov_prep_vp_update_resp_tlvs(struct ecore_hwfn *p_hwfn,
                DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
                           "VF[%d] - vport_update resp: TLV %d, status %02x\n",
                           p_vf->relative_vf_id,
-                          ecore_iov_vport_to_tlv(p_hwfn, i), resp->hdr.status);
+                          ecore_iov_vport_to_tlv(i),
+                          resp->hdr.status);
 
                total_len += size;
        }
 
-       ecore_add_tlv(p_hwfn, &p_mbx->offset, CHANNEL_TLV_LIST_END,
+       ecore_add_tlv(&p_mbx->offset, CHANNEL_TLV_LIST_END,
                      sizeof(struct channel_list_end_tlv));
 
        return total_len;
@@ -1440,13 +1485,11 @@ static void ecore_iov_prepare_resp(struct ecore_hwfn *p_hwfn,
 
        mbx->offset = (u8 *)mbx->reply_virt;
 
-       ecore_add_tlv(p_hwfn, &mbx->offset, type, length);
-       ecore_add_tlv(p_hwfn, &mbx->offset, CHANNEL_TLV_LIST_END,
+       ecore_add_tlv(&mbx->offset, type, length);
+       ecore_add_tlv(&mbx->offset, CHANNEL_TLV_LIST_END,
                      sizeof(struct channel_list_end_tlv));
 
        ecore_iov_send_response(p_hwfn, p_ptt, vf_info, length, status);
-
-       OSAL_IOV_PF_RESP_TYPE(p_hwfn, vf_info->relative_vf_id, status);
 }
 
 struct ecore_public_vf_info
@@ -1496,7 +1539,6 @@ static void ecore_iov_vf_cleanup(struct ecore_hwfn *p_hwfn,
 }
 
 static u8 ecore_iov_vf_mbx_acquire_resc(struct ecore_hwfn *p_hwfn,
-                                       struct ecore_ptt *p_ptt,
                                        struct ecore_vf_info *p_vf,
                                        struct vf_pf_resc_request *p_req,
                                        struct pf_vf_resc *p_resp)
@@ -1574,8 +1616,7 @@ static u8 ecore_iov_vf_mbx_acquire_resc(struct ecore_hwfn *p_hwfn,
        return PFVF_STATUS_SUCCESS;
 }
 
-static void ecore_iov_vf_mbx_acquire_stats(struct ecore_hwfn *p_hwfn,
-                                          struct pfvf_stats_info *p_stats)
+static void ecore_iov_vf_mbx_acquire_stats(struct pfvf_stats_info *p_stats)
 {
        p_stats->mstats.address = PXP_VF_BAR0_START_MSDM_ZONE_B +
                                  OFFSETOF(struct mstorm_vf_zone,
@@ -1698,7 +1739,7 @@ static void ecore_iov_vf_mbx_acquire(struct ecore_hwfn       *p_hwfn,
        if (req->vfdev_info.capabilities & VFPF_ACQUIRE_CAP_QUEUE_QIDS)
                pfdev_info->capabilities |= PFVF_ACQUIRE_CAP_QUEUE_QIDS;
 
-       ecore_iov_vf_mbx_acquire_stats(p_hwfn, &pfdev_info->stats_info);
+       ecore_iov_vf_mbx_acquire_stats(&pfdev_info->stats_info);
 
        OSAL_MEMCPY(pfdev_info->port_mac, p_hwfn->hw_info.hw_mac_addr,
                    ETH_ALEN);
@@ -1723,7 +1764,7 @@ static void ecore_iov_vf_mbx_acquire(struct ecore_hwfn       *p_hwfn,
        /* Fill resources available to VF; Make sure there are enough to
         * satisfy the VF's request.
         */
-       vfpf_status = ecore_iov_vf_mbx_acquire_resc(p_hwfn, p_ptt, vf,
+       vfpf_status = ecore_iov_vf_mbx_acquire_resc(p_hwfn, vf,
                                                    &req->resc_request, resc);
        if (vfpf_status != PFVF_STATUS_SUCCESS)
                goto out;
@@ -1939,8 +1980,7 @@ ecore_iov_configure_vport_forced(struct ecore_hwfn *p_hwfn,
                        struct ecore_queue_cid *p_cid = OSAL_NULL;
 
                        /* There can be at most 1 Rx queue on qzone. Find it */
-                       p_cid = ecore_iov_get_vf_rx_queue_cid(p_hwfn, p_vf,
-                                                             p_queue);
+                       p_cid = ecore_iov_get_vf_rx_queue_cid(p_queue);
                        if (p_cid == OSAL_NULL)
                                continue;
 
@@ -2079,13 +2119,15 @@ static void ecore_iov_vf_mbx_stop_vport(struct ecore_hwfn *p_hwfn,
        vf->vport_instance--;
        vf->spoof_chk = false;
 
-       if ((ecore_iov_validate_active_rxq(p_hwfn, vf)) ||
-           (ecore_iov_validate_active_txq(p_hwfn, vf))) {
+       if ((ecore_iov_validate_active_rxq(vf)) ||
+           (ecore_iov_validate_active_txq(vf))) {
                vf->b_malicious = true;
                DP_NOTICE(p_hwfn, false,
                          "VF [%02x] - considered malicious;"
                          " Unable to stop RX/TX queuess\n",
                          vf->abs_vf_id);
+               status = PFVF_STATUS_MALICIOUS;
+               goto out;
        }
 
        rc = ecore_sp_vport_stop(p_hwfn, vf->opaque_fid, vf->vport_id);
@@ -2099,6 +2141,7 @@ static void ecore_iov_vf_mbx_stop_vport(struct ecore_hwfn *p_hwfn,
        vf->configured_features = 0;
        OSAL_MEMSET(&vf->shadow_config, 0, sizeof(vf->shadow_config));
 
+out:
        ecore_iov_prepare_resp(p_hwfn, p_ptt, vf, CHANNEL_TLV_VPORT_TEARDOWN,
                               sizeof(struct pfvf_def_resp_tlv), status);
 }
@@ -2124,9 +2167,8 @@ static void ecore_iov_vf_mbx_start_rxq_resp(struct ecore_hwfn *p_hwfn,
        else
                length = sizeof(struct pfvf_def_resp_tlv);
 
-       p_tlv = ecore_add_tlv(p_hwfn, &mbx->offset, CHANNEL_TLV_START_RXQ,
-                             length);
-       ecore_add_tlv(p_hwfn, &mbx->offset, CHANNEL_TLV_LIST_END,
+       p_tlv = ecore_add_tlv(&mbx->offset, CHANNEL_TLV_START_RXQ, length);
+       ecore_add_tlv(&mbx->offset, CHANNEL_TLV_LIST_END,
                      sizeof(struct channel_list_end_tlv));
 
        /* Update the TLV with the response */
@@ -2207,7 +2249,7 @@ static void ecore_iov_vf_mbx_start_rxq(struct ecore_hwfn *p_hwfn,
        if (p_queue->cids[qid_usage_idx].p_cid)
                goto out;
 
-       vf_legacy = ecore_vf_calculate_legacy(p_hwfn, vf);
+       vf_legacy = ecore_vf_calculate_legacy(vf);
 
        /* Acquire a new queue-cid */
        OSAL_MEMSET(&params, 0, sizeof(params));
@@ -2228,7 +2270,7 @@ static void ecore_iov_vf_mbx_start_rxq(struct ecore_hwfn *p_hwfn,
        vf_params.qid_usage_idx = qid_usage_idx;
 
        p_cid = ecore_eth_queue_to_cid(p_hwfn, vf->opaque_fid,
-                                      &params, &vf_params);
+                                      &params, true, &vf_params);
        if (p_cid == OSAL_NULL)
                goto out;
 
@@ -2402,11 +2444,11 @@ static void ecore_iov_vf_mbx_update_tunn_param(struct ecore_hwfn *p_hwfn,
        }
 
 send_resp:
-       p_resp = ecore_add_tlv(p_hwfn, &mbx->offset,
+       p_resp = ecore_add_tlv(&mbx->offset,
                               CHANNEL_TLV_UPDATE_TUNN_PARAM, sizeof(*p_resp));
 
        ecore_iov_pf_update_tun_response(p_resp, p_tun, tunn_feature_mask);
-       ecore_add_tlv(p_hwfn, &mbx->offset, CHANNEL_TLV_LIST_END,
+       ecore_add_tlv(&mbx->offset, CHANNEL_TLV_LIST_END,
                      sizeof(struct channel_list_end_tlv));
 
        ecore_iov_send_response(p_hwfn, p_ptt, p_vf, sizeof(*p_resp), status);
@@ -2438,9 +2480,8 @@ static void ecore_iov_vf_mbx_start_txq_resp(struct ecore_hwfn *p_hwfn,
        else
                length = sizeof(struct pfvf_def_resp_tlv);
 
-       p_tlv = ecore_add_tlv(p_hwfn, &mbx->offset, CHANNEL_TLV_START_TXQ,
-                             length);
-       ecore_add_tlv(p_hwfn, &mbx->offset, CHANNEL_TLV_LIST_END,
+       p_tlv = ecore_add_tlv(&mbx->offset, CHANNEL_TLV_START_TXQ, length);
+       ecore_add_tlv(&mbx->offset, CHANNEL_TLV_LIST_END,
                      sizeof(struct channel_list_end_tlv));
 
        /* Update the TLV with the response */
@@ -2483,7 +2524,7 @@ static void ecore_iov_vf_mbx_start_txq(struct ecore_hwfn *p_hwfn,
        if (p_queue->cids[qid_usage_idx].p_cid)
                goto out;
 
-       vf_legacy = ecore_vf_calculate_legacy(p_hwfn, vf);
+       vf_legacy = ecore_vf_calculate_legacy(vf);
 
        /* Acquire a new queue-cid */
        params.queue_id = p_queue->fw_tx_qid;
@@ -2503,7 +2544,7 @@ static void ecore_iov_vf_mbx_start_txq(struct ecore_hwfn *p_hwfn,
        vf_params.qid_usage_idx = qid_usage_idx;
 
        p_cid = ecore_eth_queue_to_cid(p_hwfn, vf->opaque_fid,
-                                      &params, &vf_params);
+                                      &params, false, &vf_params);
        if (p_cid == OSAL_NULL)
                goto out;
 
@@ -2552,7 +2593,7 @@ static enum _ecore_status_t ecore_iov_vf_stop_rxqs(struct ecore_hwfn *p_hwfn,
            p_queue->cids[qid_usage_idx].b_is_tx) {
                struct ecore_queue_cid *p_cid;
 
-               p_cid = ecore_iov_get_vf_rx_queue_cid(p_hwfn, vf, p_queue);
+               p_cid = ecore_iov_get_vf_rx_queue_cid(p_queue);
                DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
                           "VF[%d] - Tried Closing Rx 0x%04x.%02x, but Rx is at %04x.%02x\n",
                            vf->relative_vf_id, rxq_id, qid_usage_idx,
@@ -2974,8 +3015,7 @@ ecore_iov_vp_update_rss_param(struct ecore_hwfn *p_hwfn,
                        goto out;
                }
 
-               p_cid = ecore_iov_get_vf_rx_queue_cid(p_hwfn, vf,
-                                                     &vf->vf_queues[q_idx]);
+               p_cid = ecore_iov_get_vf_rx_queue_cid(&vf->vf_queues[q_idx]);
                p_rss->rss_ind_table[i] = p_cid;
        }
 
@@ -2988,7 +3028,6 @@ out:
 
 static void
 ecore_iov_vp_update_sge_tpa_param(struct ecore_hwfn *p_hwfn,
-                                 struct ecore_vf_info *vf,
                                  struct ecore_sp_vport_update_params *p_data,
                                  struct ecore_sge_tpa_params *p_sge_tpa,
                                  struct ecore_iov_vf_mbx *p_mbx,
@@ -3078,7 +3117,7 @@ static void ecore_iov_vf_mbx_vport_update(struct ecore_hwfn *p_hwfn,
        ecore_iov_vp_update_mcast_bin_param(p_hwfn, &params, mbx, &tlvs_mask);
        ecore_iov_vp_update_accept_flag(p_hwfn, &params, mbx, &tlvs_mask);
        ecore_iov_vp_update_accept_any_vlan(p_hwfn, &params, mbx, &tlvs_mask);
-       ecore_iov_vp_update_sge_tpa_param(p_hwfn, vf, &params,
+       ecore_iov_vp_update_sge_tpa_param(p_hwfn, &params,
                                          &sge_tpa_params, mbx, &tlvs_mask);
 
        tlvs_accepted = tlvs_mask;
@@ -3425,6 +3464,76 @@ static void ecore_iov_vf_mbx_release(struct ecore_hwfn *p_hwfn,
                               length, status);
 }
 
+static void ecore_iov_vf_pf_get_coalesce(struct ecore_hwfn *p_hwfn,
+                                        struct ecore_ptt *p_ptt,
+                                        struct ecore_vf_info *p_vf)
+{
+       struct ecore_iov_vf_mbx *mbx = &p_vf->vf_mbx;
+       struct pfvf_read_coal_resp_tlv *p_resp;
+       struct vfpf_read_coal_req_tlv *req;
+       u8 status = PFVF_STATUS_FAILURE;
+       struct ecore_vf_queue *p_queue;
+       struct ecore_queue_cid *p_cid;
+       enum _ecore_status_t rc = ECORE_SUCCESS;
+       u16 coal = 0, qid, i;
+       bool b_is_rx;
+
+       mbx->offset = (u8 *)mbx->reply_virt;
+       req = &mbx->req_virt->read_coal_req;
+
+       qid = req->qid;
+       b_is_rx = req->is_rx ? true : false;
+
+       if (b_is_rx) {
+               if (!ecore_iov_validate_rxq(p_hwfn, p_vf, qid,
+                                           ECORE_IOV_VALIDATE_Q_ENABLE)) {
+                       DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
+                                  "VF[%d]: Invalid Rx queue_id = %d\n",
+                                  p_vf->abs_vf_id, qid);
+                       goto send_resp;
+               }
+
+               p_cid = ecore_iov_get_vf_rx_queue_cid(&p_vf->vf_queues[qid]);
+               rc = ecore_get_rxq_coalesce(p_hwfn, p_ptt, p_cid, &coal);
+               if (rc != ECORE_SUCCESS)
+                       goto send_resp;
+       } else {
+               if (!ecore_iov_validate_txq(p_hwfn, p_vf, qid,
+                                           ECORE_IOV_VALIDATE_Q_ENABLE)) {
+                       DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
+                                  "VF[%d]: Invalid Tx queue_id = %d\n",
+                                  p_vf->abs_vf_id, qid);
+                       goto send_resp;
+               }
+               for (i = 0; i < MAX_QUEUES_PER_QZONE; i++) {
+                       p_queue = &p_vf->vf_queues[qid];
+                       if ((p_queue->cids[i].p_cid == OSAL_NULL) ||
+                           (!p_queue->cids[i].b_is_tx))
+                               continue;
+
+                       p_cid = p_queue->cids[i].p_cid;
+
+                       rc = ecore_get_txq_coalesce(p_hwfn, p_ptt,
+                                                   p_cid, &coal);
+                       if (rc != ECORE_SUCCESS)
+                               goto send_resp;
+                       break;
+               }
+       }
+
+       status = PFVF_STATUS_SUCCESS;
+
+send_resp:
+       p_resp = ecore_add_tlv(&mbx->offset, CHANNEL_TLV_COALESCE_READ,
+                              sizeof(*p_resp));
+       p_resp->coal = coal;
+
+       ecore_add_tlv(&mbx->offset, CHANNEL_TLV_LIST_END,
+                     sizeof(struct channel_list_end_tlv));
+
+       ecore_iov_send_response(p_hwfn, p_ptt, p_vf, sizeof(*p_resp), status);
+}
+
 static void ecore_iov_vf_pf_set_coalesce(struct ecore_hwfn *p_hwfn,
                                         struct ecore_ptt *p_ptt,
                                         struct ecore_vf_info *vf)
@@ -3465,8 +3574,7 @@ static void ecore_iov_vf_pf_set_coalesce(struct ecore_hwfn *p_hwfn,
                   vf->abs_vf_id, rx_coal, tx_coal, qid);
 
        if (rx_coal) {
-               p_cid = ecore_iov_get_vf_rx_queue_cid(p_hwfn, vf,
-                                                     &vf->vf_queues[qid]);
+               p_cid = ecore_iov_get_vf_rx_queue_cid(&vf->vf_queues[qid]);
 
                rc = ecore_set_rxq_coalesce(p_hwfn, p_ptt, rx_coal, p_cid);
                if (rc != ECORE_SUCCESS) {
@@ -3552,8 +3660,7 @@ ecore_iov_pf_configure_vf_queue_coalesce(struct ecore_hwfn *p_hwfn,
                   vf->abs_vf_id, rx_coal, tx_coal, qid);
 
        if (rx_coal) {
-               p_cid = ecore_iov_get_vf_rx_queue_cid(p_hwfn, vf,
-                                                     &vf->vf_queues[qid]);
+               p_cid = ecore_iov_get_vf_rx_queue_cid(&vf->vf_queues[qid]);
 
                rc = ecore_set_rxq_coalesce(p_hwfn, p_ptt, rx_coal, p_cid);
                if (rc != ECORE_SUCCESS) {
@@ -3865,11 +3972,11 @@ void ecore_iov_get_link(struct ecore_hwfn *p_hwfn,
        p_bulletin = p_vf->bulletin.p_virt;
 
        if (p_params)
-               __ecore_vf_get_link_params(p_hwfn, p_params, p_bulletin);
+               __ecore_vf_get_link_params(p_params, p_bulletin);
        if (p_link)
-               __ecore_vf_get_link_state(p_hwfn, p_link, p_bulletin);
+               __ecore_vf_get_link_state(p_link, p_bulletin);
        if (p_caps)
-               __ecore_vf_get_link_caps(p_hwfn, p_caps, p_bulletin);
+               __ecore_vf_get_link_caps(p_caps, p_bulletin);
 }
 
 void ecore_iov_process_mbx_req(struct ecore_hwfn *p_hwfn,
@@ -3961,6 +4068,9 @@ void ecore_iov_process_mbx_req(struct ecore_hwfn *p_hwfn,
                case CHANNEL_TLV_COALESCE_UPDATE:
                        ecore_iov_vf_pf_set_coalesce(p_hwfn, p_ptt, p_vf);
                        break;
+               case CHANNEL_TLV_COALESCE_READ:
+                       ecore_iov_vf_pf_get_coalesce(p_hwfn, p_ptt, p_vf);
+                       break;
                }
        } else if (ecore_iov_tlv_supported(mbx->first_tlv.tl.type)) {
                /* If we've received a message from a VF we consider malicious
@@ -4096,10 +4206,11 @@ static void ecore_sriov_vfpf_malicious(struct ecore_hwfn *p_hwfn,
        OSAL_PF_VF_MALICIOUS(p_hwfn, p_vf->relative_vf_id);
 }
 
-enum _ecore_status_t ecore_sriov_eqe_event(struct ecore_hwfn *p_hwfn,
-                                          u8 opcode,
-                                          __le16 echo,
-                                          union event_ring_data *data)
+static enum _ecore_status_t ecore_sriov_eqe_event(struct ecore_hwfn *p_hwfn,
+                                                 u8 opcode,
+                                                 __le16 echo,
+                                                 union event_ring_data *data,
+                                                 u8 OSAL_UNUSED fw_return_code)
 {
        switch (opcode) {
        case COMMON_EVENT_VF_PF_CHANNEL: