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
2 changed files with 15 additions and 4 deletions
|
@ -100,7 +100,6 @@ static int __init dmar_parse_one_dev_scope(struct acpi_dmar_device_scope *scope,
|
|||
if (!pdev) {
|
||||
pr_warn("Device scope device [%04x:%02x:%02x.%02x] not found\n",
|
||||
segment, scope->bus, path->device, path->function);
|
||||
*dev = NULL;
|
||||
return 0;
|
||||
}
|
||||
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,
|
||||
&(*devices)[index], segment);
|
||||
if (ret) {
|
||||
kfree(*devices);
|
||||
dmar_free_dev_scope(devices, cnt);
|
||||
return ret;
|
||||
}
|
||||
index ++;
|
||||
|
@ -162,6 +161,17 @@ int __init dmar_parse_dev_scope(void *start, void *end, int *cnt,
|
|||
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
|
||||
* 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_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 */
|
||||
extern int detect_intel_iommu(void);
|
||||
|
@ -157,8 +160,6 @@ struct dmar_atsr_unit {
|
|||
int dmar_parse_rmrr_atsr_dev(void);
|
||||
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_dev_scope(void *start, void *end, int *cnt,
|
||||
struct pci_dev ***devices, u16 segment);
|
||||
extern int intel_iommu_init(void);
|
||||
#else /* !CONFIG_INTEL_IOMMU: */
|
||||
static inline int intel_iommu_init(void) { return -ENODEV; }
|
||||
|
|
Loading…
Reference in a new issue