Commit 8cbcc1db authored by David E. Box's avatar David E. Box Committed by Hans de Goede

platform/x86/intel/vsec: Fix xa_alloc memory leak

Commit 936874b7 ("platform/x86/intel/vsec: Add PCI error recovery
support to Intel PMT") added an xarray to track the list of vsec devices to
be recovered after a PCI error. But it did not provide cleanup for the list
leading to a memory leak that was caught by kmemleak.  Do xa_alloc() before
devm_add_action_or_reset() so that the list may be cleaned up with
xa_erase() in the release function.

Fixes: 936874b7 ("platform/x86/intel/vsec: Add PCI error recovery support to Intel PMT")
Signed-off-by: default avatarDavid E. Box <david.e.box@linux.intel.com>
Reviewed-by: default avatarIlpo Järvinen <ilpo.jarvinen@linux.intel.com>
Link: https://lore.kernel.org/r/20231129222132.2331261-2-david.e.box@linux.intel.com
[hdegoede@redhat.com: Add missing xa_erase() on error-exit
Signed-off-by: default avatarHans de Goede <hdegoede@redhat.com>
parent d9cd21d4
...@@ -120,6 +120,8 @@ static void intel_vsec_dev_release(struct device *dev) ...@@ -120,6 +120,8 @@ static void intel_vsec_dev_release(struct device *dev)
{ {
struct intel_vsec_device *intel_vsec_dev = dev_to_ivdev(dev); struct intel_vsec_device *intel_vsec_dev = dev_to_ivdev(dev);
xa_erase(&auxdev_array, intel_vsec_dev->id);
mutex_lock(&vsec_ida_lock); mutex_lock(&vsec_ida_lock);
ida_free(intel_vsec_dev->ida, intel_vsec_dev->auxdev.id); ida_free(intel_vsec_dev->ida, intel_vsec_dev->auxdev.id);
mutex_unlock(&vsec_ida_lock); mutex_unlock(&vsec_ida_lock);
...@@ -135,19 +137,28 @@ int intel_vsec_add_aux(struct pci_dev *pdev, struct device *parent, ...@@ -135,19 +137,28 @@ int intel_vsec_add_aux(struct pci_dev *pdev, struct device *parent,
struct auxiliary_device *auxdev = &intel_vsec_dev->auxdev; struct auxiliary_device *auxdev = &intel_vsec_dev->auxdev;
int ret, id; int ret, id;
mutex_lock(&vsec_ida_lock); ret = xa_alloc(&auxdev_array, &intel_vsec_dev->id, intel_vsec_dev,
ret = ida_alloc(intel_vsec_dev->ida, GFP_KERNEL); PMT_XA_LIMIT, GFP_KERNEL);
mutex_unlock(&vsec_ida_lock);
if (ret < 0) { if (ret < 0) {
kfree(intel_vsec_dev->resource); kfree(intel_vsec_dev->resource);
kfree(intel_vsec_dev); kfree(intel_vsec_dev);
return ret; return ret;
} }
mutex_lock(&vsec_ida_lock);
id = ida_alloc(intel_vsec_dev->ida, GFP_KERNEL);
mutex_unlock(&vsec_ida_lock);
if (id < 0) {
xa_erase(&auxdev_array, intel_vsec_dev->id);
kfree(intel_vsec_dev->resource);
kfree(intel_vsec_dev);
return id;
}
if (!parent) if (!parent)
parent = &pdev->dev; parent = &pdev->dev;
auxdev->id = ret; auxdev->id = id;
auxdev->name = name; auxdev->name = name;
auxdev->dev.parent = parent; auxdev->dev.parent = parent;
auxdev->dev.release = intel_vsec_dev_release; auxdev->dev.release = intel_vsec_dev_release;
...@@ -169,12 +180,6 @@ int intel_vsec_add_aux(struct pci_dev *pdev, struct device *parent, ...@@ -169,12 +180,6 @@ int intel_vsec_add_aux(struct pci_dev *pdev, struct device *parent,
if (ret < 0) if (ret < 0)
return ret; return ret;
/* Add auxdev to list */
ret = xa_alloc(&auxdev_array, &id, intel_vsec_dev, PMT_XA_LIMIT,
GFP_KERNEL);
if (ret)
return ret;
return 0; return 0;
} }
EXPORT_SYMBOL_NS_GPL(intel_vsec_add_aux, INTEL_VSEC); EXPORT_SYMBOL_NS_GPL(intel_vsec_add_aux, INTEL_VSEC);
......
...@@ -45,6 +45,7 @@ struct intel_vsec_device { ...@@ -45,6 +45,7 @@ struct intel_vsec_device {
struct ida *ida; struct ida *ida;
struct intel_vsec_platform_info *info; struct intel_vsec_platform_info *info;
int num_resources; int num_resources;
int id; /* xa */
void *priv_data; void *priv_data;
size_t priv_data_size; size_t priv_data_size;
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment