From: Christoph Hellwig There's tons of leaks in the hplcance probing code, and it doesn't release the memory region on removal either. Signed-off-by: Andrew Morton --- 25-akpm/drivers/net/hplance.c | 33 +++++++++++++++++++++++---------- 1 files changed, 23 insertions(+), 10 deletions(-) diff -puN drivers/net/hplance.c~hp300-lance-leak-fixes drivers/net/hplance.c --- 25/drivers/net/hplance.c~hp300-lance-leak-fixes 2004-11-16 23:10:45.029828784 -0800 +++ 25-akpm/drivers/net/hplance.c 2004-11-16 23:10:45.032828328 -0800 @@ -71,30 +71,42 @@ static struct dio_driver hplance_driver .remove = __devexit_p(hplance_remove_one), }; +/* XXX(hch): should probably move to a better place */ +#define dio_resource_start(d) \ + ((d)->resource.start) +#define dio_resource_len(d) \ + ((d)->resource.end - (d)->resource.start) + /* Find all the HP Lance boards and initialise them... */ static int __devinit hplance_init_one(struct dio_dev *d, const struct dio_device_id *ent) { struct net_device *dev; - int err; + int err = -ENOMEM; dev = alloc_etherdev(sizeof(struct hplance_private)); if (!dev) - return -ENOMEM; + goto out; - if (!request_mem_region(d->resource.start, d->resource.end-d->resource.start, d->name)) - return -EBUSY; + err = -EBUSY; + if (!request_mem_region(dio_resource_start(d), + dio_resource_len(d), d->name)) + goto out_free_netdev; - SET_MODULE_OWNER(dev); - hplance_init(dev, d); err = register_netdev(dev); - if (err) { - free_netdev(dev); - return err; - } + if (err) + goto out_free_netdev; + dio_set_drvdata(d, dev); return 0; + + out_release_mem_region: + release_mem_region(dio_resource_start(d), dio_resource_len(d)); + out_free_netdev: + free_netdev(dev); + out: + return err; } static void __devexit hplance_remove_one(struct dio_dev *d) @@ -102,6 +114,7 @@ static void __devexit hplance_remove_one struct net_device *dev = dio_get_drvdata(d); unregister_netdev(dev); + release_mem_region(dio_resource_start(d), dio_resource_len(d)); free_netdev(dev); } _