From 1953882a164f094a5e1505a1dd5c551ff1c26dc3 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Sat, 10 Jan 2004 04:54:11 -0500 Subject: [PATCH] [PATCH] (10/42) smc Based on viro NE34-smc * switched smc to dynamic allocation * smc: embedded ->priv * smc: fixed resource leaks on failure exits * smc: fixed clobbering on autoprobe --- drivers/net/Space.c | 8 +-- drivers/net/smc9194.c | 110 +++++++++++++++++++++--------------------- 2 files changed, 60 insertions(+), 58 deletions(-) diff --git a/drivers/net/Space.c b/drivers/net/Space.c index aafd6dbdc838f..93aa5c593e4ba 100644 --- a/drivers/net/Space.c +++ b/drivers/net/Space.c @@ -73,7 +73,7 @@ extern struct net_device *ni65_probe(int unit); extern int sonic_probe(struct net_device *); extern struct net_device *SK_init(int unit); extern struct net_device *seeq8005_probe(int unit); -extern int smc_init( struct net_device * ); +extern struct net_device *smc_init(int unit); extern int atarilance_probe(struct net_device *); extern int sun3lance_probe(struct net_device *); extern int sun3_82586_probe(struct net_device *); @@ -227,14 +227,14 @@ static struct devprobe isa_probes[] __initdata = { #endif #ifdef CONFIG_LANCE /* ISA/VLB (use pcnet32 for PCI cards) */ {lance_probe, 0}, -#endif -#ifdef CONFIG_SMC9194 - {smc_init, 0}, #endif {NULL, 0}, }; static struct devprobe2 isa_probes2[] __initdata = { +#ifdef CONFIG_SMC9194 + {smc_init, 0}, +#endif #ifdef CONFIG_SEEQ8005 {seeq8005_probe, 0}, #endif diff --git a/drivers/net/smc9194.c b/drivers/net/smc9194.c index 4d24343c1799a..9bac2d61bbba0 100644 --- a/drivers/net/smc9194.c +++ b/drivers/net/smc9194.c @@ -191,7 +191,7 @@ struct smc_local { . . NB:This shouldn't be static since it is referred to externally. */ -int smc_init(struct net_device *dev); +struct net_device *smc_init(int unit); /* . The kernel calls this function when someone wants to use the device, @@ -672,7 +672,7 @@ static void smc_hardware_send_packet( struct net_device * dev ) /*------------------------------------------------------------------------- | - | smc_init( struct net_device * dev ) + | smc_init(int unit) | Input parameters: | dev->base_addr == 0, try to find all possible locations | dev->base_addr == 1, return failure code @@ -680,31 +680,56 @@ static void smc_hardware_send_packet( struct net_device * dev ) | dev->base_addr == this is the address to check | | Output: - | 0 --> there is a device - | anything else, error + | pointer to net_device or ERR_PTR(error) | --------------------------------------------------------------------------- */ -int __init smc_init(struct net_device *dev) +static int io; +static int irq; +static int ifport; + +struct net_device * __init smc_init(int unit) { - int i; - int base_addr = dev->base_addr; + struct net_device *dev = alloc_etherdev(sizeof(struct smc_local)); + unsigned *port; + int err = 0; + + if (!dev) + return ERR_PTR(-ENODEV); + + if (unit >= 0) { + sprintf(dev->name, "eth%d", unit); + netdev_boot_setup_check(dev); + io = dev->base_addr; + irq = dev->irq; + } SET_MODULE_OWNER(dev); - /* try a specific location */ - if (base_addr > 0x1ff) - return smc_probe(dev, base_addr); - else if (base_addr != 0) - return -ENXIO; - - /* check every ethernet address */ - for (i = 0; smc_portlist[i]; i++) - if (smc_probe(dev, smc_portlist[i]) == 0) - return 0; - - /* couldn't find anything */ - return -ENODEV; + if (io > 0x1ff) { /* Check a single specified location. */ + err = smc_probe(dev, io); + } else if (io != 0) { /* Don't probe at all. */ + err = -ENXIO; + } else { + for (port = smc_portlist; *port; port++) { + if (smc_probe(dev, *port) == 0) + break; + } + if (!*port) + err = -ENODEV; + } + if (err) + goto out; + err = register_netdev(dev); + if (err) + goto out1; + return dev; +out1: + free_irq(dev->irq, dev); + release_region(dev->base_addr, SMC_IO_EXTENT); +out: + free_netdev(dev); + return ERR_PTR(err); } /*---------------------------------------------------------------------- @@ -821,6 +846,9 @@ static int __init smc_probe(struct net_device *dev, int ioaddr) if (!request_region(ioaddr, SMC_IO_EXTENT, dev->name)) return -EBUSY; + dev->irq = irq; + dev->if_port = ifport; + /* First, see if the high byte is 0x33 */ bank = inw( ioaddr + BANK_SELECT ); if ( (bank & 0xFF00) != 0x3300 ) { @@ -969,28 +997,14 @@ static int __init smc_probe(struct net_device *dev, int ioaddr) printk("%2.2x:", dev->dev_addr[i] ); printk("%2.2x \n", dev->dev_addr[5] ); - - /* Initialize the private structure. */ - if (dev->priv == NULL) { - dev->priv = kmalloc(sizeof(struct smc_local), GFP_KERNEL); - if (dev->priv == NULL) { - retval = -ENOMEM; - goto err_out; - } - } /* set the private data to zero by default */ memset(dev->priv, 0, sizeof(struct smc_local)); - /* Fill in the fields of the device structure with ethernet values. */ - ether_setup(dev); - /* Grab the IRQ */ retval = request_irq(dev->irq, &smc_interrupt, 0, dev->name, dev); if (retval) { printk("%s: unable to get IRQ %d (irqval=%d).\n", dev->name, dev->irq, retval); - kfree(dev->priv); - dev->priv = NULL; goto err_out; } @@ -1524,10 +1538,7 @@ static void smc_set_multicast_list(struct net_device *dev) #ifdef MODULE -static struct net_device devSMC9194; -static int io; -static int irq; -static int ifport; +static struct net_device *devSMC9194; MODULE_LICENSE("GPL"); MODULE_PARM(io, "i"); @@ -1539,32 +1550,23 @@ MODULE_PARM_DESC(ifport, "SMC 99194 interface port (0-default, 1-TP, 2-AUI)"); int init_module(void) { - int result; - if (io == 0) printk(KERN_WARNING CARDNAME": You shouldn't use auto-probing with insmod!\n" ); /* copy the parameters from insmod into the device structure */ - devSMC9194.base_addr = io; - devSMC9194.irq = irq; - devSMC9194.if_port = ifport; - devSMC9194.init = smc_init; - if ((result = register_netdev(&devSMC9194)) != 0) - return result; - + devSMC9194 = smc_init(-1); + if (IS_ERR(devSMC9194)) + return PTR_ERR(devSMC9194); return 0; } void cleanup_module(void) { - unregister_netdev(&devSMC9194); - - free_irq(devSMC9194.irq, &devSMC9194); - release_region(devSMC9194.base_addr, SMC_IO_EXTENT); - - if (devSMC9194.priv) - kfree(devSMC9194.priv); + unregister_netdev(devSMC9194); + free_irq(devSMC9194->irq, devSMC9194); + release_region(devSMC9194->base_addr, SMC_IO_EXTENT); + free_netdev(devSMC9194); } #endif /* MODULE */ -- 2.53.0