*
  * 2. When the caller starts processing its mailbox queue in response to an
  * interrupt, the structure ice_mbx_snapshot is expected to be cleared before
- * the algorithm can be run for the first time for that interrupt. This can be
- * done via ice_mbx_reset_snapshot().
+ * the algorithm can be run for the first time for that interrupt. This
+ * requires calling ice_mbx_reset_snapshot() as well as calling
+ * ice_mbx_reset_vf_info() for each VF tracking structure.
  *
  * 3. For every message read by the caller from the MBX Queue, the caller must
  * call the detection algorithm's entry function ice_mbx_vf_state_handler().
  * Before every call to ice_mbx_vf_state_handler() the struct ice_mbx_data is
  * filled as it is required to be passed to the algorithm.
  *
- * 4. Every time a message is read from the MBX queue, a VFId is received which
- * is passed to the state handler. The boolean output is_malvf of the state
- * handler ice_mbx_vf_state_handler() serves as an indicator to the caller
- * whether this VF is malicious or not.
+ * 4. Every time a message is read from the MBX queue, a tracking structure
+ * for the VF must be passed to the state handler. The boolean output
+ * report_malvf from ice_mbx_vf_state_handler() serves as an indicator to the
+ * caller whether it must report this VF as malicious or not.
  *
  * 5. When a VF is identified to be malicious, the caller can send a message
- * to the system administrator. The caller can invoke ice_mbx_report_malvf()
- * to help determine if a malicious VF is to be reported or not. This function
- * requires the caller to maintain a global bitmap to track all malicious VFs
- * and pass that to ice_mbx_report_malvf() along with the VFID which was identified
- * to be malicious by ice_mbx_vf_state_handler().
+ * to the system administrator.
  *
- * 6. The global bitmap maintained by PF can be cleared completely if PF is in
- * reset or the bit corresponding to a VF can be cleared if that VF is in reset.
- * When a VF is shut down and brought back up, we assume that the new VF
- * brought up is not malicious and hence report it if found malicious.
+ * 6. The PF is responsible for maintaining the struct ice_mbx_vf_info
+ * structure for each VF. The PF should clear the VF tracking structure if the
+ * VF is reset. When a VF is shut down and brought back up, we will then
+ * assume that the new VF is not malicious and may report it again if we
+ * detect it again.
  *
  * 7. The function ice_mbx_reset_snapshot() is called to reset the information
  * in ice_mbx_snapshot for every new mailbox interrupt handled.
- *
- * 8. The memory allocated for variables in ice_mbx_snapshot is de-allocated
- * when driver is unloaded.
  */
 #define ICE_RQ_DATA_MASK(rq_data) ((rq_data) & PF_MBX_ARQH_ARQH_M)
 /* Using the highest value for an unsigned 16-bit value 0xFFFF to indicate that
 
 /**
  * ice_mbx_reset_snapshot - Reset mailbox snapshot structure
- * @snap: pointer to mailbox snapshot structure in the ice_hw struct
- *
- * Reset the mailbox snapshot structure and clear VF counter array.
+ * @snap: pointer to the mailbox snapshot
  */
 static void ice_mbx_reset_snapshot(struct ice_mbx_snapshot *snap)
 {
-       u32 vfcntr_len;
-
-       if (!snap || !snap->mbx_vf.vf_cntr)
-               return;
+       struct ice_mbx_vf_info *vf_info;
 
-       /* Clear VF counters. */
-       vfcntr_len = snap->mbx_vf.vfcntr_len;
-       if (vfcntr_len)
-               memset(snap->mbx_vf.vf_cntr, 0,
-                      (vfcntr_len * sizeof(*snap->mbx_vf.vf_cntr)));
-
-       /* Reset mailbox snapshot for a new capture. */
+       /* Clear mbx_buf in the mailbox snaphot structure and setting the
+        * mailbox snapshot state to a new capture.
+        */
        memset(&snap->mbx_buf, 0, sizeof(snap->mbx_buf));
        snap->mbx_buf.state = ICE_MAL_VF_DETECT_STATE_NEW_SNAPSHOT;
+
+       /* Reset message counts for all VFs to zero */
+       list_for_each_entry(vf_info, &snap->mbx_vf, list_entry)
+               vf_info->msg_count = 0;
 }
 
 /**
 /**
  * ice_mbx_detect_malvf - Detect malicious VF in snapshot
  * @hw: pointer to the HW struct
- * @vf_id: relative virtual function ID
+ * @vf_info: mailbox tracking structure for a VF
  * @new_state: new algorithm state
  * @is_malvf: boolean output to indicate if VF is malicious
  *
  * the permissible number of messages to send.
  */
 static int
-ice_mbx_detect_malvf(struct ice_hw *hw, u16 vf_id,
+ice_mbx_detect_malvf(struct ice_hw *hw, struct ice_mbx_vf_info *vf_info,
                     enum ice_mbx_snapshot_state *new_state,
                     bool *is_malvf)
 {
-       struct ice_mbx_snapshot *snap = &hw->mbx_snapshot;
+       /* increment the message count for this VF */
+       vf_info->msg_count++;
 
-       if (vf_id >= snap->mbx_vf.vfcntr_len)
-               return -EIO;
-
-       /* increment the message count in the VF array */
-       snap->mbx_vf.vf_cntr[vf_id]++;
-
-       if (snap->mbx_vf.vf_cntr[vf_id] >= ICE_ASYNC_VF_MSG_THRESHOLD)
+       if (vf_info->msg_count >= ICE_ASYNC_VF_MSG_THRESHOLD)
                *is_malvf = true;
 
        /* continue to iterate through the mailbox snapshot */
  * ice_mbx_vf_state_handler - Handle states of the overflow algorithm
  * @hw: pointer to the HW struct
  * @mbx_data: pointer to structure containing mailbox data
- * @vf_id: relative virtual function (VF) ID
+ * @vf_info: mailbox tracking structure for the VF in question
  * @is_malvf: boolean output to indicate if VF is malicious
  *
  * The function serves as an entry point for the malicious VF
  */
 int
 ice_mbx_vf_state_handler(struct ice_hw *hw,
-                        struct ice_mbx_data *mbx_data, u16 vf_id,
+                        struct ice_mbx_data *mbx_data,
+                        struct ice_mbx_vf_info *vf_info,
                         bool *is_malvf)
 {
        struct ice_mbx_snapshot *snap = &hw->mbx_snapshot;
                if (snap_buf->num_pending_arq >=
                    mbx_data->async_watermark_val) {
                        new_state = ICE_MAL_VF_DETECT_STATE_DETECT;
-                       status = ice_mbx_detect_malvf(hw, vf_id, &new_state, is_malvf);
+                       status = ice_mbx_detect_malvf(hw, vf_info, &new_state,
+                                                     is_malvf);
                } else {
                        new_state = ICE_MAL_VF_DETECT_STATE_TRAVERSE;
                        ice_mbx_traverse(hw, &new_state);
 
        case ICE_MAL_VF_DETECT_STATE_DETECT:
                new_state = ICE_MAL_VF_DETECT_STATE_DETECT;
-               status = ice_mbx_detect_malvf(hw, vf_id, &new_state, is_malvf);
+               status = ice_mbx_detect_malvf(hw, vf_info, &new_state,
+                                             is_malvf);
                break;
 
        default:
 }
 
 /**
- * ice_mbx_clear_malvf - Clear VF bitmap and counter for VF ID
- * @snap: pointer to the mailbox snapshot structure
- * @vf_id: relative virtual function ID of the malicious VF
- * @vf_info: mailbox tracking structure for this VF
+ * ice_mbx_clear_malvf - Clear VF mailbox info
+ * @vf_info: the mailbox tracking structure for a VF
  *
-* In case of a VF reset, this function shall be called to clear the VF's
-* current mailbox tracking state.
-*/
-void
-ice_mbx_clear_malvf(struct ice_mbx_snapshot *snap, u16 vf_id,
-                   struct ice_mbx_vf_info *vf_info)
+ * In case of a VF reset, this function shall be called to clear the VF's
+ * current mailbox tracking state.
+ */
+void ice_mbx_clear_malvf(struct ice_mbx_vf_info *vf_info)
 {
-       if (WARN_ON(!snap))
-               return;
-
-       /* Ensure VF ID value is not larger than bitmap or VF counter length */
-       if (WARN_ON(vf_id >= snap->mbx_vf.vfcntr_len))
-               return;
-
        vf_info->malicious = 0;
-
-       /* Clear the VF counter in the mailbox snapshot structure for that VF ID.
-        * This is to ensure that if a VF is unloaded and a new one brought back
-        * up with the same VF ID for a snapshot currently in traversal or detect
-        * state the counter for that VF ID does not increment on top of existing
-        * values in the mailbox overflow detection algorithm.
-        */
-       snap->mbx_vf.vf_cntr[vf_id] = 0;
+       vf_info->msg_count = 0;
 }
 
 /**
  * @hw: pointer to the hardware structure
  * @vf_info: the mailbox tracking info structure for a VF
  *
- * Initialize a VF mailbox tracking info structure.
+ * Initialize a VF mailbox tracking info structure and insert it into the
+ * snapshot list.
+ *
+ * If you remove the VF, you must also delete the associated VF info structure
+ * from the linked list.
  */
 void ice_mbx_init_vf_info(struct ice_hw *hw, struct ice_mbx_vf_info *vf_info)
 {
-       vf_info->malicious = 0;
+       struct ice_mbx_snapshot *snap = &hw->mbx_snapshot;
+
+       ice_mbx_clear_malvf(vf_info);
+       list_add(&vf_info->list_entry, &snap->mbx_vf);
 }
 
 /**
- * ice_mbx_init_snapshot - Initialize mailbox snapshot structure
+ * ice_mbx_init_snapshot - Initialize mailbox snapshot data
  * @hw: pointer to the hardware structure
- * @vf_count: number of VFs allocated on a PF
- *
- * Clear the mailbox snapshot structure and allocate memory
- * for the VF counter array based on the number of VFs allocated
- * on that PF.
  *
- * Assumption: This function will assume ice_get_caps() has already been
- * called to ensure that the vf_count can be compared against the number
- * of VFs supported as defined in the functional capabilities of the device.
+ * Clear the mailbox snapshot structure and initialize the VF mailbox list.
  */
-int ice_mbx_init_snapshot(struct ice_hw *hw, u16 vf_count)
+void ice_mbx_init_snapshot(struct ice_hw *hw)
 {
        struct ice_mbx_snapshot *snap = &hw->mbx_snapshot;
 
-       /* Ensure that the number of VFs allocated is non-zero and
-        * is not greater than the number of supported VFs defined in
-        * the functional capabilities of the PF.
-        */
-       if (!vf_count || vf_count > hw->func_caps.num_allocd_vfs)
-               return -EINVAL;
-
-       snap->mbx_vf.vf_cntr = devm_kcalloc(ice_hw_to_dev(hw), vf_count,
-                                           sizeof(*snap->mbx_vf.vf_cntr),
-                                           GFP_KERNEL);
-       if (!snap->mbx_vf.vf_cntr)
-               return -ENOMEM;
-
-       /* Setting the VF counter length to the number of allocated
-        * VFs for given PF's functional capabilities.
-        */
-       snap->mbx_vf.vfcntr_len = vf_count;
-
-       /* Clear mbx_buf in the mailbox snaphot structure and setting the
-        * mailbox snapshot state to a new capture.
-        */
-       memset(&snap->mbx_buf, 0, sizeof(snap->mbx_buf));
-       snap->mbx_buf.state = ICE_MAL_VF_DETECT_STATE_NEW_SNAPSHOT;
-
-       return 0;
+       INIT_LIST_HEAD(&snap->mbx_vf);
+       ice_mbx_reset_snapshot(snap);
 }
 
 /**
 {
        struct ice_mbx_snapshot *snap = &hw->mbx_snapshot;
 
-       /* Free VF counter array and reset VF counter length */
-       devm_kfree(ice_hw_to_dev(hw), snap->mbx_vf.vf_cntr);
-       snap->mbx_vf.vfcntr_len = 0;
-
        /* Clear mbx_buf in the mailbox snaphot structure */
        memset(&snap->mbx_buf, 0, sizeof(snap->mbx_buf));
 }