net/qede/base: prevent stop vport assert by malicious VF
[dpdk.git] / drivers / net / qede / base / ecore_sriov.c
index b8e03d0..792cf75 100644 (file)
@@ -818,12 +818,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 +875,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;
 
@@ -2086,6 +2121,8 @@ static void ecore_iov_vf_mbx_stop_vport(struct ecore_hwfn *p_hwfn,
                          "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 +2136,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);
 }
@@ -3755,8 +3793,7 @@ cleanup:
                ack_vfs[vfid / 32] |= (1 << (vfid % 32));
                p_hwfn->pf_iov_info->pending_flr[rel_vf_id / 64] &=
                    ~(1ULL << (rel_vf_id % 64));
-               p_hwfn->pf_iov_info->pending_events[rel_vf_id / 64] &=
-                   ~(1ULL << (rel_vf_id % 64));
+               p_vf->vf_mbx.b_pending_msg = false;
        }
 
        return rc;
@@ -3886,12 +3923,22 @@ void ecore_iov_process_mbx_req(struct ecore_hwfn *p_hwfn,
        mbx = &p_vf->vf_mbx;
 
        /* ecore_iov_process_mbx_request */
-       DP_VERBOSE(p_hwfn,
-                  ECORE_MSG_IOV,
-                  "VF[%02x]: Processing mailbox message\n", p_vf->abs_vf_id);
+#ifndef CONFIG_ECORE_SW_CHANNEL
+       if (!mbx->b_pending_msg) {
+               DP_NOTICE(p_hwfn, true,
+                         "VF[%02x]: Trying to process mailbox message when none is pending\n",
+                         p_vf->abs_vf_id);
+               return;
+       }
+       mbx->b_pending_msg = false;
+#endif
 
        mbx->first_tlv = mbx->req_virt->first_tlv;
 
+       DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
+                  "VF[%02x]: Processing mailbox message [type %04x]\n",
+                  p_vf->abs_vf_id, mbx->first_tlv.tl.type);
+
        OSAL_IOV_VF_MSG_TYPE(p_hwfn,
                             p_vf->relative_vf_id,
                             mbx->first_tlv.tl.type);
@@ -4016,26 +4063,20 @@ void ecore_iov_process_mbx_req(struct ecore_hwfn *p_hwfn,
 #endif
 }
 
-void ecore_iov_pf_add_pending_events(struct ecore_hwfn *p_hwfn, u8 vfid)
+void ecore_iov_pf_get_pending_events(struct ecore_hwfn *p_hwfn,
+                                    u64 *events)
 {
-       u64 add_bit = 1ULL << (vfid % 64);
+       int i;
 
-       /* TODO - add locking mechanisms [no atomics in ecore, so we can't
-       * add the lock inside the ecore_pf_iov struct].
-       */
-       p_hwfn->pf_iov_info->pending_events[vfid / 64] |= add_bit;
-}
+       OSAL_MEM_ZERO(events, sizeof(u64) * ECORE_VF_ARRAY_LENGTH);
 
-void ecore_iov_pf_get_and_clear_pending_events(struct ecore_hwfn *p_hwfn,
-                                              u64 *events)
-{
-       u64 *p_pending_events = p_hwfn->pf_iov_info->pending_events;
+       ecore_for_each_vf(p_hwfn, i) {
+               struct ecore_vf_info *p_vf;
 
-       /* TODO - Take a lock */
-       OSAL_MEMCPY(events, p_pending_events,
-                   sizeof(u64) * ECORE_VF_ARRAY_LENGTH);
-       OSAL_MEMSET(p_pending_events, 0,
-                   sizeof(u64) * ECORE_VF_ARRAY_LENGTH);
+               p_vf = &p_hwfn->pf_iov_info->vfs_array[i];
+               if (p_vf->vf_mbx.b_pending_msg)
+                       events[i / 64] |= 1ULL << (i % 64);
+       }
 }
 
 static struct ecore_vf_info *
@@ -4069,6 +4110,8 @@ static enum _ecore_status_t ecore_sriov_vfpf_msg(struct ecore_hwfn *p_hwfn,
         */
        p_vf->vf_mbx.pending_req = (((u64)vf_msg->hi) << 32) | vf_msg->lo;
 
+       p_vf->vf_mbx.b_pending_msg = true;
+
        return OSAL_PF_VF_MSG(p_hwfn, p_vf->relative_vf_id);
 }