All of lore.kernel.org
 help / color / mirror / Atom feed
From: James Hogan <james.hogan@imgtec.com>
To: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-kernel@vger.kernel.org,
	Grant Likely <grant.likely@secretlab.ca>,
	Rob Herring <rob.herring@calxeda.com>,
	Linus Walleij <linus.walleij@linaro.org>,
	devicetree-discuss@lists.ozlabs.org,
	Rob Landley <rob@landley.net>,
	linux-doc@vger.kernel.org
Subject: Re: [PATCH 3/8] irq-imgpdc: add ImgTec PDC irqchip driver
Date: Wed, 24 Apr 2013 10:14:10 +0100	[thread overview]
Message-ID: <5177A262.1000004@imgtec.com> (raw)
In-Reply-To: <alpine.LFD.2.02.1304231647400.21884@ionos>

Thanks for the review Thomas!

On 23/04/13 16:09, Thomas Gleixner wrote:
> On Tue, 23 Apr 2013, James Hogan wrote:
>> +/**
>> + * struct pdc_intc_priv - private pdc interrupt data.
>> + * @nr_perips:		Number of peripheral interrupt signals.
>> + * @nr_syswakes:	Number of syswake signals.
>> + * @perip_irqs:		List of peripheral IRQ numbers handled.
>> + * @syswake_irq:	Shared PDC syswake IRQ number.
>> + * @domain:		IRQ domain for PDC peripheral and syswake IRQs.
>> + * @pdc_base:		Base of PDC registers.
>> + * @lock:		Lock to protect the PDC syswake registers.
>> + */
>> +struct pdc_intc_priv {
>> +	unsigned int		nr_perips;
>> +	unsigned int		nr_syswakes;
>> +	unsigned int		*perip_irqs;
>> +	unsigned int		syswake_irq;
>> +	struct irq_domain	*domain;
>> +	void __iomem		*pdc_base;
>> +
>> +	spinlock_t		lock;
> 
>   raw_spinlock_t please

Okay.

If I understand right, this would be because on RT, spinlock_t becomes a
mutex and won't work correctly with irqs actually disabled for the irq
callbacks below, is that right?

>> +static void perip_irq_mask(struct irq_data *data)
>> +{
>> +	struct pdc_intc_priv *priv = irqd_to_priv(data);
>> +	unsigned int irq_route;
>> +	unsigned long flags;
>> +
>> +	spin_lock_irqsave(&priv->lock, flags);
> 
> This is always called with interrupts disabled.

Okay, I'll switch to raw_spin_lock

>> +	irq_route = pdc_read(priv, PDC_IRQ_ROUTE);
>> +	irq_route &= ~(1 << data->hwirq);
> 
> Why not cache the mask value ?

Yes, caching PDC_IRQ_ROUTE should be possible since it should only be
used by this driver (hence the driver local spinlock).

> 
>> +	pdc_write(priv, PDC_IRQ_ROUTE, irq_route);
> 
>> +	spin_unlock_irqrestore(&priv->lock, flags);
>> +}
>> +
>> +static void perip_irq_unmask(struct irq_data *data)
>> +{
>> +	struct pdc_intc_priv *priv = irqd_to_priv(data);
>> +	unsigned int irq_route;
>> +	unsigned long flags;
>> +
>> +	spin_lock_irqsave(&priv->lock, flags);
>> +	irq_route = pdc_read(priv, PDC_IRQ_ROUTE);
>> +	irq_route |= 1 << data->hwirq;
>> +	pdc_write(priv, PDC_IRQ_ROUTE, irq_route);
> 
> This code is another slightly different copy of stuff which is
> available in kernel/irq/generic-chip.c
> 
> Can we please stop the code duplication and reuse existing
> infrastructure? Don't tell me it does not work for you.  I sent out a
> patch yesterday which makes the code suitable for irq domains.

I'll look into this. kernel/irq/generic-chip.c was added after this
driver was written.

>> +static void pdc_intc_perip_isr(unsigned int irq, struct irq_desc *desc)
>> +{
>> +	struct pdc_intc_priv *priv;
>> +	unsigned int i, irq_no;
>> +
>> +	priv = (struct pdc_intc_priv *)irq_desc_get_handler_data(desc);
>> +
>> +	/* find the peripheral number */
>> +	for (i = 0; i < priv->nr_perips; ++i)
>> +		if (irq == priv->perip_irqs[i])
>> +			goto found;
> 
> Whee. Aren't these numbers linear ?

Not necessarily as they're virtual irq numbers obtained via
platform_get_irq(), which come individually from device tree. Even their
hardware irq numbers aren't linear as they're not wired to their irqchip
in the same order:
> pdc: pdc@0x02006000 {
> 	interrupt-controller;
> 	#interrupt-cells = <3>;
> 
> 	reg = <0x02006000 0x1000>;
> 	compatible = "img,pdc-intc";
> 
> 	num-perips = <3>;
> 	num-syswakes = <3>;
> 
> 	interrupts = <18 4 /* level */>, /* Syswakes */
> 	             <30 4 /* level */>, /* Perip 0 (RTC) */
> 	             <29 4 /* level */>, /* Perip 1 (IR) */
> 	             <31 4 /* level */>; /* Perip 2 (WDT) */
> };

>> +static int pdc_intc_probe(struct platform_device *pdev)
>> +{
>> +	struct pdc_intc_priv *priv;
>> +	struct device_node *node = pdev->dev.of_node;
>> +	struct resource *res_regs;
>> +	unsigned int i;
>> +	int irq, ret;
>> +	u32 val;
>> +
>> +	if (!node)
>> +		return -ENOENT;
>> +
>> +	/* Get registers */
>> +	res_regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> +	if (res_regs == NULL) {
>> +		dev_err(&pdev->dev, "cannot find registers resource\n");
>> +		return -ENOENT;
>> +	}
>> +
>> +	/* Allocate driver data */
>> +	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
>> +	if (!priv) {
>> +		dev_err(&pdev->dev, "cannot allocate device data\n");
>> +		return -ENOMEM;
>> +	}
>> +	spin_lock_init(&priv->lock);
>> +	platform_set_drvdata(pdev, priv);
>> +
>> +	/* Ioremap the registers */
>> +	priv->pdc_base = devm_ioremap(&pdev->dev, res_regs->start,
>> +				      res_regs->end - res_regs->start);
>> +	if (!priv->pdc_base)
>> +		return -EIO;
> 
> Leaks priv.
> 
>> +	/* Get number of peripherals */
>> +	ret = of_property_read_u32(node, "num-perips", &val);
>> +	if (ret) {
>> +		dev_err(&pdev->dev, "No num-perips node property found\n");
>> +		return -EINVAL;
> 
> Leaks priv and mapping
> 
>> +	}
>> +	if (val > SYS0_HWIRQ) {
>> +		dev_err(&pdev->dev, "num-perips (%u) out of range\n", val);
>> +		return -EINVAL;
> 
> Error handling is optional, right?
> 
>> +static int pdc_intc_remove(struct platform_device *pdev)
>> +{
>> +	struct pdc_intc_priv *priv = platform_get_drvdata(pdev);
>> +
>> +	irq_domain_remove(priv->domain);
> 
> And the rest of the resources is still there?

I was under the impression devm_kzalloc and devm_ioremap took care of
that in both the probe error case and the remove case:

>  * devm_kzalloc - Resource-managed kzalloc
>  * Managed kzalloc.  Memory allocated with this function is
>  * automatically freed on driver detach. 

>  * devm_ioremap - Managed ioremap()
>  * Managed ioremap().  Map is automatically unmapped on driver detach.

I may have misunderstood the whole point of their existence though?

Thanks
James


WARNING: multiple messages have this Message-ID (diff)
From: James Hogan <james.hogan@imgtec.com>
To: Thomas Gleixner <tglx@linutronix.de>
Cc: <linux-kernel@vger.kernel.org>,
	Grant Likely <grant.likely@secretlab.ca>,
	Rob Herring <rob.herring@calxeda.com>,
	Linus Walleij <linus.walleij@linaro.org>,
	<devicetree-discuss@lists.ozlabs.org>,
	"Rob Landley" <rob@landley.net>, <linux-doc@vger.kernel.org>
Subject: Re: [PATCH 3/8] irq-imgpdc: add ImgTec PDC irqchip driver
Date: Wed, 24 Apr 2013 10:14:10 +0100	[thread overview]
Message-ID: <5177A262.1000004@imgtec.com> (raw)
In-Reply-To: <alpine.LFD.2.02.1304231647400.21884@ionos>

Thanks for the review Thomas!

On 23/04/13 16:09, Thomas Gleixner wrote:
> On Tue, 23 Apr 2013, James Hogan wrote:
>> +/**
>> + * struct pdc_intc_priv - private pdc interrupt data.
>> + * @nr_perips:		Number of peripheral interrupt signals.
>> + * @nr_syswakes:	Number of syswake signals.
>> + * @perip_irqs:		List of peripheral IRQ numbers handled.
>> + * @syswake_irq:	Shared PDC syswake IRQ number.
>> + * @domain:		IRQ domain for PDC peripheral and syswake IRQs.
>> + * @pdc_base:		Base of PDC registers.
>> + * @lock:		Lock to protect the PDC syswake registers.
>> + */
>> +struct pdc_intc_priv {
>> +	unsigned int		nr_perips;
>> +	unsigned int		nr_syswakes;
>> +	unsigned int		*perip_irqs;
>> +	unsigned int		syswake_irq;
>> +	struct irq_domain	*domain;
>> +	void __iomem		*pdc_base;
>> +
>> +	spinlock_t		lock;
> 
>   raw_spinlock_t please

Okay.

If I understand right, this would be because on RT, spinlock_t becomes a
mutex and won't work correctly with irqs actually disabled for the irq
callbacks below, is that right?

>> +static void perip_irq_mask(struct irq_data *data)
>> +{
>> +	struct pdc_intc_priv *priv = irqd_to_priv(data);
>> +	unsigned int irq_route;
>> +	unsigned long flags;
>> +
>> +	spin_lock_irqsave(&priv->lock, flags);
> 
> This is always called with interrupts disabled.

Okay, I'll switch to raw_spin_lock

>> +	irq_route = pdc_read(priv, PDC_IRQ_ROUTE);
>> +	irq_route &= ~(1 << data->hwirq);
> 
> Why not cache the mask value ?

Yes, caching PDC_IRQ_ROUTE should be possible since it should only be
used by this driver (hence the driver local spinlock).

> 
>> +	pdc_write(priv, PDC_IRQ_ROUTE, irq_route);
> 
>> +	spin_unlock_irqrestore(&priv->lock, flags);
>> +}
>> +
>> +static void perip_irq_unmask(struct irq_data *data)
>> +{
>> +	struct pdc_intc_priv *priv = irqd_to_priv(data);
>> +	unsigned int irq_route;
>> +	unsigned long flags;
>> +
>> +	spin_lock_irqsave(&priv->lock, flags);
>> +	irq_route = pdc_read(priv, PDC_IRQ_ROUTE);
>> +	irq_route |= 1 << data->hwirq;
>> +	pdc_write(priv, PDC_IRQ_ROUTE, irq_route);
> 
> This code is another slightly different copy of stuff which is
> available in kernel/irq/generic-chip.c
> 
> Can we please stop the code duplication and reuse existing
> infrastructure? Don't tell me it does not work for you.  I sent out a
> patch yesterday which makes the code suitable for irq domains.

I'll look into this. kernel/irq/generic-chip.c was added after this
driver was written.

>> +static void pdc_intc_perip_isr(unsigned int irq, struct irq_desc *desc)
>> +{
>> +	struct pdc_intc_priv *priv;
>> +	unsigned int i, irq_no;
>> +
>> +	priv = (struct pdc_intc_priv *)irq_desc_get_handler_data(desc);
>> +
>> +	/* find the peripheral number */
>> +	for (i = 0; i < priv->nr_perips; ++i)
>> +		if (irq == priv->perip_irqs[i])
>> +			goto found;
> 
> Whee. Aren't these numbers linear ?

Not necessarily as they're virtual irq numbers obtained via
platform_get_irq(), which come individually from device tree. Even their
hardware irq numbers aren't linear as they're not wired to their irqchip
in the same order:
> pdc: pdc@0x02006000 {
> 	interrupt-controller;
> 	#interrupt-cells = <3>;
> 
> 	reg = <0x02006000 0x1000>;
> 	compatible = "img,pdc-intc";
> 
> 	num-perips = <3>;
> 	num-syswakes = <3>;
> 
> 	interrupts = <18 4 /* level */>, /* Syswakes */
> 	             <30 4 /* level */>, /* Perip 0 (RTC) */
> 	             <29 4 /* level */>, /* Perip 1 (IR) */
> 	             <31 4 /* level */>; /* Perip 2 (WDT) */
> };

>> +static int pdc_intc_probe(struct platform_device *pdev)
>> +{
>> +	struct pdc_intc_priv *priv;
>> +	struct device_node *node = pdev->dev.of_node;
>> +	struct resource *res_regs;
>> +	unsigned int i;
>> +	int irq, ret;
>> +	u32 val;
>> +
>> +	if (!node)
>> +		return -ENOENT;
>> +
>> +	/* Get registers */
>> +	res_regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> +	if (res_regs == NULL) {
>> +		dev_err(&pdev->dev, "cannot find registers resource\n");
>> +		return -ENOENT;
>> +	}
>> +
>> +	/* Allocate driver data */
>> +	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
>> +	if (!priv) {
>> +		dev_err(&pdev->dev, "cannot allocate device data\n");
>> +		return -ENOMEM;
>> +	}
>> +	spin_lock_init(&priv->lock);
>> +	platform_set_drvdata(pdev, priv);
>> +
>> +	/* Ioremap the registers */
>> +	priv->pdc_base = devm_ioremap(&pdev->dev, res_regs->start,
>> +				      res_regs->end - res_regs->start);
>> +	if (!priv->pdc_base)
>> +		return -EIO;
> 
> Leaks priv.
> 
>> +	/* Get number of peripherals */
>> +	ret = of_property_read_u32(node, "num-perips", &val);
>> +	if (ret) {
>> +		dev_err(&pdev->dev, "No num-perips node property found\n");
>> +		return -EINVAL;
> 
> Leaks priv and mapping
> 
>> +	}
>> +	if (val > SYS0_HWIRQ) {
>> +		dev_err(&pdev->dev, "num-perips (%u) out of range\n", val);
>> +		return -EINVAL;
> 
> Error handling is optional, right?
> 
>> +static int pdc_intc_remove(struct platform_device *pdev)
>> +{
>> +	struct pdc_intc_priv *priv = platform_get_drvdata(pdev);
>> +
>> +	irq_domain_remove(priv->domain);
> 
> And the rest of the resources is still there?

I was under the impression devm_kzalloc and devm_ioremap took care of
that in both the probe error case and the remove case:

>  * devm_kzalloc - Resource-managed kzalloc
>  * Managed kzalloc.  Memory allocated with this function is
>  * automatically freed on driver detach. 

>  * devm_ioremap - Managed ioremap()
>  * Managed ioremap().  Map is automatically unmapped on driver detach.

I may have misunderstood the whole point of their existence though?

Thanks
James


  reply	other threads:[~2013-04-24  9:14 UTC|newest]

Thread overview: 50+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-04-23 14:33 [PATCH 0/8] Add some TZ1090 SoC infrastructure James Hogan
2013-04-23 14:33 ` James Hogan
     [not found] ` <1366727607-27444-1-git-send-email-james.hogan-1AXoQHu6uovQT0dZR+AlfA@public.gmane.org>
2013-04-23 14:33   ` [PATCH 1/8] metag: of_platform_populate from arch generic code James Hogan
2013-04-23 14:33     ` James Hogan
2013-04-23 14:33   ` [PATCH 8/8] gpio-tz1090pdc: add TZ1090 PDC gpio driver James Hogan
2013-04-23 14:33     ` James Hogan
2013-04-23 14:33 ` [PATCH 2/8] metag: minimal TZ1090 (Comet) SoC infrastructure James Hogan
2013-04-23 14:33   ` James Hogan
2013-04-23 15:25   ` Arnd Bergmann
2013-04-23 16:06     ` James Hogan
2013-04-23 16:06       ` James Hogan
2013-04-24 13:26       ` Catalin Marinas
2013-04-24 14:51         ` James Hogan
2013-04-24 14:51           ` James Hogan
2013-04-25 15:21           ` James Hogan
2013-04-25 15:21             ` James Hogan
2013-04-23 14:33 ` [PATCH 3/8] irq-imgpdc: add ImgTec PDC irqchip driver James Hogan
2013-04-23 14:33   ` James Hogan
2013-04-23 15:09   ` Thomas Gleixner
2013-04-24  9:14     ` James Hogan [this message]
2013-04-24  9:14       ` James Hogan
2013-04-24  9:32       ` Thomas Gleixner
2013-04-25 11:25     ` James Hogan
2013-04-25 11:25       ` James Hogan
2013-04-23 14:33 ` [PATCH 4/8] metag: tz1090: add <asm/soc-tz1090/gpio.h> James Hogan
2013-04-23 14:33   ` James Hogan
2013-04-25 21:52   ` Linus Walleij
2013-04-23 14:33 ` [PATCH 5/8] pinctrl-tz1090: add TZ1090 pinctrl driver James Hogan
2013-04-23 14:33   ` James Hogan
2013-04-25 22:39   ` Linus Walleij
2013-04-26 11:54     ` James Hogan
2013-05-03  9:13       ` Linus Walleij
2013-05-03 12:23         ` James Hogan
2013-05-03 13:03           ` Linus Walleij
2013-05-03 15:06             ` James Hogan
     [not found]               ` <5183D262.7000107-1AXoQHu6uovQT0dZR+AlfA@public.gmane.org>
2013-05-14 11:52                 ` Linus Walleij
2013-05-14 11:52                   ` Linus Walleij
2013-05-14 12:22                   ` James Hogan
2013-05-15 19:07                     ` Linus Walleij
2013-05-16  9:12                       ` James Hogan
2013-05-17  6:47                         ` Linus Walleij
2013-04-23 14:33 ` [PATCH 6/8] gpio-tz1090: add TZ1090 gpio driver James Hogan
2013-04-23 14:33   ` James Hogan
2013-04-25 23:01   ` Linus Walleij
2013-04-26  9:22     ` James Hogan
2013-05-03  8:49       ` Linus Walleij
2013-05-03  9:09         ` James Hogan
2013-05-15 19:09           ` Linus Walleij
2013-04-23 14:33 ` [PATCH 7/8] pinctrl-tz1090-pdc: add TZ1090 PDC pinctrl driver James Hogan
2013-04-23 14:33   ` James Hogan

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=5177A262.1000004@imgtec.com \
    --to=james.hogan@imgtec.com \
    --cc=devicetree-discuss@lists.ozlabs.org \
    --cc=grant.likely@secretlab.ca \
    --cc=linus.walleij@linaro.org \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=rob.herring@calxeda.com \
    --cc=rob@landley.net \
    --cc=tglx@linutronix.de \
    /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.