All of lore.kernel.org
 help / color / mirror / Atom feed
From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
To: Magnus Damm <magnus.damm@gmail.com>
Cc: linux-kernel@vger.kernel.org, grant.likely@secretlab.ca,
	horms@verge.net.au, linus.walleij@linaro.org,
	linux-sh@vger.kernel.org
Subject: Re: [PATCH] gpio: Renesas R-Car GPIO driver
Date: Tue, 12 Mar 2013 13:07:59 +0000	[thread overview]
Message-ID: <2638997.DezZavkCFy@avalon> (raw)
In-Reply-To: <CANqRtoR=y99NycYFexTXxxCv+GDtVJJne0y-Eh64qba-1LmtaA@mail.gmail.com>

Hi Magnus,

On Tuesday 12 March 2013 14:27:25 Magnus Damm wrote:
> On Sun, Mar 10, 2013 at 3:16 AM, Laurent Pinchart wrote:
> > Hi Magnus,
> > 
> > Thank you for the patch.
> 
> Thanks for your review!

You're welcome.

> > On Tuesday 05 March 2013 09:32:19 Magnus Damm wrote:
> >> From: Magnus Damm <damm@opensource.se>
> >> 
> >> This patch implements a GPIO driver for the R-Car series
> >> of SoCs from Renesas. This driver is designed to be reusable
> >> between multiple SoCs that share the same basic building block,
> >> but so far it has only been used on R-Car H1 (r8a7779).
> >> 
> >> Each driver instance handles 32 GPIOs with individually
> >> maskable IRQs. The driver operates on a single I/O memory
> >> range and the 32 GPIOs are hooked up a single interrupt.
> >> 
> >> In the case of R-Car H1 either external IRQ pins or GPIOs
> >> with interrupts can be used for on-board interupts. For
> >> external IRQs 4 pins are supported, and in the case of GPIO
> >> there are 202 GPIOS as 202 interrupts hooked up via 6 driver
> >> instances and to the GIC and the Cortex-A9 Quad.
> >> 
> >> At this point this driver is interfacing as a regular
> >> platform device driver. In the future DT support will be
> >> submitted as an incremental feature patch.
> >> 
> >> Signed-off-by: Magnus Damm <damm@opensource.se>
> >> ---
> >> 
> >>  drivers/gpio/Kconfig                    |    6
> >>  drivers/gpio/Makefile                   |    1
> >>  drivers/gpio/gpio-rcar.c                |  406 +++++++++++++++++++++++++
> >>  include/linux/platform_data/gpio-rcar.h |   29 ++
> >>  4 files changed, 442 insertions(+)
> >> 
> >> --- /dev/null
> >> +++ work/drivers/gpio/gpio-rcar.c     2013-03-05 09:13:23.000000000 +0900
> >> @@ -0,0 +1,406 @@

[snip]

> >> +static void gpio_rcar_config_interrupt_input_mode(struct gpio_rcar_priv
> >> *p, +                                               unsigned int hwirq,
> >> +                                               bool
> >> active_high_rising_edge, +                                              
> >> bool level_trigger) +{
> >> +     unsigned long bit = BIT(hwirq);
> >> +     unsigned long flags, tmp;
> >> +
> >> +     /* follow steps in the GPIO documentation for
> >> +      * "Setting Edge-Sensitive Interrupt Input Mode" and
> >> +      * "Setting Level-Sensitive Interrupt Input Mode"
> >> +      */
> >> +
> >> +     spin_lock_irqsave(&p->lock, flags);
> >> +
> >> +     /* Configure postive or negative logic in POSNEG */
> >> +     tmp = gpio_rcar_read(p, POSNEG);
> >> +     if (active_high_rising_edge)
> >> +             tmp &= ~bit;
> >> +     else
> >> +             tmp |= bit;
> >> +     gpio_rcar_write(p, POSNEG, tmp);
> >> +
> >> +     /* Configure edge or level trigger in EDGLEVEL */
> >> +     tmp = gpio_rcar_read(p, EDGLEVEL);
> >> +     if (level_trigger)
> >> +             tmp &= ~bit;
> >> +     else
> >> +             tmp |= bit;
> >> +     gpio_rcar_write(p, EDGLEVEL, tmp);
> >> +
> >> +     /* Select "Interrupt Input Mode" in IOINTSEL */
> >> +     tmp = gpio_rcar_read(p, IOINTSEL);
> >> +     tmp |= bit;
> >> +     gpio_rcar_write(p, IOINTSEL, tmp);
> >> +
> >> +     /* Write INTCLR in case of edge trigger */
> >> +     if (!level_trigger)
> > 
> > Maybe you could do so unconditionally.
> 
> I could, but I wouldn't follow the recommended sequence in the data sheet
> then.
> >> +             gpio_rcar_write(p, INTCLR, bit);
> > 
> > I suppose the idea here it to avoid spurious interrupts when switching to
> > edge-triggered interrupt mode. If the interrupt was already enabled
> > wouldn't it still be registered before you clear the flag ?
> 
> Maybe. Perhaps I shall use IRQCHIP_SET_TYPE_MASKED here?

That's a good idea.

> >> +
> >> +     spin_unlock_irqrestore(&p->lock, flags);
> >> +}

[snip]

> >> +static int gpio_rcar_get(struct gpio_chip *chip, unsigned offset)
> >> +{
> >> +     return (int)(gpio_rcar_read(gpio_to_priv(chip), INDT) &
> >> BIT(offset));
> >> +}
> > 
> > Isn't the get operation supposed to return 0 or 1 ? In that case
> > 
> >         return !!(gpio_rcar_read(gpio_to_priv(chip), INDT) & BIT(offset));
> > 
> > would be better.
> 
> I recall that for micro optimization purpose I believe the double
> negation is unnecessary for the GPIO ->get() operation.
> 
> Or perhaps things have changed?

I'm not sure to be honest, I was hoping you would know :-)

[snip]

> >> +static int gpio_rcar_probe(struct platform_device *pdev)
> >> +{
> >> +     struct gpio_rcar_config *pdata = pdev->dev.platform_data;
> >> +     struct gpio_rcar_priv *p;
> >> +     struct resource *io, *irq;
> >> +     struct gpio_chip *gpio_chip;
> >> +     struct irq_chip *irq_chip;
> >> +     const char *name = dev_name(&pdev->dev);
> >> +     int ret;
> >> +
> >> +     p = kzalloc(sizeof(*p), GFP_KERNEL);
> > 
> > You can use devm_kzalloc() to simplify error management.
> 
> Yep, devm is not bad.
> 
> >> +     if (!p) {
> >> +             dev_err(&pdev->dev, "failed to allocate driver data\n");
> >> +             ret = -ENOMEM;
> > 
> > You can return -ENOMEM; directly here.
> 
> I prefer to have a single point of error return.

So do I when there's any cleanup to be done in the error path, which isn't the 
case here. I'm OK if you keep the goto though.

> >> +             goto err0;
> >> +     }
> >> +
> >> +     /* deal with driver instance configuration */
> >> +     if (pdata)
> > 
> > Shouldn't you return an error if pdata = NULL ?
> 
> Platform data isn't required by this driver.
> 
> >> +             memcpy(&p->config, pdata, sizeof(*pdata));
> >> 
> >         p->config = *pdata;
> > 
> > seems to be the preferred style nowadays. You could also store a pointer
> > to a struct gpio_rcar_config in gpio_rcar_priv, but I suppose you have
> > decided not to do so in prevision for DT support.
> 
> Yes because of upcoming DT support. And this way the platform data can
> be put in some special init section too. As for memcpy(), I like to
> explicitly use that compared over your suggestion. This way it is easy
> to see which code that shouldn't happen during hot path.

I wasn't too fond of the structure assignment style to start with but changed 
my mind after receiving patches that removed memcpy() calls from across the 
whole kernel :-)

> >> +     p->pdev = pdev;
> >> +     platform_set_drvdata(pdev, p);
> >> +     spin_lock_init(&p->lock);
> >> +
> >> +     io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> >> +     irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
> >> +
> >> +     if (!io || !irq) {
> >> +             dev_err(&pdev->dev, "missing IRQ or IOMEM\n");
> >> +             ret = -EINVAL;
> >> 
> >         return -EINVAL;
> >> 
> >> +             goto err1;
> >> +     }
> >> +
> >> +     p->base = ioremap_nocache(io->start, resource_size(io));
> > 
> > devm_ioremap_nocache()
> 
> Yep, devm.
> 
> >> +     if (!p->base) {
> >> +             dev_err(&pdev->dev, "failed to remap I/O memory\n");
> >> +             ret = -ENXIO;
> >> 
> >         return -ENXIO;
> >> 
> >> +             goto err1;
> >> +     }
> >> +
> >> +     gpio_chip = &p->gpio_chip;
> >> +     gpio_chip->direction_input = gpio_rcar_direction_input;
> >> +     gpio_chip->get = gpio_rcar_get;
> >> +     gpio_chip->direction_output = gpio_rcar_direction_output;
> >> +     gpio_chip->set = gpio_rcar_set;
> >> +     gpio_chip->to_irq = gpio_rcar_to_irq;
> >> +     gpio_chip->label = name;
> >> +     gpio_chip->owner = THIS_MODULE;
> >> +     gpio_chip->base = p->config.gpio_base;
> >> +     gpio_chip->ngpio = p->config.number_of_pins;
> >> +
> >> +     irq_chip = &p->irq_chip;
> >> +     irq_chip->name = name;
> >> +     irq_chip->irq_mask = gpio_rcar_irq_disable;
> >> +     irq_chip->irq_unmask = gpio_rcar_irq_enable;
> >> +     irq_chip->irq_enable = gpio_rcar_irq_enable;
> >> +     irq_chip->irq_disable = gpio_rcar_irq_disable;
> >> +     irq_chip->irq_set_type = gpio_rcar_irq_set_type;
> >> +     irq_chip->flags = IRQCHIP_SKIP_SET_WAKE;
> >> +
> >> +     p->irq_domain = irq_domain_add_simple(pdev->dev.of_node,
> >> +                                           p->config.number_of_pins,
> >> +                                           p->config.irq_base,
> >> +                                           &gpio_rcar_irq_domain_ops,
> >> p);
> >> +     if (!p->irq_domain) {
> >> +             ret = -ENXIO;
> >> +             dev_err(&pdev->dev, "cannot initialize irq domain\n");
> >> +             goto err2;
> > 
> > return -ENXIO;
> 
> In case of devm, yes.
> 
> >> +     }
> >> +
> >> +     if (request_irq(irq->start, gpio_rcar_irq_handler, 0, name, p)) {
> > 
> > devm_request_irq()
> 
> Yes, like the devm patch for gpio-em does it. =)
> 
> >> +             dev_err(&pdev->dev, "failed to request IRQ\n");
> >> +             ret = -ENOENT;
> >> +             goto err3;
> >> +     }
> >> +
> >> +     ret = gpiochip_add(gpio_chip);
> >> +     if (ret) {
> >> +             dev_err(&pdev->dev, "failed to add GPIO controller\n");
> >> +             goto err4;
> >> +     }
> >> +
> >> +     dev_info(&pdev->dev, "driving %d GPIOs\n",
> >> p->config.number_of_pins);
> >> +
> >> +     /* warn in case of mismatch if irq base is specified */
> > 
> > When does this happen ?
> 
> If happens if the user has requested a certain static IRQ base but
> this interrupts were already installed there by some other driver.
> 
> >> +     if (p->config.irq_base) {
> >> +             ret = irq_find_mapping(p->irq_domain, 0);
> >> +             if (p->config.irq_base != ret)
> >> +                     dev_warn(&pdev->dev, "irq base mismatch (%d/%d)\n",
> > 
> > p->config.irq_base is unsigned and irq_find_mapping() returns an unsigned.
> > %u/%u would this be more appropriate.
> 
> Ok!
> 
> >> +                              p->config.irq_base, ret);
> >> +     }
> >> +
> >> +     return 0;
> >> +
> >> +err4:
> >> +     free_irq(irq->start, p);
> >> +err3:
> >> +     irq_domain_remove(p->irq_domain);
> >> +err2:
> >> +     iounmap(p->base);
> >> +err1:
> >> +     kfree(p);
> >> +err0:
> >> +     return ret;
> > 
> > With the devm_* functions used above you will have a single error label to
> > call irq_domain_remove.
> 
> Right, that makes the code simpler, I agree. I actually had devm planned as
> an incremental feature.
> 
> So what is the preferred way to handle update of this driver? I intend to
> add devm and DT support anyway, and I want both of them to be incremental to
> avoid making back porting more difficult than absolutely necessary.

How far back do you need to backport the driver ? devm_kzalloc was introduced 
in 2.6.21, devm_ioremap_nocache in 2.6.26 and devm_request_irq in 2.6.30. That 
gives you nearly 4 years of backporting, I hope it would be enough :-)

> Shall I make a V2 with everything except DT and devm, doesn't that sound
> pretty straight forward?

Could you submit a v2 with all the changes except DT ?

-- 
Regards,

Laurent Pinchart


WARNING: multiple messages have this Message-ID (diff)
From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
To: Magnus Damm <magnus.damm@gmail.com>
Cc: linux-kernel@vger.kernel.org, grant.likely@secretlab.ca,
	horms@verge.net.au, linus.walleij@linaro.org,
	linux-sh@vger.kernel.org
Subject: Re: [PATCH] gpio: Renesas R-Car GPIO driver
Date: Tue, 12 Mar 2013 14:07:59 +0100	[thread overview]
Message-ID: <2638997.DezZavkCFy@avalon> (raw)
In-Reply-To: <CANqRtoR=y99NycYFexTXxxCv+GDtVJJne0y-Eh64qba-1LmtaA@mail.gmail.com>

Hi Magnus,

On Tuesday 12 March 2013 14:27:25 Magnus Damm wrote:
> On Sun, Mar 10, 2013 at 3:16 AM, Laurent Pinchart wrote:
> > Hi Magnus,
> > 
> > Thank you for the patch.
> 
> Thanks for your review!

You're welcome.

> > On Tuesday 05 March 2013 09:32:19 Magnus Damm wrote:
> >> From: Magnus Damm <damm@opensource.se>
> >> 
> >> This patch implements a GPIO driver for the R-Car series
> >> of SoCs from Renesas. This driver is designed to be reusable
> >> between multiple SoCs that share the same basic building block,
> >> but so far it has only been used on R-Car H1 (r8a7779).
> >> 
> >> Each driver instance handles 32 GPIOs with individually
> >> maskable IRQs. The driver operates on a single I/O memory
> >> range and the 32 GPIOs are hooked up a single interrupt.
> >> 
> >> In the case of R-Car H1 either external IRQ pins or GPIOs
> >> with interrupts can be used for on-board interupts. For
> >> external IRQs 4 pins are supported, and in the case of GPIO
> >> there are 202 GPIOS as 202 interrupts hooked up via 6 driver
> >> instances and to the GIC and the Cortex-A9 Quad.
> >> 
> >> At this point this driver is interfacing as a regular
> >> platform device driver. In the future DT support will be
> >> submitted as an incremental feature patch.
> >> 
> >> Signed-off-by: Magnus Damm <damm@opensource.se>
> >> ---
> >> 
> >>  drivers/gpio/Kconfig                    |    6
> >>  drivers/gpio/Makefile                   |    1
> >>  drivers/gpio/gpio-rcar.c                |  406 +++++++++++++++++++++++++
> >>  include/linux/platform_data/gpio-rcar.h |   29 ++
> >>  4 files changed, 442 insertions(+)
> >> 
> >> --- /dev/null
> >> +++ work/drivers/gpio/gpio-rcar.c     2013-03-05 09:13:23.000000000 +0900
> >> @@ -0,0 +1,406 @@

[snip]

> >> +static void gpio_rcar_config_interrupt_input_mode(struct gpio_rcar_priv
> >> *p, +                                               unsigned int hwirq,
> >> +                                               bool
> >> active_high_rising_edge, +                                              
> >> bool level_trigger) +{
> >> +     unsigned long bit = BIT(hwirq);
> >> +     unsigned long flags, tmp;
> >> +
> >> +     /* follow steps in the GPIO documentation for
> >> +      * "Setting Edge-Sensitive Interrupt Input Mode" and
> >> +      * "Setting Level-Sensitive Interrupt Input Mode"
> >> +      */
> >> +
> >> +     spin_lock_irqsave(&p->lock, flags);
> >> +
> >> +     /* Configure postive or negative logic in POSNEG */
> >> +     tmp = gpio_rcar_read(p, POSNEG);
> >> +     if (active_high_rising_edge)
> >> +             tmp &= ~bit;
> >> +     else
> >> +             tmp |= bit;
> >> +     gpio_rcar_write(p, POSNEG, tmp);
> >> +
> >> +     /* Configure edge or level trigger in EDGLEVEL */
> >> +     tmp = gpio_rcar_read(p, EDGLEVEL);
> >> +     if (level_trigger)
> >> +             tmp &= ~bit;
> >> +     else
> >> +             tmp |= bit;
> >> +     gpio_rcar_write(p, EDGLEVEL, tmp);
> >> +
> >> +     /* Select "Interrupt Input Mode" in IOINTSEL */
> >> +     tmp = gpio_rcar_read(p, IOINTSEL);
> >> +     tmp |= bit;
> >> +     gpio_rcar_write(p, IOINTSEL, tmp);
> >> +
> >> +     /* Write INTCLR in case of edge trigger */
> >> +     if (!level_trigger)
> > 
> > Maybe you could do so unconditionally.
> 
> I could, but I wouldn't follow the recommended sequence in the data sheet
> then.
> >> +             gpio_rcar_write(p, INTCLR, bit);
> > 
> > I suppose the idea here it to avoid spurious interrupts when switching to
> > edge-triggered interrupt mode. If the interrupt was already enabled
> > wouldn't it still be registered before you clear the flag ?
> 
> Maybe. Perhaps I shall use IRQCHIP_SET_TYPE_MASKED here?

That's a good idea.

> >> +
> >> +     spin_unlock_irqrestore(&p->lock, flags);
> >> +}

[snip]

> >> +static int gpio_rcar_get(struct gpio_chip *chip, unsigned offset)
> >> +{
> >> +     return (int)(gpio_rcar_read(gpio_to_priv(chip), INDT) &
> >> BIT(offset));
> >> +}
> > 
> > Isn't the get operation supposed to return 0 or 1 ? In that case
> > 
> >         return !!(gpio_rcar_read(gpio_to_priv(chip), INDT) & BIT(offset));
> > 
> > would be better.
> 
> I recall that for micro optimization purpose I believe the double
> negation is unnecessary for the GPIO ->get() operation.
> 
> Or perhaps things have changed?

I'm not sure to be honest, I was hoping you would know :-)

[snip]

> >> +static int gpio_rcar_probe(struct platform_device *pdev)
> >> +{
> >> +     struct gpio_rcar_config *pdata = pdev->dev.platform_data;
> >> +     struct gpio_rcar_priv *p;
> >> +     struct resource *io, *irq;
> >> +     struct gpio_chip *gpio_chip;
> >> +     struct irq_chip *irq_chip;
> >> +     const char *name = dev_name(&pdev->dev);
> >> +     int ret;
> >> +
> >> +     p = kzalloc(sizeof(*p), GFP_KERNEL);
> > 
> > You can use devm_kzalloc() to simplify error management.
> 
> Yep, devm is not bad.
> 
> >> +     if (!p) {
> >> +             dev_err(&pdev->dev, "failed to allocate driver data\n");
> >> +             ret = -ENOMEM;
> > 
> > You can return -ENOMEM; directly here.
> 
> I prefer to have a single point of error return.

So do I when there's any cleanup to be done in the error path, which isn't the 
case here. I'm OK if you keep the goto though.

> >> +             goto err0;
> >> +     }
> >> +
> >> +     /* deal with driver instance configuration */
> >> +     if (pdata)
> > 
> > Shouldn't you return an error if pdata == NULL ?
> 
> Platform data isn't required by this driver.
> 
> >> +             memcpy(&p->config, pdata, sizeof(*pdata));
> >> 
> >         p->config = *pdata;
> > 
> > seems to be the preferred style nowadays. You could also store a pointer
> > to a struct gpio_rcar_config in gpio_rcar_priv, but I suppose you have
> > decided not to do so in prevision for DT support.
> 
> Yes because of upcoming DT support. And this way the platform data can
> be put in some special init section too. As for memcpy(), I like to
> explicitly use that compared over your suggestion. This way it is easy
> to see which code that shouldn't happen during hot path.

I wasn't too fond of the structure assignment style to start with but changed 
my mind after receiving patches that removed memcpy() calls from across the 
whole kernel :-)

> >> +     p->pdev = pdev;
> >> +     platform_set_drvdata(pdev, p);
> >> +     spin_lock_init(&p->lock);
> >> +
> >> +     io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> >> +     irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
> >> +
> >> +     if (!io || !irq) {
> >> +             dev_err(&pdev->dev, "missing IRQ or IOMEM\n");
> >> +             ret = -EINVAL;
> >> 
> >         return -EINVAL;
> >> 
> >> +             goto err1;
> >> +     }
> >> +
> >> +     p->base = ioremap_nocache(io->start, resource_size(io));
> > 
> > devm_ioremap_nocache()
> 
> Yep, devm.
> 
> >> +     if (!p->base) {
> >> +             dev_err(&pdev->dev, "failed to remap I/O memory\n");
> >> +             ret = -ENXIO;
> >> 
> >         return -ENXIO;
> >> 
> >> +             goto err1;
> >> +     }
> >> +
> >> +     gpio_chip = &p->gpio_chip;
> >> +     gpio_chip->direction_input = gpio_rcar_direction_input;
> >> +     gpio_chip->get = gpio_rcar_get;
> >> +     gpio_chip->direction_output = gpio_rcar_direction_output;
> >> +     gpio_chip->set = gpio_rcar_set;
> >> +     gpio_chip->to_irq = gpio_rcar_to_irq;
> >> +     gpio_chip->label = name;
> >> +     gpio_chip->owner = THIS_MODULE;
> >> +     gpio_chip->base = p->config.gpio_base;
> >> +     gpio_chip->ngpio = p->config.number_of_pins;
> >> +
> >> +     irq_chip = &p->irq_chip;
> >> +     irq_chip->name = name;
> >> +     irq_chip->irq_mask = gpio_rcar_irq_disable;
> >> +     irq_chip->irq_unmask = gpio_rcar_irq_enable;
> >> +     irq_chip->irq_enable = gpio_rcar_irq_enable;
> >> +     irq_chip->irq_disable = gpio_rcar_irq_disable;
> >> +     irq_chip->irq_set_type = gpio_rcar_irq_set_type;
> >> +     irq_chip->flags = IRQCHIP_SKIP_SET_WAKE;
> >> +
> >> +     p->irq_domain = irq_domain_add_simple(pdev->dev.of_node,
> >> +                                           p->config.number_of_pins,
> >> +                                           p->config.irq_base,
> >> +                                           &gpio_rcar_irq_domain_ops,
> >> p);
> >> +     if (!p->irq_domain) {
> >> +             ret = -ENXIO;
> >> +             dev_err(&pdev->dev, "cannot initialize irq domain\n");
> >> +             goto err2;
> > 
> > return -ENXIO;
> 
> In case of devm, yes.
> 
> >> +     }
> >> +
> >> +     if (request_irq(irq->start, gpio_rcar_irq_handler, 0, name, p)) {
> > 
> > devm_request_irq()
> 
> Yes, like the devm patch for gpio-em does it. =)
> 
> >> +             dev_err(&pdev->dev, "failed to request IRQ\n");
> >> +             ret = -ENOENT;
> >> +             goto err3;
> >> +     }
> >> +
> >> +     ret = gpiochip_add(gpio_chip);
> >> +     if (ret) {
> >> +             dev_err(&pdev->dev, "failed to add GPIO controller\n");
> >> +             goto err4;
> >> +     }
> >> +
> >> +     dev_info(&pdev->dev, "driving %d GPIOs\n",
> >> p->config.number_of_pins);
> >> +
> >> +     /* warn in case of mismatch if irq base is specified */
> > 
> > When does this happen ?
> 
> If happens if the user has requested a certain static IRQ base but
> this interrupts were already installed there by some other driver.
> 
> >> +     if (p->config.irq_base) {
> >> +             ret = irq_find_mapping(p->irq_domain, 0);
> >> +             if (p->config.irq_base != ret)
> >> +                     dev_warn(&pdev->dev, "irq base mismatch (%d/%d)\n",
> > 
> > p->config.irq_base is unsigned and irq_find_mapping() returns an unsigned.
> > %u/%u would this be more appropriate.
> 
> Ok!
> 
> >> +                              p->config.irq_base, ret);
> >> +     }
> >> +
> >> +     return 0;
> >> +
> >> +err4:
> >> +     free_irq(irq->start, p);
> >> +err3:
> >> +     irq_domain_remove(p->irq_domain);
> >> +err2:
> >> +     iounmap(p->base);
> >> +err1:
> >> +     kfree(p);
> >> +err0:
> >> +     return ret;
> > 
> > With the devm_* functions used above you will have a single error label to
> > call irq_domain_remove.
> 
> Right, that makes the code simpler, I agree. I actually had devm planned as
> an incremental feature.
> 
> So what is the preferred way to handle update of this driver? I intend to
> add devm and DT support anyway, and I want both of them to be incremental to
> avoid making back porting more difficult than absolutely necessary.

How far back do you need to backport the driver ? devm_kzalloc was introduced 
in 2.6.21, devm_ioremap_nocache in 2.6.26 and devm_request_irq in 2.6.30. That 
gives you nearly 4 years of backporting, I hope it would be enough :-)

> Shall I make a V2 with everything except DT and devm, doesn't that sound
> pretty straight forward?

Could you submit a v2 with all the changes except DT ?

-- 
Regards,

Laurent Pinchart


  reply	other threads:[~2013-03-12 13:07 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-03-05  0:32 [PATCH] gpio: Renesas R-Car GPIO driver Magnus Damm
2013-03-05  0:32 ` Magnus Damm
2013-03-09 18:16 ` Laurent Pinchart
2013-03-09 18:16   ` Laurent Pinchart
2013-03-12  5:27   ` Magnus Damm
2013-03-12  5:27     ` Magnus Damm
2013-03-12 13:07     ` Laurent Pinchart [this message]
2013-03-12 13:07       ` Laurent Pinchart
2013-03-13 17:20 ` Linus Walleij
2013-03-13 17:20   ` Linus Walleij
2013-03-14  4:07   ` Magnus Damm
2013-03-14  4:07     ` Magnus Damm
2013-03-14  8:01     ` Linus Walleij
2013-03-14  8:01       ` Linus Walleij

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=2638997.DezZavkCFy@avalon \
    --to=laurent.pinchart@ideasonboard.com \
    --cc=grant.likely@secretlab.ca \
    --cc=horms@verge.net.au \
    --cc=linus.walleij@linaro.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-sh@vger.kernel.org \
    --cc=magnus.damm@gmail.com \
    /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.