Balance alloc/free and ioremap/iounmap in gpio_mdio_probe (powerpc/platforms/pasemi/gpio_mdio.c)
PATCH 1/1 Balance alloc/free and ioremap/iounmap in gpio_mdio_probe (powerpc/platforms/pasemi/gpio_mdio.c)
I think this is how it should be done, but
please review: it was not tested.
--
Balance alloc/free and ioremap/iounmap
---
arch/powerpc/platforms/pasemi/gpio_mdio.c +47 -26
@@ -208,95 +208,116 @@ static int gpio_mdio_write(struct mii_bus *bus, int phy_id, int location, u16 va }static int gpio_mdio_reset (struct mii_bus *bus) {/*nothing here - dunno how to reset it*/ return 0 ; } - -static int __devinit gpio_mdio_probe (struct of_device *ofdev, -const struct of_device_id *match) +static int __devinit __gpio_mdio_register_bus (struct of_device *ofdev, +const struct of_device_id *match) {struct device *dev = &ofdev->dev;struct device_node *np = ofdev->node; -struct device_node *gpio_np;struct mii_bus *new_bus;struct resource res;struct gpio_priv *priv;const unsigned int *prop; -int err =0 ;int i; - gpio_np =of_find_compatible_node (NULL ,"gpio" ,"1682m-gpio" ); - -if (!gpio_np) -return -ENODEV ; - - err =of_address_to_resource (gpio_np,0 , &res); -of_node_put (gpio_np); - -if (err) -return -EINVAL ; - -if (!gpio_regs) - gpio_regs =ioremap (res.start,0x100 ); - -if (!gpio_regs) -return -EPERM ; - priv =kzalloc (sizeof (struct gpio_priv ),GFP_KERNEL ); -if (priv ==NULL ) +if (unlikely (priv ==NULL ))return -ENOMEM ; new_bus =kzalloc (sizeof (struct mii_bus ),GFP_KERNEL ); -if (new_bus ==NULL ) -return -ENOMEM ; +if (unlikely (new_bus ==NULL )) + goto free_priv; new_bus->name ="pasemi gpio mdio bus" , new_bus->read = &gpio_mdio_read, new_bus->write = &gpio_mdio_write, new_bus->reset = &gpio_mdio_reset, prop =of_get_property (np,"reg" ,NULL ); new_bus->id = *prop; new_bus->priv = priv; new_bus->phy_mask =0 ; new_bus->irq =kmalloc (sizeof (int )*PHY_MAX_ADDR ,GFP_KERNEL ); +if (unlikely (new_bus->irq ==NULL )) + goto free_new_bus; +for (i =0 ; i <PHY_MAX_ADDR ; ++i) new_bus->irq[i] =irq_create_mapping (NULL ,10 ); prop =of_get_property (np,"mdc-pin" ,NULL ); priv->mdc_pin = *prop; prop =of_get_property (np,"mdio-pin" ,NULL ); priv->mdio_pin = *prop; new_bus->dev = dev;dev_set_drvdata (dev, new_bus); err =mdiobus_register (new_bus); -if (0 != err) { +if (unlikely (0 != err)) {printk (KERN_ERR "%s: Cannot register as MDIO bus, err %d\n" , new_bus->name, err); goto bus_register_fail; }return 0 ; bus_register_fail: +kfree (new_bus->irq); +free_new_bus:kfree (new_bus); +free_priv: +kfree (priv); + +return -ENOMEM ; +} + + +static int __devinit gpio_mdio_probe (struct of_device *ofdev, +const struct of_device_id *match) +{ +struct device_node *gpio_np; +int err; + + gpio_np =of_find_compatible_node (NULL ,"gpio" ,"1682m-gpio" ); + +if (!gpio_np) +return -ENODEV ; + + err =of_address_to_resource (gpio_np,0 , &res); +of_node_put (gpio_np); + +if (err) +return -EINVAL ; + +if (!gpio_regs) { + + gpio_regs =ioremap (res.start,0x100 ); +if (unlikely (!gpio_regs)) +return -EPERM ; + + err =__gpio_mdio_register_bus (ofdev, match); +if (err <0 ) +iounmap (gpio_regs); + }else + err =__gpio_mdio_register_bus (ofdev, match);return err; + }static int gpio_mdio_remove (struct of_device *dev) {struct mii_bus *bus =dev_get_drvdata (&dev->dev);mdiobus_unregister (bus);
Hi,
Quoted 4 lines · Roel Kluin
I think this is how it should be done, but
please review: it was not tested.
--
Balance alloc/free and ioremap/iounmap
It would be more helpful if your changelog identified the objects which could be leaked. More comments below.
Quoted 26 lines
arch/powerpc/platforms/pasemi/gpio_mdio.c +2
-15-static int __devinit gpio_mdio_probe (struct of_device *ofdev, -const struct of_device_id *match) +static int __devinit __gpio_mdio_register_bus (struct of_device *ofdev, +const struct of_device_id *match) {struct device *dev = &ofdev->dev;struct device_node *np = ofdev->node; -struct device_node *gpio_np;struct mii_bus *new_bus;struct resource res;struct gpio_priv *priv;const unsigned int *prop; -int err =0 ;int i; - gpio_np =of_find_compatible_node (NULL ,"gpio" ,"1682m-gpio" ); - -if (!gpio_np) -return -ENODEV ; - - err =of_address_to_resource (gpio_np,0 , &res); -of_node_put (gpio_np); - -if (err) -return -EINVAL ; -
arch/powerpc/platforms/pasemi/gpio_mdio.c static int gpio_mdio_write(struct mii_bus *bus, int phy_id, int location, u16 va · line 229
Quoted 10 lines
arch/powerpc/platforms/pasemi/gpio_mdio.c +1
-7-if (!gpio_regs) - gpio_regs =ioremap (res.start,0x100 ); - -if (!gpio_regs) -return -EPERM ; - priv =kzalloc (sizeof (struct gpio_priv ),GFP_KERNEL ); -if (priv ==NULL ) +if (unlikely (priv ==NULL ))return -ENOMEM ;
Please don't add likely/unlikely to non-hot paths such as this.
arch/powerpc/platforms/pasemi/gpio_mdio.c static int gpio_mdio_write(struct mii_bus *bus, int phy_id, int location, u16 va · line 234
Quoted 6 lines
arch/powerpc/platforms/pasemi/gpio_mdio.c +2
-2new_bus =kzalloc (sizeof (struct mii_bus ),GFP_KERNEL ); -if (new_bus ==NULL ) -return -ENOMEM ; +if (unlikely (new_bus ==NULL )) + goto free_priv;
again
Quoted 6 lines
arch/powerpc/platforms/pasemi/gpio_mdio.c +0
-0new_bus->name ="pasemi gpio mdio bus" , new_bus->read = &gpio_mdio_read, new_bus->write = &gpio_mdio_write, new_bus->reset = &gpio_mdio_reset,
arch/powerpc/platforms/pasemi/gpio_mdio.c static int gpio_mdio_write(struct mii_bus *bus, int phy_id, int location, u16 va · line 250
Quoted 10 lines
arch/powerpc/platforms/pasemi/gpio_mdio.c +3
-0prop =of_get_property (np,"reg" ,NULL ); new_bus->id = *prop; new_bus->priv = priv; new_bus->phy_mask =0 ; new_bus->irq =kmalloc (sizeof (int )*PHY_MAX_ADDR ,GFP_KERNEL ); +if (unlikely (new_bus->irq ==NULL )) + goto free_new_bus; +
again
Quoted 7 lines
arch/powerpc/platforms/pasemi/gpio_mdio.c +0
-0for (i =0 ; i <PHY_MAX_ADDR ; ++i) new_bus->irq[i] =irq_create_mapping (NULL ,10 ); prop =of_get_property (np,"mdc-pin" ,NULL ); priv->mdc_pin = *prop;
arch/powerpc/platforms/pasemi/gpio_mdio.c static int gpio_mdio_write(struct mii_bus *bus, int phy_id, int location, u16 va · line 266
Quoted 10 lines
arch/powerpc/platforms/pasemi/gpio_mdio.c +1
-1prop =of_get_property (np,"mdio-pin" ,NULL ); priv->mdio_pin = *prop; new_bus->dev = dev;dev_set_drvdata (dev, new_bus); err =mdiobus_register (new_bus); -if (0 != err) { +if (unlikely (0 != err)) {
again
Quoted 20 lines
arch/powerpc/platforms/pasemi/gpio_mdio.c +11
-0printk (KERN_ERR "%s: Cannot register as MDIO bus, err %d\n" , new_bus->name, err); goto bus_register_fail; }return 0 ; bus_register_fail: +kfree (new_bus->irq); +free_new_bus:kfree (new_bus); +free_priv: +kfree (priv); + +return -ENOMEM ; +} + + +static int __devinit gpio_mdio_probe (struct of_device *ofdev, +const struct of_device_id *match)
arch/powerpc/platforms/pasemi/gpio_mdio.c static int gpio_mdio_write(struct mii_bus *bus, int phy_id, int location, u16 va · line 296
Quoted 10 lines
arch/powerpc/platforms/pasemi/gpio_mdio.c +10
-0+{ +struct device_node *gpio_np; +int err; + + gpio_np =of_find_compatible_node (NULL ,"gpio" ,"1682m-gpio" ); + +if (!gpio_np) +return -ENODEV ; + + err =of_address_to_resource (gpio_np,0 , &res);
Hmm, where is "res" defined?
arch/powerpc/platforms/pasemi/gpio_mdio.c static int gpio_mdio_write(struct mii_bus *bus, int phy_id, int location, u16 va · line 303
Quoted 7 lines
arch/powerpc/platforms/pasemi/gpio_mdio.c +7
-0+of_node_put (gpio_np); + +if (err) +return -EINVAL ; + +if (!gpio_regs) { +
Unneeded newline
arch/powerpc/platforms/pasemi/gpio_mdio.c static int gpio_mdio_write(struct mii_bus *bus, int phy_id, int location, u16 va · line 315
Quoted 12 lines
arch/powerpc/platforms/pasemi/gpio_mdio.c +10
-0+ gpio_regs =ioremap (res.start,0x100 ); +if (unlikely (!gpio_regs)) +return -EPERM ; + + err =__gpio_mdio_register_bus (ofdev, match); +if (err <0 ) +iounmap (gpio_regs); + }else + err =__gpio_mdio_register_bus (ofdev, match);return err; +
again
Quoted 9 lines
}
static int
gpio_mdio_remove(struct of_device *dev){arch/powerpc/platforms/pasemi/gpio_mdio.c +0
-0struct mii_bus *bus =dev_get_drvdata (&dev->dev);mdiobus_unregister (bus);
Quoted 1 line · Nathan Lynch
Hi,
I moved res to the wrong function, that's fixed as well as the unlikely's and the extra new lines.
Thanks for your quick response. Here is an updated version:
--
Upon errors gpio_regs was not iounmapped, and later priv nor new_bus->irq was freed. Testing succes of the allocation of new_bus->irq was missing as well.
This patch creates a new function __gpio_mdio_register_bus to allow the iounmapping after an ioremap.
---
arch/powerpc/platforms/pasemi/gpio_mdio.c +43 -24
@@ -208,68 +208,50 @@ static int gpio_mdio_write(struct mii_bus *bus, int phy_id, int location, u16 va }static int gpio_mdio_reset (struct mii_bus *bus) {/*nothing here - dunno how to reset it*/ return 0 ; } - -static int __devinit gpio_mdio_probe (struct of_device *ofdev, -const struct of_device_id *match) +static int __devinit __gpio_mdio_register_bus (struct of_device *ofdev, +const struct of_device_id *match) {struct device *dev = &ofdev->dev;struct device_node *np = ofdev->node; -struct device_node *gpio_np;struct mii_bus *new_bus; -struct resource res;struct gpio_priv *priv;const unsigned int *prop; -int err =0 ;int i; - gpio_np =of_find_compatible_node (NULL ,"gpio" ,"1682m-gpio" ); - -if (!gpio_np) -return -ENODEV ; - - err =of_address_to_resource (gpio_np,0 , &res); -of_node_put (gpio_np); - -if (err) -return -EINVAL ; - -if (!gpio_regs) - gpio_regs =ioremap (res.start,0x100 ); - -if (!gpio_regs) -return -EPERM ; - priv =kzalloc (sizeof (struct gpio_priv ),GFP_KERNEL );if (priv ==NULL )return -ENOMEM ; new_bus =kzalloc (sizeof (struct mii_bus ),GFP_KERNEL );if (new_bus ==NULL ) -return -ENOMEM ; + goto free_priv; new_bus->name ="pasemi gpio mdio bus" , new_bus->read = &gpio_mdio_read, new_bus->write = &gpio_mdio_write, new_bus->reset = &gpio_mdio_reset, prop =of_get_property (np,"reg" ,NULL ); new_bus->id = *prop; new_bus->priv = priv; new_bus->phy_mask =0 ; new_bus->irq =kmalloc (sizeof (int )*PHY_MAX_ADDR ,GFP_KERNEL ); +if (new_bus->irq ==NULL ) + goto free_new_bus; +for (i =0 ; i <PHY_MAX_ADDR ; ++i) new_bus->irq[i] =irq_create_mapping (NULL ,10 ); prop =of_get_property (np,"mdc-pin" ,NULL ); priv->mdc_pin = *prop; prop =of_get_property (np,"mdio-pin" ,NULL );
@@ -284,17 +266,54 @@ static int __devinit gpio_mdio_probe(struct of_device *ofdev,printk (KERN_ERR "%s: Cannot register as MDIO bus, err %d\n" , new_bus->name, err); goto bus_register_fail; }return 0 ; bus_register_fail: +kfree (new_bus->irq); +free_new_bus:kfree (new_bus); +free_priv: +kfree (priv); + +return -ENOMEM ; +} + + +static int __devinit gpio_mdio_probe (struct of_device *ofdev, +const struct of_device_id *match) +{ +struct device_node *gpio_np; +struct resource res; +int err; + + gpio_np =of_find_compatible_node (NULL ,"gpio" ,"1682m-gpio" ); + +if (!gpio_np) +return -ENODEV ; + + err =of_address_to_resource (gpio_np,0 , &res); +of_node_put (gpio_np); + +if (err) +return -EINVAL ; + +if (!gpio_regs) { + gpio_regs =ioremap (res.start,0x100 ); +if (unlikely (!gpio_regs)) +return -EPERM ; + + err =__gpio_mdio_register_bus (ofdev, match); +if (err <0 ) +iounmap (gpio_regs); + }else + err =__gpio_mdio_register_bus (ofdev, match);return err; }static int gpio_mdio_remove (struct of_device *dev) {struct mii_bus *bus =dev_get_drvdata (&dev->dev);
Quoted 2 lines · Roel Kluin
I think this is how it should be done, but
please review: it was not tested.
Hi,
Thanks for the bug report. The mdio driver needs a set of other cleanups as well. I have a more comprehensive patch that I'll post tomorrow after I have a chance to test them.
-Olof
Quoted 9 lines · Olof Johansson
Quoted 2 lines · Roel Kluin
I think this is how it should be done, but
please review: it was not tested.Hi,
Thanks for the bug report. The mdio driver needs a set of other cleanups as well. I have a more comprehensive patch that I'll post tomorrow after I have a chance to test them.
Ok, that's fine with me,
Roel
PATCH 1/1 pasemi: clean up gpio_mdio init
pasemi: clean up mdio_gpio driver init
Misc cleanups of mdio_gpio:
* Better error handling/unrolling in case of init/alloc failures
* Go through child nodes and get their interrupts instead of using hardcoded values
* Remap the GPIO registers at module load/driver init instead of during probe
* Coding style and other misc cleanups
---
Quoted 5 lines · Roel Kluin
Quoted 4 lines · Olof Johansson
Quoted 2 lines · Roel Kluin
I think this is how it should be done, but
please review: it was not tested.
Quoted 7 lines
Quoted 5 lines
Hi,
Thanks for the bug report. The mdio driver needs a set of other cleanups as well. I have a more comprehensive patch that I'll post tomorrow after I have a chance to test them.
Ok, that's fine with me,
This is what I'll queue up for 2.6.25.
-Olof
arch/powerpc/platforms/pasemi/gpio_mdio.c +49 -37
@@ -218,45 +218,27 @@ static int __devinit gpio_mdio_probe(struct of_device *ofdev, const struct of_device_id *match) {struct device *dev = &ofdev->dev; -struct device_node *np = ofdev->node; -struct device_node *gpio_np; +struct device_node *phy_dn, *np = ofdev->node;struct mii_bus *new_bus; -struct resource res;struct gpio_priv *priv;const unsigned int *prop; -int err =0 ; +int err;int i; - gpio_np =of_find_compatible_node (NULL ,"gpio" ,"1682m-gpio" ); - -if (!gpio_np) -return -ENODEV ; - - err =of_address_to_resource (gpio_np,0 , &res); -of_node_put (gpio_np); - -if (err) -return -EINVAL ; - -if (!gpio_regs) - gpio_regs =ioremap (res.start,0x100 ); - -if (!gpio_regs) -return -EPERM ; - + err = -ENOMEM ; priv =kzalloc (sizeof (struct gpio_priv ),GFP_KERNEL ); -if (priv ==NULL ) -return -ENOMEM ; +if (!priv) + goto out; new_bus =kzalloc (sizeof (struct mii_bus ),GFP_KERNEL ); -if (new_bus ==NULL ) -return -ENOMEM ; +if (!new_bus) + goto out_free_priv; - new_bus->name ="pasemi gpio mdio bus" , - new_bus->read = &gpio_mdio_read, - new_bus->write = &gpio_mdio_write, - new_bus->reset = &gpio_mdio_reset, + new_bus->name ="pasemi gpio mdio bus" ; + new_bus->read = &gpio_mdio_read; + new_bus->write = &gpio_mdio_write; + new_bus->reset = &gpio_mdio_reset; prop =of_get_property (np,"reg" ,NULL ); new_bus->id = *prop;
@@ -265,9 +247,24 @@ static int __devinit gpio_mdio_probe(struct of_device *ofdev, new_bus->phy_mask =0 ; new_bus->irq =kmalloc (sizeof (int )*PHY_MAX_ADDR ,GFP_KERNEL ); -for (i =0 ; i <PHY_MAX_ADDR ; ++i) - new_bus->irq[i] =irq_create_mapping (NULL ,10 ); +if (!new_bus->irq) + goto out_free_bus; + +for (i =0 ; i <PHY_MAX_ADDR ; i++) + new_bus->irq[i] =NO_IRQ ; + +for (phy_dn =of_get_next_child (np,NULL ); + phy_dn !=NULL ; + phy_dn =of_get_next_child (np, phy_dn)) { +const int *ip, *regp; + + ip =of_get_property (phy_dn,"interrupts" ,NULL ); + regp =of_get_property (phy_dn,"reg" ,NULL ); +if (!ip || !regp) +continue ; + new_bus->irq[*regp] =irq_create_mapping (NULL , *ip); + } prop =of_get_property (np,"mdc-pin" ,NULL ); priv->mdc_pin = *prop;
@@ -280,17 +277,21 @@ static int __devinit gpio_mdio_probe(struct of_device *ofdev, err =mdiobus_register (new_bus); -if (0 != err) { +if (err !=0 ) {printk (KERN_ERR "%s: Cannot register as MDIO bus, err %d\n" , new_bus->name, err); - goto bus_register_fail; + goto out_free_irq; }return 0 ; -bus_register_fail: +out_free_irq: +kfree (new_bus->irq); +out_free_bus:kfree (new_bus); - +out_free_priv: +kfree (priv); +out:return err; }
@@ -330,12 +331,23 @@ static struct of_platform_driver gpio_mdio_driver =int gpio_mdio_init (void ) { +struct device_node *np; + + np =of_find_compatible_node (NULL ,"gpio" ,"1682m-gpio" ); +if (!np) +return -ENODEV ; + gpio_regs =of_iomap (np,0 ); +if (!gpio_regs) +return -ENODEV ; +return of_register_platform_driver (&gpio_mdio_driver); } +module_init (gpio_mdio_init);void gpio_mdio_exit (void ) {of_unregister_platform_driver (&gpio_mdio_driver); +if (gpio_regs) +iounmap (gpio_regs); } -device_initcall (gpio_mdio_init); - +module_exit (gpio_mdio_exit);
Re: [PATCH] pasemi: clean up gpio_mdio init
Hi Olof,
Just a couple of small things ...
arch/powerpc/platforms/pasemi/gpio_mdio.c static int __devinit gpio_mdio_probe(struct of_device *ofdev, · line 266
Quoted 6 lines · On Sun, 4 Nov 2007 15:37:09 -0600 Olof Johansson <[email protected]> wrote:
arch/powerpc/platforms/pasemi/gpio_mdio.c +5
-0+ ip =of_get_property (phy_dn,"interrupts" ,NULL ); + regp =of_get_property (phy_dn,"reg" ,NULL ); +if (!ip || !regp) +continue ; + new_bus->irq[*regp] =irq_create_mapping (NULL , *ip);
Paranoid me says to check that *regp is in range.
arch/powerpc/platforms/pasemi/gpio_mdio.c static struct of_platform_driver gpio_mdio_driver = · line 339
Quoted 8 lines
int
gpio_mdio_init(void)
{arch/powerpc/platforms/pasemi/gpio_mdio.c +6
-0+struct device_node *np; + + np =of_find_compatible_node (NULL ,"gpio" ,"1682m-gpio" ); +if (!np) +return -ENODEV ; + gpio_regs =of_iomap (np,0 );
of_node_put(np); ?
Quoted 5 lines
arch/powerpc/platforms/pasemi/gpio_mdio.c +3
-0+if (!gpio_regs) +return -ENODEV ; +return of_register_platform_driver (&gpio_mdio_driver); }
Signature · 3 lines
Cheers, Stephen Rothwell [email protected] http://www.canb.auug.org.au/~sfr/
Re: [PATCH] pasemi: clean up gpio_mdio init
Hi,
Quoted 1 line · Stephen Rothwell
Just a couple of small things ...
Thanks! Unless someone finds something bigger, I'll update this before I push it out through git, but I won't repost.
Quoted 9 lines · On Sun, 4 Nov 2007 15:37:09 -0600 Olof Johansson <[email protected]> wrote:
arch/powerpc/platforms/pasemi/gpio_mdio.c static int __devinit gpio_mdio_probe(struct of_device *ofdev, · line 266
Quoted 6 lines
arch/powerpc/platforms/pasemi/gpio_mdio.c +5
-0+ ip =of_get_property (phy_dn,"interrupts" ,NULL ); + regp =of_get_property (phy_dn,"reg" ,NULL ); +if (!ip || !regp) +continue ; + new_bus->irq[*regp] =irq_create_mapping (NULL , *ip);Paranoid me says to check that *regp is in range.
Yeah, good point.
Quoted 11 lines
arch/powerpc/platforms/pasemi/gpio_mdio.c static struct of_platform_driver gpio_mdio_driver = · line 339
Quoted 9 lines
int
gpio_mdio_init(void)
{arch/powerpc/platforms/pasemi/gpio_mdio.c +6
-0+struct device_node *np; + + np =of_find_compatible_node (NULL ,"gpio" ,"1682m-gpio" ); +if (!np) +return -ENODEV ; + gpio_regs =of_iomap (np,0 );of_node_put(np); ?
Yup.
Thanks for the review,
-Olof