forked from luck/tmp_suning_uos_patched
irqdomain/treewide: Free firmware node after domain removal
Commit711419e504
("irqdomain: Add the missing assignment of domain->fwnode for named fwnode") unintentionally caused a dangling pointer page fault issue on firmware nodes that were freed after IRQ domain allocation. Commite3beca48a4
fixed that dangling pointer issue by only freeing the firmware node after an IRQ domain allocation failure. That fix no longer frees the firmware node immediately, but leaves the firmware node allocated after the domain is removed. The firmware node must be kept around through irq_domain_remove, but should be freed it afterwards. Add the missing free operations after domain removal where where appropriate. Fixes:e3beca48a4
("irqdomain/treewide: Keep firmware node unconditionally allocated") Signed-off-by: Jon Derrick <jonathan.derrick@intel.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Acked-by: Bjorn Helgaas <bhelgaas@google.com> # drivers/pci Cc: stable@vger.kernel.org Link: https://lkml.kernel.org/r/1595363169-7157-1-git-send-email-jonathan.derrick@intel.com
This commit is contained in:
parent
ba47d845d7
commit
ec0160891e
|
@ -728,6 +728,7 @@ static int bridge_probe(struct platform_device *pdev)
|
|||
pci_free_resource_list(&host->windows);
|
||||
err_remove_domain:
|
||||
irq_domain_remove(domain);
|
||||
irq_domain_free_fwnode(fn);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -735,8 +736,10 @@ static int bridge_remove(struct platform_device *pdev)
|
|||
{
|
||||
struct pci_bus *bus = platform_get_drvdata(pdev);
|
||||
struct bridge_controller *bc = BRIDGE_CONTROLLER(bus);
|
||||
struct fwnode_handle *fn = bc->domain->fwnode;
|
||||
|
||||
irq_domain_remove(bc->domain);
|
||||
irq_domain_free_fwnode(fn);
|
||||
pci_lock_rescan_remove();
|
||||
pci_stop_root_bus(bus);
|
||||
pci_remove_root_bus(bus);
|
||||
|
|
|
@ -2335,8 +2335,13 @@ static int mp_irqdomain_create(int ioapic)
|
|||
|
||||
static void ioapic_destroy_irqdomain(int idx)
|
||||
{
|
||||
struct ioapic_domain_cfg *cfg = &ioapics[idx].irqdomain_cfg;
|
||||
struct fwnode_handle *fn = ioapics[idx].irqdomain->fwnode;
|
||||
|
||||
if (ioapics[idx].irqdomain) {
|
||||
irq_domain_remove(ioapics[idx].irqdomain);
|
||||
if (!cfg->dev)
|
||||
irq_domain_free_fwnode(fn);
|
||||
ioapics[idx].irqdomain = NULL;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -628,13 +628,21 @@ static int intel_setup_irq_remapping(struct intel_iommu *iommu)
|
|||
|
||||
static void intel_teardown_irq_remapping(struct intel_iommu *iommu)
|
||||
{
|
||||
struct fwnode_handle *fn;
|
||||
|
||||
if (iommu && iommu->ir_table) {
|
||||
if (iommu->ir_msi_domain) {
|
||||
fn = iommu->ir_msi_domain->fwnode;
|
||||
|
||||
irq_domain_remove(iommu->ir_msi_domain);
|
||||
irq_domain_free_fwnode(fn);
|
||||
iommu->ir_msi_domain = NULL;
|
||||
}
|
||||
if (iommu->ir_domain) {
|
||||
fn = iommu->ir_domain->fwnode;
|
||||
|
||||
irq_domain_remove(iommu->ir_domain);
|
||||
irq_domain_free_fwnode(fn);
|
||||
iommu->ir_domain = NULL;
|
||||
}
|
||||
free_pages((unsigned long)iommu->ir_table->base,
|
||||
|
|
|
@ -616,7 +616,10 @@ static int ioc3_mfd_probe(struct pci_dev *pdev,
|
|||
/* Remove all already added MFD devices */
|
||||
mfd_remove_devices(&ipd->pdev->dev);
|
||||
if (ipd->domain) {
|
||||
struct fwnode_handle *fn = ipd->domain->fwnode;
|
||||
|
||||
irq_domain_remove(ipd->domain);
|
||||
irq_domain_free_fwnode(fn);
|
||||
free_irq(ipd->domain_irq, (void *)ipd);
|
||||
}
|
||||
pci_iounmap(pdev, regs);
|
||||
|
@ -643,7 +646,10 @@ static void ioc3_mfd_remove(struct pci_dev *pdev)
|
|||
/* Release resources */
|
||||
mfd_remove_devices(&ipd->pdev->dev);
|
||||
if (ipd->domain) {
|
||||
struct fwnode_handle *fn = ipd->domain->fwnode;
|
||||
|
||||
irq_domain_remove(ipd->domain);
|
||||
irq_domain_free_fwnode(fn);
|
||||
free_irq(ipd->domain_irq, (void *)ipd);
|
||||
}
|
||||
pci_iounmap(pdev, ipd->regs);
|
||||
|
|
|
@ -560,6 +560,7 @@ static int vmd_enable_domain(struct vmd_dev *vmd, unsigned long features)
|
|||
if (!vmd->bus) {
|
||||
pci_free_resource_list(&resources);
|
||||
irq_domain_remove(vmd->irq_domain);
|
||||
irq_domain_free_fwnode(fn);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
@ -673,6 +674,7 @@ static void vmd_cleanup_srcu(struct vmd_dev *vmd)
|
|||
static void vmd_remove(struct pci_dev *dev)
|
||||
{
|
||||
struct vmd_dev *vmd = pci_get_drvdata(dev);
|
||||
struct fwnode_handle *fn = vmd->irq_domain->fwnode;
|
||||
|
||||
sysfs_remove_link(&vmd->dev->dev.kobj, "domain");
|
||||
pci_stop_root_bus(vmd->bus);
|
||||
|
@ -680,6 +682,7 @@ static void vmd_remove(struct pci_dev *dev)
|
|||
vmd_cleanup_srcu(vmd);
|
||||
vmd_detach_resources(vmd);
|
||||
irq_domain_remove(vmd->irq_domain);
|
||||
irq_domain_free_fwnode(fn);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
|
|
Loading…
Reference in New Issue
Block a user