lkml.org 
[lkml]   [2021]   [Sep]   [20]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.19 156/293] PCI: aardvark: Fix masking and unmasking legacy INTx interrupts
    Date
    From: Pali Rohár <pali@kernel.org>

    commit d212dcee27c1f89517181047e5485fcbba4a25c2 upstream.

    irq_mask and irq_unmask callbacks need to be properly guarded by raw spin
    locks as masking/unmasking procedure needs atomic read-modify-write
    operation on hardware register.

    Link: https://lore.kernel.org/r/20210820155020.3000-1-pali@kernel.org
    Reported-by: Marc Zyngier <maz@kernel.org>
    Signed-off-by: Pali Rohár <pali@kernel.org>
    Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
    Acked-by: Marc Zyngier <maz@kernel.org>
    Cc: stable@vger.kernel.org
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    drivers/pci/controller/pci-aardvark.c | 9 +++++++++
    1 file changed, 9 insertions(+)

    --- a/drivers/pci/controller/pci-aardvark.c
    +++ b/drivers/pci/controller/pci-aardvark.c
    @@ -181,6 +181,7 @@ struct advk_pcie {
    struct list_head resources;
    struct irq_domain *irq_domain;
    struct irq_chip irq_chip;
    + raw_spinlock_t irq_lock;
    struct irq_domain *msi_domain;
    struct irq_domain *msi_inner_domain;
    struct irq_chip msi_bottom_irq_chip;
    @@ -603,22 +604,28 @@ static void advk_pcie_irq_mask(struct ir
    {
    struct advk_pcie *pcie = d->domain->host_data;
    irq_hw_number_t hwirq = irqd_to_hwirq(d);
    + unsigned long flags;
    u32 mask;

    + raw_spin_lock_irqsave(&pcie->irq_lock, flags);
    mask = advk_readl(pcie, PCIE_ISR1_MASK_REG);
    mask |= PCIE_ISR1_INTX_ASSERT(hwirq);
    advk_writel(pcie, mask, PCIE_ISR1_MASK_REG);
    + raw_spin_unlock_irqrestore(&pcie->irq_lock, flags);
    }

    static void advk_pcie_irq_unmask(struct irq_data *d)
    {
    struct advk_pcie *pcie = d->domain->host_data;
    irq_hw_number_t hwirq = irqd_to_hwirq(d);
    + unsigned long flags;
    u32 mask;

    + raw_spin_lock_irqsave(&pcie->irq_lock, flags);
    mask = advk_readl(pcie, PCIE_ISR1_MASK_REG);
    mask &= ~PCIE_ISR1_INTX_ASSERT(hwirq);
    advk_writel(pcie, mask, PCIE_ISR1_MASK_REG);
    + raw_spin_unlock_irqrestore(&pcie->irq_lock, flags);
    }

    static int advk_pcie_irq_map(struct irq_domain *h,
    @@ -701,6 +708,8 @@ static int advk_pcie_init_irq_domain(str
    struct device_node *pcie_intc_node;
    struct irq_chip *irq_chip;

    + raw_spin_lock_init(&pcie->irq_lock);
    +
    pcie_intc_node = of_get_next_child(node, NULL);
    if (!pcie_intc_node) {
    dev_err(dev, "No PCIe Intc node found\n");

    \
     
     \ /
      Last update: 2021-09-20 19:47    [W:4.073 / U:0.696 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site