From 2858176b9c8b5a551d4bb687d1b86e471c7c1079 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Sat, 10 Jan 2004 05:09:30 -0500 Subject: [PATCH] [PATCH] (36/42) hplance NE61-hplance * switched to dynamic allocation * fixed resource leaks on failure exits --- drivers/net/Space.c | 8 ++-- drivers/net/hplance.c | 85 ++++++++++++++++++++----------------------- 2 files changed, 44 insertions(+), 49 deletions(-) diff --git a/drivers/net/Space.c b/drivers/net/Space.c index 15b7dfdc500f9..ab3d52213bb67 100644 --- a/drivers/net/Space.c +++ b/drivers/net/Space.c @@ -81,7 +81,7 @@ extern int apne_probe(struct net_device *); extern int bionet_probe(struct net_device *); extern int pamsnet_probe(struct net_device *); extern struct net_device *cs89x0_probe(int unit); -extern int hplance_probe(struct net_device *dev); +extern struct net_device *hplance_probe(int unit); extern struct net_device *bagetlance_probe(int unit); extern struct net_device *mvme147lance_probe(int unit); extern struct net_device *tc515_probe(int unit); @@ -313,14 +313,14 @@ static struct devprobe m68k_probes[] __initdata = { #endif #ifdef CONFIG_ATARI_PAMSNET /* Atari PAMsNet Ethernet board */ {pamsnet_probe, 0}, -#endif -#ifdef CONFIG_HPLANCE /* HP300 internal Ethernet */ - {hplance_probe, 0}, #endif {NULL, 0}, }; static struct devprobe2 m68k_probes2[] __initdata = { +#ifdef CONFIG_HPLANCE /* HP300 internal Ethernet */ + {hplance_probe, 0}, +#endif #ifdef CONFIG_MVME147_NET /* MVME147 internal Ethernet */ {mvme147lance_probe, 0}, #endif diff --git a/drivers/net/hplance.c b/drivers/net/hplance.c index 98cb52f117426..cd0b733c7f3e5 100644 --- a/drivers/net/hplance.c +++ b/drivers/net/hplance.c @@ -50,8 +50,7 @@ struct hplance_private { * plus board-specific init, open and close actions. * Oh, and we need to tell the generic code how to read and write LANCE registers... */ -int hplance_probe(struct net_device *dev); -static int hplance_init(struct net_device *dev, int scode); +static void hplance_init(struct net_device *dev, int scode); static int hplance_open(struct net_device *dev); static int hplance_close(struct net_device *dev); static void hplance_writerap(void *priv, unsigned short value); @@ -62,57 +61,61 @@ static unsigned short hplance_readrdp(void *priv); static struct hplance_private *root_hplance_dev; #endif +static void cleanup_card(struct net_device *dev) +{ + struct hplance_private *lp = dev->priv; + dio_unconfig_board(lp->scode); +} + /* Find all the HP Lance boards and initialise them... */ -int __init hplance_probe(struct net_device *dev) +struct net_device * __init hplance_probe(int unit) { - int cards = 0, called = 0; + struct net_device *dev; + + if (!MACH_IS_HP300) + return ERR_PTR(-ENODEV); + + dev = alloc_etherdev(sizeof(struct hplance_private)); + if (!dev) + return ERR_PTR(-ENOMEM); + + if (unit >= 0) { + sprintf(dev->name, "eth%d", unit); + netdev_boot_setup_check(dev); + } - if (!MACH_IS_HP300 || called) - return(ENODEV); - called++; + SET_MODULE_OWNER(dev); /* Isn't DIO nice? */ for(;;) { - int v, scode = dio_find(DIO_ID_LAN); + int scode = dio_find(DIO_ID_LAN); if (!scode) break; - if(cards) - dev = NULL; /* don't trash previous device, make a new one */ - cards++; - - v = hplance_init(dev, scode); - if (v) /* error, abort immediately */ - return v; + dio_config_board(scode); + hplance_init(dev, scode); + if (!register_netdev(dev)) { + struct hplance_private *lp = dev->priv; + lp->next_module = root_hplance_dev; + root_hplance_dev = lp; + return dev; + } + cleanup_card(dev); } - /* OK, return success, or ENODEV if we didn't find any cards */ - if (!cards) - return -ENODEV; - return 0; + free_netdev(dev); + return ERR_PTR(-ENODEV); } /* Initialise a single lance board at the given select code */ -static int __init hplance_init(struct net_device *dev, int scode) +static void __init hplance_init(struct net_device *dev, int scode) { const char *name = dio_scodetoname(scode); void *va = dio_scodetoviraddr(scode); struct hplance_private *lp; int i; -#ifdef MODULE - dev = init_etherdev(0, sizeof(struct hplance_private)); - if (!dev) - return -ENOMEM; -#else - dev->priv = kmalloc(sizeof(struct hplance_private), GFP_KERNEL); - if (dev->priv == NULL) - return -ENOMEM; - memset(dev->priv, 0, sizeof(struct hplance_private)); -#endif - SET_MODULE_OWNER(dev); - printk("%s: %s; select code %d, addr", dev->name, name, scode); /* reset the board */ @@ -154,17 +157,7 @@ static int __init hplance_init(struct net_device *dev, int scode) lp->lance.tx_ring_mod_mask = TX_RING_MOD_MASK; lp->scode = scode; lp->base = va; - ether_setup(dev); printk(", irq %d\n", lp->lance.irq); - -#ifdef MODULE - dev->ifindex = dev_new_index(); - lp->next_module = root_hplance_dev; - root_hplance_dev = lp; -#endif /* MODULE */ - - dio_config_board(scode); /* tell bus scanning code this one's taken */ - return 0; } /* This is disgusting. We have to check the DIO status register for ack every @@ -227,8 +220,10 @@ static int hplance_close(struct net_device *dev) MODULE_LICENSE("GPL"); int init_module(void) { - root_lance_dev = NULL; - return hplance_probe(NULL); + int found = 0; + while (!IS_ERR(hplance_probe(-1))) + found++; + return found ? 0 : -ENODEV; } void cleanup_module(void) @@ -237,8 +232,8 @@ void cleanup_module(void) struct hplance_private *lp; while (root_hplance_dev) { lp = root_hplance_dev->next_module; - dio_unconfig_board(lp->scode); unregister_netdev(root_lance_dev->dev); + cleanup_card(root_lance_dev->dev); free_netdev(root_lance_dev->dev); root_lance_dev = lp; } -- 2.53.0