[PATCH] (12/42) ne
DORMANTno replies
From: Stephen Hemminger <hidden>
Date: 2003-11-13 00:42:18
Based on NE36-ne * switched ne/ne2k_cbus to dynamic allocation * ne/ne2k_cbus: fixed order of freeing bugs * ne/ne2k_cbus: fixed resource leaks on failure exits * ne/ne2k_cbus: fixed clobbering on autoprobe diff -Nru a/drivers/net/Space.c b/drivers/net/Space.c
--- a/drivers/net/Space.c Tue Nov 11 14:35:31 2003
+++ b/drivers/net/Space.c Tue Nov 11 14:35:31 2003@@ -46,7 +46,7 @@ extern int ultra32_probe(struct net_device *dev); extern int wd_probe(struct net_device *dev); extern int el2_probe(struct net_device *dev); -extern int ne_probe(struct net_device *dev); +extern struct net_device *ne_probe(int unit); extern int hp_probe(struct net_device *dev); extern int hp_plus_probe(struct net_device *dev); extern struct net_device *express_probe(int unit);
@@ -222,13 +222,13 @@ #ifdef CONFIG_E2100 /* Cabletron E21xx series. */ {e2100_probe, 0}, #endif -#if defined(CONFIG_NE2000) || defined(CONFIG_NE2K_CBUS) /* ISA & PC-9800 CBUS (use ne2k-pci for PCI cards) */ - {ne_probe, 0}, -#endif {NULL, 0}, }; static struct devprobe2 isa_probes2[] __initdata = { +#if defined(CONFIG_NE2000) || defined(CONFIG_NE2K_CBUS) /* ISA & PC-9800 CBUS (use ne2k-pci for PCI cards) */ + {ne_probe, 0}, +#endif #ifdef CONFIG_LANCE /* ISA/VLB (use pcnet32 for PCI cards) */ {lance_probe, 0}, #endif
diff -Nru a/drivers/net/ne.c b/drivers/net/ne.c
--- a/drivers/net/ne.c Tue Nov 11 14:35:31 2003
+++ b/drivers/net/ne.c Tue Nov 11 14:35:31 2003@@ -126,7 +126,6 @@ #define NESM_START_PG 0x40 /* First page of TX buffer */ #define NESM_STOP_PG 0x80 /* Last page +1 of RX ring */ -int ne_probe(struct net_device *dev); static int ne_probe1(struct net_device *dev, int ioaddr); static int ne_probe_isapnp(struct net_device *dev);
@@ -163,9 +162,10 @@ E2010 starts at 0x100 and ends at 0x4000. E2010-x starts at 0x100 and ends at 0xffff. */ -int __init ne_probe(struct net_device *dev) +static int __init do_ne_probe(struct net_device *dev) { unsigned int base_addr = dev->base_addr; + int irq = dev->irq; SET_MODULE_OWNER(dev);
@@ -183,6 +183,7 @@ /* Last resort. The semi-risky ISA auto-probe. */ for (base_addr = 0; netcard_portlist[base_addr] != 0; base_addr++) { int ioaddr = netcard_portlist[base_addr]; + dev->irq = irq; if (ne_probe1(dev, ioaddr) == 0) return 0; }
@@ -191,6 +192,44 @@ return -ENODEV; } +static void cleanup_card(struct net_device *dev) +{ + void *priv = dev->priv; + struct pnp_dev *idev = (struct pnp_dev *)ei_status.priv; + if (idev) + pnp_device_detach(idev); + free_irq(dev->irq, dev); + release_region(dev->base_addr, NE_IO_EXTENT); + kfree(priv); +} + +struct net_device * __init ne_probe(int unit) +{ + struct net_device *dev = alloc_etherdev(0); + int err; + + if (!dev) + return ERR_PTR(-ENOMEM); + + sprintf(dev->name, "eth%d", unit); + netdev_boot_setup_check(dev); + + dev->priv = NULL; /* until all 8390-based use alloc_etherdev() */ + + err = do_ne_probe(dev); + if (err) + goto out; + err = register_netdev(dev); + if (err) + goto out1; + return dev; +out1: + cleanup_card(dev); +out: + free_netdev(dev); + return ERR_PTR(err); +} + static int __init ne_probe_isapnp(struct net_device *dev) { int i;
@@ -734,7 +773,7 @@ #ifdef MODULE #define MAX_NE_CARDS 4 /* Max number of NE cards per module */ -static struct net_device dev_ne[MAX_NE_CARDS]; +static struct net_device *dev_ne[MAX_NE_CARDS]; static int io[MAX_NE_CARDS]; static int irq[MAX_NE_CARDS]; static int bad[MAX_NE_CARDS]; /* 0xbad = bad sig or no reset ack */
@@ -758,25 +797,32 @@ int this_dev, found = 0; for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) { - struct net_device *dev = &dev_ne[this_dev]; + struct net_device *dev = alloc_etherdev(0); + if (!dev) + break; + dev->priv = NULL; dev->irq = irq[this_dev]; dev->mem_end = bad[this_dev]; dev->base_addr = io[this_dev]; - dev->init = ne_probe; - if (register_netdev(dev) == 0) { - found++; - continue; - } - if (found != 0) { /* Got at least one. */ - return 0; + if (do_ne_probe(dev) == 0) { + if (register_netdev(dev) == 0) { + dev_ne[found++] = dev; + continue; + } + cleanup_card(dev); } + free_netdev(dev); + if (found) + break; if (io[this_dev] != 0) printk(KERN_WARNING "ne.c: No NE*000 card found at i/o = %#x\n", io[this_dev]); else printk(KERN_NOTICE "ne.c: You must supply \"io=0xNNN\" value(s) for ISA cards.\n"); return -ENXIO; } - return 0; + if (found) + return 0; + return -ENODEV; } void cleanup_module(void)
@@ -784,16 +830,11 @@ int this_dev; for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) { - struct net_device *dev = &dev_ne[this_dev]; - if (dev->priv != NULL) { - void *priv = dev->priv; - struct pnp_dev *idev = (struct pnp_dev *)ei_status.priv; - if (idev) - pnp_device_detach(idev); - free_irq(dev->irq, dev); - release_region(dev->base_addr, NE_IO_EXTENT); + struct net_device *dev = dev_ne[this_dev]; + if (dev) { unregister_netdev(dev); - kfree(priv); + cleanup_card(dev); + free_netdev(dev); } } }
diff -Nru a/drivers/net/ne2k_cbus.c b/drivers/net/ne2k_cbus.c
--- a/drivers/net/ne2k_cbus.c Tue Nov 11 14:35:31 2003
+++ b/drivers/net/ne2k_cbus.c Tue Nov 11 14:35:31 2003@@ -78,7 +78,6 @@ #include "ne2k_cbus.h" -int ne_probe(struct net_device *dev); static int ne_probe1(struct net_device *dev, int ioaddr); static int ne_open(struct net_device *dev); static int ne_close(struct net_device *dev);
@@ -113,9 +112,10 @@ E2010 starts at 0x100 and ends at 0x4000. E2010-x starts at 0x100 and ends at 0xffff. */ -int __init ne_probe(struct net_device *dev) +static int __init do_ne_probe(struct net_device *dev) { unsigned int base_addr = dev->base_addr; + int irq = dev->irq; SET_MODULE_OWNER(dev);
@@ -135,7 +135,7 @@ if (ei_debug > 2) printk(KERN_DEBUG "ne_probe(): call ne_probe_cbus(base_addr=0x%x)\n", base_addr); - result = ne_probe_cbus(dev, hw, base_addr); + result = ne_probe_cbus(dev, hw, base_addr, irq); if (result != 0) ne2k_cbus_destroy(dev);
@@ -156,13 +156,13 @@ if (hw && hw->hwtype) { const unsigned short *plist; for (plist = hw->portlist; *plist; plist++) - if (ne_probe_cbus(dev, hw, *plist) == 0) + if (ne_probe_cbus(dev, hw, *plist, irq) == 0) return 0; } else { for (hw = &ne2k_cbus_hwinfo_list[0]; hw->hwtype; hw++) { const unsigned short *plist; for (plist = hw->portlist; *plist; plist++) - if (ne_probe_cbus(dev, hw, *plist) == 0) + if (ne_probe_cbus(dev, hw, *plist, irq) == 0) return 0; } }
@@ -174,7 +174,47 @@ return -ENODEV; } -static int __init ne_probe_cbus(struct net_device *dev, const struct ne2k_cbus_hwinfo *hw, int ioaddr) +static void cleanup_card(struct net_device *dev) +{ + const struct ne2k_cbus_region *rlist; + const struct ne2k_cbus_hwinfo *hw = ne2k_cbus_get_hwinfo((int)(dev->mem_start & NE2K_CBUS_HARDWARE_TYPE_MASK)); + + free_irq(dev->irq, dev); + for (rlist = hw->regionlist; rlist->range; rlist++) { + release_region(dev->base_addr + rlist->start, + rlist->range); + } + ne2k_cbus_destroy(dev); +} + +struct net_device * __init ne_probe(int unit) +{ + struct net_device *dev = alloc_etherdev(0); + int err; + + if (!dev) + return ERR_PTR(-ENOMEM); + + sprintf(dev->name, "eth%d", unit); + netdev_boot_setup_check(dev); + + dev->priv = NULL; /* until all 8390-based use alloc_etherdev() */ + + err = do_ne_probe(dev); + if (err) + goto out; + err = register_netdev(dev); + if (err) + goto out1; + return dev; +out1: + cleanup_card(dev); +out: + free_netdev(dev); + return ERR_PTR(err); +} + +static int __init ne_probe_cbus(struct net_device *dev, const struct ne2k_cbus_hwinfo *hw, int ioaddr, int irq) { if (ei_debug > 2) printk(KERN_DEBUG "ne_probe_cbus(): entered. (called from %p)\n",
@@ -182,6 +222,7 @@ if (hw && hw->hwtype) { ne2k_cbus_set_hwtype(dev, hw, ioaddr); + dev->irq = irq; return ne_probe1(dev, ioaddr); } else { /* auto detect */
@@ -189,6 +230,7 @@ printk(KERN_DEBUG "ne_probe_cbus(): try to determine hardware types.\n"); for (hw = &ne2k_cbus_hwinfo_list[0]; hw->hwtype; hw++) { ne2k_cbus_set_hwtype(dev, hw, ioaddr); + dev->irq = irq; if (ne_probe1(dev, ioaddr) == 0) return 0; }
@@ -301,11 +343,12 @@ if (ei_debug > 2) printk(" [CNET98EL-specific initialize..."); outb_p(E8390_NODMA | E8390_STOP, ioaddr + E8390_CMD); /* 0x20|0x1 */ + ret = -ENODEV; i = inb(ioaddr); if ((i & ~0x2) != (0x20 | 0x01)) - return -ENODEV; + goto err_out; if ((inb(ioaddr + 0x7) & 0x80) != 0x80) - return -ENODEV; + goto err_out; outb_p(E8390_RXOFF, ioaddr + EN0_RXCR); /* out(ioaddr+0xc, 0x20) */ /* outb_p(ENDCFG_WTS|ENDCFG_FT1|ENDCFG_LS, ioaddr+EN0_DCFG); */ outb_p(ENDCFG_WTS | 0x48, ioaddr + EN0_DCFG); /* 0x49 */
@@ -330,7 +373,7 @@ if (ei_debug > 2) printk("] "); printk("memory failure at %x\n", i); - return -ENODEV; + goto err_out; } if (ei_debug > 2) printk(" good...");
@@ -338,7 +381,7 @@ if (ei_debug > 2) printk("] "); printk("IRQ must be specified for C-NET(98)E/L. probe failed.\n"); - return -ENODEV; + goto err_out; } outb((dev->irq > 5) ? (dev->irq & 4):(dev->irq >> 1), ioaddr + (0x2 | 0x400)); outb(0x7e, ioaddr + (0x4 | 0x400));
@@ -779,7 +822,7 @@ #ifdef MODULE #define MAX_NE_CARDS 4 /* Max number of NE cards per module */ -static struct net_device dev_ne[MAX_NE_CARDS]; +static struct net_device *dev_ne[MAX_NE_CARDS]; static int io[MAX_NE_CARDS]; static int irq[MAX_NE_CARDS]; static int bad[MAX_NE_CARDS]; /* 0xbad = bad sig or no reset ack */
@@ -806,26 +849,33 @@ int this_dev, found = 0; for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) { - struct net_device *dev = &dev_ne[this_dev]; + struct net_device *dev = alloc_etherdev(0); + if (!dev) + break; + dev->priv = NULL; dev->irq = irq[this_dev]; dev->mem_end = bad[this_dev]; dev->base_addr = io[this_dev]; dev->mem_start = hwtype[this_dev]; - dev->init = ne_probe; - if (register_netdev(dev) == 0) { - found++; - continue; - } - if (found != 0) { /* Got at least one. */ - return 0; + if (do_ne_probe(dev) == 0) { + if (register_netdev(dev) == 0) { + dev_ne[found++] = dev; + continue; + } + cleanup_card(dev); } + free_netdev(dev); + if (found) + break; if (io[this_dev] != 0) printk(KERN_WARNING "ne2k_cbus: No NE*000 card found at i/o = %#x\n", io[this_dev]); else - printk(KERN_NOTICE "ne2k_cbus: You must supply \"io=0xNNN\" value(s) for C-Bus cards.\n"); + printk(KERN_NOTICE "ne.c: You must supply \"io=0xNNN\" value(s) for ISA cards.\n"); return -ENXIO; } - return 0; + if (found) + return 0; + return -ENODEV; } void cleanup_module(void)
@@ -833,18 +883,11 @@ int this_dev; for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) { - struct net_device *dev = &dev_ne[this_dev]; - if (dev->priv != NULL) { - const struct ne2k_cbus_region *rlist; - const struct ne2k_cbus_hwinfo *hw = ne2k_cbus_get_hwinfo((int)(dev->mem_start & NE2K_CBUS_HARDWARE_TYPE_MASK)); - - free_irq(dev->irq, dev); - for (rlist = hw->regionlist; rlist->range; rlist++) { - release_region(dev->base_addr + rlist->start, - rlist->range); - } + struct net_device *dev = dev_ne[this_dev]; + if (dev) { unregister_netdev(dev); - ne2k_cbus_destroy(dev); + cleanup_card(dev); + free_netdev(dev); } } }
diff -Nru a/drivers/net/ne2k_cbus.h b/drivers/net/ne2k_cbus.h
--- a/drivers/net/ne2k_cbus.h Tue Nov 11 14:35:31 2003
+++ b/drivers/net/ne2k_cbus.h Tue Nov 11 14:35:31 2003@@ -477,5 +477,5 @@ } #endif -static int ne_probe_cbus(struct net_device *dev, const struct ne2k_cbus_hwinfo *hw, int ioaddr); +static int ne_probe_cbus(struct net_device *dev, const struct ne2k_cbus_hwinfo *hw, int ioaddr, int irq); /* End of ne2k_cbus.h */