]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
i40e: Restore VF MSI-X state during PCI reset
authorAndrii Staikov <andrii.staikov@intel.com>
Thu, 21 Dec 2023 13:27:35 +0000 (14:27 +0100)
committerTony Nguyen <anthony.l.nguyen@intel.com>
Wed, 3 Jan 2024 19:18:54 +0000 (11:18 -0800)
During a PCI FLR the MSI-X Enable flag in the VF PCI MSI-X capability
register will be cleared. This can lead to issues when a VF is
assigned to a VM because in these cases the VF driver receives no
indication of the PF PCI error/reset and additionally it is incapable
of restoring the cleared flag in the hypervisor configuration space
without fully reinitializing the driver interrupt functionality.

Since the VF driver is unable to easily resolve this condition on its own,
restore the VF MSI-X flag during the PF PCI reset handling.

Fixes: 19b7960b2da1 ("i40e: implement split PCI error reset handler")
Co-developed-by: Karen Ostrowska <karen.ostrowska@intel.com>
Signed-off-by: Karen Ostrowska <karen.ostrowska@intel.com>
Co-developed-by: Mateusz Palczewski <mateusz.palczewski@intel.com>
Signed-off-by: Mateusz Palczewski <mateusz.palczewski@intel.com>
Reviewed-by: Wojciech Drewek <wojciech.drewek@intel.com>
Reviewed-by: Przemek Kitszel <przemyslaw.kitszel@intel.com>
Signed-off-by: Andrii Staikov <andrii.staikov@intel.com>
Tested-by: Rafal Romanowski <rafal.romanowski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
drivers/net/ethernet/intel/i40e/i40e_main.c
drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h

index d5633a440cca6c6af50cbcf7b4c3a3f3075b9d43..d5519af3465773e57100da8662b93346a516cf76 100644 (file)
@@ -16518,6 +16518,9 @@ static void i40e_pci_error_reset_done(struct pci_dev *pdev)
                return;
 
        i40e_reset_and_rebuild(pf, false, false);
+#ifdef CONFIG_PCI_IOV
+       i40e_restore_all_vfs_msi_state(pdev);
+#endif /* CONFIG_PCI_IOV */
 }
 
 /**
index 3f99eb1982452725caa0548f01329350300cd8b9..d60f5419d6bdff3f2bf17621fb3f43c4ce6c332b 100644 (file)
@@ -154,6 +154,32 @@ void i40e_vc_notify_reset(struct i40e_pf *pf)
                             (u8 *)&pfe, sizeof(struct virtchnl_pf_event));
 }
 
+#ifdef CONFIG_PCI_IOV
+void i40e_restore_all_vfs_msi_state(struct pci_dev *pdev)
+{
+       u16 vf_id;
+       u16 pos;
+
+       /* Continue only if this is a PF */
+       if (!pdev->is_physfn)
+               return;
+
+       if (!pci_num_vf(pdev))
+               return;
+
+       pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_SRIOV);
+       if (pos) {
+               struct pci_dev *vf_dev = NULL;
+
+               pci_read_config_word(pdev, pos + PCI_SRIOV_VF_DID, &vf_id);
+               while ((vf_dev = pci_get_device(pdev->vendor, vf_id, vf_dev))) {
+                       if (vf_dev->is_virtfn && vf_dev->physfn == pdev)
+                               pci_restore_msi_state(vf_dev);
+               }
+       }
+}
+#endif /* CONFIG_PCI_IOV */
+
 /**
  * i40e_vc_notify_vf_reset
  * @vf: pointer to the VF structure
index 2ee0f8a232480c2a34fee5bee306836e2b85ebcd..5fd607c0de0a6793853e3aa8c331104d4e308824 100644 (file)
@@ -137,6 +137,9 @@ int i40e_ndo_set_vf_spoofchk(struct net_device *netdev, int vf_id, bool enable);
 
 void i40e_vc_notify_link_state(struct i40e_pf *pf);
 void i40e_vc_notify_reset(struct i40e_pf *pf);
+#ifdef CONFIG_PCI_IOV
+void i40e_restore_all_vfs_msi_state(struct pci_dev *pdev);
+#endif /* CONFIG_PCI_IOV */
 int i40e_get_vf_stats(struct net_device *netdev, int vf_id,
                      struct ifla_vf_stats *vf_stats);