From: Marc Zyngier <maz@kernel.org>
To: "Pali Rohár" <pali@kernel.org>,
"Kunihiko Hayashi" <hayashi.kunihiko@socionext.com>
Cc: "Lorenzo Pieralisi" <lorenzo.pieralisi@arm.com>,
"Rob Herring" <robh@kernel.org>,
"Krzysztof Wilczyński" <kw@linux.com>,
"Bjorn Helgaas" <bhelgaas@google.com>,
"Masami Hiramatsu" <mhiramat@kernel.org>,
linux-pci@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org
Subject: Re: [PATCH] PCI: uniphier: Serialize INTx masking/unmasking
Date: Mon, 23 Aug 2021 17:57:08 +0100 [thread overview]
Message-ID: <87zgt8p09n.wl-maz@kernel.org> (raw)
In-Reply-To: <20210823150927.jhobzfxy6e4s663r@pali>
On Mon, 23 Aug 2021 16:09:27 +0100,
Pali Rohár <pali@kernel.org> wrote:
>
> + Marc (who originally reported this issue)
>
> On Monday 23 August 2021 20:18:20 Kunihiko Hayashi wrote:
> > The condition register PCI_RCV_INTX is used in irq_mask(), irq_unmask()
> > and irq_ack() callbacks. Accesses to register can occur at the same time
> > without a lock.
> > Add a lock into each callback to prevent the issue.
> >
> > Fixes: 7e6d5cd88a6f ("PCI: uniphier: Add UniPhier PCIe host controller support")
> > Suggested-by: Pali Rohár <pali@kernel.org>
> > Signed-off-by: Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
>
> Acked-by: Pali Rohár <pali@kernel.org>
>
> > ---
> > drivers/pci/controller/dwc/pcie-uniphier.c | 15 +++++++++++++++
> > 1 file changed, 15 insertions(+)
> >
> > The previous patch is as follows:
> > https://lore.kernel.org/linux-pci/1629370566-29984-1-git-send-email-hayashi.kunihiko@socionext.com/
> >
> > Changes in the previous patch:
> > - Change the subject and commit message
> >
> > diff --git a/drivers/pci/controller/dwc/pcie-uniphier.c b/drivers/pci/controller/dwc/pcie-uniphier.c
> > index ebe43e9..5075714 100644
> > --- a/drivers/pci/controller/dwc/pcie-uniphier.c
> > +++ b/drivers/pci/controller/dwc/pcie-uniphier.c
> > @@ -186,12 +186,17 @@ static void uniphier_pcie_irq_ack(struct irq_data *d)
> > struct pcie_port *pp = irq_data_get_irq_chip_data(d);
> > struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> > struct uniphier_pcie_priv *priv = to_uniphier_pcie(pci);
> > + unsigned long flags;
> > u32 val;
> >
> > + raw_spin_lock_irqsave(&pp->lock, flags);
> > +
> > val = readl(priv->base + PCL_RCV_INTX);
> > val &= ~PCL_RCV_INTX_ALL_STATUS;
> > val |= BIT(irqd_to_hwirq(d) + PCL_RCV_INTX_STATUS_SHIFT);
> > writel(val, priv->base + PCL_RCV_INTX);
> > +
> > + raw_spin_unlock_irqrestore(&pp->lock, flags);
> > }
> >
> > static void uniphier_pcie_irq_mask(struct irq_data *d)
> > @@ -199,12 +204,17 @@ static void uniphier_pcie_irq_mask(struct irq_data *d)
> > struct pcie_port *pp = irq_data_get_irq_chip_data(d);
> > struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> > struct uniphier_pcie_priv *priv = to_uniphier_pcie(pci);
> > + unsigned long flags;
> > u32 val;
> >
> > + raw_spin_lock_irqsave(&pp->lock, flags);
> > +
> > val = readl(priv->base + PCL_RCV_INTX);
> > val &= ~PCL_RCV_INTX_ALL_MASK;
> > val |= BIT(irqd_to_hwirq(d) + PCL_RCV_INTX_MASK_SHIFT);
This looks extremely suspicious. You clear all the INTX mask bits, and
only set the one you need. How about the pre-existing bits?
> > writel(val, priv->base + PCL_RCV_INTX);
> > +
> > + raw_spin_unlock_irqrestore(&pp->lock, flags);
> > }
> >
> > static void uniphier_pcie_irq_unmask(struct irq_data *d)
> > @@ -212,12 +222,17 @@ static void uniphier_pcie_irq_unmask(struct irq_data *d)
> > struct pcie_port *pp = irq_data_get_irq_chip_data(d);
> > struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> > struct uniphier_pcie_priv *priv = to_uniphier_pcie(pci);
> > + unsigned long flags;
> > u32 val;
> >
> > + raw_spin_lock_irqsave(&pp->lock, flags);
> > +
> > val = readl(priv->base + PCL_RCV_INTX);
> > val &= ~PCL_RCV_INTX_ALL_MASK;
> > val &= ~BIT(irqd_to_hwirq(d) + PCL_RCV_INTX_MASK_SHIFT);
And by the same token, this second line is totally useless.
I think masking/unmasking is broken in this driver, locking or not.
M.
--
Without deviation from the norm, progress is not possible.
WARNING: multiple messages have this Message-ID (diff)
From: Marc Zyngier <maz@kernel.org>
To: "Pali Rohár" <pali@kernel.org>,
"Kunihiko Hayashi" <hayashi.kunihiko@socionext.com>
Cc: "Lorenzo Pieralisi" <lorenzo.pieralisi@arm.com>,
"Rob Herring" <robh@kernel.org>,
"Krzysztof Wilczyński" <kw@linux.com>,
"Bjorn Helgaas" <bhelgaas@google.com>,
"Masami Hiramatsu" <mhiramat@kernel.org>,
linux-pci@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org
Subject: Re: [PATCH] PCI: uniphier: Serialize INTx masking/unmasking
Date: Mon, 23 Aug 2021 17:57:08 +0100 [thread overview]
Message-ID: <87zgt8p09n.wl-maz@kernel.org> (raw)
In-Reply-To: <20210823150927.jhobzfxy6e4s663r@pali>
On Mon, 23 Aug 2021 16:09:27 +0100,
Pali Rohár <pali@kernel.org> wrote:
>
> + Marc (who originally reported this issue)
>
> On Monday 23 August 2021 20:18:20 Kunihiko Hayashi wrote:
> > The condition register PCI_RCV_INTX is used in irq_mask(), irq_unmask()
> > and irq_ack() callbacks. Accesses to register can occur at the same time
> > without a lock.
> > Add a lock into each callback to prevent the issue.
> >
> > Fixes: 7e6d5cd88a6f ("PCI: uniphier: Add UniPhier PCIe host controller support")
> > Suggested-by: Pali Rohár <pali@kernel.org>
> > Signed-off-by: Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
>
> Acked-by: Pali Rohár <pali@kernel.org>
>
> > ---
> > drivers/pci/controller/dwc/pcie-uniphier.c | 15 +++++++++++++++
> > 1 file changed, 15 insertions(+)
> >
> > The previous patch is as follows:
> > https://lore.kernel.org/linux-pci/1629370566-29984-1-git-send-email-hayashi.kunihiko@socionext.com/
> >
> > Changes in the previous patch:
> > - Change the subject and commit message
> >
> > diff --git a/drivers/pci/controller/dwc/pcie-uniphier.c b/drivers/pci/controller/dwc/pcie-uniphier.c
> > index ebe43e9..5075714 100644
> > --- a/drivers/pci/controller/dwc/pcie-uniphier.c
> > +++ b/drivers/pci/controller/dwc/pcie-uniphier.c
> > @@ -186,12 +186,17 @@ static void uniphier_pcie_irq_ack(struct irq_data *d)
> > struct pcie_port *pp = irq_data_get_irq_chip_data(d);
> > struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> > struct uniphier_pcie_priv *priv = to_uniphier_pcie(pci);
> > + unsigned long flags;
> > u32 val;
> >
> > + raw_spin_lock_irqsave(&pp->lock, flags);
> > +
> > val = readl(priv->base + PCL_RCV_INTX);
> > val &= ~PCL_RCV_INTX_ALL_STATUS;
> > val |= BIT(irqd_to_hwirq(d) + PCL_RCV_INTX_STATUS_SHIFT);
> > writel(val, priv->base + PCL_RCV_INTX);
> > +
> > + raw_spin_unlock_irqrestore(&pp->lock, flags);
> > }
> >
> > static void uniphier_pcie_irq_mask(struct irq_data *d)
> > @@ -199,12 +204,17 @@ static void uniphier_pcie_irq_mask(struct irq_data *d)
> > struct pcie_port *pp = irq_data_get_irq_chip_data(d);
> > struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> > struct uniphier_pcie_priv *priv = to_uniphier_pcie(pci);
> > + unsigned long flags;
> > u32 val;
> >
> > + raw_spin_lock_irqsave(&pp->lock, flags);
> > +
> > val = readl(priv->base + PCL_RCV_INTX);
> > val &= ~PCL_RCV_INTX_ALL_MASK;
> > val |= BIT(irqd_to_hwirq(d) + PCL_RCV_INTX_MASK_SHIFT);
This looks extremely suspicious. You clear all the INTX mask bits, and
only set the one you need. How about the pre-existing bits?
> > writel(val, priv->base + PCL_RCV_INTX);
> > +
> > + raw_spin_unlock_irqrestore(&pp->lock, flags);
> > }
> >
> > static void uniphier_pcie_irq_unmask(struct irq_data *d)
> > @@ -212,12 +222,17 @@ static void uniphier_pcie_irq_unmask(struct irq_data *d)
> > struct pcie_port *pp = irq_data_get_irq_chip_data(d);
> > struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> > struct uniphier_pcie_priv *priv = to_uniphier_pcie(pci);
> > + unsigned long flags;
> > u32 val;
> >
> > + raw_spin_lock_irqsave(&pp->lock, flags);
> > +
> > val = readl(priv->base + PCL_RCV_INTX);
> > val &= ~PCL_RCV_INTX_ALL_MASK;
> > val &= ~BIT(irqd_to_hwirq(d) + PCL_RCV_INTX_MASK_SHIFT);
And by the same token, this second line is totally useless.
I think masking/unmasking is broken in this driver, locking or not.
M.
--
Without deviation from the norm, progress is not possible.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
next prev parent reply other threads:[~2021-08-23 16:57 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-08-23 11:18 [PATCH] PCI: uniphier: Serialize INTx masking/unmasking Kunihiko Hayashi
2021-08-23 11:18 ` Kunihiko Hayashi
2021-08-23 15:09 ` Pali Rohár
2021-08-23 15:09 ` Pali Rohár
2021-08-23 16:57 ` Marc Zyngier [this message]
2021-08-23 16:57 ` Marc Zyngier
2021-08-25 0:01 ` Kunihiko Hayashi
2021-08-25 0:01 ` Kunihiko Hayashi
2021-08-25 9:07 ` Marc Zyngier
2021-08-25 9:07 ` Marc Zyngier
2021-08-26 10:02 ` Kunihiko Hayashi
2021-08-26 10:02 ` Kunihiko Hayashi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87zgt8p09n.wl-maz@kernel.org \
--to=maz@kernel.org \
--cc=bhelgaas@google.com \
--cc=hayashi.kunihiko@socionext.com \
--cc=kw@linux.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pci@vger.kernel.org \
--cc=lorenzo.pieralisi@arm.com \
--cc=mhiramat@kernel.org \
--cc=pali@kernel.org \
--cc=robh@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.