fm10k: re-enable VF after a full reset on detection of a Malicious event
authorJacob Keller <jacob.e.keller@intel.com>
Wed, 24 Jun 2015 20:34:48 +0000 (13:34 -0700)
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>
Wed, 16 Sep 2015 00:06:14 +0000 (17:06 -0700)
Modify behavior of Malicious Driver Detection events. Presently, the
hardware disables the VF queues and re-assigns them to the PF. This
causes the VF in question to continuously Tx hang, because it assumes
that it can transmit over the queues in question. For transient events,
this results in continuous logging of malicious events.

New behavior is to reset the LPORT and VF state, so that the VF will
have to reset and re-enable itself. This does mean that malicious VFs
will possibly be able to continue and attempt malicious events again.
However, it is expected that system administrators will step in and
manually remove or disable the VF in question.

Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Tested-by: Krishneil Singh <krishneil.k.singh@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
drivers/net/ethernet/intel/fm10k/fm10k_pci.c

index 9bdc04da451ef63af9eede40c1315ceb644df910..3d71c520611018373b0d139638535ad2aabb74e6 100644 (file)
@@ -880,10 +880,12 @@ void fm10k_netpoll(struct net_device *netdev)
 
 #endif
 #define FM10K_ERR_MSG(type) case (type): error = #type; break
-static void fm10k_print_fault(struct fm10k_intfc *interface, int type,
+static void fm10k_handle_fault(struct fm10k_intfc *interface, int type,
                              struct fm10k_fault *fault)
 {
        struct pci_dev *pdev = interface->pdev;
+       struct fm10k_hw *hw = &interface->hw;
+       struct fm10k_iov_data *iov_data = interface->iov_data;
        char *error;
 
        switch (type) {
@@ -937,6 +939,30 @@ static void fm10k_print_fault(struct fm10k_intfc *interface, int type,
                 "%s Address: 0x%llx SpecInfo: 0x%x Func: %02x.%0x\n",
                 error, fault->address, fault->specinfo,
                 PCI_SLOT(fault->func), PCI_FUNC(fault->func));
+
+       /* For VF faults, clear out the respective LPORT, reset the queue
+        * resources, and then reconnect to the mailbox. This allows the
+        * VF in question to resume behavior. For transient faults that are
+        * the result of non-malicious behavior this will log the fault and
+        * allow the VF to resume functionality. Obviously for malicious VFs
+        * they will be able to attempt malicious behavior again. In this
+        * case, the system administrator will need to step in and manually
+        * remove or disable the VF in question.
+        */
+       if (fault->func && iov_data) {
+               int vf = fault->func - 1;
+               struct fm10k_vf_info *vf_info = &iov_data->vf_info[vf];
+
+               hw->iov.ops.reset_lport(hw, vf_info);
+               hw->iov.ops.reset_resources(hw, vf_info);
+
+               /* reset_lport disables the VF, so re-enable it */
+               hw->iov.ops.set_lport(hw, vf_info, vf,
+                                     FM10K_VF_FLAG_MULTI_CAPABLE);
+
+               /* reset_resources will disconnect from the mbx  */
+               vf_info->mbx.ops.connect(hw, &vf_info->mbx);
+       }
 }
 
 static void fm10k_report_fault(struct fm10k_intfc *interface, u32 eicr)
@@ -960,7 +986,7 @@ static void fm10k_report_fault(struct fm10k_intfc *interface, u32 eicr)
                        continue;
                }
 
-               fm10k_print_fault(interface, type, &fault);
+               fm10k_handle_fault(interface, type, &fault);
        }
 }