From 70150e541ffe53806bbe30954a6d1d14716243da Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Wed, 3 Sep 2003 10:33:32 -0700 Subject: [NET]: Fix ethtool_ops thinko in sungem.c --- drivers/net/sungem.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c index a452e5942b52..de27ee588a77 100644 --- a/drivers/net/sungem.c +++ b/drivers/net/sungem.c @@ -2416,13 +2416,6 @@ static int gem_nway_reset(struct net_device *dev) return 0; } -static u32 gem_get_link(struct net_device *dev) -{ - struct gem *gp = dev->priv; - - return (gp->lstate == link_up); -} - static u32 gem_get_msglevel(struct net_device *dev) { struct gem *gp = dev->priv; @@ -2441,7 +2434,6 @@ static struct ethtool_ops gem_ethtool_ops = { .get_settings = gem_get_settings, .set_settings = gem_set_settings, .nway_reset = gem_nway_reset, - .get_link = gem_get_link, .get_msglevel = gem_get_msglevel, .set_msglevel = gem_set_msglevel, }; -- cgit v1.2.3 From db390c0eaee3da6990b39810c3cb811c724f6299 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 3 Sep 2003 10:35:52 -0700 Subject: [NET]: DLCI driver cleanups for 2.6.x - keep list of arrays for devices and use a lock - make sure header is contiguous before overlaying data structure - dynamically allocate dev->priv with alloc_netdev - get rid of MOD_INC/DEC - free devices on module unload - keep refcount on slave device's since holding a ptr --- drivers/net/wan/dlci.c | 129 +++++++++++++++++++++++------------------------- include/linux/if_frad.h | 4 +- 2 files changed, 66 insertions(+), 67 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wan/dlci.c b/drivers/net/wan/dlci.c index 5aab67436cc7..380bb830d738 100644 --- a/drivers/net/wan/dlci.c +++ b/drivers/net/wan/dlci.c @@ -55,14 +55,13 @@ #include #include -static const char devname[] = "dlci"; static const char version[] = "DLCI driver v0.35, 4 Jan 1997, mike.mclagan@linux.org"; -static struct net_device *open_dev[CONFIG_DLCI_COUNT]; - +static LIST_HEAD(dlci_devs); +static spinlock_t dlci_dev_lock = SPIN_LOCK_UNLOCKED; static char *basename[16]; -int dlci_init(struct net_device *dev); +static void dlci_setup(struct net_device *); /* allow FRAD's to register their name as a valid FRAD */ int register_frad(const char *name) @@ -115,6 +114,7 @@ int unregister_frad(const char *name) return(0); } +EXPORT_SYMBOL(unregister_frad); /* * these encapsulate the RFC 1490 requirements as well as @@ -168,6 +168,14 @@ static void dlci_receive(struct sk_buff *skb, struct net_device *dev) int process, header; dlp = dev->priv; + if (!pskb_may_pull(skb, sizeof(*hdr))) { + printk(KERN_NOTICE "%s: invalid data no header\n", + dev->name); + dlp->stats.rx_errors++; + kfree_skb(skb); + return; + } + hdr = (struct frhdr *) skb->data; process = 0; header = 0; @@ -277,7 +285,7 @@ static int dlci_transmit(struct sk_buff *skb, struct net_device *dev) return(ret); } -int dlci_config(struct net_device *dev, struct dlci_conf *conf, int get) +static int dlci_config(struct net_device *dev, struct dlci_conf *conf, int get) { struct dlci_conf config; struct dlci_local *dlp; @@ -311,7 +319,7 @@ int dlci_config(struct net_device *dev, struct dlci_conf *conf, int get) return(0); } -int dlci_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +static int dlci_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { struct dlci_local *dlp; @@ -401,21 +409,23 @@ static struct net_device_stats *dlci_get_stats(struct net_device *dev) return(&dlp->stats); } -int dlci_add(struct dlci_add *dlci) +static int dlci_add(struct dlci_add *dlci) { - struct net_device *master, *slave; + struct net_device *master, *slave; struct dlci_local *dlp; struct frad_local *flp; int err, i; - char buf[10]; + /* validate slave device */ - slave = __dev_get_by_name(dlci->devname); + slave = dev_get_by_name(dlci->devname); if (!slave) return(-ENODEV); - if (slave->type != ARPHRD_FRAD) + if (slave->type != ARPHRD_FRAD) { + dev_put(slave); return(-EINVAL); + } /* check for registration */ for (i=0;idevname) > strlen(basename[i]))) break; - if (i == sizeof(basename) / sizeof(char *)) + if (i == sizeof(basename) / sizeof(char *)) { + dev_put(slave); return(-EINVAL); - - /* check for too many open devices : should this be dynamic ? */ - for(i=0;iname, buf); - master->init = dlci_init; - master->flags = 0; + } err = register_netdev(master); - if (err < 0) - { + if (err < 0) { + dev_put(slave); kfree(master); return(err); } @@ -459,64 +458,65 @@ int dlci_add(struct dlci_add *dlci) dlp = (struct dlci_local *) master->priv; dlp->slave = slave; + dlp->master = master; flp = slave->priv; err = flp ? (*flp->assoc)(slave, master) : -EINVAL; if (err < 0) { unregister_netdev(master); - kfree(master->priv); - kfree(master); + dev_put(slave); + free_netdev(master); return(err); } - strcpy(dlci->devname, buf); - open_dev[i] = master; - MOD_INC_USE_COUNT; + strcpy(dlci->devname, master->name); + + spin_lock_bh(&dlci_dev_lock); + list_add(&dlp->list, &dlci_devs); + spin_unlock_bh(&dlci_dev_lock); + return(0); } -int dlci_del(struct dlci_add *dlci) +static int dlci_del(struct dlci_add *dlci) { struct dlci_local *dlp; struct frad_local *flp; - struct net_device *master, *slave; - int i, err; + struct net_device *master, *slave; + int err; /* validate slave device */ master = __dev_get_by_name(dlci->devname); if (!master) return(-ENODEV); - if (netif_running(master)) + if (netif_running(master)) { return(-EBUSY); + } dlp = master->priv; slave = dlp->slave; flp = slave->priv; err = (*flp->deassoc)(slave, master); - if (err) + if (err) return(err); - unregister_netdev(master); - for(i=0;ilist); + spin_unlock_bh(&dlci_dev_lock); - if (ipriv); + dev_put(slave); free_netdev(master); - MOD_DEC_USE_COUNT; - return(0); } -int dlci_ioctl(unsigned int cmd, void *arg) +static int dlci_ioctl(unsigned int cmd, void *arg) { struct dlci_add add; int err; @@ -548,16 +548,9 @@ int dlci_ioctl(unsigned int cmd, void *arg) return(err); } -int dlci_init(struct net_device *dev) +static void dlci_setup(struct net_device *dev) { - struct dlci_local *dlp; - - dev->priv = kmalloc(sizeof(struct dlci_local), GFP_KERNEL); - if (!dev->priv) - return(-ENOMEM); - - memset(dev->priv, 0, sizeof(struct dlci_local)); - dlp = dev->priv; + struct dlci_local *dlp = dev->priv; dev->flags = 0; dev->open = dlci_open; @@ -573,9 +566,7 @@ int dlci_init(struct net_device *dev) dev->type = ARPHRD_DLCI; dev->hard_header_len = sizeof(struct frhdr); dev->addr_len = sizeof(short); - memset(dev->dev_addr, 0, sizeof(dev->dev_addr)); - return(0); } int __init init_dlci(void) @@ -584,9 +575,6 @@ int __init init_dlci(void) dlci_ioctl_set(dlci_ioctl); printk("%s.\n", version); - - for(i=0;imaster); + dev_put(dlp->slave); + free_netdev(dlp->master); + } + } module_init(init_dlci); diff --git a/include/linux/if_frad.h b/include/linux/if_frad.h index 975aad03d762..3d9fc5d43803 100644 --- a/include/linux/if_frad.h +++ b/include/linux/if_frad.h @@ -155,9 +155,11 @@ struct frhdr struct dlci_local { struct net_device_stats stats; - struct net_device *slave; + struct net_device *master; + struct net_device *slave; struct dlci_conf config; int configured; + struct list_head list; /* callback function */ void (*receive)(struct sk_buff *skb, struct net_device *); -- cgit v1.2.3 From 1a66af8c6080f75ee9160c9b28329391f4149720 Mon Sep 17 00:00:00 2001 From: François Romieu Date: Wed, 3 Sep 2003 10:36:39 -0700 Subject: [NET]: Use free_netdev() even in error paths. --- drivers/net/3c509.c | 2 +- drivers/net/3c59x.c | 2 +- drivers/net/8139cp.c | 2 +- drivers/net/acenic.c | 10 +++++----- drivers/net/amd8111e.c | 2 +- drivers/net/b44.c | 2 +- drivers/net/bmac.c | 2 +- drivers/net/dgrs.c | 4 ++-- drivers/net/dl2k.c | 2 +- drivers/net/eepro100.c | 2 +- drivers/net/epic100.c | 2 +- drivers/net/fealnx.c | 2 +- drivers/net/hamachi.c | 2 +- drivers/net/ioc3-eth.c | 2 +- drivers/net/lasi_82596.c | 2 +- drivers/net/lp486e.c | 2 +- drivers/net/natsemi.c | 6 +++--- drivers/net/pcnet32.c | 47 ++++++++++++++++++++++++----------------------- drivers/net/r8169.c | 4 ++-- drivers/net/rcpci45.c | 2 +- drivers/net/sb1000.c | 4 +++- drivers/net/sis190.c | 15 ++++++++------- drivers/net/sis900.c | 2 +- drivers/net/smc-mca.c | 33 +++++++++++++++++++++++---------- drivers/net/starfire.c | 2 +- drivers/net/sundance.c | 2 +- drivers/net/sungem.c | 25 +++++++++++++++++-------- drivers/net/sunhme.c | 4 ++-- drivers/net/sunqe.c | 2 +- drivers/net/tg3.c | 2 +- drivers/net/tlan.c | 4 ++-- drivers/net/typhoon.c | 2 +- drivers/net/via-rhine.c | 2 +- drivers/net/yellowfin.c | 2 +- 34 files changed, 114 insertions(+), 88 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/3c509.c b/drivers/net/3c509.c index df5f96439afa..74fd4100332b 100644 --- a/drivers/net/3c509.c +++ b/drivers/net/3c509.c @@ -604,7 +604,7 @@ out1: pnp_device_detach(idev); #endif out: - kfree(dev); + free_netdev(dev); return err; } diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index 4e3eabe1e5ea..572de917454d 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -1468,7 +1468,7 @@ free_ring: free_region: if (vp->must_free_region) release_region(ioaddr, vci->io_size); - kfree (dev); + free_netdev(dev); printk(KERN_ERR PFX "vortex_probe1 fails. Returns %d\n", retval); out: return retval; diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c index a49241c1ae23..fc3c04c6c7bc 100644 --- a/drivers/net/8139cp.c +++ b/drivers/net/8139cp.c @@ -1768,7 +1768,7 @@ err_out_mwi: err_out_disable: pci_disable_device(pdev); err_out_free: - kfree(dev); + free_netdev(dev); return rc; } diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c index d6a4fdcec957..3350a70c2103 100644 --- a/drivers/net/acenic.c +++ b/drivers/net/acenic.c @@ -685,7 +685,7 @@ int __devinit acenic_probe (ACE_PROBE_ARG) } if (pci_enable_device(pdev)) { - kfree(dev); + free_netdev(dev); continue; } @@ -733,7 +733,7 @@ int __devinit acenic_probe (ACE_PROBE_ARG) if (register_netdev(dev)) { printk(KERN_ERR "acenic: device registration failed\n"); - kfree(dev); + free_netdev(dev); continue; } @@ -793,7 +793,7 @@ int __devinit acenic_probe (ACE_PROBE_ARG) printk(KERN_ERR "%s: Driver compiled without Tigon I" " support - NIC disabled\n", dev->name); ace_init_cleanup(dev); - kfree(dev); + free_netdev(dev); continue; } #endif @@ -803,7 +803,7 @@ int __devinit acenic_probe (ACE_PROBE_ARG) * ace_allocate_descriptors() calls * ace_init_cleanup() on error. */ - kfree(dev); + free_netdev(dev); continue; } @@ -820,7 +820,7 @@ int __devinit acenic_probe (ACE_PROBE_ARG) /* * ace_init() calls ace_init_cleanup() on error. */ - kfree(dev); + free_netdev(dev); continue; } diff --git a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c index 19464a83fdfb..bc9e1bfc7220 100755 --- a/drivers/net/amd8111e.c +++ b/drivers/net/amd8111e.c @@ -1927,7 +1927,7 @@ err_iounmap: iounmap((void *) lp->mmio); err_free_dev: - kfree(dev); + free_netdev(dev); err_free_reg: pci_release_regions(pdev); diff --git a/drivers/net/b44.c b/drivers/net/b44.c index b759af47913d..ef10d16fd679 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -1834,7 +1834,7 @@ err_out_iounmap: iounmap((void *) bp->regs); err_out_free_dev: - kfree(dev); + free_netdev(dev); err_out_free_res: pci_release_regions(pdev); diff --git a/drivers/net/bmac.c b/drivers/net/bmac.c index ed7874f4fe4e..27bc8ed937cf 100644 --- a/drivers/net/bmac.c +++ b/drivers/net/bmac.c @@ -1462,7 +1462,7 @@ out2: release_OF_resource(bp->node, 0); out1: pmac_call_feature(PMAC_FTR_BMAC_ENABLE, bp->node, 0, 0); - kfree(dev); + free_netdev(dev); } static int bmac_open(struct net_device *dev) diff --git a/drivers/net/dgrs.c b/drivers/net/dgrs.c index 00ddd19e0fd2..d28d864cbaa5 100644 --- a/drivers/net/dgrs.c +++ b/drivers/net/dgrs.c @@ -1275,7 +1275,7 @@ dgrs_found_device( SET_MODULE_OWNER(dev); if (register_netdev(dev) != 0) { - kfree(dev); + free_netdev(dev); return -EIO; } @@ -1322,7 +1322,7 @@ dgrs_found_device( ret = -EIO; if (register_netdev(devN)) { - kfree(devN); + free_netdev(devN); goto fail; } privN->chan = i+1; diff --git a/drivers/net/dl2k.c b/drivers/net/dl2k.c index d0fba4cb4df4..76f1d66eb6c1 100644 --- a/drivers/net/dl2k.c +++ b/drivers/net/dl2k.c @@ -319,7 +319,7 @@ rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent) err_out_dev: #endif - kfree (dev); + free_netdev (dev); err_out_res: pci_release_regions (pdev); diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c index 2a14f46f6014..02c2db84f603 100644 --- a/drivers/net/eepro100.c +++ b/drivers/net/eepro100.c @@ -894,7 +894,7 @@ static int __devinit speedo_found1(struct pci_dev *pdev, err_free_unlock: rtnl_unlock(); - kfree(dev); + free_netdev(dev); return -1; } diff --git a/drivers/net/epic100.c b/drivers/net/epic100.c index 93fdb1469a0c..00bbf4b7baea 100644 --- a/drivers/net/epic100.c +++ b/drivers/net/epic100.c @@ -565,7 +565,7 @@ err_out_free_res: #endif pci_release_regions(pdev); err_out_free_netdev: - kfree(dev); + free_netdev(dev); return -ENODEV; } diff --git a/drivers/net/fealnx.c b/drivers/net/fealnx.c index de914dfc56f8..ee1e45180f86 100644 --- a/drivers/net/fealnx.c +++ b/drivers/net/fealnx.c @@ -689,7 +689,7 @@ err_out_free_tx: err_out_free_rx: pci_free_consistent(pdev, RX_TOTAL_SIZE, np->rx_ring, np->rx_ring_dma); err_out_free_dev: - kfree(dev); + free_netdev(dev); err_out_unmap: #ifndef USE_IO_OPS iounmap((void *)ioaddr); diff --git a/drivers/net/hamachi.c b/drivers/net/hamachi.c index 36e7074c2bd8..ab87588a7ff3 100644 --- a/drivers/net/hamachi.c +++ b/drivers/net/hamachi.c @@ -785,7 +785,7 @@ err_out_unmap_tx: pci_free_consistent(pdev, TX_TOTAL_SIZE, hmp->tx_ring, hmp->tx_ring_dma); err_out_cleardev: - kfree (dev); + free_netdev (dev); err_out_iounmap: iounmap((char *)ioaddr); err_out_release: diff --git a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c index c3b4e5f1353d..d93767489ff0 100644 --- a/drivers/net/ioc3-eth.c +++ b/drivers/net/ioc3-eth.c @@ -1512,7 +1512,7 @@ out_stop: out_res: pci_release_regions(pdev); out_free: - kfree(dev); + free_netdev(dev); return err; } diff --git a/drivers/net/lasi_82596.c b/drivers/net/lasi_82596.c index b3045c467da8..6f8c223bf68e 100644 --- a/drivers/net/lasi_82596.c +++ b/drivers/net/lasi_82596.c @@ -1543,7 +1543,7 @@ lan_init_chip(struct parisc_device *dev) retval = register_netdev(netdevice); if (retval) { printk(KERN_WARNING __FILE__ ": register_netdevice ret'd %d\n", retval); - kfree(netdevice); + free_netdev(netdevice); return -ENODEV; }; if (dev->id.sversion == 0x72) { diff --git a/drivers/net/lp486e.c b/drivers/net/lp486e.c index fe1e255a576c..3e687d9cbd41 100644 --- a/drivers/net/lp486e.c +++ b/drivers/net/lp486e.c @@ -1324,7 +1324,7 @@ static int __init lp486e_init_module(void) { dev->base_addr = io; dev->init = lp486e_probe; if (register_netdev(dev) != 0) { - kfree(dev); + free_netdev(dev); return -EIO; } dev_lp486e = dev; diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c index b95d3030e465..14fbbef63fb6 100644 --- a/drivers/net/natsemi.c +++ b/drivers/net/natsemi.c @@ -766,7 +766,7 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev, i = pci_request_regions(pdev, dev->name); if (i) { - kfree(dev); + free_netdev(dev); return i; } @@ -774,7 +774,7 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev, void *mmio = ioremap (ioaddr, iosize); if (!mmio) { pci_release_regions(pdev); - kfree(dev); + free_netdev(dev); return -ENOMEM; } ioaddr = (unsigned long) mmio; @@ -838,7 +838,7 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev, if (i) { pci_release_regions(pdev); unregister_netdev(dev); - kfree(dev); + free_netdev(dev); pci_set_drvdata(pdev, NULL); return i; } diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c index ad6281ef7a83..2d519b696533 100644 --- a/drivers/net/pcnet32.c +++ b/drivers/net/pcnet32.c @@ -529,6 +529,7 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared, struct net_device *dev; struct pcnet32_access *a = NULL; u8 promaddr[6]; + int ret = -ENODEV; /* reset the chip */ pcnet32_wio_reset(ioaddr); @@ -540,19 +541,15 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared, pcnet32_dwio_reset(ioaddr); if (pcnet32_dwio_read_csr(ioaddr, 0) == 4 && pcnet32_dwio_check(ioaddr)) { a = &pcnet32_dwio; - } else { - release_region(ioaddr, PCNET32_TOTAL_SIZE); - return -ENODEV; - } + } else + goto err_release_region; } chip_version = a->read_csr(ioaddr, 88) | (a->read_csr(ioaddr,89) << 16); if (pcnet32_debug > 2) printk(KERN_INFO " PCnet chip version is %#x.\n", chip_version); - if ((chip_version & 0xfff) != 0x003) { - release_region(ioaddr, PCNET32_TOTAL_SIZE); - return -ENODEV; - } + if ((chip_version & 0xfff) != 0x003) + goto err_release_region; /* initialize variables */ fdx = mii = fset = dxsuflo = ltint = 0; @@ -614,8 +611,7 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared, default: printk(KERN_INFO PFX "PCnet version %#x, no PCnet32 chip.\n", chip_version); - release_region(ioaddr, PCNET32_TOTAL_SIZE); - return -ENODEV; + goto err_release_region; } /* @@ -635,8 +631,8 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared, dev = alloc_etherdev(0); if(!dev) { - release_region(ioaddr, PCNET32_TOTAL_SIZE); - return -ENOMEM; + ret = -ENOMEM; + goto err_release_region; } SET_NETDEV_DEV(dev, &pdev->dev); @@ -708,8 +704,8 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared, dev->base_addr = ioaddr; /* pci_alloc_consistent returns page-aligned memory, so we do not have to check the alignment */ if ((lp = pci_alloc_consistent(pdev, sizeof(*lp), &lp_dma_addr)) == NULL) { - release_region(ioaddr, PCNET32_TOTAL_SIZE); - return -ENOMEM; + ret = -ENOMEM; + goto err_free_netdev; } memset(lp, 0, sizeof(*lp)); @@ -741,9 +737,8 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared, if (!a) { printk(KERN_ERR PFX "No access methods\n"); - pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr); - release_region(ioaddr, PCNET32_TOTAL_SIZE); - return -ENODEV; + ret = -ENODEV; + goto err_free_consistent; } lp->a = *a; @@ -785,14 +780,12 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared, mdelay (1); dev->irq = probe_irq_off (irq_mask); - if (dev->irq) - printk(", probed IRQ %d.\n", dev->irq); - else { + if (!dev->irq) { printk(", failed to detect IRQ line.\n"); - pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr); - release_region(ioaddr, PCNET32_TOTAL_SIZE); - return -ENODEV; + ret = -ENODEV; + goto err_free_consistent; } + printk(", probed IRQ %d.\n", dev->irq); } /* Set the mii phy_id so that we can query the link state */ @@ -821,6 +814,14 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared, printk(KERN_INFO "%s: registered as %s\n",dev->name, lp->name); cards_found++; return 0; + +err_free_consistent: + pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr); +err_free_netdev: + free_netdev(dev); +err_release_region: + release_region(ioaddr, PCNET32_TOTAL_SIZE); + return ret; } diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index a0b4b659aa0e..c11b83e6adeb 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -454,7 +454,7 @@ err_out_disable: pci_disable_device(pdev); err_out: - kfree(dev); + free_netdev(dev); return rc; } @@ -514,7 +514,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) iounmap(ioaddr); pci_release_regions(pdev); pci_disable_device(pdev); - kfree(dev); + free_netdev(dev); return rc; } diff --git a/drivers/net/rcpci45.c b/drivers/net/rcpci45.c index f5cdead40f14..e7e1a9f2d71a 100644 --- a/drivers/net/rcpci45.c +++ b/drivers/net/rcpci45.c @@ -269,7 +269,7 @@ err_out_free_msgbuf: pci_free_consistent (pdev, MSG_BUF_SIZE, pDpa->msgbuf, pDpa->msgbuf_dma); err_out_free_dev: - kfree (dev); + free_netdev (dev); err_out: card_idx--; return error; diff --git a/drivers/net/sb1000.c b/drivers/net/sb1000.c index d0153f60a036..5326dee62c74 100644 --- a/drivers/net/sb1000.c +++ b/drivers/net/sb1000.c @@ -213,9 +213,11 @@ sb1000_probe_one(struct pnp_dev *pdev, const struct pnp_device_id *id) error = register_netdev(dev); if (error) - goto out_release_regions; + goto out_free_netdev; return 0; + out_free_netdev: + free_netdev(dev); out_release_regions: release_region(ioaddr[1], 16); out_release_region0: diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c index 1c79e7b9c34e..9f421480b233 100644 --- a/drivers/net/sis190.c +++ b/drivers/net/sis190.c @@ -470,7 +470,7 @@ SiS190_init_board(struct pci_dev *pdev, struct net_device **dev_out, rc = pci_set_dma_mask(pdev, 0xffffffffULL); if (rc) - goto err_out; + goto err_out_disable; mmio_start = pci_resource_start(pdev, 0); mmio_end = pci_resource_end(pdev, 0); @@ -482,18 +482,18 @@ SiS190_init_board(struct pci_dev *pdev, struct net_device **dev_out, printk(KERN_ERR PFX "region #0 not an MMIO resource, aborting\n"); rc = -ENODEV; - goto err_out; + goto err_out_disable; } // check for weird/broken PCI region reporting if (mmio_len < SiS190_MIN_IO_SIZE) { printk(KERN_ERR PFX "Invalid PCI region size(s), aborting\n"); rc = -ENODEV; - goto err_out; + goto err_out_disable; } rc = pci_request_regions(pdev, dev->name); if (rc) - goto err_out; + goto err_out_disable; // enable PCI bus-mastering pci_set_master(pdev); @@ -521,9 +521,10 @@ SiS190_init_board(struct pci_dev *pdev, struct net_device **dev_out, err_out_free_res: pci_release_regions(pdev); -err_out: +err_out_disable: pci_disable_device(pdev); - kfree(dev); +err_out: + free_netdev(dev); return rc; } @@ -603,7 +604,7 @@ SiS190_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) iounmap(ioaddr); pci_release_regions(pdev); pci_disable_device(pdev); - kfree(dev); + free_netdev(dev); return rc; } diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c index b5853f1a9fbd..6422eb2a4208 100644 --- a/drivers/net/sis900.c +++ b/drivers/net/sis900.c @@ -503,7 +503,7 @@ static int __devinit sis900_probe (struct pci_dev *pci_dev, const struct pci_dev pci_set_drvdata(pci_dev, NULL); pci_release_regions(pci_dev); err_out: - kfree(net_dev); + free_netdev(net_dev); return ret; } diff --git a/drivers/net/smc-mca.c b/drivers/net/smc-mca.c index e33c7a2a2f7f..c5a085707302 100644 --- a/drivers/net/smc-mca.c +++ b/drivers/net/smc-mca.c @@ -132,7 +132,7 @@ int __init ultramca_probe(struct device *gen_dev) struct mca_device *mca_dev = to_mca_device(gen_dev); char slot = mca_dev->slot; unsigned char pos2 = 0xff, pos3 = 0xff, pos4 = 0xff, pos5 = 0xff; - int i; + int i, rc; int adapter = mca_dev->index; int tbase = 0; int tirq = 0; @@ -209,8 +209,9 @@ int __init ultramca_probe(struct device *gen_dev) SET_MODULE_OWNER(dev); SET_NETDEV_DEV(dev, gen_dev); - if((i = register_netdev(dev)) != 0) - return i; + rc = register_netdev(dev); + if (rc) + goto err_free_netdev; printk(KERN_INFO "%s: %s found in slot %d\n", dev->name, smc_mca_adapter_names[adapter], slot + 1); @@ -262,11 +263,15 @@ int __init ultramca_probe(struct device *gen_dev) } } - if (dev->mem_start == 0) /* sanity check, shouldn't happen */ - return -ENODEV; + /* sanity check, shouldn't happen */ + if (dev->mem_start == 0) { + rc = -ENODEV; + goto err_unregister_netdev; + } - if (!request_region(ioaddr, ULTRA_IO_EXTENT, dev->name)) - return -EBUSY; + rc = request_region(ioaddr, ULTRA_IO_EXTENT, dev->name); + if (rc) + goto err_unregister_netdev; reg4 = inb(ioaddr + 4) & 0x7f; outb(reg4, ioaddr + 4); @@ -296,10 +301,10 @@ int __init ultramca_probe(struct device *gen_dev) /* Allocate dev->priv and fill in 8390 specific dev fields. */ - if (ethdev_init(dev)) { + rc = ethdev_init(dev); + if (rc) { printk (", no memory for dev->priv.\n"); - release_region(ioaddr, ULTRA_IO_EXTENT); - return -ENOMEM; + goto err_release_region; } gen_dev->driver_data = dev; @@ -334,6 +339,14 @@ int __init ultramca_probe(struct device *gen_dev) NS8390_init(dev, 0); return 0; + +err_release_region: + release_region(ioaddr, ULTRA_IO_EXTENT); +err_unregister_netdev: + unregister_netdev(dev); +err_free_netdev: + free_netdev(dev); + return rc; } static int ultramca_open(struct net_device *dev) diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c index dcf1db7ea6ef..c2bddf1f1700 100644 --- a/drivers/net/starfire.c +++ b/drivers/net/starfire.c @@ -1070,7 +1070,7 @@ err_out_cleardev: err_out_free_res: pci_release_regions (pdev); err_out_free_netdev: - kfree(dev); + free_netdev(dev); return -ENODEV; } diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c index 5bd8be316547..aad877c5400b 100644 --- a/drivers/net/sundance.c +++ b/drivers/net/sundance.c @@ -734,7 +734,7 @@ err_out_res: #endif pci_release_regions(pdev); err_out_netdev: - kfree (dev); + free_netdev (dev); return -ENODEV; } diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c index de27ee588a77..a346fd1d4dba 100644 --- a/drivers/net/sungem.c +++ b/drivers/net/sungem.c @@ -2622,7 +2622,7 @@ static int __devinit gem_init_one(struct pci_dev *pdev, if (err) { printk(KERN_ERR PFX "No usable DMA configuration, " "aborting.\n"); - return err; + goto err_disable_device; } pci_using_dac = 0; } @@ -2633,20 +2633,23 @@ static int __devinit gem_init_one(struct pci_dev *pdev, if ((pci_resource_flags(pdev, 0) & IORESOURCE_IO) != 0) { printk(KERN_ERR PFX "Cannot find proper PCI device " "base address, aborting.\n"); - return -ENODEV; + err = -ENODEV; + goto err_disable_device; } dev = alloc_etherdev(sizeof(*gp)); if (!dev) { printk(KERN_ERR PFX "Etherdev alloc failed, aborting.\n"); - return -ENOMEM; + err = -ENOMEM; + goto err_disable_device; } SET_MODULE_OWNER(dev); SET_NETDEV_DEV(dev, &pdev->dev); gp = dev->priv; - if (pci_request_regions(pdev, dev->name)) { + err = pci_request_regions(pdev, dev->name); + if (err) { printk(KERN_ERR PFX "Cannot obtain PCI resources, " "aborting.\n"); goto err_out_free_netdev; @@ -2680,6 +2683,7 @@ static int __devinit gem_init_one(struct pci_dev *pdev, if (gp->regs == 0UL) { printk(KERN_ERR PFX "Cannot map device registers, " "aborting.\n"); + err = -EIO; goto err_out_free_res; } @@ -2703,8 +2707,10 @@ static int __devinit gem_init_one(struct pci_dev *pdev, /* By default, we start with autoneg */ gp->want_autoneg = 1; - if (gem_check_invariants(gp)) + if (gem_check_invariants(gp)) { + err = -ENODEV; goto err_out_iounmap; + } /* It is guaranteed that the returned buffer will be at least * PAGE_SIZE aligned. @@ -2715,6 +2721,7 @@ static int __devinit gem_init_one(struct pci_dev *pdev, if (!gp->init_block) { printk(KERN_ERR PFX "Cannot allocate init block, " "aborting.\n"); + err = -ENOMEM; goto err_out_iounmap; } @@ -2727,6 +2734,7 @@ static int __devinit gem_init_one(struct pci_dev *pdev, if (register_netdev(dev)) { printk(KERN_ERR PFX "Cannot register net device, " "aborting.\n"); + err = -ENOMEM; goto err_out_free_consistent; } @@ -2796,9 +2804,10 @@ err_out_free_res: pci_release_regions(pdev); err_out_free_netdev: - kfree(dev); - - return -ENODEV; + free_netdev(dev); +err_disable_device: + pci_disable_device(pdev); + return err; } diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c index 8c786ab7b3c5..b91f7d0199bf 100644 --- a/drivers/net/sunhme.c +++ b/drivers/net/sunhme.c @@ -2895,7 +2895,7 @@ err_out_iounmap: sbus_iounmap(hp->tcvregs, TCVR_REG_SIZE); err_out_free_netdev: - kfree(dev); + free_netdev(dev); err_out: return err; @@ -3247,7 +3247,7 @@ err_out_clear_quattro: if (qp != NULL) qp->happy_meals[qfe_slot] = NULL; - kfree(dev); + free_netdev(dev); err_out: return err; diff --git a/drivers/net/sunqe.c b/drivers/net/sunqe.c index b5d8879c2035..5116b5152e8a 100644 --- a/drivers/net/sunqe.c +++ b/drivers/net/sunqe.c @@ -949,7 +949,7 @@ out1: i = 4; out: while (i--) - kfree(qe_devs[i]); + free_netdev(qe_devs[i]); return res; } diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index c31dc44a6fd2..3ebedccf00b3 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -7740,7 +7740,7 @@ err_out_iounmap: iounmap((void *) tp->regs); err_out_free_dev: - kfree(dev); + free_netdev(dev); err_out_free_res: pci_release_regions(pdev); diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c index 5a45900a816e..c5b6999712fb 100644 --- a/drivers/net/tlan.c +++ b/drivers/net/tlan.c @@ -670,7 +670,7 @@ err_out_uninit: pci_free_consistent(priv->pciDev, priv->dmaSize, priv->dmaStorage, priv->dmaStorageDMA ); err_out_free_dev: - kfree(dev); + free_netdev(dev); err_out_regions: if (pdev) pci_release_regions(pdev); @@ -695,7 +695,7 @@ static void TLan_Eisa_Cleanup(void) release_region( dev->base_addr, 0x10); unregister_netdev( dev ); TLan_Eisa_Devices = priv->nextDevice; - kfree( dev ); + free_netdev( dev ); tlan_have_eisa--; } } diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c index e83372b7adbb..f30b72218b30 100644 --- a/drivers/net/typhoon.c +++ b/drivers/net/typhoon.c @@ -2455,7 +2455,7 @@ error_out_remap: error_out_regions: pci_release_regions(pdev); error_out_dev: - kfree(dev); + free_netdev(dev); error_out: return err; } diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c index c247af6bf6ad..3059d04aaf0d 100644 --- a/drivers/net/via-rhine.c +++ b/drivers/net/via-rhine.c @@ -868,7 +868,7 @@ err_out_free_res: #endif pci_release_regions(pdev); err_out_free_netdev: - kfree (dev); + free_netdev (dev); err_out: return -ENODEV; } diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c index 8a3328687d1f..c22ca46b0d81 100644 --- a/drivers/net/yellowfin.c +++ b/drivers/net/yellowfin.c @@ -577,7 +577,7 @@ err_out_free_res: #endif pci_release_regions(pdev); err_out_free_netdev: - kfree (dev); + free_netdev (dev); return -ENODEV; } -- cgit v1.2.3 From 775b235696ae07bf126a355ebe3b9d7fb7fa3aa0 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 3 Sep 2003 10:37:09 -0700 Subject: [NET]: Add probe_old_netdevs() hook. This set of patches is a mixture of Al's work to device initialization, and some of my own to complete it for all the ether, tr, sbni, and loopback devices. The first patch adds the hook for converting old driver initialization code over to dynamic allocation. This part extracted from Al viro's set of net driver changes for ethertap. --- drivers/net/Space.c | 6 ++++++ include/linux/netdevice.h | 1 + net/core/dev.c | 2 ++ 3 files changed, 9 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/Space.c b/drivers/net/Space.c index 46777c8dcf18..275c32627507 100644 --- a/drivers/net/Space.c +++ b/drivers/net/Space.c @@ -382,6 +382,12 @@ static int __init ethif_probe(struct net_device *dev) return -ENODEV; } +/* Statically configured drivers -- order matters here. */ +void probe_old_netdevs(void) +{ + +} + #ifdef CONFIG_SDLA extern int sdla_init(struct net_device *); static struct net_device sdla0_dev = { diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index dfc1aa47f35c..f2a63e8004d6 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -498,6 +498,7 @@ extern struct net_device loopback_dev; /* The loopback */ extern struct net_device *dev_base; /* All devices */ extern rwlock_t dev_base_lock; /* Device list lock */ +extern void probe_old_netdevs(void); extern int netdev_boot_setup_add(char *name, struct ifmap *map); extern int netdev_boot_setup_check(struct net_device *dev); extern struct net_device *dev_getbyhwaddr(unsigned short type, char *hwaddr); diff --git a/net/core/dev.c b/net/core/dev.c index fe8976f4e757..1ac07dc5077e 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3098,6 +3098,8 @@ static int __init net_dev_init(void) dev_boot_phase = 0; + probe_old_netdevs(); + open_softirq(NET_TX_SOFTIRQ, net_tx_action, NULL); open_softirq(NET_RX_SOFTIRQ, net_rx_action, NULL); -- cgit v1.2.3 From 51845e3a3848fe875d1e074d1feaa6e64752fd22 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 3 Sep 2003 10:37:58 -0700 Subject: [NET]: Convert SDLA to new initialization. Based on Al viro's NE10-sdla * switched sdla to dynamic allocation * sdla: embedded ->priv * sdla: fixed resource leaks on failure exits Additionally fixes. * get rid of cli/sti * get rid of MOD/INC Builds and probes, but don't have the hardware. Driver has never built on 2.6 before this. --- drivers/net/Space.c | 17 ++---- drivers/net/wan/sdla.c | 160 +++++++++++++++++++++++++++---------------------- 2 files changed, 96 insertions(+), 81 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/Space.c b/drivers/net/Space.c index 275c32627507..2292798aa348 100644 --- a/drivers/net/Space.c +++ b/drivers/net/Space.c @@ -98,6 +98,9 @@ extern int macsonic_probe(struct net_device *dev); extern int mac8390_probe(struct net_device *dev); extern int mac89x0_probe(struct net_device *dev); extern int mc32_probe(struct net_device *dev); +#ifdef CONFIG_SDLA +extern struct net_device *sdla_init(void); +#endif /* Detachable devices ("pocket adaptors") */ extern int de620_probe(struct net_device *); @@ -385,20 +388,12 @@ static int __init ethif_probe(struct net_device *dev) /* Statically configured drivers -- order matters here. */ void probe_old_netdevs(void) { - -} - #ifdef CONFIG_SDLA -extern int sdla_init(struct net_device *); -static struct net_device sdla0_dev = { - .name = "sdla0", - .next = NEXT_DEV, - .init = sdla_init, -}; -#undef NEXT_DEV -#define NEXT_DEV (&sdla0_dev) + sdla_init(); #endif +} + #if defined(CONFIG_LTPC) extern int ltpc_probe(struct net_device *); static struct net_device dev_ltpc = { diff --git a/drivers/net/wan/sdla.c b/drivers/net/wan/sdla.c index 8079d8b5ddee..c91e59da2ed9 100644 --- a/drivers/net/wan/sdla.c +++ b/drivers/net/wan/sdla.c @@ -71,6 +71,8 @@ static unsigned int valid_mem[] __initdata = { 0xD0000, 0xD2000, 0xD4000, 0xD6000, 0xD8000, 0xDA000, 0xDC000, 0xDE000, 0xE0000, 0xE2000, 0xE4000, 0xE6000, 0xE8000, 0xEA000, 0xEC000, 0xEE000}; +static spinlock_t sdla_lock = SPIN_LOCK_UNLOCKED; + /********************************************************* * * these are the core routines that access the card itself @@ -79,10 +81,10 @@ static unsigned int valid_mem[] __initdata = { #define SDLA_WINDOW(dev,addr) outb((((addr) >> 13) & 0x1F), (dev)->base_addr + SDLA_REG_Z80_WINDOW) -static void sdla_read(struct net_device *dev, int addr, void *buf, short len) +static void __sdla_read(struct net_device *dev, int addr, void *buf, short len) { - unsigned long flags; - char *temp, *base; + char *temp; + const void *base; int offset, bytes; temp = buf; @@ -90,13 +92,10 @@ static void sdla_read(struct net_device *dev, int addr, void *buf, short len) { offset = addr & SDLA_ADDR_MASK; bytes = offset + len > SDLA_WINDOW_SIZE ? SDLA_WINDOW_SIZE - offset : len; - base = (void *) (dev->mem_start + offset); + base = (const void *) (dev->mem_start + offset); - save_flags(flags); - cli(); SDLA_WINDOW(dev, addr); memcpy(temp, base, bytes); - restore_flags(flags); addr += bytes; temp += bytes; @@ -104,10 +103,19 @@ static void sdla_read(struct net_device *dev, int addr, void *buf, short len) } } -static void sdla_write(struct net_device *dev, int addr, void *buf, short len) +static void sdla_read(struct net_device *dev, int addr, void *buf, short len) { unsigned long flags; - char *temp, *base; + spin_lock_irqsave(&sdla_lock, flags); + __sdla_read(dev, addr, buf, len); + spin_unlock_irqrestore(&sdla_lock, flags); +} + +static void __sdla_write(struct net_device *dev, int addr, + const void *buf, short len) +{ + const char *temp; + void *base; int offset, bytes; temp = buf; @@ -116,17 +124,27 @@ static void sdla_write(struct net_device *dev, int addr, void *buf, short len) offset = addr & SDLA_ADDR_MASK; bytes = offset + len > SDLA_WINDOW_SIZE ? SDLA_WINDOW_SIZE - offset : len; base = (void *) (dev->mem_start + offset); - save_flags(flags); - cli(); + SDLA_WINDOW(dev, addr); memcpy(base, temp, bytes); - restore_flags(flags); + addr += bytes; temp += bytes; len -= bytes; } } +static void sdla_write(struct net_device *dev, int addr, + const void *buf, short len) +{ + unsigned long flags; + + spin_lock_irqsave(&sdla_lock, flags); + __sdla_write(dev, addr, buf, len); + spin_unlock_irqrestore(&sdla_lock, flags); +} + + static void sdla_clear(struct net_device *dev) { unsigned long flags; @@ -138,8 +156,7 @@ static void sdla_clear(struct net_device *dev) bytes = SDLA_WINDOW_SIZE; base = (void *) dev->mem_start; - save_flags(flags); - cli(); + spin_lock_irqsave(&sdla_lock, flags); while(len) { SDLA_WINDOW(dev, addr); @@ -148,7 +165,8 @@ static void sdla_clear(struct net_device *dev) addr += bytes; len -= bytes; } - restore_flags(flags); + spin_unlock_irqrestore(&sdla_lock, flags); + } static char sdla_byte(struct net_device *dev, int addr) @@ -158,11 +176,10 @@ static char sdla_byte(struct net_device *dev, int addr) temp = (void *) (dev->mem_start + (addr & SDLA_ADDR_MASK)); - save_flags(flags); - cli(); + spin_lock_irqsave(&sdla_lock, flags); SDLA_WINDOW(dev, addr); byte = *temp; - restore_flags(flags); + spin_unlock_irqrestore(&sdla_lock, flags); return(byte); } @@ -414,7 +431,8 @@ static int sdla_cmd(struct net_device *dev, int cmd, short dlci, short flags, struct frad_local *flp; struct sdla_cmd *cmd_buf; unsigned long pflags; - int jiffs, ret, waiting, len; + unsigned long jiffs; + int ret, waiting, len; long window; flp = dev->priv; @@ -423,8 +441,8 @@ static int sdla_cmd(struct net_device *dev, int cmd, short dlci, short flags, ret = 0; len = 0; jiffs = jiffies + HZ; /* 1 second is plenty */ - save_flags(pflags); - cli(); + + spin_lock_irqsave(&sdla_lock, pflags); SDLA_WINDOW(dev, window); cmd_buf->cmd = cmd; cmd_buf->dlci = dlci; @@ -436,7 +454,7 @@ static int sdla_cmd(struct net_device *dev, int cmd, short dlci, short flags, cmd_buf->length = inlen; cmd_buf->opp_flag = 1; - restore_flags(pflags); + spin_unlock_irqrestore(&sdla_lock, pflags); waiting = 1; len = 0; @@ -444,18 +462,17 @@ static int sdla_cmd(struct net_device *dev, int cmd, short dlci, short flags, { if (waiting++ % 3) { - save_flags(pflags); - cli(); + spin_lock_irqsave(&sdla_lock, pflags); SDLA_WINDOW(dev, window); waiting = ((volatile int)(cmd_buf->opp_flag)); - restore_flags(pflags); + spin_unlock_irqrestore(&sdla_lock, pflags); } } if (!waiting) { - save_flags(pflags); - cli(); + + spin_lock_irqsave(&sdla_lock, pflags); SDLA_WINDOW(dev, window); ret = cmd_buf->retval; len = cmd_buf->length; @@ -471,7 +488,7 @@ static int sdla_cmd(struct net_device *dev, int cmd, short dlci, short flags, if (ret) memcpy(&status, cmd_buf->data, len > sizeof(status) ? sizeof(status) : len); - restore_flags(pflags); + spin_unlock_irqrestore(&sdla_lock, pflags); } else ret = SDLA_RET_TIMEOUT; @@ -555,7 +572,6 @@ int sdla_assoc(struct net_device *slave, struct net_device *master) if (i == CONFIG_DLCI_MAX) return(-EMLINK); /* #### Alan: Comments on this ?? */ - MOD_INC_USE_COUNT; flp->master[i] = master; flp->dlci[i] = -*(short *)(master->dev_addr); @@ -588,7 +604,6 @@ int sdla_deassoc(struct net_device *slave, struct net_device *master) flp->master[i] = NULL; flp->dlci[i] = 0; - MOD_DEC_USE_COUNT; if (netif_running(slave)) { if (flp->config.station == FRAD_STATION_CPE) @@ -688,14 +703,14 @@ static int sdla_transmit(struct sk_buff *skb, struct net_device *dev) ret = sdla_cmd(dev, SDLA_INFORMATION_WRITE, *(short *)(skb->dev->dev_addr), 0, NULL, skb->len, &addr, &size); if (ret == SDLA_RET_OK) { - save_flags(flags); - cli(); + + spin_lock_irqsave(&sdla_lock, flags); SDLA_WINDOW(dev, addr); pbuf = (void *)(((int) dev->mem_start) + (addr & SDLA_ADDR_MASK)); - sdla_write(dev, pbuf->buf_addr, skb->data, skb->len); - SDLA_WINDOW(dev, addr); + __sdla_write(dev, pbuf->buf_addr, skb->data, skb->len); + SDLA_WINDOW(dev, addr); pbuf->opp_flag = 1; - restore_flags(flags); + spin_unlock_irqrestore(&sdla_lock, flags); } break; } @@ -753,8 +768,7 @@ static void sdla_receive(struct net_device *dev) pbufi = NULL; pbuf = NULL; - save_flags(flags); - cli(); + spin_lock_irqsave(&sdla_lock, flags); switch (flp->type) { @@ -821,7 +835,7 @@ static void sdla_receive(struct net_device *dev) case SDLA_S502A: case SDLA_S502E: if (success) - sdla_read(dev, SDLA_502_RCV_BUF + SDLA_502_DATA_OFS, skb_put(skb,len), len); + __sdla_read(dev, SDLA_502_RCV_BUF + SDLA_502_DATA_OFS, skb_put(skb,len), len); SDLA_WINDOW(dev, SDLA_502_RCV_BUF); cmd->opp_flag = 0; @@ -834,9 +848,9 @@ static void sdla_receive(struct net_device *dev) split = addr + len > buf_top + 1 ? len - (buf_top - addr + 1) : 0; len2 = len - split; - sdla_read(dev, addr, skb_put(skb, len2), len2); + __sdla_read(dev, addr, skb_put(skb, len2), len2); if (split) - sdla_read(dev, buf_base, skb_put(skb, split), split); + __sdla_read(dev, buf_base, skb_put(skb, split), split); } /* increment the buffer we're looking at */ @@ -853,7 +867,7 @@ static void sdla_receive(struct net_device *dev) (*dlp->receive)(skb, master); } - restore_flags(flags); + spin_unlock_irqrestore(&sdla_lock, flags); } static irqreturn_t sdla_isr(int irq, void *dev_id, struct pt_regs * regs) @@ -979,8 +993,6 @@ static int sdla_close(struct net_device *dev) netif_stop_queue(dev); - MOD_DEC_USE_COUNT; - return(0); } @@ -1082,8 +1094,6 @@ static int sdla_open(struct net_device *dev) netif_start_queue(dev); - MOD_INC_USE_COUNT; - return(0); } @@ -1614,19 +1624,30 @@ static struct net_device_stats *sdla_stats(struct net_device *dev) return(&flp->stats); } -int __init sdla_init(struct net_device *dev) +static void setup_sdla(struct net_device *dev) { + dev->flags = 0; + dev->type = 0xFFFF; + dev->hard_header_len = 0; + dev->addr_len = 0; + dev->mtu = SDLA_MAX_MTU; +} + +struct net_device * __init sdla_init(void) +{ + struct net_device *dev; struct frad_local *flp; + int err = -ENOMEM; - /* allocate the private data structure */ - flp = kmalloc(sizeof(struct frad_local), GFP_KERNEL); - if (!flp) - return(-ENOMEM); + dev = alloc_netdev(sizeof(struct frad_local), "sdla0", setup_sdla); + if (!dev) + goto out; - memset(flp, 0, sizeof(struct frad_local)); - dev->priv = flp; + SET_MODULE_OWNER(dev); + netdev_boot_setup_check(dev); + + flp = dev->priv; - dev->flags = 0; dev->open = sdla_open; dev->stop = sdla_close; dev->do_ioctl = sdla_ioctl; @@ -1635,12 +1656,6 @@ int __init sdla_init(struct net_device *dev) dev->hard_start_xmit = sdla_transmit; dev->change_mtu = sdla_change_mtu; - dev->type = 0xFFFF; - dev->hard_header_len = 0; - dev->addr_len = 0; - dev->mtu = SDLA_MAX_MTU; - SET_MODULE_OWNER(dev); - flp->activate = sdla_activate; flp->deactivate = sdla_deactivate; flp->assoc = sdla_assoc; @@ -1652,7 +1667,14 @@ int __init sdla_init(struct net_device *dev) flp->timer.data = (unsigned long) dev; flp->timer.function = sdla_poll; - return(0); + err = register_netdev(dev); + if (err) + goto out1; + return dev; +out1: + kfree(dev); +out: + return ERR_PTR(err); } int __init sdla_c_setup(void) @@ -1663,10 +1685,7 @@ int __init sdla_c_setup(void) } #ifdef MODULE -static struct net_device sdla0 = { - .name = "sdla0", - .init = sdla_init -}; +static struct net_device *sdla0; #endif /* MODULE */ static int __init init_sdla(void) @@ -1675,7 +1694,9 @@ static int __init init_sdla(void) sdla_c_setup(); #ifdef MODULE - result = register_netdev(&sdla0); + sdla0 = sdla_init(); + if (IS_ERR(sdla0)) + result = PTR_ERR(sdla0); #endif return result; } @@ -1683,11 +1704,10 @@ static int __init init_sdla(void) static void __exit exit_sdla(void) { #ifdef MODULE - unregister_netdev(&sdla0); - if (sdla0.priv) - kfree(sdla0.priv); - if (sdla0.irq) - free_irq(sdla0.irq, &sdla0); + unregister_netdev(sdla0); + if (sdla0->irq) + free_irq(sdla0->irq, sdla0); + free_netdev(sdla0); #endif } -- cgit v1.2.3 From fc9e07930b17eed12208b95411fd27aedf7d6327 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 3 Sep 2003 10:38:42 -0700 Subject: [NET]: Convert cops over to new initialization. More from Al NE12-cops * switched cops to dynamic allocation * cops: embedded ->priv * cops: fixed ->irq clobbering on autoprobe Added * free_netdev --- drivers/net/Space.c | 29 +++------- drivers/net/appletalk/cops.c | 132 +++++++++++++++++++++---------------------- 2 files changed, 73 insertions(+), 88 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/Space.c b/drivers/net/Space.c index 2292798aa348..c13607036260 100644 --- a/drivers/net/Space.c +++ b/drivers/net/Space.c @@ -101,6 +101,9 @@ extern int mc32_probe(struct net_device *dev); #ifdef CONFIG_SDLA extern struct net_device *sdla_init(void); #endif +#ifdef CONFIG_COPS +extern struct net_device *cops_probe(int unit); +#endif /* Detachable devices ("pocket adaptors") */ extern int de620_probe(struct net_device *); @@ -388,6 +391,11 @@ static int __init ethif_probe(struct net_device *dev) /* Statically configured drivers -- order matters here. */ void probe_old_netdevs(void) { +#ifdef CONFIG_COPS + cops_probe(0); + cops_probe(1); + cops_probe(2); +#endif #ifdef CONFIG_SDLA sdla_init(); #endif @@ -405,27 +413,6 @@ static struct net_device dev_ltpc = { #define NEXT_DEV (&dev_ltpc) #endif /* LTPC */ -#if defined(CONFIG_COPS) -extern int cops_probe(struct net_device *); -static struct net_device cops2_dev = { - .name = "lt2", - .next = NEXT_DEV, - .init = cops_probe, -}; -static struct net_device cops1_dev = { - .name = "lt1", - .next = &cops2_dev, - .init = cops_probe, -}; -static struct net_device cops0_dev = { - .name = "lt0", - .next = &cops1_dev, - .init = cops_probe, -}; -#undef NEXT_DEV -#define NEXT_DEV (&cops0_dev) -#endif /* COPS */ - static struct net_device eth7_dev = { .name = "eth%d", .next = NEXT_DEV, diff --git a/drivers/net/appletalk/cops.c b/drivers/net/appletalk/cops.c index cb8dac24f286..579cf0d2ee5b 100644 --- a/drivers/net/appletalk/cops.c +++ b/drivers/net/appletalk/cops.c @@ -92,12 +92,8 @@ static int board_type = DAYNA; /* Module exported */ static int board_type = TANGENT; #endif -#ifdef MODULE static int io = 0x240; /* Default IO for Dayna */ static int irq = 5; /* Default IRQ */ -#else -static int io; /* Default IO for Dayna */ -#endif /* * COPS Autoprobe information. @@ -146,7 +142,7 @@ static int io; /* Default IO for Dayna */ * Zero terminated list of IO ports to probe. */ -static unsigned int cops_portlist[] = { +static unsigned int ports[] = { 0x240, 0x340, 0x200, 0x210, 0x220, 0x230, 0x260, 0x2A0, 0x300, 0x310, 0x320, 0x330, 0x350, 0x360, 0 @@ -184,7 +180,6 @@ struct cops_local }; /* Index to functions, as function prototypes. */ -extern int cops_probe (struct net_device *dev); static int cops_probe1 (struct net_device *dev, int ioaddr); static int cops_irq (int ioaddr, int board); @@ -208,6 +203,12 @@ static int cops_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); static int cops_close (struct net_device *dev); static struct net_device_stats *cops_get_stats (struct net_device *dev); +static void cleanup_card(struct net_device *dev) +{ + if (dev->irq) + free_irq(dev->irq, dev); + release_region(dev->base_addr, COPS_IO_EXTENT); +} /* * Check for a network adaptor of this type, and return '0' iff one exists. @@ -215,31 +216,54 @@ static struct net_device_stats *cops_get_stats (struct net_device *dev); * If dev->base_addr in [1..0x1ff], always return failure. * otherwise go with what we pass in. */ -int __init cops_probe(struct net_device *dev) +struct net_device * __init cops_probe(int unit) { - int i; - int base_addr = dev->base_addr; + struct net_device *dev; + unsigned *port; + int base_addr; + int err = 0; + + dev = alloc_netdev(sizeof(struct cops_local), "lt%d", ltalk_setup); + if (!dev) + return ERR_PTR(-ENOMEM); + + if (unit >= 0) { + sprintf(dev->name, "lt%d", unit); + netdev_boot_setup_check(dev); + irq = dev->irq; + base_addr = dev->base_addr; + } else { + base_addr = dev->base_addr = io; + } SET_MODULE_OWNER(dev); - if(base_addr == 0 && io) - base_addr=io; - - if(base_addr > 0x1ff) /* Check a single specified location. */ - return cops_probe1(dev, base_addr); - else if(base_addr != 0) /* Don't probe at all. */ - return -ENXIO; - - /* FIXME Does this really work for cards which generate irq? - * It's definitely N.G. for polled Tangent. sh - * Dayna cards don't autoprobe well at all, but if your card is - * at IRQ 5 & IO 0x240 we find it every time. ;) JS - */ - for(i=0; cops_portlist[i]; i++) - if(cops_probe1(dev, cops_portlist[i]) == 0) - return 0; - - return -ENODEV; + if (base_addr > 0x1ff) { /* Check a single specified location. */ + err = cops_probe1(dev, base_addr); + } else if (base_addr != 0) { /* Don't probe at all. */ + err = -ENXIO; + } else { + /* FIXME Does this really work for cards which generate irq? + * It's definitely N.G. for polled Tangent. sh + * Dayna cards don't autoprobe well at all, but if your card is + * at IRQ 5 & IO 0x240 we find it every time. ;) JS + */ + for (port = ports; *port && cops_probe1(dev, *port) < 0; port++) + ; + if (!*port) + err = -ENODEV; + } + if (err) + goto out; + err = register_netdev(dev); + if (err) + goto out1; + return dev; +out1: + cleanup_card(dev); +out: + kfree(dev); + return ERR_PTR(err); } /* @@ -268,16 +292,15 @@ static int __init cops_probe1(struct net_device *dev, int ioaddr) * interrupts are typically not reported by the boards, and we must * used AutoIRQ to find them. */ + dev->irq = irq; switch (dev->irq) { case 0: /* COPS AutoIRQ routine */ dev->irq = cops_irq(ioaddr, board); - if(!dev->irq) { - retval = -EINVAL; /* No IRQ found on this port */ - goto err_out; - } - + if (dev->irq) + break; + /* No IRQ found on this port, fallthrough */ case 1: retval = -EINVAL; goto err_out; @@ -302,22 +325,13 @@ static int __init cops_probe1(struct net_device *dev, int ioaddr) } /* Reserve any actual interrupt. */ - if(dev->irq) { + if (dev->irq) { retval = request_irq(dev->irq, &cops_interrupt, 0, dev->name, dev); if (retval) goto err_out; } - dev->base_addr = ioaddr; - - /* Initialize the private device structure. */ - dev->priv = kmalloc(sizeof(struct cops_local), GFP_KERNEL); - if(dev->priv == NULL) { - if (dev->irq) - free_irq(dev->irq, dev); - retval = -ENOMEM; - goto err_out; - } + dev->base_addr = ioaddr; lp = (struct cops_local *)dev->priv; memset(lp, 0, sizeof(struct cops_local)); @@ -326,9 +340,6 @@ static int __init cops_probe1(struct net_device *dev, int ioaddr) /* Copy local board variable to lp struct. */ lp->board = board; - /* Fill in the fields of the device structure with LocalTalk values. */ - ltalk_setup(dev); - dev->hard_start_xmit = cops_send_packet; dev->tx_timeout = cops_timeout; dev->watchdog_timeo = HZ * 2; @@ -1013,7 +1024,7 @@ static struct net_device_stats *cops_get_stats(struct net_device *dev) } #ifdef MODULE -static struct net_device cops0_dev = { .init = cops_probe }; +static struct net_device *cops_dev; MODULE_LICENSE("GPL"); MODULE_PARM(io, "i"); @@ -1022,33 +1033,20 @@ MODULE_PARM(board_type, "i"); int init_module(void) { - int result, err; - - if(io == 0) + if (io == 0) printk(KERN_WARNING "%s: You shouldn't autoprobe with insmod\n", cardname); - - /* Copy the parameters from insmod into the device structure. */ - cops0_dev.base_addr = io; - cops0_dev.irq = irq; - - err=dev_alloc_name(&cops0_dev, "lt%d"); - if(err < 0) - return err; - - if((result = register_netdev(&cops0_dev)) != 0) - return result; - + cops_dev = cops_probe(-1); + if (IS_ERR(cops_dev)) + return PTR_ERR(cops_dev); return 0; } void cleanup_module(void) { - unregister_netdev(&cops0_dev); - kfree(cops0_dev.priv); - if(cops0_dev.irq) - free_irq(cops0_dev.irq, &cops0_dev); - release_region(cops0_dev.base_addr, COPS_IO_EXTENT); + unregister_netdev(cops_dev); + cleanup_card(cops_dev); + free_netdev(cops_dev); } #endif /* MODULE */ -- cgit v1.2.3 From 5691ce005540b0b2f847d2db3eaa53445af6c5be Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 3 Sep 2003 10:39:24 -0700 Subject: [NET]: Convert ether probes to probe_old_netdevs(). Convert old ethernet device probing from dev_base linked list to the probe_old_netdevs. Blame me for this one ;-) Builds and runs, but don't have old ISA hardware to really test it. So please find some or review it carefully. --- drivers/net/Space.c | 96 ++++++++++++++++++----------------------------------- 1 file changed, 32 insertions(+), 64 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/Space.c b/drivers/net/Space.c index c13607036260..2fb13e14b477 100644 --- a/drivers/net/Space.c +++ b/drivers/net/Space.c @@ -32,6 +32,7 @@ */ #include #include +#include #include #include #include @@ -358,39 +359,52 @@ static struct devprobe mips_probes[] __initdata = { * per bus interface. This drives the legacy devices only for now. */ -static int __init ethif_probe(struct net_device *dev) +static int __init ethif_probe(void) { - unsigned long base_addr = dev->base_addr; + struct net_device *dev; + int err = -ENODEV; + + dev = alloc_etherdev(0); + if (!dev) + return -ENOMEM; + + netdev_boot_setup_check(dev); /* * Backwards compatibility - historically an I/O base of 1 was * used to indicate not to probe for this ethN interface */ - if (base_addr == 1) - return 1; /* ENXIO */ + if (dev->base_addr == 1) { + free_netdev(dev); + return -ENXIO; + } /* * The arch specific probes are 1st so that any on-board ethernet * will be probed before other ISA/EISA/MCA/PCI bus cards. */ - if (probe_list(dev, m68k_probes) == 0) - return 0; - if (probe_list(dev, mips_probes) == 0) - return 0; - if (probe_list(dev, eisa_probes) == 0) - return 0; - if (probe_list(dev, mca_probes) == 0) - return 0; - if (probe_list(dev, isa_probes) == 0) - return 0; - if (probe_list(dev, parport_probes) == 0) - return 0; - return -ENODEV; + if (probe_list(dev, m68k_probes) == 0 || + probe_list(dev, mips_probes) == 0 || + probe_list(dev, eisa_probes) == 0 || + probe_list(dev, mca_probes) == 0 || + probe_list(dev, isa_probes) == 0 || + probe_list(dev, parport_probes) == 0) + err = register_netdev(dev); + + if (err) + free_netdev(dev); + return err; + } /* Statically configured drivers -- order matters here. */ -void probe_old_netdevs(void) +void __init probe_old_netdevs(void) { + int num; + + for (num = 0; num < 8; ++num) + if (ethif_probe()) + break; #ifdef CONFIG_COPS cops_probe(0); cops_probe(1); @@ -413,52 +427,6 @@ static struct net_device dev_ltpc = { #define NEXT_DEV (&dev_ltpc) #endif /* LTPC */ -static struct net_device eth7_dev = { - .name = "eth%d", - .next = NEXT_DEV, - .init = ethif_probe, -}; -static struct net_device eth6_dev = { - .name = "eth%d", - .next = ð7_dev, - .init = ethif_probe, -}; -static struct net_device eth5_dev = { - .name = "eth%d", - .next = ð6_dev, - .init = ethif_probe, -}; -static struct net_device eth4_dev = { - .name = "eth%d", - .next = ð5_dev, - .init = ethif_probe, -}; -static struct net_device eth3_dev = { - .name = "eth%d", - .next = ð4_dev, - .init = ethif_probe, -}; -static struct net_device eth2_dev = { - .name = "eth%d", - .next = ð3_dev, - .init = ethif_probe, -}; -static struct net_device eth1_dev = { - .name = "eth%d", - .next = ð2_dev, - .init = ethif_probe, -}; -static struct net_device eth0_dev = { - .name = "eth%d", - .next = ð1_dev, - .init = ethif_probe, -}; - -#undef NEXT_DEV -#define NEXT_DEV (ð0_dev) - - - #ifdef CONFIG_TR /* Token-ring device probe */ extern int ibmtr_probe(struct net_device *); -- cgit v1.2.3 From 118977532ef1885eaf9afc55a8c8eabdd6d52877 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 3 Sep 2003 10:40:11 -0700 Subject: [NET]: Convert tr probes to probe_old_netdevs(). Analogous to previous patch. Instead of dev_base list of static entries, use a loop and dynamically allocate devices. Tested only the 'no hardware' case. --- drivers/net/Space.c | 118 ++++++++++++++++++++-------------------------------- 1 file changed, 46 insertions(+), 72 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/Space.c b/drivers/net/Space.c index 2fb13e14b477..fbde41893d3f 100644 --- a/drivers/net/Space.c +++ b/drivers/net/Space.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -397,11 +398,56 @@ static int __init ethif_probe(void) } +#ifdef CONFIG_TR +/* Token-ring device probe */ +extern int ibmtr_probe(struct net_device *); +extern int sk_isa_probe(struct net_device *); +extern int proteon_probe(struct net_device *); +extern int smctr_probe(struct net_device *); + +static __init int trif_probe(void) +{ + struct net_device *dev; + int err = -ENODEV; + + dev = alloc_trdev(0); + if (!dev) + return -ENOMEM; + + netdev_boot_setup_check(dev); + if ( +#ifdef CONFIG_IBMTR + ibmtr_probe(dev) == 0 || +#endif +#ifdef CONFIG_SKISA + sk_isa_probe(dev) == 0 || +#endif +#ifdef CONFIG_PROTEON + proteon_probe(dev) == 0 || +#endif +#ifdef CONFIG_SMCTR + smctr_probe(dev) == 0 || +#endif + 0 ) + err = register_netdev(dev); + + if (err) + free_netdev(dev); + return err; + +} +#endif + /* Statically configured drivers -- order matters here. */ void __init probe_old_netdevs(void) { int num; +#ifdef CONFIG_TR + for (num = 0; num < 8; ++num) + if (trif_probe()) + break; +#endif for (num = 0; num < 8; ++num) if (ethif_probe()) break; @@ -427,78 +473,6 @@ static struct net_device dev_ltpc = { #define NEXT_DEV (&dev_ltpc) #endif /* LTPC */ -#ifdef CONFIG_TR -/* Token-ring device probe */ -extern int ibmtr_probe(struct net_device *); -extern int sk_isa_probe(struct net_device *); -extern int proteon_probe(struct net_device *); -extern int smctr_probe(struct net_device *); - -static int -trif_probe(struct net_device *dev) -{ - if (1 -#ifdef CONFIG_IBMTR - && ibmtr_probe(dev) -#endif -#ifdef CONFIG_SKISA - && sk_isa_probe(dev) -#endif -#ifdef CONFIG_PROTEON - && proteon_probe(dev) -#endif -#ifdef CONFIG_SMCTR - && smctr_probe(dev) -#endif - && 1 ) { - return 1; /* -ENODEV or -EAGAIN would be more accurate. */ - } - return 0; -} -static struct net_device tr7_dev = { - .name = "tr%d", - .next = NEXT_DEV, - .init = trif_probe, -}; -static struct net_device tr6_dev = { - .name = "tr%d", - .next = &tr7_dev, - .init = trif_probe, -}; -static struct net_device tr5_dev = { - .name = "tr%d", - .next = &tr6_dev, - .init = trif_probe, -}; -static struct net_device tr4_dev = { - .name = "tr%d", - .next = &tr5_dev, - .init = trif_probe, -}; -static struct net_device tr3_dev = { - .name = "tr%d", - .next = &tr4_dev, - .init = trif_probe, -}; -static struct net_device tr2_dev = { - .name = "tr%d", - .next = &tr3_dev, - .init = trif_probe, -}; -static struct net_device tr1_dev = { - .name = "tr%d", - .next = &tr2_dev, - .init = trif_probe, -}; -static struct net_device tr0_dev = { - .name = "tr%d", - .next = &tr1_dev, - .init = trif_probe, -}; -#undef NEXT_DEV -#define NEXT_DEV (&tr0_dev) - -#endif #ifdef CONFIG_SBNI static struct net_device sbni7_dev = { -- cgit v1.2.3 From 4976b816869168610853f5a49cecac852404681b Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 3 Sep 2003 10:40:58 -0700 Subject: [NET]: Convert sbni initialization. Convert sbni driver - new probing - single allocation using alloc_netdev for private data --- drivers/net/Space.c | 54 ++++++----------------------------------------- drivers/net/wan/sbni.c | 57 +++++++++++++++++++++++++++++++------------------- 2 files changed, 41 insertions(+), 70 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/Space.c b/drivers/net/Space.c index fbde41893d3f..a8a92838db26 100644 --- a/drivers/net/Space.c +++ b/drivers/net/Space.c @@ -114,7 +114,7 @@ extern int de620_probe(struct net_device *); extern int iph5526_probe(struct net_device *dev); /* SBNI adapters */ -extern int sbni_probe(struct net_device *); +extern int sbni_probe(void); struct devprobe { @@ -443,6 +443,11 @@ void __init probe_old_netdevs(void) { int num; +#ifdef CONFIG_SBNI + for (num = 0; num < 8; ++num) + if (sbni_probe()) + break; +#endif #ifdef CONFIG_TR for (num = 0; num < 8; ++num) if (trif_probe()) @@ -472,53 +477,6 @@ static struct net_device dev_ltpc = { #undef NEXT_DEV #define NEXT_DEV (&dev_ltpc) #endif /* LTPC */ - - -#ifdef CONFIG_SBNI -static struct net_device sbni7_dev = { - .name = "sbni7", - .next = NEXT_DEV, - .init = sbni_probe, -}; -static struct net_device sbni6_dev = { - .name = "sbni6", - .next = &sbni7_dev, - .init = sbni_probe, -}; -static struct net_device sbni5_dev = { - .name = "sbni5", - .next = &sbni6_dev, - .init = sbni_probe, -}; -static struct net_device sbni4_dev = { - .name = "sbni4", - .next = &sbni5_dev, - .init = sbni_probe, -}; -static struct net_device sbni3_dev = { - .name = "sbni3", - .next = &sbni4_dev, - .init = sbni_probe, -}; -static struct net_device sbni2_dev = { - .name = "sbni2", - .next = &sbni3_dev, - .init = sbni_probe, -}; -static struct net_device sbni1_dev = { - .name = "sbni1", - .next = &sbni2_dev, - .init = sbni_probe, -}; -static struct net_device sbni0_dev = { - .name = "sbni0", - .next = &sbni1_dev, - .init = sbni_probe, -}; - -#undef NEXT_DEV -#define NEXT_DEV (&sbni0_dev) -#endif /* * The loopback device is global so it can be directly referenced diff --git a/drivers/net/wan/sbni.c b/drivers/net/wan/sbni.c index 349400d4d95a..81b2f271036c 100644 --- a/drivers/net/wan/sbni.c +++ b/drivers/net/wan/sbni.c @@ -140,6 +140,7 @@ static void change_level( struct net_device * ); static void timeout_change_level( struct net_device * ); static u32 calc_crc32( u32, u8 *, u32 ); static struct sk_buff * get_rx_buf( struct net_device * ); +static int sbni_init( struct net_device * ); #ifdef CONFIG_SBNI_MULTILINE static int enslave( struct net_device *, struct net_device * ); @@ -205,23 +206,44 @@ sbni_isa_probe( struct net_device *dev ) } } - -int __init -sbni_probe( struct net_device *dev ) +static void __init sbni_devsetup(struct net_device *dev) { - int i; + ether_setup( dev ); + dev->init = &sbni_init; + dev->open = &sbni_open; + dev->stop = &sbni_close; + dev->hard_start_xmit = &sbni_start_xmit; + dev->get_stats = &sbni_get_stats; + dev->set_multicast_list = &set_multicast_list; + dev->do_ioctl = &sbni_ioctl; + + SET_MODULE_OWNER( dev ); +} +int __init sbni_probe(void) +{ + struct net_device *dev; static unsigned version_printed __initdata = 0; + if( version_printed++ == 0 ) printk( KERN_INFO "%s", version ); - if( !dev ) { /* simple sanity check */ - printk( KERN_ERR "sbni: NULL device!\n" ); - return -ENODEV; - } + dev = alloc_netdev(sizeof(struct net_local), "sbni%d", sbni_devsetup); + if (!dev) + return -ENOMEM; - SET_MODULE_OWNER( dev ); + netdev_boot_setup_check(dev); + + if (register_netdev(dev)) { + kfree(dev); + return -ENODEV; + } + return 0; +} +static int __init sbni_init(struct net_device *dev) +{ + int i; if( dev->base_addr ) return sbni_isa_probe( dev ); /* otherwise we have to perform search our adapter */ @@ -338,7 +360,7 @@ sbni_probe1( struct net_device *dev, unsigned long ioaddr, int irq ) dev->base_addr = ioaddr; /* Allocate dev->priv and fill in sbni-specific dev fields. */ - nl = (struct net_local *) kmalloc(sizeof(struct net_local), GFP_KERNEL); + nl = dev->priv; if( !nl ) { printk( KERN_ERR "%s: unable to get memory!\n", dev->name ); release_region( ioaddr, SBNI_IO_EXTENT ); @@ -389,14 +411,6 @@ sbni_probe1( struct net_device *dev, unsigned long ioaddr, int irq ) nl->link = NULL; #endif - dev->open = &sbni_open; - dev->stop = &sbni_close; - dev->hard_start_xmit = &sbni_start_xmit; - dev->get_stats = &sbni_get_stats; - dev->set_multicast_list = &set_multicast_list; - dev->do_ioctl = &sbni_ioctl; - ether_setup( dev ); - sbni_cards[ num++ ] = dev; return dev; } @@ -1478,15 +1492,15 @@ init_module( void ) struct net_device *dev; while( num < SBNI_MAX_NUM_CARDS ) { - if( !(dev = kmalloc(sizeof(struct net_device), GFP_KERNEL)) ){ + dev = alloc_netdev(sizeof(struct net_local), + "sbni%d", sbni_devsetup); + if( !dev) { printk( KERN_ERR "sbni: unable to allocate device!\n" ); return -ENOMEM; } - memset( dev, 0, sizeof(struct net_device) ); sprintf( dev->name, "sbni%d", num ); - dev->init = sbni_probe; if( register_netdev( dev ) ) { kfree( dev ); break; @@ -1506,7 +1520,6 @@ cleanup_module( void ) if( (dev = sbni_cards[ num ]) != NULL ) { unregister_netdev( dev ); release_region( dev->base_addr, SBNI_IO_EXTENT ); - kfree( dev->priv ); free_netdev( dev ); } } -- cgit v1.2.3 From 4e39f29be0eae39e05bdb2d881849ff0560a7b64 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 3 Sep 2003 10:41:35 -0700 Subject: [NET]: Loopback device simplification. Now that all the magic chain of static devices is gone from Space.c The initialization of the one remaining static device (ie the loopback driver) can be simplified. One small change was to reduce possibility of failing the initialization if allocation of private data failed by just going without statistics. --- drivers/net/Space.c | 29 +++++++++----------- drivers/net/loopback.c | 72 ++++++++++++++++++++++++++------------------------ net/core/dev.c | 70 ------------------------------------------------ 3 files changed, 50 insertions(+), 121 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/Space.c b/drivers/net/Space.c index a8a92838db26..470cae32a543 100644 --- a/drivers/net/Space.c +++ b/drivers/net/Space.c @@ -39,9 +39,6 @@ #include #include -#define NEXT_DEV NULL - - /* A unified ethernet device probe. This is the easiest way to have every ethernet adaptor have the name "eth[0123...]". */ @@ -438,11 +435,23 @@ static __init int trif_probe(void) } #endif + +/* + * The loopback device is global so it can be directly referenced + * by the network code. Also, it must be first on device list. + */ +extern int loopback_init(void); + /* Statically configured drivers -- order matters here. */ void __init probe_old_netdevs(void) { int num; + if (loopback_init()) { + printk(KERN_ERR "Network loopback device setup failed\n"); + } + + #ifdef CONFIG_SBNI for (num = 0; num < 8; ++num) if (sbni_probe()) @@ -477,18 +486,6 @@ static struct net_device dev_ltpc = { #undef NEXT_DEV #define NEXT_DEV (&dev_ltpc) #endif /* LTPC */ - -/* - * The loopback device is global so it can be directly referenced - * by the network code. Also, it must be first on device list. - */ - -extern int loopback_init(struct net_device *dev); -struct net_device loopback_dev = { - .name = "lo", - .next = NEXT_DEV, - .init = loopback_init -}; /* * The @dev_base list is protected by @dev_base_lock and the rtln @@ -509,6 +506,6 @@ struct net_device loopback_dev = { * unregister_netdevice(), which must be called with the rtnl * semaphore held. */ -struct net_device *dev_base = &loopback_dev; +struct net_device *dev_base; rwlock_t dev_base_lock = RW_LOCK_UNLOCKED; diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index 7382804af6b0..5dd2b3393edc 100644 --- a/drivers/net/loopback.c +++ b/drivers/net/loopback.c @@ -55,6 +55,7 @@ #include #include + #define LOOPBACK_OVERHEAD (128 + MAX_HEADER + 16 + 16) /* KISS: just allocate small chunks and copy bits. @@ -152,10 +153,12 @@ static int loopback_xmit(struct sk_buff *skb, struct net_device *dev) } dev->last_rx = jiffies; - stats->rx_bytes+=skb->len; - stats->tx_bytes+=skb->len; - stats->rx_packets++; - stats->tx_packets++; + if (likely(stats)) { + stats->rx_bytes+=skb->len; + stats->tx_bytes+=skb->len; + stats->rx_packets++; + stats->tx_packets++; + } netif_rx(skb); @@ -167,36 +170,35 @@ static struct net_device_stats *get_stats(struct net_device *dev) return (struct net_device_stats *)dev->priv; } -/* Initialize the rest of the LOOPBACK device. */ -int __init loopback_init(struct net_device *dev) -{ - dev->mtu = (16 * 1024) + 20 + 20 + 12; - dev->hard_start_xmit = loopback_xmit; - dev->hard_header = eth_header; - dev->hard_header_cache = eth_header_cache; - dev->header_cache_update= eth_header_cache_update; - dev->hard_header_len = ETH_HLEN; /* 14 */ - dev->addr_len = ETH_ALEN; /* 6 */ - dev->tx_queue_len = 0; - dev->type = ARPHRD_LOOPBACK; /* 0x0001 */ - dev->rebuild_header = eth_rebuild_header; - dev->flags = IFF_LOOPBACK; - dev->features = NETIF_F_SG|NETIF_F_FRAGLIST|NETIF_F_NO_CSUM|NETIF_F_HIGHDMA; - - /* Current netfilter will die with oom linearizing large skbs, - * however this will be cured before 2.5.x is done. - */ - dev->features |= NETIF_F_TSO; - - dev->priv = kmalloc(sizeof(struct net_device_stats), GFP_KERNEL); - if (dev->priv == NULL) - return -ENOMEM; - memset(dev->priv, 0, sizeof(struct net_device_stats)); - dev->get_stats = get_stats; +struct net_device loopback_dev = { + .name = "lo", + .mtu = (16 * 1024) + 20 + 20 + 12, + .hard_start_xmit = loopback_xmit, + .hard_header = eth_header, + .hard_header_cache = eth_header_cache, + .header_cache_update = eth_header_cache_update, + .hard_header_len = ETH_HLEN, /* 14 */ + .addr_len = ETH_ALEN, /* 6 */ + .tx_queue_len = 0, + .type = ARPHRD_LOOPBACK, /* 0x0001*/ + .rebuild_header = eth_rebuild_header, + .flags = IFF_LOOPBACK, + .features = NETIF_F_SG|NETIF_F_FRAGLIST + |NETIF_F_NO_CSUM|NETIF_F_HIGHDMA|NETIF_F_TSO, +}; - /* - * Fill in the generic fields of the device structure. - */ - - return(0); +/* Setup and register the of the LOOPBACK device. */ +int __init loopback_init(void) +{ + struct net_device_stats *stats; + + /* Can survive without statistics */ + stats = kmalloc(sizeof(struct net_device_stats), GFP_KERNEL); + if (stats) { + memset(stats, 0, sizeof(struct net_device_stats)); + loopback_dev.priv = stats; + loopback_dev.get_stats = &get_stats; + } + + return register_netdev(&loopback_dev); }; diff --git a/net/core/dev.c b/net/core/dev.c index 1ac07dc5077e..8a598f7f300c 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2981,7 +2981,6 @@ int unregister_netdevice(struct net_device *dev) */ static int __init net_dev_init(void) { - struct net_device *dev, **dp; int i, rc = -ENOMEM; BUG_ON(!dev_boot_phase); @@ -3027,75 +3026,6 @@ static int __init net_dev_init(void) add_timer(&samp_timer); #endif - /* - * Add the devices. - * If the call to dev->init fails, the dev is removed - * from the chain disconnecting the device until the - * next reboot. - * - * NB At boot phase networking is dead. No locking is required. - * But we still preserve dev_base_lock for sanity. - */ - - dp = &dev_base; - while ((dev = *dp) != NULL) { - spin_lock_init(&dev->queue_lock); - spin_lock_init(&dev->xmit_lock); -#ifdef CONFIG_NET_FASTROUTE - dev->fastpath_lock = RW_LOCK_UNLOCKED; -#endif - dev->xmit_lock_owner = -1; - dev->iflink = -1; - dev_hold(dev); - - /* - * Allocate name. If the init() fails - * the name will be reissued correctly. - */ - if (strchr(dev->name, '%')) - dev_alloc_name(dev, dev->name); - - /* - * Check boot time settings for the device. - */ - netdev_boot_setup_check(dev); - - if ( (dev->init && dev->init(dev)) || - netdev_register_sysfs(dev) ) { - /* - * It failed to come up. It will be unhooked later. - * dev_alloc_name can now advance to next suitable - * name that is checked next. - */ - dp = &dev->next; - } else { - dp = &dev->next; - dev->ifindex = dev_new_index(); - dev->reg_state = NETREG_REGISTERED; - if (dev->iflink == -1) - dev->iflink = dev->ifindex; - if (!dev->rebuild_header) - dev->rebuild_header = default_rebuild_header; - dev_init_scheduler(dev); - set_bit(__LINK_STATE_PRESENT, &dev->state); - } - } - - /* - * Unhook devices that failed to come up - */ - dp = &dev_base; - while ((dev = *dp) != NULL) { - if (dev->reg_state != NETREG_REGISTERED) { - write_lock_bh(&dev_base_lock); - *dp = dev->next; - write_unlock_bh(&dev_base_lock); - dev_put(dev); - } else { - dp = &dev->next; - } - } - dev_boot_phase = 0; probe_old_netdevs(); -- cgit v1.2.3 From c9f8652ff899ba78b313cd10c9192445c028c5ed Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 3 Sep 2003 10:42:21 -0700 Subject: [NET]: Convert ltpc to new initialization. Originally from Al Viro NE11-ltpc * switched ltpc to dynamic allocation * ltpc: embedded ->priv * ltpc: fixed bugs in DMA allocation * ltpc: fixed resource leaks on failure exits * ltpc: fixed part of timer bugs (still a-f**ing-plenty of those) * ltpc: fixed order of freeing bugs Added * switch to free_netdev --- drivers/net/Space.c | 17 ++- drivers/net/appletalk/ltpc.c | 251 ++++++++++++++++++------------------------- 2 files changed, 112 insertions(+), 156 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/Space.c b/drivers/net/Space.c index 470cae32a543..1963e60de0b2 100644 --- a/drivers/net/Space.c +++ b/drivers/net/Space.c @@ -103,6 +103,9 @@ extern struct net_device *sdla_init(void); #ifdef CONFIG_COPS extern struct net_device *cops_probe(int unit); #endif +#ifdef CONFIG_LTPC +extern struct net_device *ltpc_probe(void); +#endif /* Detachable devices ("pocket adaptors") */ extern int de620_probe(struct net_device *); @@ -470,23 +473,15 @@ void __init probe_old_netdevs(void) cops_probe(1); cops_probe(2); #endif +#ifdef CONFIG_LTPC + ltpc_probe(); +#endif #ifdef CONFIG_SDLA sdla_init(); #endif } -#if defined(CONFIG_LTPC) -extern int ltpc_probe(struct net_device *); -static struct net_device dev_ltpc = { - .name = "lt0", - .next = NEXT_DEV, - .init = ltpc_probe -}; -#undef NEXT_DEV -#define NEXT_DEV (&dev_ltpc) -#endif /* LTPC */ - /* * The @dev_base list is protected by @dev_base_lock and the rtln * semaphore. diff --git a/drivers/net/appletalk/ltpc.c b/drivers/net/appletalk/ltpc.c index ddbd4f765b12..1b10bc14867c 100644 --- a/drivers/net/appletalk/ltpc.c +++ b/drivers/net/appletalk/ltpc.c @@ -879,34 +879,6 @@ static int ltpc_hard_header (struct sk_buff *skb, struct net_device *dev, return 0; } -static int ltpc_init(struct net_device *dev) -{ - /* Initialize the device structure. */ - - /* Fill in the fields of the device structure with ethernet-generic values. */ - ltalk_setup(dev); - dev->hard_start_xmit = ltpc_xmit; - dev->hard_header = ltpc_hard_header; - - dev->priv = kmalloc(sizeof(struct ltpc_private), GFP_KERNEL); - if(!dev->priv) - { - printk(KERN_INFO "%s: could not allocate statistics buffer\n", dev->name); - return -ENOMEM; - } - - memset(dev->priv, 0, sizeof(struct ltpc_private)); - dev->get_stats = ltpc_get_stats; - - /* add the ltpc-specific things */ - dev->do_ioctl = <pc_ioctl; - - dev->set_multicast_list = &set_multicast_list; - dev->mc_list = NULL; - - return 0; -} - static int ltpc_poll_counter; static void ltpc_poll(unsigned long l) @@ -983,35 +955,40 @@ static struct net_device_stats *ltpc_get_stats(struct net_device *dev) /* initialization stuff */ -static int __init ltpc_probe_dma(int base) +static int __init ltpc_probe_dma(int base, int dma) { - int dma = 0; + int want = (dma == 3) ? 2 : (dma == 1) ? 1 : 3; unsigned long timeout; unsigned long f; - if (!request_dma(1,"ltpc")) { - f=claim_dma_lock(); - disable_dma(1); - clear_dma_ff(1); - set_dma_mode(1,DMA_MODE_WRITE); - set_dma_addr(1,virt_to_bus(ltdmabuf)); - set_dma_count(1,sizeof(struct lt_mem)); - enable_dma(1); - release_dma_lock(f); - dma|=1; + if (want & 1) { + if (request_dma(1,"ltpc")) { + want &= ~1; + } else { + f=claim_dma_lock(); + disable_dma(1); + clear_dma_ff(1); + set_dma_mode(1,DMA_MODE_WRITE); + set_dma_addr(1,virt_to_bus(ltdmabuf)); + set_dma_count(1,sizeof(struct lt_mem)); + enable_dma(1); + release_dma_lock(f); + } } - if (!request_dma(3,"ltpc")) { - f=claim_dma_lock(); - disable_dma(3); - clear_dma_ff(3); - set_dma_mode(3,DMA_MODE_WRITE); - set_dma_addr(3,virt_to_bus(ltdmabuf)); - set_dma_count(3,sizeof(struct lt_mem)); - enable_dma(3); - release_dma_lock(f); - dma|=2; + if (want & 2) { + if (request_dma(3,"ltpc")) { + want &= ~2; + } else { + f=claim_dma_lock(); + disable_dma(3); + clear_dma_ff(3); + set_dma_mode(3,DMA_MODE_WRITE); + set_dma_addr(3,virt_to_bus(ltdmabuf)); + set_dma_count(3,sizeof(struct lt_mem)); + enable_dma(3); + release_dma_lock(f); + } } - /* set up request */ /* FIXME -- do timings better! */ @@ -1037,65 +1014,62 @@ static int __init ltpc_probe_dma(int base) /* release the other dma channel (if we opened both of them) */ - if ( (dma&0x2) && (get_dma_residue(3)==sizeof(struct lt_mem)) ){ - dma&=1; + if ((want & 2) && (get_dma_residue(3)==sizeof(struct lt_mem))) { + want &= ~2; free_dma(3); } - - if ( (dma&0x1) && (get_dma_residue(1)==sizeof(struct lt_mem)) ){ - dma&=0x2; + + if ((want & 1) && (get_dma_residue(1)==sizeof(struct lt_mem))) { + want &= ~1; free_dma(1); } - /* fix up dma number */ - dma|=1; + if (!want) + return 0; - return dma; + return (want & 2) ? 3 : 1; } -int __init ltpc_probe(struct net_device *dev) +struct net_device * __init ltpc_probe(void) { - int err; + struct net_device *dev; + int err = -ENOMEM; int x=0,y=0; int autoirq; unsigned long f; - int portfound=0; unsigned long timeout; + dev = alloc_netdev(sizeof(struct ltpc_private), "lt%d", ltalk_setup); + if (!dev) + goto out; + SET_MODULE_OWNER(dev); /* probe for the I/O port address */ + if (io != 0x240 && request_region(0x220,8,"ltpc")) { x = inb_p(0x220+6); if ( (x!=0xff) && (x>=0xf0) ) { io = 0x220; - portfound=1; - } - else { - release_region(0x220,8); + goto got_port; } + release_region(0x220,8); } - if (io != 0x220 && request_region(0x240,8,"ltpc")) { y = inb_p(0x240+6); if ( (y!=0xff) && (y>=0xf0) ){ io = 0x240; - portfound=1; - } - else { - release_region(0x240,8); + goto got_port; } + release_region(0x240,8); } - if(io && !portfound && request_region(io,8,"ltpc")){ - portfound = 1; - } - if(!portfound) { - /* give up in despair */ - printk(KERN_ERR "LocalTalk card not found; 220 = %02x, 240 = %02x.\n", x,y); - return -1; - } + /* give up in despair */ + printk(KERN_ERR "LocalTalk card not found; 220 = %02x, 240 = %02x.\n", x,y); + err = -ENODEV; + goto out1; + got_port: /* probe for the IRQ line */ if (irq < 2) { unsigned long irq_mask; @@ -1111,22 +1085,21 @@ int __init ltpc_probe(struct net_device *dev) if (autoirq == 0) { printk(KERN_ERR "ltpc: probe at %#x failed to detect IRQ line.\n", io); - } - else { + } else { irq = autoirq; } } /* allocate a DMA buffer */ ltdmabuf = (unsigned char *) dma_mem_alloc(1000); - - if (ltdmabuf) ltdmacbuf = <dmabuf[800]; - if (!ltdmabuf) { printk(KERN_ERR "ltpc: mem alloc failed\n"); - return -1; + err = -ENOMEM; + goto out2; } + ltdmacbuf = <dmabuf[800]; + if(debug & DEBUG_VERBOSE) { printk("ltdmabuf pointer %08lx\n",(unsigned long) ltdmabuf); } @@ -1154,25 +1127,29 @@ int __init ltpc_probe(struct net_device *dev) already been specified */ /* well, 0 is a legal DMA channel, but the LTPC card doesn't use it... */ - if (dma == 0) { - dma = ltpc_probe_dma(io); - if (!dma) { /* no dma channel */ - printk(KERN_ERR "No DMA channel found on ltpc card.\n"); - return -1; - } + dma = ltpc_probe_dma(io, dma); + if (!dma) { /* no dma channel */ + printk(KERN_ERR "No DMA channel found on ltpc card.\n"); + err = -ENODEV; + goto out3; } /* print out friendly message */ - if(irq) printk(KERN_INFO "Apple/Farallon LocalTalk-PC card at %03x, IR%d, DMA%d.\n",io,irq,dma); else printk(KERN_INFO "Apple/Farallon LocalTalk-PC card at %03x, DMA%d. Using polled mode.\n",io,dma); - /* seems more logical to do this *after* probing the card... */ - err = ltpc_init(dev); - if (err) return err; + /* Fill in the fields of the device structure with ethernet-generic values. */ + dev->hard_start_xmit = ltpc_xmit; + dev->hard_header = ltpc_hard_header; + dev->get_stats = ltpc_get_stats; + /* add the ltpc-specific things */ + dev->do_ioctl = <pc_ioctl; + + dev->set_multicast_list = &set_multicast_list; + dev->mc_list = NULL; dev->base_addr = io; dev->irq = irq; dev->dma = dma; @@ -1212,6 +1189,7 @@ int __init ltpc_probe(struct net_device *dev) } else { if( irq ) printk(KERN_ERR "ltpc: IRQ already in use, using polled mode.\n"); + dev->irq = 0; /* polled mode -- 20 times per second */ /* this is really, really slow... should it poll more often? */ init_timer(<pc_timer); @@ -1221,8 +1199,23 @@ int __init ltpc_probe(struct net_device *dev) ltpc_timer.expires = jiffies + HZ/20; add_timer(<pc_timer); } + err = register_netdev(dev); + if (err) + goto out4; return 0; +out4: + del_timer_sync(<pc_timer); + if (dev->irq) + free_irq(dev->irq, dev); +out3: + free_pages((unsigned long)ltdmabuf, get_order(1000)); +out2: + release_region(io, 8); +out1: + kfree(dev); +out: + return ERR_PTR(err); } #ifndef MODULE @@ -1259,7 +1252,7 @@ static int __init ltpc_setup(char *str) __setup("ltpc=", ltpc_setup); #endif /* MODULE */ -static struct net_device dev_ltpc; +static struct net_device *dev_ltpc; #ifdef MODULE @@ -1272,79 +1265,47 @@ MODULE_PARM(dma, "i"); int __init init_module(void) { - int err, result; - if(io == 0) printk(KERN_NOTICE "ltpc: Autoprobing is not recommended for modules\n"); - /* Find a name for this unit */ - dev_ltpc.init = ltpc_probe; - err=dev_alloc_name(&dev_ltpc,"lt%d"); - - if(err<0) - return err; - - if ((result = register_netdev(&dev_ltpc)) != 0) { - printk(KERN_DEBUG "could not register Localtalk-PC device\n"); - return result; - } else { - if(debug & DEBUG_VERBOSE) printk("0 from register_netdev\n"); - return 0; - } + dev_ltpc = ltpc_probe(); + if (IS_ERR(dev_ltpc)) + return PTR_ERR(dev_ltpc); + return 0; } #endif static void __exit ltpc_cleanup(void) { - unsigned long timeout; + + if(debug & DEBUG_VERBOSE) printk("unregister_netdev\n"); + unregister_netdev(dev_ltpc); ltpc_timer.data = 0; /* signal the poll routine that we're done */ + del_timer_sync(<pc_timer); + if(debug & DEBUG_VERBOSE) printk("freeing irq\n"); - if(dev_ltpc.irq) { - free_irq(dev_ltpc.irq,&dev_ltpc); - dev_ltpc.irq = 0; - } - - if(del_timer(<pc_timer)) - { - /* either the poll was never started, or a poll is in process */ - if(debug & DEBUG_VERBOSE) printk("waiting\n"); - /* if it's in process, wait a bit for it to finish */ - timeout = jiffies+HZ; - add_timer(<pc_timer); - while(del_timer(<pc_timer) && time_after(timeout, jiffies)) - { - add_timer(<pc_timer); - schedule(); - } - } + if (dev_ltpc->irq) + free_irq(dev_ltpc->irq, dev_ltpc); if(debug & DEBUG_VERBOSE) printk("freeing dma\n"); - if(dev_ltpc.dma) { - free_dma(dev_ltpc.dma); - dev_ltpc.dma = 0; - } + if (dev_ltpc->dma) + free_dma(dev_ltpc->dma); if(debug & DEBUG_VERBOSE) printk("freeing ioaddr\n"); - if(dev_ltpc.base_addr) { - release_region(dev_ltpc.base_addr,8); - dev_ltpc.base_addr = 0; - } + if (dev_ltpc->base_addr) + release_region(dev_ltpc->base_addr,8); + + free_netdev(dev_ltpc); if(debug & DEBUG_VERBOSE) printk("free_pages\n"); free_pages( (unsigned long) ltdmabuf, get_order(1000)); - ltdmabuf=NULL; - ltdmacbuf=NULL; - - if(debug & DEBUG_VERBOSE) printk("unregister_netdev\n"); - - unregister_netdev(&dev_ltpc); if(debug & DEBUG_VERBOSE) printk("returning from cleanup_module\n"); } -- cgit v1.2.3