lkml.org 
[lkml]   [2020]   [Aug]   [20]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.14 163/228] irqdomain/treewide: Free firmware node after domain removal
    Date
    From: Jon Derrick <jonathan.derrick@intel.com>

    commit ec0160891e387f4771f953b888b1fe951398e5d9 upstream.

    Commit 711419e504eb ("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. Commit e3beca48a45b 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: e3beca48a45b ("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
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    arch/x86/kernel/apic/io_apic.c | 5 +++++
    drivers/iommu/intel_irq_remapping.c | 8 ++++++++
    drivers/pci/host/vmd.c | 3 +++
    3 files changed, 16 insertions(+)

    --- a/arch/x86/kernel/apic/io_apic.c
    +++ b/arch/x86/kernel/apic/io_apic.c
    @@ -2252,8 +2252,13 @@ static int mp_irqdomain_create(int ioapi

    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;
    }
    }
    --- a/drivers/iommu/intel_irq_remapping.c
    +++ b/drivers/iommu/intel_irq_remapping.c
    @@ -601,13 +601,21 @@ out_free_table:

    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,
    --- a/drivers/pci/host/vmd.c
    +++ b/drivers/pci/host/vmd.c
    @@ -651,6 +651,7 @@ static int vmd_enable_domain(struct vmd_
    if (!vmd->bus) {
    pci_free_resource_list(&resources);
    irq_domain_remove(vmd->irq_domain);
    + irq_domain_free_fwnode(fn);
    return -ENODEV;
    }

    @@ -753,6 +754,7 @@ static void vmd_cleanup_srcu(struct 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);
    @@ -761,6 +763,7 @@ static void vmd_remove(struct pci_dev *d
    vmd_teardown_dma_ops(vmd);
    vmd_detach_resources(vmd);
    irq_domain_remove(vmd->irq_domain);
    + irq_domain_free_fwnode(fn);
    }

    #ifdef CONFIG_PM_SLEEP

    \
     
     \ /
      Last update: 2020-08-20 13:02    [W:3.699 / U:0.028 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site