iommu/vt-d: fix PCI device reference leakage on error recovery path
Function dmar_parse_dev_scope() should release the PCI device reference count gained in function dmar_parse_one_dev_scope() on error recovery, otherwise it will cause PCI device object leakage. This patch also introduces dmar_free_dev_scope(), which will be used to support DMAR device hotplug. Reviewed-by: Yijing Wang <wangyijing@huawei.com> Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com> Signed-off-by: Joerg Roedel <joro@8bytes.org>
This commit is contained in:
parent
360eb3c568
commit
ada4d4b2a3
|
@ -100,7 +100,6 @@ static int __init dmar_parse_one_dev_scope(struct acpi_dmar_device_scope *scope,
|
||||||
if (!pdev) {
|
if (!pdev) {
|
||||||
pr_warn("Device scope device [%04x:%02x:%02x.%02x] not found\n",
|
pr_warn("Device scope device [%04x:%02x:%02x.%02x] not found\n",
|
||||||
segment, scope->bus, path->device, path->function);
|
segment, scope->bus, path->device, path->function);
|
||||||
*dev = NULL;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if ((scope->entry_type == ACPI_DMAR_SCOPE_TYPE_ENDPOINT && \
|
if ((scope->entry_type == ACPI_DMAR_SCOPE_TYPE_ENDPOINT && \
|
||||||
|
@ -151,7 +150,7 @@ int __init dmar_parse_dev_scope(void *start, void *end, int *cnt,
|
||||||
ret = dmar_parse_one_dev_scope(scope,
|
ret = dmar_parse_one_dev_scope(scope,
|
||||||
&(*devices)[index], segment);
|
&(*devices)[index], segment);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
kfree(*devices);
|
dmar_free_dev_scope(devices, cnt);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
index ++;
|
index ++;
|
||||||
|
@ -162,6 +161,17 @@ int __init dmar_parse_dev_scope(void *start, void *end, int *cnt,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void dmar_free_dev_scope(struct pci_dev ***devices, int *cnt)
|
||||||
|
{
|
||||||
|
if (*devices && *cnt) {
|
||||||
|
while (--*cnt >= 0)
|
||||||
|
pci_dev_put((*devices)[*cnt]);
|
||||||
|
kfree(*devices);
|
||||||
|
*devices = NULL;
|
||||||
|
*cnt = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* dmar_parse_one_drhd - parses exactly one DMA remapping hardware definition
|
* dmar_parse_one_drhd - parses exactly one DMA remapping hardware definition
|
||||||
* structure which uniquely represent one DMA remapping hardware unit
|
* structure which uniquely represent one DMA remapping hardware unit
|
||||||
|
|
|
@ -62,6 +62,9 @@ extern struct list_head dmar_drhd_units;
|
||||||
|
|
||||||
extern int dmar_table_init(void);
|
extern int dmar_table_init(void);
|
||||||
extern int dmar_dev_scope_init(void);
|
extern int dmar_dev_scope_init(void);
|
||||||
|
extern int dmar_parse_dev_scope(void *start, void *end, int *cnt,
|
||||||
|
struct pci_dev ***devices, u16 segment);
|
||||||
|
extern void dmar_free_dev_scope(struct pci_dev ***devices, int *cnt);
|
||||||
|
|
||||||
/* Intel IOMMU detection */
|
/* Intel IOMMU detection */
|
||||||
extern int detect_intel_iommu(void);
|
extern int detect_intel_iommu(void);
|
||||||
|
@ -157,8 +160,6 @@ struct dmar_atsr_unit {
|
||||||
int dmar_parse_rmrr_atsr_dev(void);
|
int dmar_parse_rmrr_atsr_dev(void);
|
||||||
extern int dmar_parse_one_rmrr(struct acpi_dmar_header *header);
|
extern int dmar_parse_one_rmrr(struct acpi_dmar_header *header);
|
||||||
extern int dmar_parse_one_atsr(struct acpi_dmar_header *header);
|
extern int dmar_parse_one_atsr(struct acpi_dmar_header *header);
|
||||||
extern int dmar_parse_dev_scope(void *start, void *end, int *cnt,
|
|
||||||
struct pci_dev ***devices, u16 segment);
|
|
||||||
extern int intel_iommu_init(void);
|
extern int intel_iommu_init(void);
|
||||||
#else /* !CONFIG_INTEL_IOMMU: */
|
#else /* !CONFIG_INTEL_IOMMU: */
|
||||||
static inline int intel_iommu_init(void) { return -ENODEV; }
|
static inline int intel_iommu_init(void) { return -ENODEV; }
|
||||||
|
|
Loading…
Reference in New Issue