Skip to content

Commit 348ccc7

Browse files
l1kij-intel
authored andcommitted
platform/x86/intel/vsec: Fix enable_cnt imbalance on PCIe error recovery
After a PCIe Uncorrectable Error has been reported by a device with Intel Vendor Specific Extended Capabilities and has been recovered through a Secondary Bus Reset, its driver calls intel_vsec_pci_probe() to rescan and reinitialize VSECs. intel_vsec_pci_probe() invokes pcim_enable_device() and thereby adds another devm action which calls pcim_disable_device() on driver unbind. So once the driver unbinds, pcim_disable_device() will be called as many times as an Uncorrectable Error occurred, plus one. This will lead to an enable_cnt imbalance on driver unbind. Additionally, since commit dc957ab ("platform/x86/intel/vsec: Add private data for per-device data"), a devm_kzalloc() allocation is leaked on every Uncorrectable Error. Avoid by splitting the VSEC rescan out of intel_vsec_pci_probe() into a separate helper and calling that on PCIe error recovery. Fixes: 936874b ("platform/x86/intel/vsec: Add PCI error recovery support to Intel PMT") Signed-off-by: Lukas Wunner <lukas@wunner.de> Cc: stable@vger.kernel.org # v6.0+ Link: https://patch.msgid.link/bd594d09fa866dc51dddc9a447c3b23f9b1402cc.1778736835.git.lukas@wunner.de Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
1 parent 26cbe11 commit 348ccc7

1 file changed

Lines changed: 30 additions & 24 deletions

File tree

  • drivers/platform/x86/intel

drivers/platform/x86/intel/vsec.c

Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -649,29 +649,13 @@ static void intel_vsec_skip_missing_dependencies(struct pci_dev *pdev)
649649
}
650650
}
651651

652-
static int intel_vsec_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
652+
static int intel_vsec_pci_init(struct pci_dev *pdev)
653653
{
654-
const struct intel_vsec_platform_info *info;
655-
struct vsec_priv *priv;
656-
int num_caps, ret;
654+
struct vsec_priv *priv = pci_get_drvdata(pdev);
655+
const struct intel_vsec_platform_info *info = priv->info;
657656
int run_once = 0;
658657
bool found_any = false;
659-
660-
ret = pcim_enable_device(pdev);
661-
if (ret)
662-
return ret;
663-
664-
pci_save_state(pdev);
665-
info = (const struct intel_vsec_platform_info *)id->driver_data;
666-
if (!info)
667-
return -EINVAL;
668-
669-
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
670-
if (!priv)
671-
return -ENOMEM;
672-
673-
priv->info = info;
674-
pci_set_drvdata(pdev, priv);
658+
int num_caps;
675659

676660
num_caps = hweight_long(info->caps);
677661
while (num_caps--) {
@@ -692,6 +676,31 @@ static int intel_vsec_pci_probe(struct pci_dev *pdev, const struct pci_device_id
692676
return 0;
693677
}
694678

679+
static int intel_vsec_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
680+
{
681+
const struct intel_vsec_platform_info *info;
682+
struct vsec_priv *priv;
683+
int ret;
684+
685+
ret = pcim_enable_device(pdev);
686+
if (ret)
687+
return ret;
688+
689+
pci_save_state(pdev);
690+
info = (const struct intel_vsec_platform_info *)id->driver_data;
691+
if (!info)
692+
return -EINVAL;
693+
694+
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
695+
if (!priv)
696+
return -ENOMEM;
697+
698+
priv->info = info;
699+
pci_set_drvdata(pdev, priv);
700+
701+
return intel_vsec_pci_init(pdev);
702+
}
703+
695704
int intel_vsec_set_mapping(struct oobmsm_plat_info *plat_info,
696705
struct intel_vsec_device *vsec_dev)
697706
{
@@ -832,7 +841,6 @@ static pci_ers_result_t intel_vsec_pci_slot_reset(struct pci_dev *pdev)
832841
{
833842
struct intel_vsec_device *intel_vsec_dev;
834843
pci_ers_result_t status = PCI_ERS_RESULT_DISCONNECT;
835-
const struct pci_device_id *pci_dev_id;
836844
unsigned long index;
837845

838846
dev_info(&pdev->dev, "Resetting PCI slot\n");
@@ -853,10 +861,8 @@ static pci_ers_result_t intel_vsec_pci_slot_reset(struct pci_dev *pdev)
853861
devm_release_action(&pdev->dev, intel_vsec_remove_aux,
854862
&intel_vsec_dev->auxdev);
855863
}
856-
pci_disable_device(pdev);
857864
pci_restore_state(pdev);
858-
pci_dev_id = pci_match_id(intel_vsec_pci_ids, pdev);
859-
intel_vsec_pci_probe(pdev, pci_dev_id);
865+
intel_vsec_pci_init(pdev);
860866

861867
out:
862868
return status;

0 commit comments

Comments
 (0)