|
@@ -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);
|
|
|
}
|
|
|
}
|
|
|
|