diff options
194 files changed, 923 insertions, 2013 deletions
diff --git a/Documentation/networking/driver.txt b/Documentation/networking/driver.txt index ffdd2f2d5944..11fd0ef5ff57 100644 --- a/Documentation/networking/driver.txt +++ b/Documentation/networking/driver.txt @@ -82,3 +82,13 @@ Probing guidelines: 1) Any hardware layer address you obtain for your device should be verified. For example, for ethernet check it with linux/etherdevice.h:is_valid_ether_addr() + +Close/stop guidelines: + +1) After the dev->stop routine has been called, the hardware must + not receive or transmit any data. All in flight packets must + be aborted. If necessary, poll or wait for completion of + any reset commands. + +2) The dev->stop routine will be called by unregister_netdevice + if device is still UP. diff --git a/Documentation/networking/netdevices.txt b/Documentation/networking/netdevices.txt index 0723093cf896..8c456edb6aad 100644 --- a/Documentation/networking/netdevices.txt +++ b/Documentation/networking/netdevices.txt @@ -7,6 +7,18 @@ Introduction The following is a random collection of documentation regarding network devices. +struct net_device allocation rules +================================== +Network device structures need to persist even after module is unloaded and +must be allocated with kmalloc. If device has registered successfully, +it will be freed on last use by free_netdev. This is required to handle the +pathologic case cleanly (example: rmmod mydriver </sys/class/net/myeth/mtu ) + +There are routines in net_init.c to handle the common cases of +alloc_etherdev, alloc_netdev. These reserve extra space for driver +private data which gets freed when the network device is freed. If +separately allocated data is attached to the network device +(dev->priv) then it is up to the module exit handler to free that. struct net_device synchronization rules diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c index 56dfdec553a6..d8f7468ae9e2 100644 --- a/arch/um/drivers/net_kern.c +++ b/arch/um/drivers/net_kern.c @@ -609,7 +609,7 @@ static int net_remove(char *str) unregister_netdev(dev); list_del(&device->list); - kfree(device); + free_netdev(device); return(0); } diff --git a/drivers/atm/ambassador.c b/drivers/atm/ambassador.c index b07ec73a3277..ecd90347a99c 100644 --- a/drivers/atm/ambassador.c +++ b/drivers/atm/ambassador.c @@ -1556,33 +1556,6 @@ static int amb_send (struct atm_vcc * atm_vcc, struct sk_buff * skb) { return 0; } -/********** Scatter Gather Send Capability **********/ - -static int amb_sg_send (struct atm_vcc * atm_vcc, - unsigned long start, - unsigned long size) { - PRINTD (DBG_FLOW|DBG_VCC, "amb_sg_send: never"); - return 0; - if (atm_vcc->qos.aal == ATM_AAL5) { - PRINTD (DBG_FLOW|DBG_VCC, "amb_sg_send: yes"); - return 1; - } else { - PRINTD (DBG_FLOW|DBG_VCC, "amb_sg_send: no"); - return 0; - } - PRINTD (DBG_FLOW|DBG_VCC, "amb_sg_send: always"); - return 1; -} - -/********** Send OAM **********/ - -// static int amb_send_oam (struct atm_vcc * atm_vcc, void * cell, int flags); - -/********** Feedback to Driver **********/ - -// void amb_feedback (struct atm_vcc * atm_vcc, struct sk_buff * skb, -// unsigned long start, unsigned long dest, int len); - /********** Change QoS on a VC **********/ // int amb_change_qos (struct atm_vcc * atm_vcc, struct atm_qos * qos, int flags); @@ -1693,7 +1666,6 @@ static const struct atmdev_ops amb_ops = { .open = amb_open, .close = amb_close, .send = amb_send, - .sg_send = amb_sg_send, .proc_read = amb_proc_read, .owner = THIS_MODULE, }; diff --git a/drivers/atm/eni.c b/drivers/atm/eni.c index a95b9bbd155d..c113f6e1c054 100644 --- a/drivers/atm/eni.c +++ b/drivers/atm/eni.c @@ -2122,15 +2122,6 @@ backlogged++; return 0; } - -static int eni_sg_send(struct atm_vcc *vcc,unsigned long start, - unsigned long size) -{ - return vcc->qos.aal == ATM_AAL5 && !((start | size) & 3); - /* don't tolerate misalignment */ -} - - static void eni_phy_put(struct atm_dev *dev,unsigned char value, unsigned long addr) { @@ -2269,7 +2260,6 @@ static const struct atmdev_ops ops = { .getsockopt = eni_getsockopt, .setsockopt = eni_setsockopt, .send = eni_send, - .sg_send = eni_sg_send, .phy_put = eni_phy_put, .phy_get = eni_phy_get, .change_qos = eni_change_qos, diff --git a/drivers/atm/firestream.c b/drivers/atm/firestream.c index 18ec5415f745..54b054e60932 100644 --- a/drivers/atm/firestream.c +++ b/drivers/atm/firestream.c @@ -1268,14 +1268,6 @@ static unsigned char fs_phy_get(struct atm_dev *dev,unsigned long addr) } -static void fs_feedback(struct atm_vcc *vcc,struct sk_buff *skb, - unsigned long start,unsigned long dest,int len) -{ - func_enter (); - func_exit (); -} - - static int fs_change_qos(struct atm_vcc *vcc,struct atm_qos *qos,int flags) { func_enter (); @@ -1293,11 +1285,9 @@ static const struct atmdev_ops ops = { #if 0 .owner = THIS_MODULE, #endif - /* fs_sg_send */ /* ioctl: fs_ioctl, */ /* getsockopt: fs_getsockopt, */ /* setsockopt: fs_setsockopt, */ - /* feedback: fs_feedback, */ /* change_qos: fs_change_qos, */ /* For now implement these internally here... */ diff --git a/drivers/atm/he.c b/drivers/atm/he.c index c55a8df0a5cb..a69810f871b3 100644 --- a/drivers/atm/he.c +++ b/drivers/atm/he.c @@ -138,7 +138,6 @@ static char *version = "$Id: he.c,v 1.18 2003/05/06 22:57:15 chas Exp $"; static int he_open(struct atm_vcc *vcc, short vpi, int vci); static void he_close(struct atm_vcc *vcc); static int he_send(struct atm_vcc *vcc, struct sk_buff *skb); -static int he_sg_send(struct atm_vcc *vcc, unsigned long start, unsigned long size); static int he_ioctl(struct atm_dev *dev, unsigned int cmd, void *arg); static irqreturn_t he_irq_handler(int irq, void *dev_id, struct pt_regs *regs); static void he_tasklet(unsigned long data); @@ -166,7 +165,6 @@ static struct atmdev_ops he_ops = .close = he_close, .ioctl = he_ioctl, .send = he_send, - .sg_send = he_sg_send, .phy_put = he_phy_put, .phy_get = he_phy_get, .proc_read = he_proc_read, @@ -2727,16 +2725,6 @@ close_tx_incomplete: } static int -he_sg_send(struct atm_vcc *vcc, unsigned long start, unsigned long size) -{ -#ifdef USE_SCATTERGATHER - return 1; -#else - return 0; -#endif -} - -static int he_send(struct atm_vcc *vcc, struct sk_buff *skb) { unsigned long flags; diff --git a/drivers/atm/horizon.c b/drivers/atm/horizon.c index 5249e906fd22..911eab75200b 100644 --- a/drivers/atm/horizon.c +++ b/drivers/atm/horizon.c @@ -2663,18 +2663,6 @@ static int hrz_setsockopt (struct atm_vcc * atm_vcc, int level, int optname, } #endif -static int hrz_sg_send (struct atm_vcc * atm_vcc, - unsigned long start, - unsigned long size) { - if (atm_vcc->qos.aal == ATM_AAL5) { - PRINTD (DBG_FLOW|DBG_VCC, "hrz_sg_send: yes"); - return 1; - } else { - PRINTD (DBG_FLOW|DBG_VCC, "hrz_sg_send: no"); - return 0; - } -} - #if 0 static int hrz_ioctl (struct atm_dev * atm_dev, unsigned int cmd, void *arg) { hrz_dev * dev = HRZ_DEV(atm_dev); @@ -2748,7 +2736,6 @@ static const struct atmdev_ops hrz_ops = { .open = hrz_open, .close = hrz_close, .send = hrz_send, - .sg_send = hrz_sg_send, .proc_read = hrz_proc_read, .owner = THIS_MODULE, }; diff --git a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c index 7ad553deeb8d..ea503304329e 100644 --- a/drivers/atm/idt77252.c +++ b/drivers/atm/idt77252.c @@ -1954,7 +1954,7 @@ idt77252_phy_get(struct atm_dev *dev, unsigned long addr) return read_utility(dev->dev_data, 0x100 + (addr & 0x1ff)); } -static int +static inline int idt77252_send_skb(struct atm_vcc *vcc, struct sk_buff *skb, int oam) { struct atm_dev *dev = vcc->dev; diff --git a/drivers/atm/iphase.c b/drivers/atm/iphase.c index 5dd61f55da2a..044591ff985a 100644 --- a/drivers/atm/iphase.c +++ b/drivers/atm/iphase.c @@ -3112,14 +3112,6 @@ static int ia_send(struct atm_vcc *vcc, struct sk_buff *skb) } -static int ia_sg_send(struct atm_vcc *vcc, unsigned long start, - unsigned long size) -{ - IF_EVENT(printk(">ia_sg_send\n");) - return 0; -} - - static int ia_proc_read(struct atm_dev *dev,loff_t *pos,char *page) { int left = *pos, n; @@ -3179,7 +3171,6 @@ static const struct atmdev_ops ops = { .getsockopt = ia_getsockopt, .setsockopt = ia_setsockopt, .send = ia_send, - .sg_send = ia_sg_send, .phy_put = ia_phy_put, .phy_get = ia_phy_get, .change_qos = ia_change_qos, diff --git a/drivers/atm/lanai.c b/drivers/atm/lanai.c index ab2c5971aefb..1247846c538f 100644 --- a/drivers/atm/lanai.c +++ b/drivers/atm/lanai.c @@ -2788,11 +2788,8 @@ static const struct atmdev_ops ops = { .getsockopt = NULL, .setsockopt = NULL, .send = lanai_send, - .sg_send = NULL, /* no scatter-gather on card */ - .send_oam = NULL, /* OAM support not in linux yet */ .phy_put = NULL, .phy_get = NULL, - .feedback = NULL, .change_qos = lanai_change_qos, .proc_read = lanai_proc_read }; diff --git a/drivers/atm/zatm.c b/drivers/atm/zatm.c index 77df684887c0..8ea8b49cc784 100644 --- a/drivers/atm/zatm.c +++ b/drivers/atm/zatm.c @@ -307,37 +307,6 @@ static void unuse_pool(struct atm_dev *dev,int pool) drain_free(dev,pool); } - -static void zatm_feedback(struct atm_vcc *vcc,struct sk_buff *skb, - unsigned long start,unsigned long dest,int len) -{ - struct zatm_pool_info *pool; - unsigned long offset,flags; - struct zatm_dev *zatm_dev = ZATM_DEV(vcc->dev); - - DPRINTK("start 0x%08lx dest 0x%08lx len %d\n",start,dest,len); - if (len < PAGE_SIZE) return; - pool = &zatm_dev->pool_info[ZATM_VCC(vcc)->pool]; - offset = (dest-start) & (PAGE_SIZE-1); - spin_lock_irqsave(&zatm_dev->lock, flags); - if (!offset || pool->offset == offset) { - pool->next_cnt = 0; - spin_unlock_irqrestore(&zatm_dev->lock, flags); - return; - } - if (offset != pool->next_off) { - pool->next_off = offset; - pool->next_cnt = 0; - spin_unlock_irqrestore(&zatm_dev->lock, flags); - return; - } - if (++pool->next_cnt >= pool->next_thres) { - pool->offset = pool->next_off; - pool->next_cnt = 0; - } - spin_unlock_irqrestore(&zatm_dev->lock, flags); -} - /*----------------------------------- RX ------------------------------------*/ @@ -1548,17 +1517,6 @@ static int zatm_setsockopt(struct atm_vcc *vcc,int level,int optname, return -EINVAL; } - -#if 0 -static int zatm_sg_send(struct atm_vcc *vcc,unsigned long start, - unsigned long size) -{ - return vcc->aal == ATM_AAL5; - /* @@@ should check size and maybe alignment*/ -} -#endif - - static int zatm_send(struct atm_vcc *vcc,struct sk_buff *skb) { int error; @@ -1615,10 +1573,8 @@ static const struct atmdev_ops ops = { .getsockopt = zatm_getsockopt, .setsockopt = zatm_setsockopt, .send = zatm_send, - /*zatm_sg_send*/ .phy_put = zatm_phy_put, .phy_get = zatm_phy_get, - .feedback = zatm_feedback, .change_qos = zatm_change_qos, }; diff --git a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c index 1c8adc3bd22e..29409d251f1f 100644 --- a/drivers/ieee1394/eth1394.c +++ b/drivers/ieee1394/eth1394.c @@ -502,7 +502,7 @@ static void ether1394_remove_host (struct hpsb_host *host) if (hi->dev) { unregister_netdev (hi->dev); - kfree(hi->dev); + free_netdev(hi->dev); } } diff --git a/drivers/isdn/hysdn/hysdn_net.c b/drivers/isdn/hysdn/hysdn_net.c index abfe601e9eea..af2ea81fce6b 100644 --- a/drivers/isdn/hysdn/hysdn_net.c +++ b/drivers/isdn/hysdn/hysdn_net.c @@ -334,7 +334,7 @@ hysdn_net_release(hysdn_card * card) flush_tx_buffers((struct net_local *) dev); /* empty buffers */ unregister_netdev(dev); /* release the device */ - kfree(dev); /* release the memory allocated */ + free_netdev(dev); /* release the memory allocated */ if (card->debug_flags & LOG_NET_INIT) hysdn_addlog(card, "network device deleted"); diff --git a/drivers/message/fusion/mptlan.c b/drivers/message/fusion/mptlan.c index ed4d0b4b5c55..720a50a84a78 100644 --- a/drivers/message/fusion/mptlan.c +++ b/drivers/message/fusion/mptlan.c @@ -1534,7 +1534,7 @@ static void __exit mpt_lan_exit(void) printk (KERN_INFO ": %s/%s: Fusion MPT LAN device unregistered\n", IOC_AND_NETDEV_NAMES_s_s(dev)); unregister_netdev(dev); - //mpt_landev[i] = (struct net_device *) 0xdeadbeef; /* Debug */ + free_netdev(dev); mpt_landev[i] = NULL; } diff --git a/drivers/net/3c509.c b/drivers/net/3c509.c index 02ddba0865a8..71cbebe5b69e 100644 --- a/drivers/net/3c509.c +++ b/drivers/net/3c509.c @@ -355,7 +355,7 @@ static void el3_common_remove (struct net_device *dev) unregister_netdev (dev); release_region(dev->base_addr, EL3_IO_EXTENT); - kfree (dev); + free_netdev (dev); } static int __init el3_probe(int card_idx) diff --git a/drivers/net/3c515.c b/drivers/net/3c515.c index c7214a926788..977a2fbbf456 100644 --- a/drivers/net/3c515.c +++ b/drivers/net/3c515.c @@ -1676,7 +1676,7 @@ void cleanup_module(void) outw(TotalReset, root_corkscrew_dev->base_addr + EL3_CMD); release_region(root_corkscrew_dev->base_addr, CORKSCREW_TOTAL_SIZE); - kfree(root_corkscrew_dev); + free_netdev(root_corkscrew_dev); root_corkscrew_dev = next_dev; } } diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index 72ca98c3a220..e86b78d1de94 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -1012,7 +1012,7 @@ static int vortex_eisa_remove (struct device *device) outw (TotalReset|0x14, ioaddr + EL3_CMD); release_region (ioaddr, VORTEX_TOTAL_SIZE); - kfree (dev); + free_netdev (dev); return 0; } #endif @@ -3057,7 +3057,7 @@ static void __devexit vortex_remove_one (struct pci_dev *pdev) vp->rx_ring_dma); if (vp->must_free_region) release_region(dev->base_addr, vp->io_size); - kfree(dev); + free_netdev(dev); } @@ -3111,7 +3111,7 @@ static void __exit vortex_eisa_cleanup (void) outw (TotalReset, ioaddr + EL3_CMD); release_region (ioaddr, VORTEX_TOTAL_SIZE); - kfree (compaq_net_device); + free_netdev (compaq_net_device); } } diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c index d1e6832913c3..995bc19afaad 100644 --- a/drivers/net/8139cp.c +++ b/drivers/net/8139cp.c @@ -1969,7 +1969,7 @@ static void __devexit cp_remove_one (struct pci_dev *pdev) pci_release_regions(pdev); pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); - kfree(dev); + free_netdev(dev); } #ifdef CONFIG_PM diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c index 8db88af8becd..9f59b28c4c20 100644 --- a/drivers/net/8139too.c +++ b/drivers/net/8139too.c @@ -723,7 +723,7 @@ static void __rtl8139_cleanup_dev (struct net_device *dev) sizeof (struct rtl8139_private)); #endif /* RTL8139_NDEBUG */ - kfree (dev); + free_netdev(dev); pci_set_drvdata (pdev, NULL); } diff --git a/drivers/net/a2065.c b/drivers/net/a2065.c index b9eda56b056f..2bfc20332c95 100644 --- a/drivers/net/a2065.c +++ b/drivers/net/a2065.c @@ -820,7 +820,7 @@ static void __exit a2065_cleanup(void) release_mem_region(ZTWO_PADDR(dev->base_addr), sizeof(struct lance_regs)); release_mem_region(ZTWO_PADDR(dev->mem_start), A2065_RAM_SIZE); - kfree(dev); + free_netdev(dev); root_a2065_dev = next; } #endif diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c index 7cb53edc35bd..d6a4fdcec957 100644 --- a/drivers/net/acenic.c +++ b/drivers/net/acenic.c @@ -955,7 +955,7 @@ static void __exit ace_module_cleanup(void) } ace_init_cleanup(root_dev); - kfree(root_dev); + free_netdev(root_dev); root_dev = next; } } diff --git a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c index 7c245f7dd66b..19464a83fdfb 100755 --- a/drivers/net/amd8111e.c +++ b/drivers/net/amd8111e.c @@ -1711,7 +1711,7 @@ static void __devexit amd8111e_remove_one(struct pci_dev *pdev) if (dev) { unregister_netdev(dev); iounmap((void *) ((struct amd8111e_priv *)(dev->priv))->mmio); - kfree(dev); + free_netdev(dev); pci_release_regions(pdev); pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); diff --git a/drivers/net/arcnet/arc-rimi.c b/drivers/net/arcnet/arc-rimi.c index 4668ca870292..9530fb4cddd0 100644 --- a/drivers/net/arcnet/arc-rimi.c +++ b/drivers/net/arcnet/arc-rimi.c @@ -345,7 +345,7 @@ void cleanup_module(void) iounmap(lp->mem_start); release_mem_region(dev->mem_start, dev->mem_end - dev->mem_start + 1); kfree(dev->priv); - kfree(dev); + free_netdev(dev); } #else diff --git a/drivers/net/arcnet/com20020.c b/drivers/net/arcnet/com20020.c index 80326bcbedfd..b84a5c0669f1 100644 --- a/drivers/net/arcnet/com20020.c +++ b/drivers/net/arcnet/com20020.c @@ -344,7 +344,7 @@ void com20020_remove(struct net_device *dev) free_irq(dev->irq, dev); release_region(dev->base_addr, ARCNET_TOTAL_SIZE); kfree(dev->priv); - kfree(dev); + free_netdev(dev); } #ifdef MODULE diff --git a/drivers/net/arcnet/com90io.c b/drivers/net/arcnet/com90io.c index 92ad8f6c009b..563b76b006a7 100644 --- a/drivers/net/arcnet/com90io.c +++ b/drivers/net/arcnet/com90io.c @@ -411,7 +411,7 @@ void cleanup_module(void) free_irq(dev->irq, dev); release_region(dev->base_addr, ARCNET_TOTAL_SIZE); kfree(dev->priv); - kfree(dev); + free_netdev(dev); } #else diff --git a/drivers/net/arcnet/com90xx.c b/drivers/net/arcnet/com90xx.c index f87660123972..50d959b300c6 100644 --- a/drivers/net/arcnet/com90xx.c +++ b/drivers/net/arcnet/com90xx.c @@ -639,7 +639,7 @@ static void __exit com90xx_exit(void) release_region(dev->base_addr, ARCNET_TOTAL_SIZE); release_mem_region(dev->mem_start, dev->mem_end - dev->mem_start + 1); kfree(dev->priv); - kfree(dev); + free_netdev(dev); } } diff --git a/drivers/net/ariadne.c b/drivers/net/ariadne.c index 705e7a6c2549..0babdc528932 100644 --- a/drivers/net/ariadne.c +++ b/drivers/net/ariadne.c @@ -852,7 +852,7 @@ static void __exit ariadne_cleanup(void) unregister_netdev(dev); release_mem_region(ZTWO_PADDR(dev->base_addr), sizeof(struct Am79C960)); release_mem_region(ZTWO_PADDR(dev->mem_start), ARIADNE_RAM_SIZE); - kfree(dev); + free_netdev(dev); root_ariadne_dev = next; } #endif diff --git a/drivers/net/arm/ether00.c b/drivers/net/arm/ether00.c index 12816c7ee439..f86ed8b5797f 100644 --- a/drivers/net/arm/ether00.c +++ b/drivers/net/arm/ether00.c @@ -983,7 +983,7 @@ static int ether00_remove_devices(void) unregister_netdev(dev_list[i]); iounmap((void*)dev_list[i]->base_addr); release_mem_region(dev_list[i]->base_addr, MAC_REG_SIZE); - kfree(dev_list[i]); + free_netdev(dev_list[i]); dev_list[i]=0; } } diff --git a/drivers/net/arm/ether1.c b/drivers/net/arm/ether1.c index 6195325d3973..b4b8f5055795 100644 --- a/drivers/net/arm/ether1.c +++ b/drivers/net/arm/ether1.c @@ -1082,7 +1082,7 @@ static void __devexit ether1_remove(struct expansion_card *ec) release_region(dev->base_addr, 16); release_region(dev->base_addr + 0x800, 4096); - kfree(dev); + free_netdev(dev); } static const struct ecard_id ether1_ids[] = { diff --git a/drivers/net/arm/ether3.c b/drivers/net/arm/ether3.c index 8dc62828eaef..d271c74bc52a 100644 --- a/drivers/net/arm/ether3.c +++ b/drivers/net/arm/ether3.c @@ -921,7 +921,7 @@ static void __devexit ether3_remove(struct expansion_card *ec) unregister_netdev(dev); release_region(dev->base_addr, 128); - kfree(dev); + free_netdev(dev); } static const struct ecard_id ether3_ids[] = { diff --git a/drivers/net/arm/etherh.c b/drivers/net/arm/etherh.c index 73c3e9c93e14..4388f7e82b78 100644 --- a/drivers/net/arm/etherh.c +++ b/drivers/net/arm/etherh.c @@ -721,7 +721,7 @@ static void __devexit etherh_remove(struct expansion_card *ec) if (ec->cid.product == PROD_ANT_ETHERM) size <<= 3; release_region(dev->base_addr, size); - kfree(dev); + free_netdev(dev); ec->ops = NULL; kfree(ec->irq_data); diff --git a/drivers/net/atp.c b/drivers/net/atp.c index e22e5553779e..9c36def252a7 100644 --- a/drivers/net/atp.c +++ b/drivers/net/atp.c @@ -943,7 +943,7 @@ static void __exit atp_cleanup_module(void) { next_dev = ((struct net_local *)root_atp_dev->priv)->next_module; unregister_netdev(root_atp_dev); /* No need to release_region(), since we never snarf it. */ - kfree(root_atp_dev); + free_netdev(root_atp_dev); root_atp_dev = next_dev; } } diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c index 4a940aeb370a..b0a8b3793cfc 100644 --- a/drivers/net/au1000_eth.c +++ b/drivers/net/au1000_eth.c @@ -811,7 +811,7 @@ free_region: MAX_BUF_SIZE * (NUM_TX_BUFFS+NUM_RX_BUFFS)); printk(KERN_ERR "%s: au1000_probe1 failed. Returns %d\n", dev->name, retval); - kfree(dev); + free_netdev(dev); return retval; } diff --git a/drivers/net/b44.c b/drivers/net/b44.c index 308c8d567edb..b759af47913d 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -1852,7 +1852,7 @@ static void __devexit b44_remove_one(struct pci_dev *pdev) if (dev) { unregister_netdev(dev); iounmap((void *) ((struct b44 *)(dev->priv))->regs); - kfree(dev); + free_netdev(dev); pci_release_regions(pdev); pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); diff --git a/drivers/net/bmac.c b/drivers/net/bmac.c index cb280081b6da..ed7874f4fe4e 100644 --- a/drivers/net/bmac.c +++ b/drivers/net/bmac.c @@ -1720,7 +1720,7 @@ static void __exit bmac_cleanup (void) free_irq(bp->tx_dma_intr, dev); free_irq(bp->rx_dma_intr, dev); - kfree(dev); + free_netdev(dev); } while (bmac_devs != NULL); } diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 9ef8dab49d2f..a171742fa8cf 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -3892,7 +3892,7 @@ static void __exit bonding_exit(void) remove_proc_entry(dev->name, proc_net); #endif unregister_netdev(dev); - kfree(dev); + free_netdev(dev); } } diff --git a/drivers/net/declance.c b/drivers/net/declance.c index 32a259b04024..905f92d49cad 100644 --- a/drivers/net/declance.c +++ b/drivers/net/declance.c @@ -1244,7 +1244,7 @@ static int __init dec_lance_init(const int type, const int slot) err_out: unregister_netdev(dev); - kfree(dev); + free_netdev(dev); return ret; } @@ -1295,7 +1295,7 @@ static void __exit dec_lance_cleanup(void) #endif root_lance_dev = lp->next; unregister_netdev(dev); - kfree(dev); + free_netdev(dev); } } diff --git a/drivers/net/defxx.c b/drivers/net/defxx.c index b2c31c02d609..52948d2cbad6 100644 --- a/drivers/net/defxx.c +++ b/drivers/net/defxx.c @@ -3376,7 +3376,7 @@ static void __devexit dfx_remove_one_pci_or_eisa(struct pci_dev *pdev, struct ne if (bp->kmalloced) pci_free_consistent(pdev, alloc_size, bp->kmalloced, bp->kmalloced_dma); - kfree(dev); + free_netdev(dev); } static void __devexit dfx_remove_one (struct pci_dev *pdev) diff --git a/drivers/net/dgrs.c b/drivers/net/dgrs.c index 050d3408e964..00ddd19e0fd2 100644 --- a/drivers/net/dgrs.c +++ b/drivers/net/dgrs.c @@ -1337,7 +1337,7 @@ fail: aux = priv->next_dev; dgrs_root_dev = ((DGRS_PRIV *)d->priv)->next_dev; unregister_netdev(d); - kfree(d); + free_netdev(d); } return ret; } @@ -1529,7 +1529,7 @@ static void __exit dgrs_cleanup_module (void) if (dgrs_root_dev->irq) free_irq(dgrs_root_dev->irq, dgrs_root_dev); - kfree(dgrs_root_dev); + free_netdev(dgrs_root_dev); dgrs_root_dev = next_dev; } } diff --git a/drivers/net/dl2k.c b/drivers/net/dl2k.c index f6d0cb277f00..d0fba4cb4df4 100644 --- a/drivers/net/dl2k.c +++ b/drivers/net/dl2k.c @@ -1844,7 +1844,7 @@ rio_remove1 (struct pci_dev *pdev) #ifdef MEM_MAPPING iounmap ((char *) (dev->base_addr)); #endif - kfree (dev); + free_netdev (dev); pci_release_regions (pdev); pci_disable_device (pdev); } diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c index 7739a846cc19..068b22a5ee70 100644 --- a/drivers/net/dummy.c +++ b/drivers/net/dummy.c @@ -107,7 +107,7 @@ static int __init dummy_init_module(void) static void __exit dummy_cleanup_module(void) { unregister_netdev(dev_dummy); - kfree(dev_dummy); + free_netdev(dev_dummy); dev_dummy = NULL; } diff --git a/drivers/net/e100/e100_main.c b/drivers/net/e100/e100_main.c index cc5d2bf33200..d04f63dc4585 100644 --- a/drivers/net/e100/e100_main.c +++ b/drivers/net/e100/e100_main.c @@ -730,7 +730,7 @@ e100_clear_structs(struct net_device *dev) e100_dealloc_space(bdp); pci_set_drvdata(bdp->pdev, NULL); - kfree(dev); + free_netdev(dev); } static void __devexit diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index f744ceb67295..04e8574be205 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -531,7 +531,7 @@ e1000_remove(struct pci_dev *pdev) iounmap(adapter->hw.hw_addr); pci_release_regions(pdev); - kfree(netdev); + free_netdev(netdev); } /** diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c index 446d4e9038a2..2a14f46f6014 100644 --- a/drivers/net/eepro100.c +++ b/drivers/net/eepro100.c @@ -2378,7 +2378,7 @@ static void __devexit eepro100_remove_one (struct pci_dev *pdev) + sizeof(struct speedo_stats), sp->tx_ring, sp->tx_ring_dma); pci_disable_device(pdev); - kfree(dev); + free_netdev(dev); } static struct pci_device_id eepro100_pci_tbl[] = { diff --git a/drivers/net/epic100.c b/drivers/net/epic100.c index 82be5cac83a2..da86ea07fc7c 100644 --- a/drivers/net/epic100.c +++ b/drivers/net/epic100.c @@ -1482,7 +1482,7 @@ static void __devexit epic_remove_one (struct pci_dev *pdev) iounmap((void*) dev->base_addr); #endif pci_release_regions(pdev); - kfree(dev); + free_netdev(dev); pci_set_drvdata(pdev, NULL); /* pci_power_off(pdev, -1); */ } diff --git a/drivers/net/eql.c b/drivers/net/eql.c index c6eb4ff867b8..6f82a2d0236e 100644 --- a/drivers/net/eql.c +++ b/drivers/net/eql.c @@ -607,7 +607,7 @@ static int __init eql_init_module(void) static void __exit eql_cleanup_module(void) { unregister_netdev(dev_eql); - kfree(dev_eql); + free_netdev(dev_eql); } module_init(eql_init_module); diff --git a/drivers/net/ewrk3.c b/drivers/net/ewrk3.c index 99bb5e96366a..bc2402359aee 100644 --- a/drivers/net/ewrk3.c +++ b/drivers/net/ewrk3.c @@ -2097,7 +2097,7 @@ static void ewrk3_exit_module(void) ewrk3_devs[i]->irq = 0; release_region(ewrk3_devs[i]->base_addr, EWRK3_TOTAL_SIZE); - kfree(ewrk3_devs[i]); + free_netdev(ewrk3_devs[i]); ewrk3_devs[i] = NULL; } } diff --git a/drivers/net/fc/iph5526.c b/drivers/net/fc/iph5526.c index fbbc8eaaad15..4762724c8bc0 100644 --- a/drivers/net/fc/iph5526.c +++ b/drivers/net/fc/iph5526.c @@ -4527,7 +4527,7 @@ static void __exit iph5526_exit(void) clean_up_memory(fc[i]); if (dev->priv) kfree(priv); - kfree(dev); + free_netdev(dev); dev = NULL; i++; } diff --git a/drivers/net/fealnx.c b/drivers/net/fealnx.c index ba195cdfb890..3b2d473feedd 100644 --- a/drivers/net/fealnx.c +++ b/drivers/net/fealnx.c @@ -712,7 +712,7 @@ static void __devexit fealnx_remove_one(struct pci_dev *pdev) #ifndef USE_IO_OPS iounmap((void *)dev->base_addr); #endif - kfree(dev); + free_netdev(dev); pci_release_regions(pdev); pci_set_drvdata(pdev, NULL); } else diff --git a/drivers/net/gt96100eth.c b/drivers/net/gt96100eth.c index c4a811740b0b..c25b9fda3f38 100644 --- a/drivers/net/gt96100eth.c +++ b/drivers/net/gt96100eth.c @@ -826,7 +826,7 @@ gt96100_probe1(int port_num) free_region: release_region(gtif->iobase, GT96100_ETH_IO_SIZE); unregister_netdev(dev); - kfree (dev); + free_netdev (dev); err("%s failed. Returns %d\n", __FUNCTION__, retval); return retval; } @@ -1575,7 +1575,7 @@ static void gt96100_cleanup_module(void) (struct gt96100_private *)gtif->dev->priv; release_region(gtif->iobase, gp->io_size); unregister_netdev(gtif->dev); - kfree (gtif->dev); + free_netdev (gtif->dev); } } } diff --git a/drivers/net/hamachi.c b/drivers/net/hamachi.c index a4ad424921b3..36e7074c2bd8 100644 --- a/drivers/net/hamachi.c +++ b/drivers/net/hamachi.c @@ -1976,7 +1976,7 @@ static void __devexit hamachi_remove_one (struct pci_dev *pdev) hmp->tx_ring_dma); unregister_netdev(dev); iounmap((char *)dev->base_addr); - kfree(dev); + free_netdev(dev); pci_release_regions(pdev); pci_set_drvdata(pdev, NULL); } diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c index db6a403ca9c1..735f3525095a 100644 --- a/drivers/net/hamradio/bpqether.c +++ b/drivers/net/hamradio/bpqether.c @@ -482,7 +482,7 @@ static void bpq_setup(struct net_device *dev) dev->set_mac_address = bpq_set_mac_address; dev->get_stats = bpq_get_stats; dev->do_ioctl = bpq_ioctl; - dev->destructor = (void (*)(struct net_device *)) kfree; + dev->destructor = free_netdev; memcpy(dev->broadcast, ax25_bcast, AX25_ADDR_LEN); memcpy(dev->dev_addr, ax25_defaddr, AX25_ADDR_LEN); diff --git a/drivers/net/hamradio/scc.c b/drivers/net/hamradio/scc.c index 1c5de989caaf..bc0cca8c8463 100644 --- a/drivers/net/hamradio/scc.c +++ b/drivers/net/hamradio/scc.c @@ -2121,7 +2121,7 @@ static void __exit scc_cleanup_driver(void) if (Nchips == 0) { unregister_netdev(SCC_Info[0].dev); - kfree(SCC_Info[0].dev); + free_netdev(SCC_Info[0].dev); } /* Guard against chip prattle */ @@ -2153,7 +2153,7 @@ static void __exit scc_cleanup_driver(void) if (scc->dev) { unregister_netdev(scc->dev); - kfree(scc->dev); + free_netdev(scc->dev); } } diff --git a/drivers/net/hamradio/yam.c b/drivers/net/hamradio/yam.c index 59a2965d4b88..1b7f468e363d 100644 --- a/drivers/net/hamradio/yam.c +++ b/drivers/net/hamradio/yam.c @@ -1176,7 +1176,7 @@ static int __init yam_init_driver(void) error: while (--i >= 0) { unregister_netdev(yam_devs[i]); - kfree(yam_devs[i]); + free_netdev(yam_devs[i]); } return err; } diff --git a/drivers/net/hp100.c b/drivers/net/hp100.c index c8f1751d0ebf..f45719a216c2 100644 --- a/drivers/net/hp100.c +++ b/drivers/net/hp100.c @@ -2965,7 +2965,7 @@ static void release_dev(int i) iounmap(p->mem_ptr_virt); kfree(d->priv); d->priv = NULL; - kfree(d); + free_netdev(d); hp100_devlist[i] = NULL; } diff --git a/drivers/net/hplance.c b/drivers/net/hplance.c index 29aa6abced63..98cb52f11742 100644 --- a/drivers/net/hplance.c +++ b/drivers/net/hplance.c @@ -239,7 +239,7 @@ void cleanup_module(void) lp = root_hplance_dev->next_module; dio_unconfig_board(lp->scode); unregister_netdev(root_lance_dev->dev); - kfree(root_lance_dev->dev); + free_netdev(root_lance_dev->dev); root_lance_dev = lp; } } diff --git a/drivers/net/hydra.c b/drivers/net/hydra.c index 18f026ba1397..b183b1159bd5 100644 --- a/drivers/net/hydra.c +++ b/drivers/net/hydra.c @@ -226,7 +226,7 @@ static void __exit hydra_cleanup(void) unregister_netdev(dev); free_irq(IRQ_AMIGA_PORTS, dev); release_mem_region(ZTWO_PADDR(dev->base_addr)-HYDRA_NIC_BASE, 0x10000); - kfree(dev); + free_netdev(dev); root_hydra_dev = next; } } diff --git a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c index 4cdcc1655178..c3b4e5f1353d 100644 --- a/drivers/net/ioc3-eth.c +++ b/drivers/net/ioc3-eth.c @@ -1525,7 +1525,7 @@ static void __devexit ioc3_remove_one (struct pci_dev *pdev) unregister_netdev(dev); iounmap(ioc3); pci_release_regions(pdev); - kfree(dev); + free_netdev(dev); } static struct pci_device_id ioc3_pci_tbl[] = { diff --git a/drivers/net/irda/Kconfig b/drivers/net/irda/Kconfig index 705f95c0cf8d..1b5bfb454334 100644 --- a/drivers/net/irda/Kconfig +++ b/drivers/net/irda/Kconfig @@ -68,20 +68,6 @@ config TEKRAM_DONGLE comment "Old SIR device drivers" -config IRTTY_OLD - tristate "Old IrTTY (broken)" - depends on IRDA && EXPERIMENTAL - help - Say Y here if you want to build support for the IrTTY line - discipline. If you want to compile it as a module (irtty), say M - here and read <file:Documentation/modules.txt>. IrTTY makes it - possible to use Linux's own serial driver for all IrDA ports that - are 16550 compatible. Most IrDA chips are 16550 compatible so you - should probably say Y to this option. Using IrTTY will however - limit the speed of the connection to 115200 bps (IrDA SIR mode). - - If unsure, say N. - config IRPORT_SIR tristate "IrPORT (IrDA serial driver)" depends on IRDA diff --git a/drivers/net/irda/Makefile b/drivers/net/irda/Makefile index 9d656e1993f3..a05395e2dcd1 100644 --- a/drivers/net/irda/Makefile +++ b/drivers/net/irda/Makefile @@ -5,8 +5,7 @@ # Rewritten to use lists instead of if-statements. # -# Old SIR drivers (irtty is broken) -obj-$(CONFIG_IRTTY_OLD) += irtty.o +# Old SIR drivers obj-$(CONFIG_IRPORT_SIR) += irport.o # FIR drivers obj-$(CONFIG_USB_IRDA) += irda-usb.o diff --git a/drivers/net/irda/irtty.c b/drivers/net/irda/irtty.c deleted file mode 100644 index de24aeb1b235..000000000000 --- a/drivers/net/irda/irtty.c +++ /dev/null @@ -1,1077 +0,0 @@ -/********************************************************************* - * - * Filename: irtty.c - * Version: 1.1 - * Description: IrDA line discipline implementation - * Status: Experimental. - * Author: Dag Brattli <dagb@cs.uit.no> - * Created at: Tue Dec 9 21:18:38 1997 - * Modified at: Sat Mar 11 07:43:30 2000 - * Modified by: Dag Brattli <dagb@cs.uit.no> - * Sources: slip.c by Laurence Culhane, <loz@holmes.demon.co.uk> - * Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org> - * - * Copyright (c) 1998-2000 Dag Brattli, All Rights Reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * Neither Dag Brattli nor University of Tromsø admit liability nor - * provide warranty for any of this software. This material is - * provided "AS-IS" and at no charge. - * - ********************************************************************/ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/tty.h> -#include <linux/init.h> -#include <linux/skbuff.h> -#include <linux/if_arp.h> -#include <linux/rtnetlink.h> - -#include <asm/uaccess.h> - -#include <net/irda/irda.h> -#include <net/irda/irtty.h> -#include <net/irda/wrapper.h> -#include <net/irda/irda_device.h> - -static int qos_mtt_bits = 0x03; /* 5 ms or more */ - -/* Network device fuction prototypes */ -static int irtty_hard_xmit(struct sk_buff *skb, struct net_device *dev); -static int irtty_net_init(struct net_device *dev); -static int irtty_net_open(struct net_device *dev); -static int irtty_net_close(struct net_device *dev); -static int irtty_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); -static struct net_device_stats *irtty_net_get_stats(struct net_device *dev); - -/* Line discipline function prototypes */ -static int irtty_open(struct tty_struct *tty); -static void irtty_close(struct tty_struct *tty); -static int irtty_ioctl(struct tty_struct *, struct file *, - unsigned int, unsigned long); -static int irtty_receive_room(struct tty_struct *tty); -static void irtty_write_wakeup(struct tty_struct *tty); -static void irtty_receive_buf(struct tty_struct *, const unsigned char *, - char *, int); - -/* IrDA specific function protoctypes */ -static int irtty_is_receiving(struct irtty_cb *self); -static int irtty_set_dtr_rts(struct net_device *dev, int dtr, int rts); -static int irtty_raw_write(struct net_device *dev, __u8 *buf, int len); -static int irtty_raw_read(struct net_device *dev, __u8 *buf, int len); -static int irtty_set_mode(struct net_device *dev, int mode); -static int irtty_change_speed(struct irda_task *task); - -static struct tty_ldisc irda_ldisc = { - .owner = THIS_MODULE, - .magic = TTY_LDISC_MAGIC, - .name = "irda", - .open = irtty_open, - .close = irtty_close, - .ioctl = irtty_ioctl, - .receive_buf = irtty_receive_buf, - .receive_room = irtty_receive_room, - .write_wakeup = irtty_write_wakeup, -}; - -int __init irtty_init(void) -{ - int status; - - if ((status = tty_register_ldisc(N_IRDA, &irda_ldisc)) != 0) { - ERROR("IrDA: can't register line discipline (err = %d)\n", - status); - } - - return status; -} - -/* - * Function irtty_cleanup ( ) - * - * Called when the irda module is removed. Here we remove all instances - * of the driver, and the master array. - */ -static void __exit irtty_cleanup(void) -{ - int ret; - - /* Unregister tty line-discipline */ - if ((ret = tty_register_ldisc(N_IRDA, NULL))) { - ERROR("%s(), can't unregister line discipline (err = %d)\n", - __FUNCTION__, ret); - } - -} - -/* - * Function irtty_open(tty) - * - * This function is called by the TTY module when the IrDA line - * discipline is called for. Because we are sure the tty line exists, - * we only have to link it to a free IrDA channel. - */ -static int irtty_open(struct tty_struct *tty) -{ - struct net_device *dev; - struct irtty_cb *self; - char name[16]; - int err; - - ASSERT(tty != NULL, return -EEXIST;); - - /* First make sure we're not already connected. */ - self = (struct irtty_cb *) tty->disc_data; - - if (self != NULL && self->magic == IRTTY_MAGIC) - return -EEXIST; - - /* - * Allocate new instance of the driver - */ - self = kmalloc(sizeof(struct irtty_cb), GFP_KERNEL); - if (self == NULL) { - printk(KERN_ERR "IrDA: Can't allocate memory for " - "IrDA control block!\n"); - return -ENOMEM; - } - memset(self, 0, sizeof(struct irtty_cb)); - spin_lock_init(&self->lock); - - self->tty = tty; - tty->disc_data = self; - - /* Give self a name */ - strcpy(name, tty->name); - - if (tty->driver->flush_buffer) - tty->driver->flush_buffer(tty); - - if (tty->ldisc.flush_buffer) - tty->ldisc.flush_buffer(tty); - - self->magic = IRTTY_MAGIC; - self->mode = IRDA_IRLAP; - - /* - * Initialize QoS capabilities, we fill in all the stuff that - * we support. Be careful not to place any restrictions on values - * that are not device dependent (such as link disconnect time) so - * this parameter can be set by IrLAP (or the user) instead. DB - */ - irda_init_max_qos_capabilies(&self->qos); - - /* The only value we must override it the baudrate */ - self->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600| - IR_115200; - self->qos.min_turn_time.bits = qos_mtt_bits; - self->flags = IFF_SIR | IFF_PIO; - irda_qos_bits_to_value(&self->qos); - - /* Specify how much memory we want */ - self->rx_buff.truesize = 4000; - self->tx_buff.truesize = 4000; - - /* Allocate memory if needed */ - if (self->rx_buff.truesize > 0) { - self->rx_buff.head = (__u8 *) kmalloc(self->rx_buff.truesize, - GFP_KERNEL); - if (self->rx_buff.head == NULL) - return -ENOMEM; - memset(self->rx_buff.head, 0, self->rx_buff.truesize); - } - if (self->tx_buff.truesize > 0) { - self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize, - GFP_KERNEL); - if (self->tx_buff.head == NULL) { - kfree(self->rx_buff.head); - return -ENOMEM; - } - memset(self->tx_buff.head, 0, self->tx_buff.truesize); - } - - self->rx_buff.in_frame = FALSE; - self->rx_buff.state = OUTSIDE_FRAME; - self->tx_buff.data = self->tx_buff.head; - self->rx_buff.data = self->rx_buff.head; - - if (!(dev = dev_alloc("irda%d", &err))) { - ERROR("%s(), dev_alloc() failed!\n", __FUNCTION__); - return -ENOMEM; - } - - dev->priv = (void *) self; - self->netdev = dev; - - /* Override the network functions we need to use */ - dev->init = irtty_net_init; - dev->hard_start_xmit = irtty_hard_xmit; - dev->open = irtty_net_open; - dev->stop = irtty_net_close; - dev->get_stats = irtty_net_get_stats; - dev->do_ioctl = irtty_net_ioctl; - - rtnl_lock(); - err = register_netdevice(dev); - rtnl_unlock(); - if (err) { - ERROR("%s(), register_netdev() failed!\n", __FUNCTION__); - return -1; - } - - MESSAGE("IrDA: Registered device %s\n", dev->name); - - return 0; -} - -/* - * Function irtty_close (tty) - * - * Close down a IrDA channel. This means flushing out any pending queues, - * and then restoring the TTY line discipline to what it was before it got - * hooked to IrDA (which usually is TTY again). - */ -static void irtty_close(struct tty_struct *tty) -{ - struct irtty_cb *self = (struct irtty_cb *) tty->disc_data; - unsigned long flags; - - /* First make sure we're connected. */ - ASSERT(self != NULL, return;); - ASSERT(self->magic == IRTTY_MAGIC, return;); - - /* Stop tty */ - tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP); - tty->disc_data = 0; - - /* We are not using any dongle anymore! */ - if (self->dongle) - irda_device_dongle_cleanup(self->dongle); - self->dongle = NULL; - - /* Remove netdevice */ - if (self->netdev) - unregister_netdev(self->netdev); - - /* Protect access to self->task and self->?x_buff - Jean II */ - spin_lock_irqsave(&self->lock, flags); - - /* Remove speed changing task if any */ - if (self->task) - irda_task_delete(self->task); - - self->tty = NULL; - self->magic = 0; - - if (self->tx_buff.head) - kfree(self->tx_buff.head); - - if (self->rx_buff.head) - kfree(self->rx_buff.head); - spin_unlock_irqrestore(&self->lock, flags); - - kfree(self); -} - -/* - * Function irtty_stop_receiver (self, stop) - * - * - * - */ -static void irtty_stop_receiver(struct irtty_cb *self, int stop) -{ - struct termios old_termios; - int cflag; - - old_termios = *(self->tty->termios); - cflag = self->tty->termios->c_cflag; - - if (stop) - cflag &= ~CREAD; - else - cflag |= CREAD; - - /* This is unsafe, but currently under discussion - Jean II */ - self->tty->termios->c_cflag = cflag; - self->tty->driver->set_termios(self->tty, &old_termios); -} - -/* - * Function irtty_do_change_speed (self, speed) - * - * Change the speed of the serial port. - */ -static void __irtty_change_speed(struct irtty_cb *self, __u32 speed) -{ - struct termios old_termios; - int cflag; - - ASSERT(self != NULL, return;); - ASSERT(self->magic == IRTTY_MAGIC, return;); - - old_termios = *(self->tty->termios); - cflag = self->tty->termios->c_cflag; - - cflag &= ~CBAUD; - - IRDA_DEBUG(2, "%s(), Setting speed to %d\n", __FUNCTION__, speed); - - switch (speed) { - case 1200: - cflag |= B1200; - break; - case 2400: - cflag |= B2400; - break; - case 4800: - cflag |= B4800; - break; - case 19200: - cflag |= B19200; - break; - case 38400: - cflag |= B38400; - break; - case 57600: - cflag |= B57600; - break; - case 115200: - cflag |= B115200; - break; - case 9600: - default: - cflag |= B9600; - break; - } - - /* This is unsafe, but currently under discussion - Jean II */ - self->tty->termios->c_cflag = cflag; - self->tty->driver->set_termios(self->tty, &old_termios); - - self->io.speed = speed; -} - -/* - * Function irtty_change_speed (instance, state, param) - * - * State machine for changing speed of the device. We do it this way since - * we cannot use schedule_timeout() when we are in interrupt context - */ -static int irtty_change_speed(struct irda_task *task) -{ - struct irtty_cb *self; - unsigned long flags; - __u32 speed = (__u32) task->param; - int ret = 0; - - IRDA_DEBUG(2, "%s(), <%ld>\n", __FUNCTION__, jiffies); - - self = (struct irtty_cb *) task->instance; - ASSERT(self != NULL, return -1;); - - /* Protect access to self->task - Jean II */ - spin_lock_irqsave(&self->lock, flags); - - /* Check if busy */ - if (self->task && self->task != task) { - IRDA_DEBUG(0, "%s(), busy!\n", __FUNCTION__); - spin_unlock_irqrestore(&self->lock, flags); - return MSECS_TO_JIFFIES(10); - } else - self->task = task; - spin_unlock_irqrestore(&self->lock, flags); - - switch (task->state) { - case IRDA_TASK_INIT: - /* - * Make sure all data is sent before changing the speed of the - * serial port. - */ - if (self->tty->driver->chars_in_buffer(self->tty)) { - /* Keep state, and try again later */ - ret = MSECS_TO_JIFFIES(10); - break; - } else { - /* Transmit buffer is now empty, but it may still - * take over 13 ms for the FIFO to become empty, so - * wait some more to be sure all data is sent - */ - irda_task_next_state(task, IRDA_TASK_WAIT); - ret = MSECS_TO_JIFFIES(13); - } - case IRDA_TASK_WAIT: - if (self->dongle) - irda_task_next_state(task, IRDA_TASK_CHILD_INIT); - else - irda_task_next_state(task, IRDA_TASK_CHILD_DONE); - break; - case IRDA_TASK_CHILD_INIT: - /* Go to default speed */ - __irtty_change_speed(self, 9600); - - /* Change speed of dongle */ - if (irda_task_execute(self->dongle, - self->dongle->issue->change_speed, - NULL, task, (void *) speed)) - { - /* Dongle need more time to change its speed */ - irda_task_next_state(task, IRDA_TASK_CHILD_WAIT); - - /* Give dongle 1 sec to finish */ - ret = MSECS_TO_JIFFIES(1000); - } else - /* Child finished immediately */ - irda_task_next_state(task, IRDA_TASK_CHILD_DONE); - break; - case IRDA_TASK_CHILD_WAIT: - WARNING("%s(), changing speed of dongle timed out!\n", __FUNCTION__); - ret = -1; - break; - case IRDA_TASK_CHILD_DONE: - /* Finally we are ready to change the speed */ - __irtty_change_speed(self, speed); - - irda_task_next_state(task, IRDA_TASK_DONE); - self->task = NULL; - break; - default: - ERROR("%s(), unknown state %d\n", __FUNCTION__, task->state); - irda_task_next_state(task, IRDA_TASK_DONE); - self->task = NULL; - ret = -1; - break; - } - return ret; -} - -/* - * Function irtty_ioctl (tty, file, cmd, arg) - * - * The Swiss army knife of system calls :-) - * - */ -static int irtty_ioctl(struct tty_struct *tty, struct file *file, - unsigned int cmd, unsigned long arg) -{ - dongle_t *dongle; - struct irtty_info info; - struct irtty_cb *self; - int size = _IOC_SIZE(cmd); - int err = 0; - - self = (struct irtty_cb *) tty->disc_data; - - ASSERT(self != NULL, return -ENODEV;); - ASSERT(self->magic == IRTTY_MAGIC, return -EBADR;); - - if (_IOC_DIR(cmd) & _IOC_READ) - err = verify_area(VERIFY_WRITE, (void *) arg, size); - else if (_IOC_DIR(cmd) & _IOC_WRITE) - err = verify_area(VERIFY_READ, (void *) arg, size); - if (err) - return err; - - switch (cmd) { - case TCGETS: - case TCGETA: - /* Unsure about locking here, to check - Jean II */ - return n_tty_ioctl(tty, (struct file *) file, cmd, arg); - break; - case IRTTY_IOCTDONGLE: - /* Initialize dongle */ - dongle = irda_device_dongle_init(self->netdev, (int) arg); - if (!dongle) - break; - - /* Initialize callbacks */ - dongle->set_mode = irtty_set_mode; - dongle->read = irtty_raw_read; - dongle->write = irtty_raw_write; - dongle->set_dtr_rts = irtty_set_dtr_rts; - - /* Now initialize the dongle! */ - dongle->issue->open(dongle, &self->qos); - - /* Reset dongle */ - irda_task_execute(dongle, dongle->issue->reset, NULL, NULL, - NULL); - - /* Make dongle available to driver only now to avoid - * race conditions - Jean II */ - self->dongle = dongle; - break; - case IRTTY_IOCGET: - ASSERT(self->netdev != NULL, return -1;); - - memset(&info, 0, sizeof(struct irtty_info)); - strncpy(info.name, self->netdev->name, 5); - - if (copy_to_user((void *) arg, &info, sizeof(struct irtty_info))) - return -EFAULT; - break; - default: - return -ENOIOCTLCMD; - } - return 0; -} - -/* - * Function irtty_receive_buf( tty, cp, count) - * - * Handle the 'receiver data ready' interrupt. This function is called - * by the 'tty_io' module in the kernel when a block of IrDA data has - * been received, which can now be decapsulated and delivered for - * further processing - */ -static void irtty_receive_buf(struct tty_struct *tty, const unsigned char *cp, - char *fp, int count) -{ - struct irtty_cb *self = (struct irtty_cb *) tty->disc_data; - - if (!self || !self->netdev) { - IRDA_DEBUG(0, "%s(), not ready yet!\n", __FUNCTION__); - return; - } - - // Are we in interrupt context ? What locking is done ? - Jean II - //spin_lock_irqsave(&self->lock, flags); - - /* Read the characters out of the buffer */ - while (count--) { - /* - * Characters received with a parity error, etc? - */ - if (fp && *fp++) { - IRDA_DEBUG(0, "Framing or parity error!\n"); - irda_device_set_media_busy(self->netdev, TRUE); - - cp++; - continue; - } - - switch (self->mode) { - case IRDA_IRLAP: - /* Unwrap and destuff one byte */ - async_unwrap_char(self->netdev, &self->stats, - &self->rx_buff, *cp++); - break; - case IRDA_RAW: - /* What should we do when the buffer is full? */ - if (self->rx_buff.len == self->rx_buff.truesize) - self->rx_buff.len = 0; - - self->rx_buff.data[self->rx_buff.len++] = *cp++; - break; - default: - break; - } - } - //spin_unlock_irqrestore(&self->lock, flags); -} - -/* - * Function irtty_change_speed_complete (task) - * - * Called when the change speed operation completes - * - */ -static int irtty_change_speed_complete(struct irda_task *task) -{ - struct irtty_cb *self; - - IRDA_DEBUG(2, "%s()\n", __FUNCTION__); - - self = (struct irtty_cb *) task->instance; - - ASSERT(self != NULL, return -1;); - ASSERT(self->netdev != NULL, return -1;); - - /* Finished changing speed, so we are not busy any longer */ - /* Signal network layer so it can try to send the frame */ - netif_wake_queue(self->netdev); - - return 0; -} - -/* - * Function irtty_hard_xmit (skb, dev) - * - * Transmit frame - * - */ -static int irtty_hard_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct irtty_cb *self; - int actual = 0; - __s32 speed; - unsigned long flags; - - self = (struct irtty_cb *) dev->priv; - ASSERT(self != NULL, return 0;); - - /* Lock transmit buffer - * this serialise operations, no need to spinlock - Jean II */ - netif_stop_queue(dev); - - /* Check if we need to change the speed */ - speed = irda_get_next_speed(skb); - if ((speed != self->io.speed) && (speed != -1)) { - /* Check for empty frame */ - if (!skb->len) { - irda_task_execute(self, irtty_change_speed, - irtty_change_speed_complete, - NULL, (void *) speed); - dev_kfree_skb(skb); - return 0; - } else - self->new_speed = speed; - } - - /* Protect access to self->tx_buff - Jean II */ - spin_lock_irqsave(&self->lock, flags); - - /* Init tx buffer*/ - self->tx_buff.data = self->tx_buff.head; - - /* Copy skb to tx_buff while wrapping, stuffing and making CRC */ - self->tx_buff.len = async_wrap_skb(skb, self->tx_buff.data, - self->tx_buff.truesize); - - self->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP); - - dev->trans_start = jiffies; - self->stats.tx_bytes += self->tx_buff.len; - - if (self->tty->driver->write) - actual = self->tty->driver->write(self->tty, 0, - self->tx_buff.data, - self->tx_buff.len); - /* Hide the part we just transmitted */ - self->tx_buff.data += actual; - self->tx_buff.len -= actual; - - spin_unlock_irqrestore(&self->lock, flags); - - dev_kfree_skb(skb); - - return 0; -} - -/* - * Function irtty_receive_room (tty) - * - * Used by the TTY to find out how much data we can receive at a time - * -*/ -static int irtty_receive_room(struct tty_struct *tty) -{ - IRDA_DEBUG(0, "%s()\n", __FUNCTION__); - return 65536; /* We can handle an infinite amount of data. :-) */ -} - -/* - * Function irtty_write_wakeup (tty) - * - * Called by the driver when there's room for more data. If we have - * more packets to send, we send them here. - * - */ -static void irtty_write_wakeup(struct tty_struct *tty) -{ - struct irtty_cb *self = (struct irtty_cb *) tty->disc_data; - int actual = 0; - unsigned long flags; - - /* - * First make sure we're connected. - */ - ASSERT(self != NULL, return;); - ASSERT(self->magic == IRTTY_MAGIC, return;); - - /* Protected via netif_stop_queue(dev); - Jean II */ - - /* Protect access to self->tx_buff - Jean II */ - spin_lock_irqsave(&self->lock, flags); - - /* Finished with frame? */ - if (self->tx_buff.len > 0) { - /* Write data left in transmit buffer */ - actual = tty->driver->write(tty, 0, self->tx_buff.data, - self->tx_buff.len); - - self->tx_buff.data += actual; - self->tx_buff.len -= actual; - spin_unlock_irqrestore(&self->lock, flags); - } else { - /* - * Now serial buffer is almost free & we can start - * transmission of another packet - */ - IRDA_DEBUG(5, "%s(), finished with frame!\n", __FUNCTION__); - - self->stats.tx_packets++; - - tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP); - - /* Don't change speed with irq off */ - spin_unlock_irqrestore(&self->lock, flags); - - if (self->new_speed) { - IRDA_DEBUG(5, "%s(), Changing speed!\n", __FUNCTION__); - irda_task_execute(self, irtty_change_speed, - irtty_change_speed_complete, - NULL, (void *) self->new_speed); - self->new_speed = 0; - } else { - /* Tell network layer that we want more frames */ - netif_wake_queue(self->netdev); - } - } -} - -/* - * Function irtty_is_receiving (self) - * - * Return TRUE is we are currently receiving a frame - * - */ -static int irtty_is_receiving(struct irtty_cb *self) -{ - return (self->rx_buff.state != OUTSIDE_FRAME); -} - -/* - * Function irtty_set_dtr_rts (tty, dtr, rts) - * - * This function can be used by dongles etc. to set or reset the status - * of the dtr and rts lines - */ -static int irtty_set_dtr_rts(struct net_device *dev, int dtr, int rts) -{ - struct irtty_cb *self; - struct tty_struct *tty; - //unsigned long flags; - mm_segment_t fs; - int arg = 0; - - self = (struct irtty_cb *) dev->priv; - tty = self->tty; - - /* Was protected in ioctl handler, but the serial driver doesn't - * like it. This may need to change. - Jean II */ - //spin_lock_irqsave(&self->lock, flags); - -#ifdef TIOCM_OUT2 /* Not defined for ARM */ - arg = TIOCM_OUT2; -#endif - if (rts) - arg |= TIOCM_RTS; - if (dtr) - arg |= TIOCM_DTR; - - /* - * The ioctl() function, or actually set_modem_info() in serial.c - * expects a pointer to the argument in user space. To hack us - * around this, we use the set_fs() function to fool the routines - * that check if they are called from user space. We also need - * to send a pointer to the argument so get_user() gets happy. DB. - */ - - fs = get_fs(); - set_fs(get_ds()); - - /* This is probably unsafe, but currently under discussion - Jean II */ - if (tty->driver->ioctl(tty, NULL, TIOCMSET, (unsigned long) &arg)) { - IRDA_DEBUG(2, "%s(), error doing ioctl!\n", __FUNCTION__); - } - set_fs(fs); - - //spin_unlock_irqrestore(&self->lock, flags); - - return 0; -} - -/* - * Function irtty_set_mode (self, status) - * - * For the airport dongle, we need support for reading raw characters - * from the IrDA device. This function switches between those modes. - * FALSE is the default mode, and will then treat incoming data as IrDA - * packets. - */ -int irtty_set_mode(struct net_device *dev, int mode) -{ - struct irtty_cb *self; - unsigned long flags; - - self = (struct irtty_cb *) dev->priv; - - ASSERT(self != NULL, return -1;); - - IRDA_DEBUG(2, "%s(), mode=%s\n", __FUNCTION__, infrared_mode[mode]); - - /* Protect access to self->rx_buff - Jean II */ - spin_lock_irqsave(&self->lock, flags); - - /* save status for driver */ - self->mode = mode; - - /* reset the buffer state */ - self->rx_buff.data = self->rx_buff.head; - self->rx_buff.len = 0; - self->rx_buff.state = OUTSIDE_FRAME; - - spin_unlock_irqrestore(&self->lock, flags); - - return 0; -} - -/* - * Function irtty_raw_read (self, buf, len) - * - * Receive incoming data. This function sleeps, so it must only be - * called with a process context. Timeout is currently defined to be - * a multiple of 10 ms. - */ -static int irtty_raw_read(struct net_device *dev, __u8 *buf, int len) -{ - struct irtty_cb *self; - int count; - - self = (struct irtty_cb *) dev->priv; - - ASSERT(self != NULL, return 0;); - ASSERT(self->magic == IRTTY_MAGIC, return 0;); - - return 0; -#if 0 - buf = self->rx_buff.data; - - /* Wait for the requested amount of data to arrive */ - while (len < self->rx_buff.len) { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(MSECS_TO_JIFFIES(10)); - - if (!timeout--) - break; - } - - count = self->rx_buff.len < len ? self->rx_buff.len : len; - - /* - * Reset the state, this mean that a raw read is sort of a - * datagram read, and _not_ a stream style read. Be aware of the - * difference. Implementing it the other way will just be painful ;-) - */ - self->rx_buff.data = self->rx_buff.head; - self->rx_buff.len = 0; - self->rx_buff.state = OUTSIDE_FRAME; -#endif - /* Return the amount we were able to get */ - return count; -} - -static int irtty_raw_write(struct net_device *dev, __u8 *buf, int len) -{ - struct irtty_cb *self; - int actual = 0; - - self = (struct irtty_cb *) dev->priv; - - ASSERT(self != NULL, return 0;); - ASSERT(self->magic == IRTTY_MAGIC, return 0;); - - if (self->tty->driver->write) - actual = self->tty->driver->write(self->tty, 0, buf, len); - - return actual; -} - -static int irtty_net_init(struct net_device *dev) -{ - /* Set up to be a normal IrDA network device driver */ - irda_device_setup(dev); - - /* Insert overrides below this line! */ - - return 0; -} - -static int irtty_net_open(struct net_device *dev) -{ - struct irtty_cb *self = (struct irtty_cb *) dev->priv; - struct tty_struct *tty = self->tty; - - ASSERT(self != NULL, return -1;); - ASSERT(self->magic == IRTTY_MAGIC, return -1;); - - IRDA_DEBUG(0, "%s()\n", __FUNCTION__); - - /* Ready to play! */ - netif_start_queue(dev); - - /* Make sure we can receive more data */ - irtty_stop_receiver(self, FALSE); - - /* - * Open new IrLAP layer instance, now that everything should be - * initialized properly - */ - self->irlap = irlap_open(dev, &self->qos, tty->name); - - return 0; -} - -static int irtty_net_close(struct net_device *dev) -{ - struct irtty_cb *self = (struct irtty_cb *) dev->priv; - - ASSERT(self != NULL, return -1;); - ASSERT(self->magic == IRTTY_MAGIC, return -1;); - - /* Make sure we don't receive more data */ - irtty_stop_receiver(self, TRUE); - - /* Stop device */ - netif_stop_queue(dev); - - /* Stop and remove instance of IrLAP */ - if (self->irlap) - irlap_close(self->irlap); - self->irlap = NULL; - - return 0; -} - -/* - * Function irtty_net_ioctl (dev, rq, cmd) - * - * Process IOCTL commands for this device - * - */ -static int irtty_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - struct if_irda_req *irq = (struct if_irda_req *) rq; - struct irtty_cb *self; - dongle_t *dongle; - int ret = 0; - - ASSERT(dev != NULL, return -1;); - - self = dev->priv; - - ASSERT(self != NULL, return -1;); - ASSERT(self->magic == IRTTY_MAGIC, return -1;); - - IRDA_DEBUG(3, "%s(), %s, (cmd=0x%X)\n", __FUNCTION__, dev->name, cmd); - - /* Locking : - * irda_device_dongle_init() can't be locked. - * irda_task_execute() doesn't need to be locked (but - * irtty_change_speed() should protect itself). - * Other calls protect themselves. - * Jean II - */ - - switch (cmd) { - case SIOCSBANDWIDTH: /* Set bandwidth */ - if (!capable(CAP_NET_ADMIN)) - ret = -EPERM; - else - irda_task_execute(self, irtty_change_speed, NULL, NULL, - (void *) irq->ifr_baudrate); - break; - case SIOCSDONGLE: /* Set dongle */ - if (!capable(CAP_NET_ADMIN)) { - ret = -EPERM; - break; - } - - /* Initialize dongle */ - dongle = irda_device_dongle_init(dev, irq->ifr_dongle); - if (!dongle) - break; - - dongle->set_mode = irtty_set_mode; - dongle->read = irtty_raw_read; - dongle->write = irtty_raw_write; - dongle->set_dtr_rts = irtty_set_dtr_rts; - - /* Now initialize the dongle! - * Safe to do unlocked : self->dongle is still NULL. */ - dongle->issue->open(dongle, &self->qos); - - /* Reset dongle */ - irda_task_execute(dongle, dongle->issue->reset, NULL, NULL, - NULL); - - /* Make dongle available to driver only now to avoid - * race conditions - Jean II */ - self->dongle = dongle; - break; - case SIOCSMEDIABUSY: /* Set media busy */ - if (!capable(CAP_NET_ADMIN)) - ret = -EPERM; - else - irda_device_set_media_busy(self->netdev, TRUE); - break; - case SIOCGRECEIVING: /* Check if we are receiving right now */ - irq->ifr_receiving = irtty_is_receiving(self); - break; - case SIOCSDTRRTS: - if (!capable(CAP_NET_ADMIN)) - ret = -EPERM; - else { - irtty_set_dtr_rts(dev, irq->ifr_dtr, irq->ifr_rts); - } - break; - case SIOCSMODE: - if (!capable(CAP_NET_ADMIN)) - ret = -EPERM; - else { - irtty_set_mode(dev, irq->ifr_mode); - } - break; - default: - ret = -EOPNOTSUPP; - } - - return ret; -} - -static struct net_device_stats *irtty_net_get_stats(struct net_device *dev) -{ - struct irtty_cb *self = (struct irtty_cb *) dev->priv; - - return &self->stats; -} - -MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>"); -MODULE_DESCRIPTION("IrDA TTY device driver"); -MODULE_LICENSE("GPL"); - - -MODULE_PARM(qos_mtt_bits, "i"); -MODULE_PARM_DESC(qos_mtt_bits, "Minimum Turn Time"); - -/* - * Function init_module (void) - * - * Initialize IrTTY module - * - */ -module_init(irtty_init); - -/* - * Function cleanup_module (void) - * - * Cleanup IrTTY module - * - */ -module_exit(irtty_cleanup); diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c index 805af3253ff4..6f176bf3ce53 100644 --- a/drivers/net/ixgb/ixgb_main.c +++ b/drivers/net/ixgb/ixgb_main.c @@ -478,7 +478,7 @@ ixgb_remove(struct pci_dev *pdev) iounmap((void *) adapter->hw.hw_addr); pci_release_regions(pdev); - kfree(netdev); + free_netdev(netdev); } /** diff --git a/drivers/net/lasi_82596.c b/drivers/net/lasi_82596.c index c215fe3c1ecb..b3045c467da8 100644 --- a/drivers/net/lasi_82596.c +++ b/drivers/net/lasi_82596.c @@ -1596,7 +1596,7 @@ static void __exit lasi_82596_exit(void) lp = (struct i596_private *) netdevice->priv; dma_free_noncoherent(lp->dev, sizeof(struct i596_private), (void *)netdevice->mem_start, lp->dma_addr); - netdevice->priv = NULL; + free_netdev(netdevice); } unregister_parisc_driver(&lan_driver); diff --git a/drivers/net/lp486e.c b/drivers/net/lp486e.c index a6979d2b37bd..fe1e255a576c 100644 --- a/drivers/net/lp486e.c +++ b/drivers/net/lp486e.c @@ -1336,7 +1336,7 @@ static int __init lp486e_init_module(void) { static void __exit lp486e_cleanup_module(void) { unregister_netdev(dev_lp486e); release_region(dev_lp486e->base_addr, LP486E_TOTAL_SIZE); - kfree(dev_lp486e); + free_netdev(dev_lp486e); } module_init(lp486e_init_module); diff --git a/drivers/net/mace.c b/drivers/net/mace.c index 725aea12b82f..135af8ee8965 100644 --- a/drivers/net/mace.c +++ b/drivers/net/mace.c @@ -254,7 +254,7 @@ err_out: release_OF_resource(mp->of_node, 1); release_OF_resource(mp->of_node, 2); } - kfree(dev); + free_netdev(dev); } static void dbdma_reset(volatile struct dbdma_regs *dma) diff --git a/drivers/net/mvme147.c b/drivers/net/mvme147.c index 699ed000cbe0..00d3c94c76d7 100644 --- a/drivers/net/mvme147.c +++ b/drivers/net/mvme147.c @@ -199,7 +199,7 @@ void cleanup_module(void) lp = root_m147lance_dev->next_module; unregister_netdev(root_lance_dev->dev); free_pages(lp->ram, 3); - kfree(root_lance_dev->dev); + free_netdev(root_lance_dev->dev); root_lance_dev = lp; } } diff --git a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c index fdcad85b7cc6..07ab72c68a5d 100644 --- a/drivers/net/myri_sbus.c +++ b/drivers/net/myri_sbus.c @@ -1151,7 +1151,7 @@ static void __exit myri_sbus_cleanup(void) unregister_netdev(root_myri_dev->dev); /* this will also free the co-allocated 'root_myri_dev' */ - kfree(root_myri_dev->dev); + free_netdev(root_myri_dev->dev); root_myri_dev = next; } #endif /* MODULE */ diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c index b067be196128..b95d3030e465 100644 --- a/drivers/net/natsemi.c +++ b/drivers/net/natsemi.c @@ -2552,7 +2552,7 @@ static void __devexit natsemi_remove1 (struct pci_dev *pdev) unregister_netdev (dev); pci_release_regions (pdev); iounmap ((char *) dev->base_addr); - kfree (dev); + free_netdev (dev); pci_set_drvdata(pdev, NULL); } diff --git a/drivers/net/ne2k-pci.c b/drivers/net/ne2k-pci.c index 94e8d881e930..913e97d8e980 100644 --- a/drivers/net/ne2k-pci.c +++ b/drivers/net/ne2k-pci.c @@ -636,7 +636,7 @@ static void __devexit ne2k_pci_remove_one (struct pci_dev *pdev) unregister_netdev(dev); release_region(dev->base_addr, NE_IO_EXTENT); kfree(dev->priv); - kfree(dev); + free_netdev(dev); pci_set_drvdata(pdev, NULL); } diff --git a/drivers/net/ns83820.c b/drivers/net/ns83820.c index 0ceb548cd5a3..0e315b8d3753 100644 --- a/drivers/net/ns83820.c +++ b/drivers/net/ns83820.c @@ -438,7 +438,7 @@ struct rx_info { struct ns83820 { - struct net_device net_dev; + struct net_device net_dev; /* must be first */ struct net_device_stats stats; u8 *base; @@ -2057,7 +2057,7 @@ static void __devexit ns83820_remove_one(struct pci_dev *pci_dev) pci_free_consistent(dev->pci_dev, 4 * DESC_SIZE * NR_RX_DESC, dev->rx_info.descs, dev->rx_info.phy_descs); pci_disable_device(dev->pci_dev); - kfree(dev); + free_netdev(&dev->net_dev); pci_set_drvdata(pci_dev, NULL); } diff --git a/drivers/net/oaknet.c b/drivers/net/oaknet.c index 0029c3c54f3c..08124c5b24b0 100644 --- a/drivers/net/oaknet.c +++ b/drivers/net/oaknet.c @@ -687,7 +687,7 @@ static void __exit oaknet_cleanup_module (void) release_region(ioaddr, OAKNET_IO_SIZE); iounmap(ioaddr); unregister_netdev(oaknet_dev); - kfree(priv); + free_netdev(priv); } /* Convert to loop once driver supports multiple devices. */ diff --git a/drivers/net/pci-skeleton.c b/drivers/net/pci-skeleton.c index a2454b53633c..75f2da5c3928 100644 --- a/drivers/net/pci-skeleton.c +++ b/drivers/net/pci-skeleton.c @@ -871,7 +871,7 @@ static void __devexit netdrv_remove_one (struct pci_dev *pdev) sizeof (struct netdrv_private)); #endif /* NETDRV_NDEBUG */ - kfree (dev); + free_netdev (dev); pci_set_drvdata (pdev, NULL); diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c index 8f8747d0e4cd..a80ab490e3b0 100644 --- a/drivers/net/pcmcia/3c574_cs.c +++ b/drivers/net/pcmcia/3c574_cs.c @@ -384,9 +384,11 @@ static void tc574_detach(dev_link_t *link) /* Unlink device structure, free bits */ *linkp = link->next; - if (link->dev) + if (link->dev) { unregister_netdev(dev); - kfree(dev); + free_netdev(dev); + } else + kfree(dev); } /* tc574_detach */ diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c index 33d2aaa33f25..f0ba5d67a033 100644 --- a/drivers/net/pcmcia/3c589_cs.c +++ b/drivers/net/pcmcia/3c589_cs.c @@ -308,9 +308,11 @@ static void tc589_detach(dev_link_t *link) /* Unlink device structure, free bits */ *linkp = link->next; - if (link->dev) + if (link->dev) { unregister_netdev(dev); - kfree(dev); + free_netdev(dev); + } else + kfree(dev); } /* tc589_detach */ diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c index f1bc8529bed3..c495c2d715d0 100644 --- a/drivers/net/pcmcia/axnet_cs.c +++ b/drivers/net/pcmcia/axnet_cs.c @@ -267,9 +267,11 @@ static void axnet_detach(dev_link_t *link) /* Unlink device structure, free bits */ *linkp = link->next; - if (link->dev) + if (link->dev) { unregister_netdev(&info->dev); - kfree(info); + free_netdev(&info->dev); + } else + kfree(info); } /* axnet_detach */ diff --git a/drivers/net/pcmcia/com20020_cs.c b/drivers/net/pcmcia/com20020_cs.c index fb7e95b4b838..3a9b1cd38ee3 100644 --- a/drivers/net/pcmcia/com20020_cs.c +++ b/drivers/net/pcmcia/com20020_cs.c @@ -329,7 +329,7 @@ static void com20020_detach(dev_link_t *link) DEBUG(1,"kfree...\n"); kfree(dev->priv); - kfree(dev); + free_netdev(dev); } DEBUG(1,"kfree2...\n"); kfree(info); diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c index 70dd02350220..dfa7b5fd49df 100644 --- a/drivers/net/pcmcia/fmvj18x_cs.c +++ b/drivers/net/pcmcia/fmvj18x_cs.c @@ -365,9 +365,11 @@ static void fmvj18x_detach(dev_link_t *link) /* Unlink device structure, free pieces */ *linkp = link->next; - if (link->dev) + if (link->dev) { unregister_netdev(dev); - kfree(dev); + free_netdev(dev); + } else + kfree(dev); } /* fmvj18x_detach */ diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c index 990d64aec994..def583ce36f4 100644 --- a/drivers/net/pcmcia/ibmtr_cs.c +++ b/drivers/net/pcmcia/ibmtr_cs.c @@ -306,7 +306,7 @@ static void ibmtr_detach(dev_link_t *link) /* Unlink device structure, free bits */ *linkp = link->next; unregister_netdev(dev); - kfree(dev); + free_netdev(dev); } /* ibmtr_detach */ /*====================================================================== diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c index 0ffb1d4d945c..d73141cb91bc 100644 --- a/drivers/net/pcmcia/nmclan_cs.c +++ b/drivers/net/pcmcia/nmclan_cs.c @@ -579,9 +579,11 @@ static void nmclan_detach(dev_link_t *link) /* Unlink device structure, free bits */ *linkp = link->next; - if (link->dev) + if (link->dev) { unregister_netdev(dev); - kfree(dev); + free_netdev(dev); + } else + kfree(dev); } /* nmclan_detach */ diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index 3dc3315d6454..d18e622c08b6 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c @@ -367,9 +367,11 @@ static void pcnet_detach(dev_link_t *link) /* Unlink device structure, free bits */ *linkp = link->next; - if (link->dev) + if (link->dev) { unregister_netdev(&info->dev); - kfree(info); + free_netdev(&info->dev); + } else + kfree(info); } /* pcnet_detach */ diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index 925e46b4bb7e..a22e100c673d 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c @@ -443,9 +443,11 @@ static void smc91c92_detach(dev_link_t *link) /* Unlink device structure, free bits */ *linkp = link->next; - if (link->dev) + if (link->dev) { unregister_netdev(dev); - kfree(dev); + free_netdev(dev); + } else + kfree(dev); } /* smc91c92_detach */ diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c index 48f896ff26db..c73ff046dc14 100644 --- a/drivers/net/pcmcia/xirc2ps_cs.c +++ b/drivers/net/pcmcia/xirc2ps_cs.c @@ -699,9 +699,11 @@ xirc2ps_detach(dev_link_t * link) /* Unlink device structure, free it */ *linkp = link->next; - if (link->dev) + if (link->dev) { unregister_netdev(dev); - kfree(dev); + free_netdev(dev); + } else + kfree(dev); } /* xirc2ps_detach */ diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c index ebc368a79d83..ccd3a75ede50 100644 --- a/drivers/net/pcnet32.c +++ b/drivers/net/pcnet32.c @@ -1762,7 +1762,7 @@ static void __exit pcnet32_cleanup_module(void) if (lp->pci_dev) pci_unregister_driver(&pcnet32_driver); pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr); - kfree(pcnet32_dev); + free_netdev(pcnet32_dev); pcnet32_dev = next_dev; } } diff --git a/drivers/net/plip.c b/drivers/net/plip.c index ddc7f4bf478f..e4cd7b02e29b 100644 --- a/drivers/net/plip.c +++ b/drivers/net/plip.c @@ -1346,7 +1346,7 @@ static void __exit plip_cleanup_module (void) if (nl->port_owner) parport_release(nl->pardev); parport_unregister_device(nl->pardev); - kfree(dev); + free_netdev(dev); dev_plip[i] = NULL; } } diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index f022276d7aba..c96dbc2bd150 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c @@ -2256,11 +2256,6 @@ ppp_get_stats(struct ppp *ppp, struct ppp_stats *st) * and for initialization. */ -static void ppp_device_destructor(struct net_device *dev) -{ - kfree(dev); -} - /* * Create a new ppp interface unit. Fails if it can't allocate memory * or if there is already a unit with the requested number. @@ -2309,7 +2304,7 @@ ppp_create_interface(int unit, int *retp) dev->init = ppp_net_init; sprintf(dev->name, "ppp%d", unit); dev->priv = ppp; - dev->destructor = ppp_device_destructor; + dev->destructor = free_netdev; rtnl_lock(); ret = register_netdevice(dev); diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 2f37835c43a1..a0b4b659aa0e 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -646,7 +646,7 @@ rtl8169_remove_one(struct pci_dev *pdev) sizeof (struct net_device) + sizeof (struct rtl8169_private)); pci_disable_device(pdev); - kfree(dev); + free_netdev(dev); pci_set_drvdata(pdev, NULL); } diff --git a/drivers/net/rcpci45.c b/drivers/net/rcpci45.c index 285003f1f689..f5cdead40f14 100644 --- a/drivers/net/rcpci45.c +++ b/drivers/net/rcpci45.c @@ -146,7 +146,7 @@ rcpci45_remove_one (struct pci_dev *pdev) pDpa->msgbuf_dma); if (pDpa->pPab) kfree (pDpa->pPab); - kfree (dev); + free_netdev (dev); pci_set_drvdata (pdev, NULL); } diff --git a/drivers/net/rrunner.c b/drivers/net/rrunner.c index 6ca8dda68f26..87c980ff9112 100644 --- a/drivers/net/rrunner.c +++ b/drivers/net/rrunner.c @@ -253,7 +253,7 @@ static void __devexit rr_remove_one (struct pci_dev *pdev) rr->tx_ring_dma); unregister_netdev(dev); iounmap(rr->regs); - kfree(dev); + free_netdev(dev); pci_release_regions(pdev); pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); diff --git a/drivers/net/sb1000.c b/drivers/net/sb1000.c index 4a151b4198c0..d0153f60a036 100644 --- a/drivers/net/sb1000.c +++ b/drivers/net/sb1000.c @@ -235,7 +235,7 @@ sb1000_remove_one(struct pnp_dev *pdev) unregister_netdev(dev); release_region(dev->base_addr, 16); release_region(dev->mem_start, 16); - kfree(dev); + free_netdev(dev); } static struct pnp_driver sb1000_driver = { diff --git a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c index 3e5a78e2f30b..68838bbd0023 100644 --- a/drivers/net/sb1250-mac.c +++ b/drivers/net/sb1250-mac.c @@ -2929,7 +2929,7 @@ sbmac_cleanup_module(void) port = A_MAC_CHANNEL_BASE(idx); SBMAC_WRITECSR(KSEG1ADDR(port+R_MAC_ETHERNET_ADDR), sbmac_orig_hwaddr[idx] ); - kfree(dev); + free_netdev(dev); dev_sbmac[idx] = NULL; } } diff --git a/drivers/net/sgiseeq.c b/drivers/net/sgiseeq.c index c0b240416526..203e4c2eb000 100644 --- a/drivers/net/sgiseeq.c +++ b/drivers/net/sgiseeq.c @@ -704,7 +704,7 @@ static void __exit sgiseeq_exit(void) free_irq(dev->irq, dev); free_page((unsigned long) sp); unregister_netdev(dev); - kfree(dev); + free_netdev(dev); dev = next; } } diff --git a/drivers/net/shaper.c b/drivers/net/shaper.c index a8ac494e46ed..0e7f3159398f 100644 --- a/drivers/net/shaper.c +++ b/drivers/net/shaper.c @@ -642,7 +642,7 @@ static void __init shaper_setup(struct net_device *dev) dev->open = shaper_open; dev->stop = shaper_close; - dev->destructor = (void (*)(struct net_device *))kfree; + dev->destructor = free_netdev; dev->hard_start_xmit = shaper_start_xmit; dev->get_stats = shaper_get_stats; dev->set_multicast_list = NULL; diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c index a8b701e0281d..3094b09fa4e5 100644 --- a/drivers/net/sis190.c +++ b/drivers/net/sis190.c @@ -706,7 +706,7 @@ SiS190_remove_one(struct pci_dev *pdev) memset(dev, 0xBC, sizeof (struct net_device) + sizeof (struct sis190_private)); - kfree(dev); + free_netdev(dev); pci_set_drvdata(pdev, NULL); } diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c index 80976c9742ef..1881b03297f2 100644 --- a/drivers/net/sis900.c +++ b/drivers/net/sis900.c @@ -2190,7 +2190,7 @@ static void __devexit sis900_remove(struct pci_dev *pci_dev) pci_free_consistent(pci_dev, TX_TOTAL_SIZE, sis_priv->tx_ring, sis_priv->tx_ring_dma); unregister_netdev(net_dev); - kfree(net_dev); + free_netdev(net_dev); pci_release_regions(pci_dev); pci_set_drvdata(pci_dev, NULL); } diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c index 76ccbb897a25..a38036f73346 100644 --- a/drivers/net/sk98lin/skge.c +++ b/drivers/net/sk98lin/skge.c @@ -1082,7 +1082,7 @@ SK_EVPARA EvPara; * invalid IO ... :-( */ unregister_netdev(SkGeRootDev); - kfree(SkGeRootDev); + free_netdev(SkGeRootDev); kfree(pAC); SkGeRootDev = next; } diff --git a/drivers/net/sk_g16.c b/drivers/net/sk_g16.c index 3251e9c0dab3..70c13d040911 100644 --- a/drivers/net/sk_g16.c +++ b/drivers/net/sk_g16.c @@ -652,7 +652,7 @@ static void __exit SK_cleanup_module (void) SK_dev->priv = NULL; } unregister_netdev(SK_dev); - kfree(SK_dev); + free_netdev(SK_dev); SK_dev = NULL; } if (SK_ioaddr) { diff --git a/drivers/net/skfp/skfddi.c b/drivers/net/skfp/skfddi.c index e04107c8e5ee..79c3a0f2b935 100644 --- a/drivers/net/skfp/skfddi.c +++ b/drivers/net/skfp/skfddi.c @@ -2582,7 +2582,7 @@ static struct net_device *unlink_modules(struct net_device *p) } unregister_netdev(p); printk("%s: unloaded\n", p->name); - kfree(p); /* Free the device structure */ + free_netdev(p); /* Free the device structure */ return next; } // unlink_modules diff --git a/drivers/net/slip.c b/drivers/net/slip.c index 45f6f3869f5c..867cc1c3a5d6 100644 --- a/drivers/net/slip.c +++ b/drivers/net/slip.c @@ -640,7 +640,7 @@ static void sl_setup(struct net_device *dev) dev->init = sl_init; dev->uninit = sl_uninit; dev->open = sl_open; - dev->destructor = (void (*)(struct net_device *))kfree; + dev->destructor = free_netdev; dev->stop = sl_close; dev->get_stats = sl_get_stats; dev->change_mtu = sl_change_mtu; diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c index a0651801124e..dcf1db7ea6ef 100644 --- a/drivers/net/starfire.c +++ b/drivers/net/starfire.c @@ -2196,7 +2196,7 @@ static void __devexit starfire_remove_one (struct pci_dev *pdev) pci_release_regions(pdev); pci_set_drvdata(pdev, NULL); - kfree(dev); /* Will also free np!! */ + free_netdev(dev); /* Will also free np!! */ } diff --git a/drivers/net/sunbmac.c b/drivers/net/sunbmac.c index 2b3197ed55d8..e9a71e7c986e 100644 --- a/drivers/net/sunbmac.c +++ b/drivers/net/sunbmac.c @@ -1275,7 +1275,7 @@ static void __exit bigmac_cleanup(void) bp->bblock_dvma); unregister_netdev(bp->dev); - kfree(bp->dev); + free_netdev(bp->dev); root_bigmac_dev = bp_nxt; } } diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c index b3a95683f833..5bd8be316547 100644 --- a/drivers/net/sundance.c +++ b/drivers/net/sundance.c @@ -1790,7 +1790,7 @@ static void __devexit sundance_remove1 (struct pci_dev *pdev) #ifndef USE_IO_OPS iounmap((char *)(dev->base_addr)); #endif - kfree(dev); + free_netdev(dev); pci_set_drvdata(pdev, NULL); } } diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c index 8b8d9dfb3a4f..dff930c3f546 100644 --- a/drivers/net/sungem.c +++ b/drivers/net/sungem.c @@ -2879,7 +2879,7 @@ static void __devexit gem_remove_one(struct pci_dev *pdev) gp->gblock_dvma); iounmap((void *) gp->regs); pci_release_regions(pdev); - kfree(dev); + free_netdev(dev); pci_set_drvdata(pdev, NULL); } diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c index 655df2eeb4cc..89cf5924e6aa 100644 --- a/drivers/net/sunhme.c +++ b/drivers/net/sunhme.c @@ -3348,7 +3348,7 @@ static void __exit happy_meal_cleanup_module(void) pci_release_regions(hp->happy_dev); } #endif - kfree(dev); + free_netdev(dev); root_happy_dev = next; } diff --git a/drivers/net/sunlance.c b/drivers/net/sunlance.c index a2f21b82510d..d62eec7db6e4 100644 --- a/drivers/net/sunlance.c +++ b/drivers/net/sunlance.c @@ -1582,7 +1582,7 @@ static void __exit sparc_lance_cleanup(void) unregister_netdev(root_lance_dev->dev); lance_free_hwresources(root_lance_dev); - kfree(root_lance_dev->dev); + free_netdev(root_lance_dev->dev); root_lance_dev = lp; } } diff --git a/drivers/net/sunqe.c b/drivers/net/sunqe.c index 207fe52c8603..c68c52562d0e 100644 --- a/drivers/net/sunqe.c +++ b/drivers/net/sunqe.c @@ -998,7 +998,7 @@ static void __exit qec_cleanup(void) sizeof(struct sunqe_buffers), root_qec_dev->qes[i]->buffers, root_qec_dev->qes[i]->buffers_dvma); - kfree(root_qec_dev->qes[i]->dev); + free_netdev(root_qec_dev->qes[i]->dev); } free_irq(root_qec_dev->qec_sdev->irqs[0], (void *)root_qec_dev); sbus_iounmap(root_qec_dev->gregs, GLOB_REG_SIZE); diff --git a/drivers/net/tc35815.c b/drivers/net/tc35815.c index f28c3342775c..b9411c1337aa 100644 --- a/drivers/net/tc35815.c +++ b/drivers/net/tc35815.c @@ -1769,7 +1769,7 @@ static void __exit tc35815_cleanup_module(void) next_dev = ((struct tc35815_local *)dev->priv)->next_module; iounmap((void *)(dev->base_addr)); unregister_netdev(dev); - kfree(dev); + free_netdev(dev); root_tc35815_dev = next_dev; } } diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 1c968a6899d5..024bfa46834b 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -6882,7 +6882,7 @@ static void __devexit tg3_remove_one(struct pci_dev *pdev) if (dev) { unregister_netdev(dev); iounmap((void *) ((struct tg3 *)(dev->priv))->regs); - kfree(dev); + free_netdev(dev); pci_release_regions(pdev); pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c index 8c8149aebe64..5a45900a816e 100644 --- a/drivers/net/tlan.c +++ b/drivers/net/tlan.c @@ -447,7 +447,7 @@ static void __devexit tlan_remove_one( struct pci_dev *pdev) pci_release_regions(pdev); - kfree( dev ); + free_netdev( dev ); pci_set_drvdata( pdev, NULL ); } diff --git a/drivers/net/tokenring/3c359.c b/drivers/net/tokenring/3c359.c index d8a95b47bcf9..c97573aa5513 100644 --- a/drivers/net/tokenring/3c359.c +++ b/drivers/net/tokenring/3c359.c @@ -1787,7 +1787,7 @@ static void __devexit xl_remove_one (struct pci_dev *pdev) iounmap(xl_priv->xl_mmio) ; pci_release_regions(pdev) ; pci_set_drvdata(pdev,NULL) ; - kfree(dev); + free_netdev(dev); return ; } diff --git a/drivers/net/tokenring/abyss.c b/drivers/net/tokenring/abyss.c index ba329d156c96..ea63827aa62f 100644 --- a/drivers/net/tokenring/abyss.c +++ b/drivers/net/tokenring/abyss.c @@ -443,7 +443,7 @@ static void __devexit abyss_detach (struct pci_dev *pdev) release_region(dev->base_addr-0x10, ABYSS_IO_EXTENT); free_irq(dev->irq, dev); tmsdev_term(dev); - kfree(dev); + free_netdev(dev); pci_set_drvdata(pdev, NULL); } diff --git a/drivers/net/tokenring/ibmtr.c b/drivers/net/tokenring/ibmtr.c index d9d8d2488a49..dcee7eecda24 100644 --- a/drivers/net/tokenring/ibmtr.c +++ b/drivers/net/tokenring/ibmtr.c @@ -1975,7 +1975,7 @@ static void __exit ibmtr_cleanup(void) iounmap((u32 *)ti->sram_virt); } #endif - kfree(dev_ibmtr[i]); + free_netdev(dev_ibmtr[i]); dev_ibmtr[i] = NULL; } } diff --git a/drivers/net/tokenring/lanstreamer.c b/drivers/net/tokenring/lanstreamer.c index c2f7e028632e..32e56c4d9043 100644 --- a/drivers/net/tokenring/lanstreamer.c +++ b/drivers/net/tokenring/lanstreamer.c @@ -433,7 +433,7 @@ static void __devexit streamer_remove_one(struct pci_dev *pdev) /* shouldn't we do iounmap here? */ release_region(pci_resource_start(pdev, 0), pci_resource_len(pdev,0)); release_mem_region(pci_resource_start(pdev, 1), pci_resource_len(pdev,1)); - kfree(dev); + free_netdev(dev); pci_set_drvdata(pdev, NULL); } diff --git a/drivers/net/tokenring/madgemc.c b/drivers/net/tokenring/madgemc.c index 4849f5f62777..a871e629ca35 100644 --- a/drivers/net/tokenring/madgemc.c +++ b/drivers/net/tokenring/madgemc.c @@ -774,7 +774,7 @@ static void __exit madgemc_exit(void) release_region(dev->base_addr-MADGEMC_SIF_OFFSET, MADGEMC_IO_EXTENT); free_irq(dev->irq, dev); tmsdev_term(dev); - kfree(dev); + free_netdev(dev); this_card = madgemc_card_list; madgemc_card_list = this_card->next; kfree(this_card); diff --git a/drivers/net/tokenring/olympic.c b/drivers/net/tokenring/olympic.c index eeb044914022..d74b22b0a20c 100644 --- a/drivers/net/tokenring/olympic.c +++ b/drivers/net/tokenring/olympic.c @@ -1779,7 +1779,7 @@ static void __devexit olympic_remove_one(struct pci_dev *pdev) iounmap(olympic_priv->olympic_lap) ; pci_release_regions(pdev) ; pci_set_drvdata(pdev,NULL) ; - kfree(dev) ; + free_netdev(dev) ; } static struct pci_driver olympic_driver = { diff --git a/drivers/net/tokenring/proteon.c b/drivers/net/tokenring/proteon.c index f8b0295942ba..4c4b4dd034ab 100644 --- a/drivers/net/tokenring/proteon.c +++ b/drivers/net/tokenring/proteon.c @@ -436,7 +436,7 @@ void cleanup_module(void) free_irq(dev->irq, dev); free_dma(dev->dma); tmsdev_term(dev); - kfree(dev); + free_netdev(dev); this_card = proteon_card_list; proteon_card_list = this_card->next; kfree(this_card); diff --git a/drivers/net/tokenring/skisa.c b/drivers/net/tokenring/skisa.c index 92711606d4ce..da77f8bdb53f 100644 --- a/drivers/net/tokenring/skisa.c +++ b/drivers/net/tokenring/skisa.c @@ -449,7 +449,7 @@ void cleanup_module(void) free_irq(dev->irq, dev); free_dma(dev->dma); tmsdev_term(dev); - kfree(dev); + free_netdev(dev); this_card = sk_isa_card_list; sk_isa_card_list = this_card->next; kfree(this_card); diff --git a/drivers/net/tokenring/smctr.c b/drivers/net/tokenring/smctr.c index a1e365ebdd6b..4aea1df360e8 100644 --- a/drivers/net/tokenring/smctr.c +++ b/drivers/net/tokenring/smctr.c @@ -5730,7 +5730,7 @@ void cleanup_module(void) if (dev) { unregister_netdev(dev); cleanup_card(dev); - kfree(dev); + free_netdev(dev); } } } diff --git a/drivers/net/tokenring/tmspci.c b/drivers/net/tokenring/tmspci.c index 3408852ffac4..82b1abd8d50a 100644 --- a/drivers/net/tokenring/tmspci.c +++ b/drivers/net/tokenring/tmspci.c @@ -229,7 +229,7 @@ static void __devexit tms_pci_detach (struct pci_dev *pdev) release_region(dev->base_addr, TMS_PCI_IO_EXTENT); free_irq(dev->irq, dev); tmsdev_term(dev); - kfree(dev); + free_netdev(dev); pci_set_drvdata(pdev, NULL); } diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c index 7cf949b57b54..ab7dccd941f8 100644 --- a/drivers/net/tulip/de2104x.c +++ b/drivers/net/tulip/de2104x.c @@ -2152,7 +2152,7 @@ static void __exit de_remove_one (struct pci_dev *pdev) pci_release_regions(pdev); pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); - kfree(dev); + free_netdev(dev); } #ifdef CONFIG_PM diff --git a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c index 97f36b5f440f..96fe51d22763 100644 --- a/drivers/net/tulip/de4x5.c +++ b/drivers/net/tulip/de4x5.c @@ -5837,7 +5837,7 @@ unlink_modules(struct net_device *p) kfree(lp->cache.priv); /* Free the private area */ } unregister_netdev(p); - kfree(p); /* Free the device structure */ + free_netdev(p); /* Free the device structure */ return next; } diff --git a/drivers/net/tulip/dmfe.c b/drivers/net/tulip/dmfe.c index eb43f60594e8..f7b253b2bc8d 100644 --- a/drivers/net/tulip/dmfe.c +++ b/drivers/net/tulip/dmfe.c @@ -478,7 +478,7 @@ static void __devexit dmfe_remove_one (struct pci_dev *pdev) db->buf_pool_ptr, db->buf_pool_dma_ptr); unregister_netdev(dev); pci_release_regions(pdev); - kfree(dev); /* free board information */ + free_netdev(dev); /* free board information */ pci_set_drvdata(pdev, NULL); } diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c index 14b86129e0ee..daf5cea7612f 100644 --- a/drivers/net/tulip/tulip_core.c +++ b/drivers/net/tulip/tulip_core.c @@ -1780,7 +1780,7 @@ static void __devexit tulip_remove_one (struct pci_dev *pdev) #ifndef USE_IO_OPS iounmap((void *)dev->base_addr); #endif - kfree (dev); + free_netdev (dev); pci_release_regions (pdev); pci_set_drvdata (pdev, NULL); diff --git a/drivers/net/tulip/winbond-840.c b/drivers/net/tulip/winbond-840.c index cfd15c0653c3..42dee7a5d423 100644 --- a/drivers/net/tulip/winbond-840.c +++ b/drivers/net/tulip/winbond-840.c @@ -1623,7 +1623,7 @@ static void __devexit w840_remove1 (struct pci_dev *pdev) #ifndef USE_IO_OPS iounmap((char *)(dev->base_addr)); #endif - kfree(dev); + free_netdev(dev); } pci_set_drvdata(pdev, NULL); diff --git a/drivers/net/tulip/xircom_cb.c b/drivers/net/tulip/xircom_cb.c index 373abb843fcb..518121a6c12f 100644 --- a/drivers/net/tulip/xircom_cb.c +++ b/drivers/net/tulip/xircom_cb.c @@ -338,7 +338,7 @@ static void __devexit xircom_remove(struct pci_dev *pdev) } release_region(dev->base_addr, 128); unregister_netdev(dev); - kfree(dev); + free_netdev(dev); leave("xircom_remove"); } diff --git a/drivers/net/tulip/xircom_tulip_cb.c b/drivers/net/tulip/xircom_tulip_cb.c index b1401e78bb11..04577943733a 100644 --- a/drivers/net/tulip/xircom_tulip_cb.c +++ b/drivers/net/tulip/xircom_tulip_cb.c @@ -1702,7 +1702,7 @@ static void __devexit xircom_remove_one(struct pci_dev *pdev) printk(KERN_INFO "xircom_remove_one(%s)\n", dev->name); unregister_netdev(dev); pci_release_regions(pdev); - kfree(dev); + free_netdev(dev); pci_set_drvdata(pdev, NULL); } diff --git a/drivers/net/tun.c b/drivers/net/tun.c index cff9fec672f6..860e53b4d696 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -358,7 +358,7 @@ static void tun_setup(struct net_device *dev) dev->hard_start_xmit = tun_net_xmit; dev->stop = tun_net_close; dev->get_stats = tun_net_stats; - dev->destructor = (void (*)(struct net_device *))kfree; + dev->destructor = free_netdev; } static struct tun_struct *tun_get_by_name(const char *name) diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c index 515235e410d2..e83372b7adbb 100644 --- a/drivers/net/typhoon.c +++ b/drivers/net/typhoon.c @@ -2476,7 +2476,7 @@ typhoon_remove_one(struct pci_dev *pdev) pci_release_regions(pdev); pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); - kfree(dev); + free_netdev(dev); } static struct pci_driver typhoon_driver = { diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c index 069632e35583..b4fa9c684a45 100644 --- a/drivers/net/via-rhine.c +++ b/drivers/net/via-rhine.c @@ -1893,7 +1893,7 @@ static void __devexit via_rhine_remove_one (struct pci_dev *pdev) iounmap((char *)(dev->base_addr)); #endif - kfree(dev); + free_netdev(dev); pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); } diff --git a/drivers/net/wan/comx.c b/drivers/net/wan/comx.c index 8cd73bc9a3d5..1418fd1e7b38 100644 --- a/drivers/net/wan/comx.c +++ b/drivers/net/wan/comx.c @@ -908,7 +908,7 @@ static int comx_rmdir(struct inode *dir, struct dentry *dentry) if (dev->priv) { kfree(dev->priv); } - kfree(dev); + free_netdev(dev); remove_proc_entry(FILENAME_DEBUG, entry); remove_proc_entry(FILENAME_LINEUPDELAY, entry); diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c index c6c95b0166c6..869b2c47e469 100644 --- a/drivers/net/wan/cosa.c +++ b/drivers/net/wan/cosa.c @@ -632,6 +632,7 @@ static void sppp_channel_delete(struct channel_data *chan) { sppp_detach(chan->pppdev.dev); unregister_netdev(chan->pppdev.dev); + free_netdev(chan->ppp.dev); } static int cosa_sppp_open(struct net_device *d) diff --git a/drivers/net/wan/dlci.c b/drivers/net/wan/dlci.c index e32052b5aaa7..5aab67436cc7 100644 --- a/drivers/net/wan/dlci.c +++ b/drivers/net/wan/dlci.c @@ -509,7 +509,7 @@ int dlci_del(struct dlci_add *dlci) open_dev[i] = NULL; kfree(master->priv); - kfree(master); + free_netdev(master); MOD_DEC_USE_COUNT; diff --git a/drivers/net/wan/hdlc_fr.c b/drivers/net/wan/hdlc_fr.c index dcf2b3b313b8..a6c81713f492 100644 --- a/drivers/net/wan/hdlc_fr.c +++ b/drivers/net/wan/hdlc_fr.c @@ -1055,7 +1055,7 @@ static int fr_add_pvc(hdlc_device *hdlc, unsigned int dlci, int type) return -EIO; } - dev->destructor = (void (*)(struct net_device *)) kfree; + dev->destructor = free_netdev; *get_dev_p(pvc, type) = dev; if (!used) { hdlc->state.fr.dce_changed = 1; diff --git a/drivers/net/wan/lapbether.c b/drivers/net/wan/lapbether.c index 17169184f72c..293ce6cf9aca 100644 --- a/drivers/net/wan/lapbether.c +++ b/drivers/net/wan/lapbether.c @@ -324,7 +324,7 @@ static void lapbeth_setup(struct net_device *dev) dev->hard_start_xmit = lapbeth_xmit; dev->open = lapbeth_open; dev->stop = lapbeth_close; - dev->destructor = (void (*)(struct net_device *))kfree; + dev->destructor = free_netdev; dev->set_mac_address = lapbeth_set_mac_address; dev->get_stats = lapbeth_get_stats; dev->type = ARPHRD_X25; diff --git a/drivers/net/wan/lmc/lmc_main.c b/drivers/net/wan/lmc/lmc_main.c index 992e560ec1ce..439226bd8867 100644 --- a/drivers/net/wan/lmc/lmc_main.c +++ b/drivers/net/wan/lmc/lmc_main.c @@ -1913,7 +1913,7 @@ static void __exit exit_lmc(void) kfree (dev->priv); dev->priv = NULL; - kfree ((struct ppp_device *) dev); + free_netdev (dev); dev = NULL; } diff --git a/drivers/net/wan/sbni.c b/drivers/net/wan/sbni.c index 362f28421c01..791d479b7af9 100644 --- a/drivers/net/wan/sbni.c +++ b/drivers/net/wan/sbni.c @@ -1507,7 +1507,7 @@ cleanup_module( void ) unregister_netdev( dev ); release_region( dev->base_addr, SBNI_IO_EXTENT ); kfree( dev->priv ); - kfree( dev ); + free_netdev( dev ); } } diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c index 0b90e4bf41ef..3825f880de32 100644 --- a/drivers/net/wan/x25_asy.c +++ b/drivers/net/wan/x25_asy.c @@ -840,7 +840,7 @@ static void __exit exit_x25_asy(void) * unregistered while close proc. */ unregister_netdev(dev); - kfree(dev); + free_netdev(dev); } } diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index acd124beccca..816e34ee4b54 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -1608,7 +1608,7 @@ void stop_airo_card( struct net_device *dev, int freeres ) unregister_netdev( dev ); if (ai->wifidev) { unregister_netdev(ai->wifidev); - kfree(ai->wifidev); + free_netdev(ai->wifidev); ai->wifidev = 0; } ai->registered = 0; @@ -1625,7 +1625,7 @@ void stop_airo_card( struct net_device *dev, int freeres ) release_region( dev->base_addr, 64 ); } del_airo_dev( dev ); - kfree( dev ); + free_netdev( dev ); } EXPORT_SYMBOL(stop_airo_card); diff --git a/drivers/net/wireless/airport.c b/drivers/net/wireless/airport.c index a7b6e14cbf21..71e0a70ce2d8 100644 --- a/drivers/net/wireless/airport.c +++ b/drivers/net/wireless/airport.c @@ -284,7 +284,7 @@ airport_detach(struct net_device *dev) current->state = TASK_UNINTERRUPTIBLE; schedule_timeout(HZ); - kfree(dev); + free_netdev(dev); } /* airport_detach */ static char version[] __initdata = "airport.c 0.13e (Benjamin Herrenschmidt <benh@kernel.crashing.org>)"; diff --git a/drivers/net/wireless/arlan.c b/drivers/net/wireless/arlan.c index 2bddbef9cd0c..0de038cd8275 100644 --- a/drivers/net/wireless/arlan.c +++ b/drivers/net/wireless/arlan.c @@ -2061,7 +2061,7 @@ void cleanup_module(void) unregister_netdev(arlan_device[i]); ap = arlan_device[i]->priv; if (ap->init_etherdev_alloc) { - kfree(arlan_device[i]); + free_netdev(arlan_device[i]); arlan_device[i] = NULL; } else { kfree(ap); diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c index 2638b7613041..2dfcc5e49308 100644 --- a/drivers/net/wireless/atmel.c +++ b/drivers/net/wireless/atmel.c @@ -1468,7 +1468,7 @@ void stop_atmel_card(struct net_device *dev, int freeres) /* PCMCIA frees this stuff, so only for PCI */ release_region(dev->base_addr, 64); } - kfree(dev); + free_netdev(dev); } EXPORT_SYMBOL(stop_atmel_card); diff --git a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c index 0d0a3d86c2f5..a704847b1fd9 100644 --- a/drivers/net/wireless/netwave_cs.c +++ b/drivers/net/wireless/netwave_cs.c @@ -574,9 +574,9 @@ static void netwave_detach(dev_link_t *link) /* Unlink device structure, free pieces */ *linkp = link->next; - if (link->dev) + if (link->dev) unregister_netdev(dev); - kfree(dev); + free_netdev(dev); } /* netwave_detach */ diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c index c4469710e7fd..cf37a7a08a1a 100644 --- a/drivers/net/wireless/orinoco_cs.c +++ b/drivers/net/wireless/orinoco_cs.c @@ -286,7 +286,7 @@ orinoco_cs_detach(dev_link_t * link) dev); unregister_netdev(dev); } - kfree(dev); + free_netdev(dev); } /* orinoco_cs_detach */ /* diff --git a/drivers/net/wireless/orinoco_pci.c b/drivers/net/wireless/orinoco_pci.c index 60e8eff72f7f..54a59dbdf57a 100644 --- a/drivers/net/wireless/orinoco_pci.c +++ b/drivers/net/wireless/orinoco_pci.c @@ -289,7 +289,7 @@ static void __devexit orinoco_pci_remove_one(struct pci_dev *pdev) iounmap((unsigned char *) priv->hw.iobase); pci_set_drvdata(pdev, NULL); - kfree(dev); + free_netdev(dev); pci_disable_device(pdev); } diff --git a/drivers/net/wireless/orinoco_plx.c b/drivers/net/wireless/orinoco_plx.c index 900847268da4..bc3b5d63f7d4 100644 --- a/drivers/net/wireless/orinoco_plx.c +++ b/drivers/net/wireless/orinoco_plx.c @@ -291,7 +291,7 @@ static void __devexit orinoco_plx_remove_one(struct pci_dev *pdev) pci_set_drvdata(pdev, NULL); - kfree(dev); + free_netdev(dev); release_region(pci_resource_start(pdev, 3), pci_resource_len(pdev, 3)); diff --git a/drivers/net/wireless/orinoco_tmd.c b/drivers/net/wireless/orinoco_tmd.c index 2a1da0b071ff..7b551fbf3150 100644 --- a/drivers/net/wireless/orinoco_tmd.c +++ b/drivers/net/wireless/orinoco_tmd.c @@ -182,7 +182,7 @@ static void __devexit orinoco_tmd_remove_one(struct pci_dev *pdev) pci_set_drvdata(pdev, NULL); - kfree(dev); + free_netdev(dev); release_region(pci_resource_start(pdev, 2), pci_resource_len(pdev, 2)); diff --git a/drivers/net/wireless/strip.c b/drivers/net/wireless/strip.c index 6e25b0494941..feb7e9d2f6a4 100644 --- a/drivers/net/wireless/strip.c +++ b/drivers/net/wireless/strip.c @@ -103,6 +103,7 @@ static const char StripVersion[] = "1.3A-STUART.CHESHIRE"; #include <linux/if_arp.h> #include <linux/if_strip.h> #include <linux/proc_fs.h> +#include <linux/seq_file.h> #include <linux/serial.h> #include <linux/serialP.h> #include <net/arp.h> @@ -259,8 +260,8 @@ struct strip { * Internal variables. */ - struct strip *next; /* The next struct in the list */ - struct strip **referrer; /* The pointer that points to us */ + struct list_head list; /* Linked list of devices */ + int discard; /* Set if serial error */ int working; /* Is radio working correctly? */ int firmware_level; /* Message structuring level */ @@ -434,8 +435,8 @@ static const long LongTime = 0x7FFFFFFF; /************************************************************************/ /* Global variables */ -static struct strip *struct_strip_list; -static spinlock_t strip_lock; +static LIST_HEAD(strip_list); +static spinlock_t strip_lock = SPIN_LOCK_UNLOCKED; /************************************************************************/ /* Macros */ @@ -844,11 +845,11 @@ static __u8 *radio_address_to_string(const MetricomAddress * addr, * big enough to receive a large radio neighbour list (currently 4K). */ -static int allocate_buffers(struct strip *strip_info) +static int allocate_buffers(struct strip *strip_info, int mtu) { struct net_device *dev = strip_info->dev; int sx_size = MAX(STRIP_ENCAP_SIZE(MAX_RECV_MTU), 4096); - int tx_size = STRIP_ENCAP_SIZE(dev->mtu) + MaxCommandStringLength; + int tx_size = STRIP_ENCAP_SIZE(mtu) + MaxCommandStringLength; __u8 *r = kmalloc(MAX_RECV_MTU, GFP_ATOMIC); __u8 *s = kmalloc(sx_size, GFP_ATOMIC); __u8 *t = kmalloc(tx_size, GFP_ATOMIC); @@ -858,7 +859,7 @@ static int allocate_buffers(struct strip *strip_info) strip_info->tx_buff = t; strip_info->sx_size = sx_size; strip_info->tx_size = tx_size; - strip_info->mtu = dev->mtu; + strip_info->mtu = dev->mtu = mtu; return (1); } if (r) @@ -871,34 +872,31 @@ static int allocate_buffers(struct strip *strip_info) } /* - * MTU has been changed by the IP layer. Unfortunately we are not told - * about this, but we spot it ourselves and fix things up. We could be in + * MTU has been changed by the IP layer. + * We could be in * an upcall from the tty driver, or in an ip packet queue. - * - * Caller must hold the strip_lock */ - -static void strip_changedmtu(struct strip *strip_info) +static int strip_change_mtu(struct net_device *dev, int new_mtu) { + struct strip *strip_info = dev->priv; int old_mtu = strip_info->mtu; - struct net_device *dev = strip_info->dev; unsigned char *orbuff = strip_info->rx_buff; unsigned char *osbuff = strip_info->sx_buff; unsigned char *otbuff = strip_info->tx_buff; - if (dev->mtu > MAX_SEND_MTU) { + if (new_mtu > MAX_SEND_MTU) { printk(KERN_ERR "%s: MTU exceeds maximum allowable (%d), MTU change cancelled.\n", strip_info->dev->name, MAX_SEND_MTU); - dev->mtu = old_mtu; - return; + return -EINVAL; } - if (!allocate_buffers(strip_info)) { + spin_lock_bh(&strip_lock); + if (!allocate_buffers(strip_info, new_mtu)) { printk(KERN_ERR "%s: unable to grow strip buffers, MTU change cancelled.\n", strip_info->dev->name); - dev->mtu = old_mtu; - return; + spin_unlock_bh(&strip_lock); + return -ENOMEM; } if (strip_info->sx_count) { @@ -921,6 +919,7 @@ static void strip_changedmtu(struct strip *strip_info) } } strip_info->tx_head = strip_info->tx_buff; + spin_unlock_bh(&strip_lock); printk(KERN_NOTICE "%s: strip MTU changed fom %d to %d.\n", strip_info->dev->name, old_mtu, strip_info->mtu); @@ -931,6 +930,8 @@ static void strip_changedmtu(struct strip *strip_info) kfree(osbuff); if (otbuff) kfree(otbuff); + + return 0; } static void strip_unlock(struct strip *strip_info) @@ -944,74 +945,6 @@ static void strip_unlock(struct strip *strip_info) } -/************************************************************************/ -/* Callback routines for exporting information through /proc */ - -/* - * This function updates the total amount of data printed so far. It then - * determines if the amount of data printed into a buffer has reached the - * offset requested. If it hasn't, then the buffer is shifted over so that - * the next bit of data can be printed over the old bit. If the total - * amount printed so far exceeds the total amount requested, then this - * function returns 1, otherwise 0. - */ -static int -shift_buffer(char *buffer, int requested_offset, int requested_len, - int *total, int *slop, char **buf) -{ - int printed; - - /* printk(KERN_DEBUG "shift: buffer: %d o: %d l: %d t: %d buf: %d\n", - (int) buffer, requested_offset, requested_len, *total, - (int) *buf); */ - printed = *buf - buffer; - if (*total + printed <= requested_offset) { - *total += printed; - *buf = buffer; - } else { - if (*total < requested_offset) { - *slop = requested_offset - *total; - } - *total = requested_offset + printed - *slop; - } - if (*total > requested_offset + requested_len) { - return 1; - } else { - return 0; - } -} - -/* - * This function calculates the actual start of the requested data - * in the buffer. It also calculates actual length of data returned, - * which could be less that the amount of data requested. - */ -static int -calc_start_len(char *buffer, char **start, int requested_offset, - int requested_len, int total, char *buf) -{ - int return_len, buffer_len; - - buffer_len = buf - buffer; - if (buffer_len >= 4095) { - printk(KERN_ERR "STRIP: exceeded /proc buffer size\n"); - } - - /* - * There may be bytes before and after the - * chunk that was actually requested. - */ - return_len = total - requested_offset; - if (return_len < 0) { - return_len = 0; - } - *start = buf - return_len; - if (return_len > requested_len) { - return_len = requested_len; - } - /* printk(KERN_DEBUG "return_len: %d\n", return_len); */ - return return_len; -} /* * If the time is in the near future, time_delta prints the number of @@ -1032,44 +965,89 @@ static char *time_delta(char buffer[], long time) return (buffer); } -static int sprintf_neighbours(char *buffer, MetricomNodeTable * table, - char *title) +#define STRIP_PROC_HEADER ((void *)1) + +/* get Nth element of the linked list */ +static struct strip *strip_get_idx(loff_t pos) +{ + struct list_head *l; + int i = 0; + + list_for_each_rcu(l, &strip_list) { + if (pos == i) + return list_entry(l, struct strip, list); + ++i; + } + return NULL; +} + +static void *strip_seq_start(struct seq_file *seq, loff_t *pos) +{ + rcu_read_lock(); + return *pos ? strip_get_idx(*pos - 1) : STRIP_PROC_HEADER; +} + +static void *strip_seq_next(struct seq_file *seq, void *v, loff_t *pos) +{ + struct list_head *l; + struct strip *s; + + ++*pos; + if (v == STRIP_PROC_HEADER) + return strip_get_idx(1); + + s = v; + l = &s->list; + list_for_each_continue_rcu(l, &strip_list) { + return list_entry(l, struct strip, list); + } + return NULL; +} + +static void strip_seq_stop(struct seq_file *seq, void *v) +{ + rcu_read_unlock(); +} + +static void strip_seq_neighbours(struct seq_file *seq, + const MetricomNodeTable * table, + const char *title) { /* We wrap this in a do/while loop, so if the table changes */ /* while we're reading it, we just go around and try again. */ struct timeval t; - char *ptr; - unsigned long flags; do { int i; t = table->timestamp; - ptr = buffer; if (table->num_nodes) - ptr += sprintf(ptr, "\n %s\n", title); + seq_printf(seq, "\n %s\n", title); for (i = 0; i < table->num_nodes; i++) { MetricomNode node; - spin_lock_irqsave(&strip_lock, flags); + spin_lock_bh(&strip_lock); node = table->node[i]; - spin_unlock_irqrestore(&strip_lock, flags); - ptr += sprintf(ptr, " %s\n", node.c); + spin_unlock_bh(&strip_lock); + seq_printf(seq, " %s\n", node.c); } } while (table->timestamp.tv_sec != t.tv_sec || table->timestamp.tv_usec != t.tv_usec); - return ptr - buffer; } /* - * This function prints radio status information into the specified buffer. - * I think the buffer size is 4K, so this routine should never print more - * than 4K of data into it. With the maximum of 32 portables and 32 poletops + * This function prints radio status information via the seq_file + * interface. The interface takes care of buffer size and over + * run issues. + * + * The buffer in seq_file is PAGESIZE (4K) + * so this routine should never print more or it will get truncated. + * With the maximum of 32 portables and 32 poletops * reported, the routine outputs 3107 bytes into the buffer. */ -static int sprintf_status_info(char *buffer, struct strip *strip_info) +static void strip_seq_status_info(struct seq_file *seq, + const struct strip *strip_info) { char temp[32]; - char *p = buffer; MetricomAddressString addr_string; /* First, we must copy all of our data to a safe place, */ @@ -1103,98 +1081,104 @@ static int sprintf_status_info(char *buffer, struct strip *strip_info) unsigned long tx_ebytes = strip_info->tx_ebytes; #endif - p += sprintf(p, "\nInterface name\t\t%s\n", if_name); - p += sprintf(p, " Radio working:\t\t%s\n", working ? "Yes" : "No"); + seq_printf(seq, "\nInterface name\t\t%s\n", if_name); + seq_printf(seq, " Radio working:\t\t%s\n", working ? "Yes" : "No"); radio_address_to_string(&true_dev_addr, &addr_string); - p += sprintf(p, " Radio address:\t\t%s\n", addr_string.c); + seq_printf(seq, " Radio address:\t\t%s\n", addr_string.c); if (manual_dev_addr) { radio_address_to_string(&dev_dev_addr, &addr_string); - p += sprintf(p, " Device address:\t%s\n", addr_string.c); + seq_printf(seq, " Device address:\t%s\n", addr_string.c); } - p += sprintf(p, " Firmware version:\t%s", !working ? "Unknown" : + seq_printf(seq, " Firmware version:\t%s", !working ? "Unknown" : !firmware_level ? "Should be upgraded" : firmware_version.c); if (firmware_level >= ChecksummedMessages) - p += sprintf(p, " (Checksums Enabled)"); - p += sprintf(p, "\n"); - p += sprintf(p, " Serial number:\t\t%s\n", serial_number.c); - p += sprintf(p, " Battery voltage:\t%s\n", battery_voltage.c); - p += sprintf(p, " Transmit queue (bytes):%d\n", tx_left); - p += sprintf(p, " Receive packet rate: %ld packets per second\n", + seq_printf(seq, " (Checksums Enabled)"); + seq_printf(seq, "\n"); + seq_printf(seq, " Serial number:\t\t%s\n", serial_number.c); + seq_printf(seq, " Battery voltage:\t%s\n", battery_voltage.c); + seq_printf(seq, " Transmit queue (bytes):%d\n", tx_left); + seq_printf(seq, " Receive packet rate: %ld packets per second\n", rx_average_pps / 8); - p += sprintf(p, " Transmit packet rate: %ld packets per second\n", + seq_printf(seq, " Transmit packet rate: %ld packets per second\n", tx_average_pps / 8); - p += sprintf(p, " Sent packet rate: %ld packets per second\n", + seq_printf(seq, " Sent packet rate: %ld packets per second\n", sx_average_pps / 8); - p += sprintf(p, " Next watchdog probe:\t%s\n", + seq_printf(seq, " Next watchdog probe:\t%s\n", time_delta(temp, watchdog_doprobe)); - p += sprintf(p, " Next watchdog reset:\t%s\n", + seq_printf(seq, " Next watchdog reset:\t%s\n", time_delta(temp, watchdog_doreset)); - p += sprintf(p, " Next gratuitous ARP:\t"); + seq_printf(seq, " Next gratuitous ARP:\t"); if (!memcmp (strip_info->dev->dev_addr, zero_address.c, sizeof(zero_address))) - p += sprintf(p, "Disabled\n"); + seq_printf(seq, "Disabled\n"); else { - p += sprintf(p, "%s\n", time_delta(temp, gratuitous_arp)); - p += sprintf(p, " Next ARP interval:\t%ld seconds\n", + seq_printf(seq, "%s\n", time_delta(temp, gratuitous_arp)); + seq_printf(seq, " Next ARP interval:\t%ld seconds\n", JIFFIE_TO_SEC(arp_interval)); } if (working) { #ifdef EXT_COUNTERS - p += sprintf(p, "\n"); - p += sprintf(p, + seq_printf(seq, "\n"); + seq_printf(seq, " Total bytes: \trx:\t%lu\ttx:\t%lu\n", rx_bytes, tx_bytes); - p += sprintf(p, + seq_printf(seq, " thru radio: \trx:\t%lu\ttx:\t%lu\n", rx_rbytes, tx_rbytes); - p += sprintf(p, + seq_printf(seq, " thru serial port: \trx:\t%lu\ttx:\t%lu\n", rx_sbytes, tx_sbytes); - p += sprintf(p, + seq_printf(seq, " Total stat/err bytes:\trx:\t%lu\ttx:\t%lu\n", rx_ebytes, tx_ebytes); #endif - p += sprintf_neighbours(p, &strip_info->poletops, + strip_seq_neighbours(seq, &strip_info->poletops, "Poletops:"); - p += sprintf_neighbours(p, &strip_info->portables, + strip_seq_neighbours(seq, &strip_info->portables, "Portables:"); } - - return p - buffer; } /* * This function is exports status information from the STRIP driver through * the /proc file system. */ +static int strip_seq_show(struct seq_file *seq, void *v) +{ + if (v == STRIP_PROC_HEADER) + seq_printf(seq, "strip_version: %s\n", StripVersion); + else + strip_seq_status_info(seq, (const struct strip *)v); + return 0; +} + -static int get_status_info(char *buffer, char **start, off_t req_offset, - int req_len) +static struct seq_operations strip_seq_ops = { + .start = strip_seq_start, + .next = strip_seq_next, + .stop = strip_seq_stop, + .show = strip_seq_show, +}; + +static int strip_seq_open(struct inode *inode, struct file *file) { - int total = 0, slop = 0; - struct strip *strip_info = struct_strip_list; - char *buf = buffer; - - buf += sprintf(buf, "strip_version: %s\n", StripVersion); - if (shift_buffer(buffer, req_offset, req_len, &total, &slop, &buf)) - goto exit; - - while (strip_info != NULL) { - buf += sprintf_status_info(buf, strip_info); - if (shift_buffer - (buffer, req_offset, req_len, &total, &slop, &buf)) - break; - strip_info = strip_info->next; - } - exit: - return (calc_start_len - (buffer, start, req_offset, req_len, total, buf)); + return seq_open(file, &strip_seq_ops); } +static struct file_operations strip_seq_fops = { + .owner = THIS_MODULE, + .open = strip_seq_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + + + /************************************************************************/ /* Sending routines */ @@ -1578,7 +1562,6 @@ static void strip_send(struct strip *strip_info, struct sk_buff *skb) static int strip_xmit(struct sk_buff *skb, struct net_device *dev) { struct strip *strip_info = (struct strip *) (dev->priv); - unsigned long flags; if (!netif_running(dev)) { printk(KERN_ERR "%s: xmit call when iface is down\n", @@ -1617,14 +1600,11 @@ static int strip_xmit(struct sk_buff *skb, struct net_device *dev) strip_info->dev->name, sx_pps_count / 8); } - spin_lock_irqsave(&strip_lock, flags); - /* See if someone has been ifconfigging */ - if (strip_info->mtu != strip_info->dev->mtu) - strip_changedmtu(strip_info); + spin_lock_bh(&strip_lock); strip_send(strip_info, skb); - spin_unlock_irqrestore(&strip_lock, flags); + spin_unlock_bh(&strip_lock); if (skb) dev_kfree_skb(skb); @@ -2317,18 +2297,12 @@ static void strip_receive_buf(struct tty_struct *tty, const unsigned char *cp, { struct strip *strip_info = (struct strip *) tty->disc_data; const unsigned char *end = cp + count; - unsigned long flags; if (!strip_info || strip_info->magic != STRIP_MAGIC || !netif_running(strip_info->dev)) return; - spin_lock_irqsave(&strip_lock, flags); - - /* Argh! mtu change time! - costs us the packet part received at the change */ - if (strip_info->mtu != strip_info->dev->mtu) - strip_changedmtu(strip_info); - + spin_lock_bh(&strip_lock); #if 0 { struct timeval tv; @@ -2395,7 +2369,7 @@ static void strip_receive_buf(struct tty_struct *tty, const unsigned char *cp, } cp++; } - spin_unlock_irqrestore(&strip_lock, flags); + spin_unlock_bh(&strip_lock); } @@ -2483,7 +2457,7 @@ static int strip_open_low(struct net_device *dev) if (strip_info->tty == NULL) return (-ENODEV); - if (!allocate_buffers(strip_info)) + if (!allocate_buffers(strip_info, dev->mtu)) return (-ENOMEM); strip_info->sx_count = 0; @@ -2543,12 +2517,14 @@ static int strip_close_low(struct net_device *dev) * (dynamically assigned) device is registered */ -static int strip_dev_init(struct net_device *dev) +static void strip_dev_setup(struct net_device *dev) { /* * Finish setting up the DEVICE info. */ + SET_MODULE_OWNER(dev); + dev->trans_start = 0; dev->last_rx = 0; dev->tx_queue_len = 30; /* Drop after 30 frames queued */ @@ -2576,7 +2552,7 @@ static int strip_dev_init(struct net_device *dev) dev->rebuild_header = strip_rebuild_header; dev->set_mac_address = dev_set_mac_address; dev->get_stats = strip_get_stats; - return 0; + dev->change_mtu = strip_change_mtu; } /* @@ -2585,65 +2561,34 @@ static int strip_dev_init(struct net_device *dev) static void strip_free(struct strip *strip_info) { - *(strip_info->referrer) = strip_info->next; - if (strip_info->next) - strip_info->next->referrer = strip_info->referrer; + spin_lock_bh(&strip_lock); + list_del_rcu(&strip_info->list); + spin_unlock_bh(&strip_lock); + strip_info->magic = 0; - if (strip_info->dev) - kfree(strip_info->dev); - kfree(strip_info); + + kfree(strip_info->dev); } + /* * Allocate a new free STRIP channel */ - static struct strip *strip_alloc(void) { - int channel_id = 0; - struct strip **s = &struct_strip_list; + struct list_head *n; struct net_device *dev; - struct strip *strip_info = (struct strip *) - kmalloc(sizeof(struct strip), GFP_KERNEL); + struct strip *strip_info; - if (!strip_info) - return NULL; /* If no more memory, return */ + dev = alloc_netdev(sizeof(struct strip), "st%d", + strip_dev_setup); - /* - * Clear the allocated memory - */ + if (!dev) + return NULL; /* If no more memory, return */ - memset(strip_info, 0, sizeof(struct strip)); - /* allocate the net_device */ - dev = kmalloc(sizeof(struct net_device), GFP_KERNEL); - if (!dev) { - kfree(strip_info); - return NULL; - } + strip_info = dev->priv; strip_info->dev = dev; - SET_MODULE_OWNER(dev); - - /* - * Search the list to find where to put our new entry - * (and in the process decide what channel number it is - * going to be) - */ - - while (*s && (*s)->dev->base_addr == channel_id) { - channel_id++; - s = &(*s)->next; - } - - /* - * Fill in the link pointers - */ - - strip_info->next = *s; - if (*s) - (*s)->referrer = &strip_info->next; - strip_info->referrer = s; - *s = strip_info; strip_info->magic = STRIP_MAGIC; strip_info->tty = NULL; @@ -2654,12 +2599,27 @@ static struct strip *strip_alloc(void) strip_info->idle_timer.data = (long) dev; strip_info->idle_timer.function = strip_IdleTask; - /* Note: strip_info->if_name is currently 8 characters long */ - sprintf(dev->name, "st%d", channel_id); - dev->base_addr = channel_id; - dev->priv = (void *) strip_info; - dev->next = NULL; - dev->init = strip_dev_init; + + spin_lock_bh(&strip_lock); + rescan: + /* + * Search the list to find where to put our new entry + * (and in the process decide what channel number it is + * going to be) + */ + list_for_each(n, &strip_list) { + struct strip *s = hlist_entry(n, struct strip, list); + + if (s->dev->base_addr == dev->base_addr) { + ++dev->base_addr; + goto rescan; + } + } + + sprintf(dev->name, "st%ld", dev->base_addr); + + list_add_tail_rcu(&strip_info->list, &strip_list); + spin_unlock_bh(&strip_lock); return strip_info; } @@ -2809,6 +2769,7 @@ static int strip_ioctl(struct tty_struct *tty, struct file *file, static struct tty_ldisc strip_ldisc = { .magic = TTY_LDISC_MAGIC, .name = "strip", + .owner = THIS_MODULE, .open = strip_open, .close = strip_close, .ioctl = strip_ioctl, @@ -2832,7 +2793,6 @@ static int __init strip_init_driver(void) printk(signon, StripVersion); - spin_lock_init(&strip_lock); /* * Fill in our line protocol discipline, and register it @@ -2844,7 +2804,7 @@ static int __init strip_init_driver(void) /* * Register the status file with /proc */ - proc_net_create("strip", S_IFREG | S_IRUGO, get_status_info); + proc_net_fops_create("strip", S_IFREG | S_IRUGO, &strip_seq_fops); return status; } @@ -2857,8 +2817,13 @@ static const char signoff[] __exitdata = static void __exit strip_exit_driver(void) { int i; - while (struct_strip_list) - strip_free(struct_strip_list); + struct list_head *p,*n; + + /* module ref count rules assure that all entries are unregistered */ + list_for_each_safe(p, n, &strip_list) { + struct strip *s = list_entry(p, struct strip, list); + strip_free(s); + } /* Unregister with the /proc/net file here. */ proc_net_remove("strip"); diff --git a/drivers/net/wireless/wavelan.c b/drivers/net/wireless/wavelan.c index 1289254b24a6..6751898d5c88 100644 --- a/drivers/net/wireless/wavelan.c +++ b/drivers/net/wireless/wavelan.c @@ -4410,7 +4410,7 @@ void cleanup_module(void) /* Free pieces. */ kfree(dev->priv); - kfree(dev); + free_netdev(dev); } #ifdef DEBUG_MODULE_TRACE diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c index 83fb2e0873b9..57d70a61a1a6 100644 --- a/drivers/net/yellowfin.c +++ b/drivers/net/yellowfin.c @@ -1486,7 +1486,7 @@ static void __devexit yellowfin_remove_one (struct pci_dev *pdev) iounmap ((void *) dev->base_addr); #endif - kfree (dev); + free_netdev (dev); pci_set_drvdata(pdev, NULL); } diff --git a/drivers/net/znet.c b/drivers/net/znet.c index 741a223f293e..910d5e898b0f 100644 --- a/drivers/net/znet.c +++ b/drivers/net/znet.c @@ -941,7 +941,7 @@ static __exit void znet_cleanup (void) kfree (znet->rx_start); kfree (znet->tx_start); unregister_netdev (znet_dev); - kfree (znet_dev); + free_netdev (znet_dev); } #endif } diff --git a/drivers/net/zorro8390.c b/drivers/net/zorro8390.c index ade2d297e4ea..05b9d98a873f 100644 --- a/drivers/net/zorro8390.c +++ b/drivers/net/zorro8390.c @@ -413,7 +413,7 @@ static void __exit zorro8390_cleanup(void) unregister_netdev(dev); free_irq(IRQ_AMIGA_PORTS, dev); release_mem_region(ZTWO_PADDR(dev->base_addr), NE_IO_EXTENT*2); - kfree(dev); + free_netdev(dev); root_zorro8390_dev = next; } #endif diff --git a/drivers/s390/net/ctcmain.c b/drivers/s390/net/ctcmain.c index aff23e1ff8c7..d40c0f756adf 100644 --- a/drivers/s390/net/ctcmain.c +++ b/drivers/s390/net/ctcmain.c @@ -2708,7 +2708,7 @@ ctc_free_netdevice(struct net_device * dev, int free_dev) } #ifdef MODULE if (free_dev) - kfree(dev); + free_netdev(dev); #endif } diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c index 89359886cfa0..684b33491bfe 100644 --- a/drivers/s390/net/netiucv.c +++ b/drivers/s390/net/netiucv.c @@ -1654,7 +1654,7 @@ netiucv_free_netdevice(struct net_device *dev) kfree_fsm(privptr->fsm); kfree(privptr); } - kfree(dev); + free_netdev(dev); } static ssize_t diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index 9f2cfa519ca2..9d0073171a8f 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c @@ -1635,6 +1635,7 @@ eth_unbind (struct usb_gadget *gadget) } unregister_netdev (dev->net); + free_netdev(dev->net); /* assuming we used keventd, it must quiesce too */ flush_scheduled_work (); diff --git a/drivers/usb/net/catc.c b/drivers/usb/net/catc.c index 720032cf79e8..51299e45989d 100644 --- a/drivers/usb/net/catc.c +++ b/drivers/usb/net/catc.c @@ -961,7 +961,7 @@ static void catc_disconnect(struct usb_interface *intf) usb_free_urb(catc->tx_urb); usb_free_urb(catc->rx_urb); usb_free_urb(catc->irq_urb); - kfree(catc->netdev); + free_netdev(catc->netdev); kfree(catc); } } diff --git a/drivers/usb/net/kaweth.c b/drivers/usb/net/kaweth.c index a0253e49cff3..00a368f0ff1a 100644 --- a/drivers/usb/net/kaweth.c +++ b/drivers/usb/net/kaweth.c @@ -1189,7 +1189,7 @@ static void kaweth_disconnect(struct usb_interface *intf) kaweth_dbg("Unregistering net device"); unregister_netdev(kaweth->net); - kfree(kaweth->net); + free_netdev(kaweth->net); } usb_free_urb(kaweth->rx_urb); diff --git a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c index 60a3fb1d1f7e..eabaae5e4e22 100644 --- a/drivers/usb/net/pegasus.c +++ b/drivers/usb/net/pegasus.c @@ -1310,7 +1310,7 @@ static void pegasus_disconnect(struct usb_interface *intf) free_skb_pool(pegasus); if (pegasus->rx_skb) dev_kfree_skb(pegasus->rx_skb); - kfree(pegasus->net); + free_netdev(pegasus->net); kfree(pegasus); } diff --git a/drivers/usb/net/rtl8150.c b/drivers/usb/net/rtl8150.c index a42b90921905..eb12cca50935 100644 --- a/drivers/usb/net/rtl8150.c +++ b/drivers/usb/net/rtl8150.c @@ -870,7 +870,7 @@ static void rtl8150_disconnect(struct usb_interface *intf) free_skb_pool(dev); if (dev->rx_skb) dev_kfree_skb(dev->rx_skb); - kfree(dev->netdev); + free_netdev(dev->netdev); kfree(dev->intr_buff); kfree(dev); } diff --git a/include/linux/atmdev.h b/include/linux/atmdev.h index 0fcfe8f1abae..0bf8106530b9 100644 --- a/include/linux/atmdev.h +++ b/include/linux/atmdev.h @@ -335,15 +335,16 @@ struct atm_dev { struct list_head dev_list; /* linkage */ }; + +/* OF: send_Oam Flags */ -/* - * ioctl, getsockopt, setsockopt, and sg_send are optional and can be set to - * NULL. */ +#define ATM_OF_IMMED 1 /* Attempt immediate delivery */ +#define ATM_OF_INRATE 2 /* Attempt in-rate delivery */ -/* OF: send_Oam Flags */ -#define ATM_OF_IMMED 1 /* Attempt immediate delivery */ -#define ATM_OF_INRATE 2 /* Attempt in-rate delivery */ +/* + * ioctl, getsockopt, and setsockopt are optional and can be set to NULL. + */ struct atmdev_ops { /* only send is required */ void (*dev_close)(struct atm_dev *dev); @@ -355,24 +356,15 @@ struct atmdev_ops { /* only send is required */ int (*setsockopt)(struct atm_vcc *vcc,int level,int optname, void *optval,int optlen); int (*send)(struct atm_vcc *vcc,struct sk_buff *skb); - int (*sg_send)(struct atm_vcc *vcc,unsigned long start, - unsigned long size); -#if 0 /* keep the current hack for now */ - int (*send_iovec)(struct atm_vcc *vcc,struct iovec *iov,int size, - void (*discard)(struct atm_vcc *vcc,void *user),void *user); -#endif int (*send_oam)(struct atm_vcc *vcc,void *cell,int flags); void (*phy_put)(struct atm_dev *dev,unsigned char value, unsigned long addr); unsigned char (*phy_get)(struct atm_dev *dev,unsigned long addr); - void (*feedback)(struct atm_vcc *vcc,struct sk_buff *skb, - unsigned long start,unsigned long dest,int len); int (*change_qos)(struct atm_vcc *vcc,struct atm_qos *qos,int flags); int (*proc_read)(struct atm_dev *dev,loff_t *pos,char *page); struct module *owner; }; - struct atmphy_ops { int (*start)(struct atm_dev *dev); int (*ioctl)(struct atm_dev *dev,unsigned int cmd,void *arg); diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 7b39dbf331d3..cfa7e4087684 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -51,6 +51,7 @@ struct ethtool_ops; #define HAVE_ALLOC_NETDEV /* feature macro: alloc_xxxdev functions are available. */ +#define HAVE_FREE_NETDEV #define NET_XMIT_SUCCESS 0 #define NET_XMIT_DROP 1 /* skb dropped */ @@ -384,6 +385,7 @@ struct net_device NETREG_REGISTERED, /* completed register todo */ NETREG_UNREGISTERING, /* called unregister_netdevice */ NETREG_UNREGISTERED, /* completed unregister todo */ + NETREG_RELEASED, /* called free_netdev */ } reg_state; /* Net device features */ @@ -516,6 +518,7 @@ extern int dev_close(struct net_device *dev); extern int dev_queue_xmit(struct sk_buff *skb); extern int register_netdevice(struct net_device *dev); extern int unregister_netdevice(struct net_device *dev); +extern void free_netdev(struct net_device *dev); extern void synchronize_net(void); extern int register_netdevice_notifier(struct notifier_block *nb); extern int unregister_netdevice_notifier(struct notifier_block *nb); diff --git a/include/net/irda/irlan_common.h b/include/net/irda/irlan_common.h index de3a7fdbebc3..5568fb8b4478 100644 --- a/include/net/irda/irlan_common.h +++ b/include/net/irda/irlan_common.h @@ -33,7 +33,6 @@ #include <linux/skbuff.h> #include <linux/netdevice.h> -#include <net/irda/irqueue.h> #include <net/irda/irttp.h> #define IRLAN_MTU 1518 @@ -161,10 +160,9 @@ struct irlan_provider_cb { * IrLAN control block */ struct irlan_cb { - irda_queue_t q; /* Must be first */ - int magic; - struct net_device dev; /* Ethernet device structure*/ + struct list_head dev_list; + struct net_device *dev; /* Ethernet device structure*/ struct net_device_stats stats; __u32 saddr; /* Source device address */ @@ -204,6 +202,7 @@ void irlan_open_data_tsap(struct irlan_cb *self); int irlan_run_ctrl_tx_queue(struct irlan_cb *self); +struct irlan_cb *irlan_get_any(void); void irlan_get_provider_info(struct irlan_cb *self); void irlan_get_unicast_addr(struct irlan_cb *self); void irlan_get_media_char(struct irlan_cb *self); @@ -222,8 +221,6 @@ int irlan_insert_array_param(struct sk_buff *skb, char *name, __u8 *value, int irlan_extract_param(__u8 *buf, char *name, char *value, __u16 *len); void print_ret_code(__u8 code); -extern hashbin_t *irlan; - #endif diff --git a/include/net/irda/irlan_eth.h b/include/net/irda/irlan_eth.h index 53c6ae82bd6c..e74c63021f6a 100644 --- a/include/net/irda/irlan_eth.h +++ b/include/net/irda/irlan_eth.h @@ -25,7 +25,7 @@ #ifndef IRLAN_ETH_H #define IRLAN_ETH_H -int irlan_eth_init(struct net_device *dev); +void irlan_eth_setup(struct net_device *dev); int irlan_eth_open(struct net_device *dev); int irlan_eth_close(struct net_device *dev); int irlan_eth_receive(void *instance, void *sap, struct sk_buff *skb); diff --git a/include/net/irda/irlan_filter.h b/include/net/irda/irlan_filter.h index b68eec161b47..118212a0f31a 100644 --- a/include/net/irda/irlan_filter.h +++ b/include/net/irda/irlan_filter.h @@ -28,6 +28,6 @@ void irlan_check_command_param(struct irlan_cb *self, char *param, char *value); void handle_filter_request(struct irlan_cb *self, struct sk_buff *skb); -int irlan_print_filter(int filter_type, char *buf); +int irlan_print_filter(struct seq_file *seq, int filter_type); #endif /* IRLAN_FILTER_H */ diff --git a/include/net/neighbour.h b/include/net/neighbour.h index 1307be7bf187..24bee28fd7fb 100644 --- a/include/net/neighbour.h +++ b/include/net/neighbour.h @@ -181,6 +181,7 @@ extern struct neighbour * neigh_create(struct neigh_table *tbl, extern void neigh_destroy(struct neighbour *neigh); extern int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb); extern int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new, int override, int arp); +extern void neigh_changeaddr(struct neigh_table *tbl, struct net_device *dev); extern int neigh_ifdown(struct neigh_table *tbl, struct net_device *dev); extern int neigh_resolve_output(struct sk_buff *skb); extern int neigh_connected_output(struct sk_buff *skb); diff --git a/net/802/tr.c b/net/802/tr.c index 6e029d3932fe..1eb39e9e2e57 100644 --- a/net/802/tr.c +++ b/net/802/tr.c @@ -33,6 +33,7 @@ #include <linux/timer.h> #include <linux/net.h> #include <linux/proc_fs.h> +#include <linux/seq_file.h> #include <linux/init.h> #include <net/arp.h> @@ -456,84 +457,108 @@ static void rif_check_expire(unsigned long dummy) * routing. */ -#ifndef CONFIG_PROC_FS -static int rif_get_info(char *buffer,char **start, off_t offset, int length) { return 0;} -#else -static int rif_get_info(char *buffer,char **start, off_t offset, int length) +#ifdef CONFIG_PROC_FS +/* Magic token to indicate first entry (header line) */ +#define RIF_PROC_START ((void *)1) + +static struct rif_cache_s *rif_get_idx(loff_t pos) +{ + int i; + struct rif_cache_s *entry; + loff_t off = 0; + + for(i=0;i < RIF_TABLE_SIZE;i++) + for(entry=rif_table[i];entry;entry=entry->next) { + if (off == pos) + return entry; + ++off; + } + + return NULL; +} + +static void *rif_seq_start(struct seq_file *seq, loff_t *pos) { - int len=0; - off_t begin=0; - off_t pos=0; - int size,i,j,rcf_len,segment,brdgnmb; - unsigned long now=jiffies; unsigned long flags; - rif_cache entry; + spin_lock_irqsave(&rif_lock, flags); + seq->private = (void *) flags; + + return *pos ? rif_get_idx(*pos - 1) : RIF_PROC_START; +} + +static void *rif_seq_next(struct seq_file *seq, void *v, loff_t *pos) +{ + return rif_get_idx(*pos++); +} - size=sprintf(buffer, +static void rif_seq_stop(struct seq_file *seq, void *v) +{ + unsigned long flags = (unsigned long) seq->private; + spin_lock_irqsave(&rif_lock, flags); +} + +static int rif_seq_show(struct seq_file *seq, void *v) +{ + int j, rcf_len, segment, brdgnmb; + rif_cache entry = v; + + if (v == RIF_PROC_START) + seq_puts(seq, "if TR address TTL rcf routing segments\n"); - pos+=size; - len+=size; + else { + struct net_device *dev = dev_get_by_index(entry->iface); - spin_lock_irqsave(&rif_lock,flags); - for(i=0;i < RIF_TABLE_SIZE;i++) - { - for(entry=rif_table[i];entry;entry=entry->next) { - struct net_device *dev = __dev_get_by_index(entry->iface); + seq_printf(seq, "%s %02X:%02X:%02X:%02X:%02X:%02X %7li ", + dev?dev->name:"?", + entry->addr[0],entry->addr[1],entry->addr[2], + entry->addr[3],entry->addr[4],entry->addr[5], + sysctl_tr_rif_timeout-(jiffies-entry->last_used)); - size=sprintf(buffer+len,"%s %02X:%02X:%02X:%02X:%02X:%02X %7li ", - dev?dev->name:"?",entry->addr[0],entry->addr[1],entry->addr[2],entry->addr[3],entry->addr[4],entry->addr[5], - sysctl_tr_rif_timeout-(now-entry->last_used)); - len+=size; - pos=begin+len; if (entry->local_ring) - size=sprintf(buffer+len,"local\n"); + seq_puts(seq, "local\n"); else { - size=sprintf(buffer+len,"%04X", ntohs(entry->rcf)); + + seq_printf(seq, "%04X", ntohs(entry->rcf)); rcf_len = ((ntohs(entry->rcf) & TR_RCF_LEN_MASK)>>8)-2; if (rcf_len) rcf_len >>= 1; for(j = 1; j < rcf_len; j++) { if(j==1) { segment=ntohs(entry->rseg[j-1])>>4; - len+=size; - pos=begin+len; - size=sprintf(buffer+len," %03X",segment); + seq_printf(seq," %03X",segment); }; segment=ntohs(entry->rseg[j])>>4; brdgnmb=ntohs(entry->rseg[j-1])&0x00f; - len+=size; - pos=begin+len; - size=sprintf(buffer+len,"-%01X-%03X",brdgnmb,segment); + seq_printf(seq,"-%01X-%03X",brdgnmb,segment); } - len+=size; - pos=begin+len; - size=sprintf(buffer+len,"\n"); + seq_putc(seq, '\n'); } - len+=size; - pos=begin+len; - - if(pos<offset) - { - len=0; - begin=pos; - } - if(pos>offset+length) - break; } - if(pos>offset+length) - break; - } - spin_unlock_irqrestore(&rif_lock,flags); + return 0; +} + + +static struct seq_operations rif_seq_ops = { + .start = rif_seq_start, + .next = rif_seq_next, + .stop = rif_seq_stop, + .show = rif_seq_show, +}; - *start=buffer+(offset-begin); /* Start of wanted data */ - len-=(offset-begin); /* Start slop */ - if(len>length) - len=length; /* Ending slop */ - if (len<0) - len=0; - return len; +static int rif_seq_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &rif_seq_ops); } + +static struct file_operations rif_seq_fops = { + .owner = THIS_MODULE, + .open = rif_seq_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + #endif /* @@ -549,7 +574,7 @@ static int __init rif_init(void) rif_timer.function = rif_check_expire; add_timer(&rif_timer); - proc_net_create("tr_rif",0,rif_get_info); + proc_net_fops_create("tr_rif", S_IRUGO, &rif_seq_fops); return 0; } diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index f4dd67ca3118..03f7077524f5 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c @@ -358,7 +358,7 @@ static void vlan_setup(struct net_device *new_dev) new_dev->stop = vlan_dev_stop; new_dev->set_mac_address = vlan_dev_set_mac_address; new_dev->set_multicast_list = vlan_dev_set_multicast_list; - new_dev->destructor = (void (*)(struct net_device *)) kfree; + new_dev->destructor = free_netdev; } /* Attach a VLAN device to a mac address (ie Ethernet Card). diff --git a/net/Kconfig b/net/Kconfig index e2aa43ed5c15..7aab60e25d25 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -662,6 +662,7 @@ menu "Network testing" config NET_PKTGEN tristate "Packet Generator (USE WITH CAUTION)" + depends on PROC_FS ---help--- This module will inject preconfigured packets, at a configurable rate, out of a given interface. It is used for network interface diff --git a/net/atm/br2684.c b/net/atm/br2684.c index 6c7f4fa24552..fa25cbdd9a80 100644 --- a/net/atm/br2684.c +++ b/net/atm/br2684.c @@ -66,7 +66,7 @@ enum br2684_encaps { struct br2684_vcc { struct atm_vcc *atmvcc; - struct br2684_dev *brdev; + struct net_device *device; /* keep old push,pop functions for chaining */ void (*old_push)(struct atm_vcc *vcc,struct sk_buff *skb); /* void (*old_pop)(struct atm_vcc *vcc,struct sk_buff *skb); */ @@ -81,7 +81,7 @@ struct br2684_vcc { }; struct br2684_dev { - struct net_device net_dev; + struct net_device *net_dev; struct list_head br2684_devs; int number; struct list_head brvccs; /* one device <=> one vcc (before xmas) */ @@ -102,13 +102,12 @@ static LIST_HEAD(br2684_devs); static inline struct br2684_dev *BRPRIV(const struct net_device *net_dev) { - return (struct br2684_dev *) ((char *) (net_dev) - - (unsigned long) (&((struct br2684_dev *) 0)->net_dev)); + return (struct br2684_dev *) net_dev->priv; } -static inline struct br2684_dev *list_entry_brdev(const struct list_head *le) +static inline struct net_device *list_entry_brdev(const struct list_head *le) { - return list_entry(le, struct br2684_dev, br2684_devs); + return list_entry(le, struct br2684_dev, br2684_devs)->net_dev; } static inline struct br2684_vcc *BR2684_VCC(const struct atm_vcc *atmvcc) @@ -122,24 +121,23 @@ static inline struct br2684_vcc *list_entry_brvcc(const struct list_head *le) } /* Caller should hold read_lock(&devs_lock) */ -static struct br2684_dev *br2684_find_dev(const struct br2684_if_spec *s) +static struct net_device *br2684_find_dev(const struct br2684_if_spec *s) { struct list_head *lh; - struct br2684_dev *brdev; + struct net_device *net_dev; switch (s->method) { case BR2684_FIND_BYNUM: list_for_each(lh, &br2684_devs) { - brdev = list_entry_brdev(lh); - if (brdev->number == s->spec.devnum) - return brdev; + net_dev = list_entry_brdev(lh); + if (BRPRIV(net_dev)->number == s->spec.devnum) + return net_dev; } break; case BR2684_FIND_BYIFNAME: list_for_each(lh, &br2684_devs) { - brdev = list_entry_brdev(lh); - if (!strncmp(brdev->net_dev.name, s->spec.ifname, - sizeof brdev->net_dev.name)) - return brdev; + net_dev = list_entry_brdev(lh); + if (!strncmp(net_dev->name, s->spec.ifname, IFNAMSIZ)) + return net_dev; } break; } @@ -357,7 +355,7 @@ static int br2684_setfilt(struct atm_vcc *atmvcc, unsigned long arg) */ struct br2684_dev *brdev; read_lock(&devs_lock); - brdev = br2684_find_dev(&fs.ifspec); + brdev = BRPRIV(br2684_find_dev(&fs.ifspec)); if (brdev == NULL || list_empty(&brdev->brvccs) || brdev->brvccs.next != brdev->brvccs.prev) /* >1 VCC */ brvcc = NULL; @@ -393,33 +391,35 @@ packet_fails_filter(u16 type, struct br2684_vcc *brvcc, struct sk_buff *skb) static void br2684_close_vcc(struct br2684_vcc *brvcc) { - DPRINTK("removing VCC %p from dev %p\n", brvcc, brvcc->brdev); + DPRINTK("removing VCC %p from dev %p\n", brvcc, brvcc->device); write_lock_irq(&devs_lock); list_del(&brvcc->brvccs); write_unlock_irq(&devs_lock); brvcc->atmvcc->user_back = NULL; /* what about vcc->recvq ??? */ brvcc->old_push(brvcc->atmvcc, NULL); /* pass on the bad news */ kfree(brvcc); - MOD_DEC_USE_COUNT; + module_put(THIS_MODULE); } /* when AAL5 PDU comes in: */ static void br2684_push(struct atm_vcc *atmvcc, struct sk_buff *skb) { struct br2684_vcc *brvcc = BR2684_VCC(atmvcc); - struct br2684_dev *brdev = brvcc->brdev; + struct net_device *net_dev = brvcc->device; + struct br2684_dev *brdev = BRPRIV(net_dev); int plen = sizeof(llc_oui_pid_pad) + ETH_HLEN; DPRINTK("br2684_push\n"); - if (skb == NULL) { /* skb==NULL means VCC is being destroyed */ + if (unlikely(skb == NULL)) { + /* skb==NULL means VCC is being destroyed */ br2684_close_vcc(brvcc); if (list_empty(&brdev->brvccs)) { read_lock(&devs_lock); list_del(&brdev->br2684_devs); read_unlock(&devs_lock); - unregister_netdev(&brdev->net_dev); - kfree(brdev); + unregister_netdev(net_dev); + free_netdev(net_dev); } return; } @@ -460,24 +460,25 @@ static void br2684_push(struct atm_vcc *atmvcc, struct sk_buff *skb) #ifdef CONFIG_BR2684_FAST_TRANS skb->protocol = ((u16 *) skb->data)[-1]; #else /* some protocols might require this: */ - skb->protocol = br_type_trans(skb, &brdev->net_dev); + skb->protocol = br_type_trans(skb, net_dev); #endif /* CONFIG_BR2684_FAST_TRANS */ #else skb_pull(skb, plen - ETH_HLEN); - skb->protocol = eth_type_trans(skb, &brdev->net_dev); + skb->protocol = eth_type_trans(skb, net_dev); #endif /* FASTER_VERSION */ #ifdef CONFIG_ATM_BR2684_IPFILTER - if (packet_fails_filter(skb->protocol, brvcc, skb)) { + if (unlikely(packet_fails_filter(skb->protocol, brvcc, skb))) { brdev->stats.rx_dropped++; dev_kfree_skb(skb); return; } #endif /* CONFIG_ATM_BR2684_IPFILTER */ - skb->dev = &brdev->net_dev; + skb->dev = net_dev; ATM_SKB(skb)->vcc = atmvcc; /* needed ? */ DPRINTK("received packet's protocol: %x\n", ntohs(skb->protocol)); skb_debug(skb); - if (!(brdev->net_dev.flags & IFF_UP)) { /* sigh, interface is down */ + if (unlikely(!(net_dev->flags & IFF_UP))) { + /* sigh, interface is down */ brdev->stats.rx_dropped++; dev_kfree_skb(skb); return; @@ -498,26 +499,30 @@ Note: we do not have explicit unassign, but look at _push() struct sk_buff_head copy; struct sk_buff *skb; struct br2684_dev *brdev; + struct net_device *net_dev; struct atm_backend_br2684 be; - MOD_INC_USE_COUNT; - if (copy_from_user(&be, (void *) arg, sizeof be)) { - MOD_DEC_USE_COUNT; + if (copy_from_user(&be, (void *) arg, sizeof be)) return -EFAULT; - } + brvcc = kmalloc(sizeof(struct br2684_vcc), GFP_KERNEL); + if (!brvcc) + return -ENOMEM; + memset(brvcc, 0, sizeof(struct br2684_vcc)); write_lock_irq(&devs_lock); - brdev = br2684_find_dev(&be.ifspec); - if (brdev == NULL) { + net_dev = br2684_find_dev(&be.ifspec); + if (net_dev == NULL) { printk(KERN_ERR "br2684: tried to attach to non-existant device\n"); err = -ENXIO; goto error; } + brdev = BRPRIV(net_dev); if (atmvcc->push == NULL) { err = -EBADFD; goto error; } - if (!list_empty(&brdev->brvccs)) { /* Only 1 VCC/dev right now */ + if (!list_empty(&brdev->brvccs)) { + /* Only 1 VCC/dev right now */ err = -EEXIST; goto error; } @@ -528,25 +533,18 @@ Note: we do not have explicit unassign, but look at _push() err = -EINVAL; goto error; } - brvcc = kmalloc(sizeof(struct br2684_vcc), GFP_KERNEL); - if (!brvcc) { - err = -ENOMEM; - goto error; - } - memset(brvcc, 0, sizeof(struct br2684_vcc)); DPRINTK("br2684_regvcc vcc=%p, encaps=%d, brvcc=%p\n", atmvcc, be.encaps, brvcc); if (list_empty(&brdev->brvccs) && !brdev->mac_was_set) { unsigned char *esi = atmvcc->dev->esi; if (esi[0] | esi[1] | esi[2] | esi[3] | esi[4] | esi[5]) - memcpy(brdev->net_dev.dev_addr, esi, - brdev->net_dev.addr_len); + memcpy(net_dev->dev_addr, esi, net_dev->addr_len); else - brdev->net_dev.dev_addr[2] = 1; + net_dev->dev_addr[2] = 1; } list_add(&brvcc->brvccs, &brdev->brvccs); write_unlock_irq(&devs_lock); - brvcc->brdev = brdev; + brvcc->device = net_dev; brvcc->atmvcc = atmvcc; atmvcc->user_back = brvcc; brvcc->encaps = (enum br2684_encaps) be.encaps; @@ -560,80 +558,74 @@ Note: we do not have explicit unassign, but look at _push() BRPRIV(skb->dev)->stats.rx_packets--; br2684_push(atmvcc, skb); } + (void) try_module_get(THIS_MODULE); return 0; error: write_unlock_irq(&devs_lock); - MOD_DEC_USE_COUNT; + kfree(brvcc); return err; } +static void br2684_setup(struct net_device *netdev) +{ + struct br2684_dev *brdev = BRPRIV(netdev); + + ether_setup(netdev); + brdev->net_dev = netdev; + +#ifdef FASTER_VERSION + my_eth_header = netdev->hard_header; + netdev->hard_header = br2684_header; + my_eth_header_cache = netdev->hard_header_cache; + netdev->hard_header_cache = br2684_header_cache; + netdev->hard_header_len = sizeof(llc_oui_pid_pad) + ETH_HLEN; /* 10 + 14 */ +#endif + my_eth_mac_addr = netdev->set_mac_address; + netdev->set_mac_address = br2684_mac_addr; + netdev->hard_start_xmit = br2684_start_xmit; + netdev->get_stats = br2684_get_stats; + + INIT_LIST_HEAD(&brdev->brvccs); +} + static int br2684_create(unsigned long arg) { int err; + struct net_device *netdev; struct br2684_dev *brdev; struct atm_newif_br2684 ni; DPRINTK("br2684_create\n"); - /* - * We track module use by vcc's NOT the devices they're on. We're - * protected here against module death by the kernel_lock, but if - * we need to sleep we should make sure that the module doesn't - * disappear under us. - */ - MOD_INC_USE_COUNT; + if (copy_from_user(&ni, (void *) arg, sizeof ni)) { - MOD_DEC_USE_COUNT; return -EFAULT; } if (ni.media != BR2684_MEDIA_ETHERNET || ni.mtu != 1500) { - MOD_DEC_USE_COUNT; return -EINVAL; } - if ((brdev = kmalloc(sizeof(struct br2684_dev), GFP_KERNEL)) == NULL) { - MOD_DEC_USE_COUNT; - return -ENOMEM; - } - memset(brdev, 0, sizeof(struct br2684_dev)); - INIT_LIST_HEAD(&brdev->brvccs); - write_lock_irq(&devs_lock); - brdev->number = list_empty(&br2684_devs) ? 1 : - list_entry_brdev(br2684_devs.prev)->number + 1; - list_add_tail(&brdev->br2684_devs, &br2684_devs); - write_unlock_irq(&devs_lock); + netdev = alloc_netdev(sizeof(struct br2684_dev), + ni.ifname[0] ? ni.ifname : "nas%d", + br2684_setup); + if (!netdev) + return -ENOMEM; - if (ni.ifname[0] != '\0') { - memcpy(brdev->net_dev.name, ni.ifname, - sizeof(brdev->net_dev.name)); - brdev->net_dev.name[sizeof(brdev->net_dev.name) - 1] = '\0'; - } else - sprintf(brdev->net_dev.name, "nas%d", brdev->number); - DPRINTK("registered netdev %s\n", brdev->net_dev.name); - ether_setup(&brdev->net_dev); - brdev->mac_was_set = 0; -#ifdef FASTER_VERSION - my_eth_header = brdev->net_dev.hard_header; - brdev->net_dev.hard_header = br2684_header; - my_eth_header_cache = brdev->net_dev.hard_header_cache; - brdev->net_dev.hard_header_cache = br2684_header_cache; - brdev->net_dev.hard_header_len = sizeof(llc_oui_pid_pad) + ETH_HLEN; /* 10 + 14 */ -#endif - my_eth_mac_addr = brdev->net_dev.set_mac_address; - brdev->net_dev.set_mac_address = br2684_mac_addr; - brdev->net_dev.hard_start_xmit = br2684_start_xmit; - brdev->net_dev.get_stats = br2684_get_stats; + brdev = BRPRIV(netdev); + DPRINTK("registered netdev %s\n", netdev->name); /* open, stop, do_ioctl ? */ - err = register_netdev(&brdev->net_dev); - MOD_DEC_USE_COUNT; + err = register_netdev(netdev); if (err < 0) { printk(KERN_ERR "br2684_create: register_netdev failed\n"); - write_lock_irq(&devs_lock); - list_del(&brdev->br2684_devs); - write_unlock_irq(&devs_lock); - kfree(brdev); + free_netdev(netdev); return err; } + + write_lock_irq(&devs_lock); + brdev->number = list_empty(&br2684_devs) ? 1 : + BRPRIV(list_entry_brdev(br2684_devs.prev))->number + 1; + list_add_tail(&brdev->br2684_devs, &br2684_devs); + write_unlock_irq(&devs_lock); return 0; } @@ -649,9 +641,7 @@ static int br2684_ioctl(struct atm_vcc *atmvcc, unsigned int cmd, case ATM_SETBACKEND: case ATM_NEWBACKENDIF: { atm_backend_t b; - MOD_INC_USE_COUNT; err = get_user(b, (atm_backend_t *) arg); - MOD_DEC_USE_COUNT; if (err) return -EFAULT; if (b != ATM_BACKEND_BR2684) @@ -669,9 +659,7 @@ static int br2684_ioctl(struct atm_vcc *atmvcc, unsigned int cmd, return -ENOIOCTLCMD; if (!capable(CAP_NET_ADMIN)) return -EPERM; - MOD_INC_USE_COUNT; err = br2684_setfilt(atmvcc, arg); - MOD_DEC_USE_COUNT; return err; #endif /* CONFIG_ATM_BR2684_IPFILTER */ } @@ -682,20 +670,22 @@ static int br2684_ioctl(struct atm_vcc *atmvcc, unsigned int cmd, static int br2684_proc_engine(loff_t pos, char *buf) { struct list_head *lhd, *lhc; + struct net_device *net_dev; struct br2684_dev *brdev; struct br2684_vcc *brvcc; list_for_each(lhd, &br2684_devs) { - brdev = list_entry_brdev(lhd); + net_dev = list_entry_brdev(lhd); + brdev = BRPRIV(net_dev); if (pos-- == 0) return sprintf(buf, "dev %.16s: num=%d, mac=%02X:%02X:" - "%02X:%02X:%02X:%02X (%s)\n", brdev->net_dev.name, + "%02X:%02X:%02X:%02X (%s)\n", net_dev->name, brdev->number, - brdev->net_dev.dev_addr[0], - brdev->net_dev.dev_addr[1], - brdev->net_dev.dev_addr[2], - brdev->net_dev.dev_addr[3], - brdev->net_dev.dev_addr[4], - brdev->net_dev.dev_addr[5], + net_dev->dev_addr[0], + net_dev->dev_addr[1], + net_dev->dev_addr[2], + net_dev->dev_addr[3], + net_dev->dev_addr[4], + net_dev->dev_addr[5], brdev->mac_was_set ? "set" : "auto"); list_for_each(lhc, &brdev->brvccs) { brvcc = list_entry_brvcc(lhc); @@ -766,15 +756,13 @@ static ssize_t br2684_proc_read(struct file *file, char *buf, size_t count, } static struct file_operations br2684_proc_operations = { - read: br2684_proc_read, + .owner = THIS_MODULE, + .read = br2684_proc_read, }; extern struct proc_dir_entry *atm_proc_root; /* from proc.c */ -/* the following avoids some spurious warnings from the compiler */ -#define UNUSED __attribute__((unused)) - -static int __init UNUSED br2684_init(void) +static int __init br2684_init(void) { struct proc_dir_entry *p; if ((p = create_proc_entry("br2684", 0, atm_proc_root)) == NULL) @@ -784,16 +772,26 @@ static int __init UNUSED br2684_init(void) return 0; } -static void __exit UNUSED br2684_exit(void) +static void __exit br2684_exit(void) { + struct net_device *net_dev; struct br2684_dev *brdev; + struct br2684_vcc *brvcc; br2684_ioctl_set(NULL); + remove_proc_entry("br2684", atm_proc_root); + while (!list_empty(&br2684_devs)) { - brdev = list_entry_brdev(br2684_devs.next); - unregister_netdev(&brdev->net_dev); + net_dev = list_entry_brdev(br2684_devs.next); + brdev = BRPRIV(net_dev); + while (!list_empty(&brdev->brvccs)) { + brvcc = list_entry_brvcc(brdev->brvccs.next); + br2684_close_vcc(brvcc); + } + list_del(&brdev->br2684_devs); - kfree(brdev); + unregister_netdev(net_dev); + free_netdev(net_dev); } } diff --git a/net/atm/clip.c b/net/atm/clip.c index 3eac40cd88ee..74a58eee32fd 100644 --- a/net/atm/clip.c +++ b/net/atm/clip.c @@ -786,7 +786,7 @@ static void __exit atm_clip_exit(void) while (dev) { next = PRIV(dev)->next; unregister_netdev(dev); - kfree(dev); + free_netdev(dev); dev = next; } if (start_timer == 0) del_timer(&idle_timer); diff --git a/net/atm/common.c b/net/atm/common.c index 63b649bb7800..91f2c8fbe9e0 100644 --- a/net/atm/common.c +++ b/net/atm/common.c @@ -545,9 +545,6 @@ int vcc_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, if (error) return error; sock_recv_timestamp(msg, sk, skb); - if (vcc->dev->ops->feedback) - vcc->dev->ops->feedback(vcc, skb, (unsigned long) skb->data, - (unsigned long) msg->msg_iov->iov_base, copied); DPRINTK("RcvM %d -= %d\n", atomic_read(&vcc->sk->rmem_alloc), skb->truesize); atm_return(vcc, skb->truesize); skb_free_datagram(sk, skb); diff --git a/net/atm/lec.c b/net/atm/lec.c index 67228a48527d..a3058de18f90 100644 --- a/net/atm/lec.c +++ b/net/atm/lec.c @@ -864,7 +864,7 @@ static void __exit lane_module_cleanup(void) if (dev_lec[i] != NULL) { priv = (struct lec_priv *)dev_lec[i]->priv; unregister_netdev(dev_lec[i]); - kfree(dev_lec[i]); + free_netdev(dev_lec[i]); dev_lec[i] = NULL; } } diff --git a/net/atm/pppoatm.c b/net/atm/pppoatm.c index b462ded246e2..cca22da87ae6 100644 --- a/net/atm/pppoatm.c +++ b/net/atm/pppoatm.c @@ -132,7 +132,7 @@ static void pppoatm_unassign_vcc(struct atm_vcc *atmvcc) atmvcc->user_back = NULL; kfree(pvcc); /* Gee, I hope we have the big kernel lock here... */ - MOD_DEC_USE_COUNT; + module_put(THIS_MODULE); } /* Called when an AAL5 PDU comes in */ @@ -286,12 +286,9 @@ static int pppoatm_assign_vcc(struct atm_vcc *atmvcc, unsigned long arg) if (be.encaps != PPPOATM_ENCAPS_AUTODETECT && be.encaps != PPPOATM_ENCAPS_VC && be.encaps != PPPOATM_ENCAPS_LLC) return -EINVAL; - MOD_INC_USE_COUNT; pvcc = kmalloc(sizeof(*pvcc), GFP_KERNEL); - if (pvcc == NULL) { - MOD_DEC_USE_COUNT; + if (pvcc == NULL) return -ENOMEM; - } memset(pvcc, 0, sizeof(*pvcc)); pvcc->atmvcc = atmvcc; pvcc->old_push = atmvcc->push; @@ -310,6 +307,7 @@ static int pppoatm_assign_vcc(struct atm_vcc *atmvcc, unsigned long arg) atmvcc->user_back = pvcc; atmvcc->push = pppoatm_push; atmvcc->pop = pppoatm_pop; + (void) try_module_get(THIS_MODULE); return 0; } diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index 36d02b08989d..e208f0a42763 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c @@ -110,22 +110,6 @@ static int br_dev_accept_fastpath(struct net_device *dev, struct dst_entry *dst) return -1; } -/* convert later to direct kfree */ -static void br_dev_free(struct net_device *dev) -{ - struct net_bridge *br = dev->priv; - - WARN_ON(!list_empty(&br->port_list)); - WARN_ON(!list_empty(&br->age_list)); - - BUG_ON(timer_pending(&br->hello_timer)); - BUG_ON(timer_pending(&br->tcn_timer)); - BUG_ON(timer_pending(&br->topology_change_timer)); - BUG_ON(timer_pending(&br->gc_timer)); - - kfree(dev); -} - void br_dev_setup(struct net_device *dev) { memset(dev->dev_addr, 0, ETH_ALEN); @@ -137,7 +121,7 @@ void br_dev_setup(struct net_device *dev) dev->hard_start_xmit = br_dev_xmit; dev->open = br_dev_open; dev->set_multicast_list = br_dev_set_multicast_list; - dev->destructor = br_dev_free; + dev->destructor = free_netdev; SET_MODULE_OWNER(dev); dev->stop = br_dev_stop; dev->accept_fastpath = br_dev_accept_fastpath; diff --git a/net/core/dev.c b/net/core/dev.c index 6b184e9a90ea..c24e705172a4 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1836,8 +1836,7 @@ static int dev_ifconf(char *arg) * This is invoked by the /proc filesystem handler to display a device * in detail. */ -static __inline__ struct net_device *dev_get_idx(struct seq_file *seq, - loff_t pos) +static __inline__ struct net_device *dev_get_idx(loff_t pos) { struct net_device *dev; loff_t i; @@ -1850,7 +1849,7 @@ static __inline__ struct net_device *dev_get_idx(struct seq_file *seq, void *dev_seq_start(struct seq_file *seq, loff_t *pos) { read_lock(&dev_base_lock); - return *pos ? dev_get_idx(seq, *pos - 1) : (void *)1; + return *pos ? dev_get_idx(*pos - 1) : (void *)1; } void *dev_seq_next(struct seq_file *seq, void *v, loff_t *pos) @@ -2643,7 +2642,7 @@ int register_netdevice(struct net_device *dev) ASSERT_RTNL(); /* When net_device's are persistent, this will be fatal. */ - WARN_ON(dev->reg_state != NETREG_UNINITIALIZED); + BUG_ON(dev->reg_state != NETREG_UNINITIALIZED); spin_lock_init(&dev->queue_lock); spin_lock_init(&dev->xmit_lock); @@ -2788,6 +2787,8 @@ static void netdev_wait_allrefs(struct net_device *dev) * unregister_netdevice(y2); * ... * rtnl_unlock(); + * free_netdev(y1); + * free_netdev(y2); * * We are invoked by rtnl_unlock() after it drops the semaphore. * This allows us to deal with problems: @@ -2827,7 +2828,7 @@ void netdev_run_todo(void) break; case NETREG_UNREGISTERING: - class_device_unregister(&dev->class_dev); + class_device_del(&dev->class_dev); dev->reg_state = NETREG_UNREGISTERED; netdev_wait_allrefs(dev); @@ -2856,6 +2857,29 @@ void netdev_run_todo(void) up(&net_todo_run_mutex); } +/** + * free_netdev - free network device + * @dev: device + * + * This function does the last stage of destroying an allocated device + * interface. The reference to the device object is released. + * If this is the last reference then it will be freed. + */ +void free_netdev(struct net_device *dev) +{ + /* Compatiablity with error handling in drivers */ + if (dev->reg_state == NETREG_UNINITIALIZED) { + kfree(dev); + return; + } + + BUG_ON(dev->reg_state != NETREG_UNREGISTERED); + dev->reg_state = NETREG_RELEASED; + + /* will free via class release */ + class_device_put(&dev->class_dev); +} + /* Synchronize with packet receive processing. */ void synchronize_net(void) { diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 001fdb40e6de..f87894a7dc93 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -50,6 +50,7 @@ static void neigh_timer_handler(unsigned long arg); static void neigh_app_notify(struct neighbour *n); #endif static int pneigh_ifdown(struct neigh_table *tbl, struct net_device *dev); +void neigh_changeaddr(struct neigh_table *tbl, struct net_device *dev); static int neigh_glbl_allocs; static struct neigh_table *neigh_tables; @@ -168,6 +169,33 @@ static void pneigh_queue_purge(struct sk_buff_head *list) } } +void neigh_changeaddr(struct neigh_table *tbl, struct net_device *dev) +{ + int i; + + write_lock_bh(&tbl->lock); + + for (i=0; i <= NEIGH_HASHMASK; i++) { + struct neighbour *n, **np; + + np = &tbl->hash_buckets[i]; + while ((n = *np) != NULL) { + if (dev && n->dev != dev) { + np = &n->next; + continue; + } + *np = n->next; + write_lock_bh(&n->lock); + n->dead = 1; + neigh_del_timer(n); + write_unlock_bh(&n->lock); + neigh_release(n); + } + } + + write_unlock_bh(&tbl->lock); +} + int neigh_ifdown(struct neigh_table *tbl, struct net_device *dev) { int i; diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index 3e3c7c524f2f..3ff9e58a06c8 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c @@ -361,8 +361,23 @@ static int netdev_hotplug(struct class_device *cd, char **envp, } #endif +/* + * netdev_release -- destroy and free a dead device. + * Called when last reference to class_device kobject is gone. + */ +static void netdev_release(struct class_device *cd) +{ + struct net_device *dev + = container_of(cd, struct net_device, class_dev); + + BUG_ON(dev->reg_state != NETREG_RELEASED); + + kfree(dev); +} + static struct class net_class = { .name = "net", + .release = netdev_release, #ifdef CONFIG_HOTPLUG .hotplug = netdev_hotplug, #endif diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index 1324b4e97d83..4fd817944e99 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c @@ -1071,6 +1071,26 @@ out: return err; } +static int arp_netdev_event(struct notifier_block *this, unsigned long event, void *ptr) +{ + struct net_device *dev = ptr; + + switch (event) { + case NETDEV_CHANGEADDR: + neigh_changeaddr(&arp_tbl, dev); + rt_cache_flush(0); + break; + default: + break; + } + + return NOTIFY_DONE; +} + +struct notifier_block arp_netdev_notifier = { + .notifier_call = arp_netdev_event, +}; + /* Note, that it is not on notifier chain. It is necessary, that this routine was called after route cache will be flushed. @@ -1103,6 +1123,7 @@ void __init arp_init(void) neigh_sysctl_register(NULL, &arp_tbl.parms, NET_IPV4, NET_IPV4_NEIGH, "ipv4"); #endif + register_netdevice_notifier(&arp_netdev_notifier); } #ifdef CONFIG_PROC_FS diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index c793f48b8df3..90ace8969820 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -1128,7 +1128,7 @@ static void ipgre_tunnel_setup(struct net_device *dev) { SET_MODULE_OWNER(dev); dev->uninit = ipgre_tunnel_uninit; - dev->destructor = (void (*)(struct net_device *))kfree; + dev->destructor = free_netdev; dev->hard_start_xmit = ipgre_tunnel_xmit; dev->get_stats = ipgre_tunnel_get_stats; dev->do_ioctl = ipgre_tunnel_ioctl; diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index 19eab54dceb8..d272c9dc1099 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c @@ -246,7 +246,7 @@ static struct ip_tunnel * ipip_tunnel_locate(struct ip_tunnel_parm *parms, int c nt = dev->priv; SET_MODULE_OWNER(dev); dev->init = ipip_tunnel_init; - dev->destructor = (void (*)(struct net_device *))kfree; + dev->destructor = free_netdev; nt->parms = *parms; if (register_netdevice(dev) < 0) { diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 689ae198d82c..3f671efed9e6 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -193,7 +193,7 @@ static void reg_vif_setup(struct net_device *dev) dev->flags = IFF_NOARP; dev->hard_start_xmit = reg_vif_xmit; dev->get_stats = reg_vif_get_stats; - dev->destructor = (void (*)(struct net_device *)) kfree; + dev->destructor = free_netdev; } static struct net_device *ipmr_reg_vif(void) diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 3728805d5d60..ef434507c04a 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -1447,6 +1447,26 @@ int ndisc_rcv(struct sk_buff *skb) return 0; } +static int ndisc_netdev_event(struct notifier_block *this, unsigned long event, void *ptr) +{ + struct net_device *dev = ptr; + + switch (event) { + case NETDEV_CHANGEADDR: + neigh_changeaddr(&nd_tbl, dev); + fib6_run_gc(0); + break; + default: + break; + } + + return NOTIFY_DONE; +} + +struct notifier_block ndisc_netdev_notifier = { + .notifier_call = ndisc_netdev_event, +}; + int __init ndisc_init(struct net_proto_family *ops) { struct ipv6_pinfo *np; @@ -1480,6 +1500,7 @@ int __init ndisc_init(struct net_proto_family *ops) neigh_sysctl_register(NULL, &nd_tbl.parms, NET_IPV6, NET_IPV6_NEIGH, "ipv6"); #endif + register_netdevice_notifier(&ndisc_netdev_notifier); return 0; } diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 6d58029d1fe5..8576eda7d5f4 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -722,7 +722,7 @@ static void ipip6_tunnel_setup(struct net_device *dev) { SET_MODULE_OWNER(dev); dev->uninit = ipip6_tunnel_uninit; - dev->destructor = (void (*)(struct net_device *))kfree; + dev->destructor = free_netdev; dev->hard_start_xmit = ipip6_tunnel_xmit; dev->get_stats = ipip6_tunnel_get_stats; dev->do_ioctl = ipip6_tunnel_ioctl; diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c index 56095cbe1490..82c090f08df5 100644 --- a/net/irda/ircomm/ircomm_tty.c +++ b/net/irda/ircomm/ircomm_tty.c @@ -117,6 +117,7 @@ int __init ircomm_tty_init(void) return -ENOMEM; } + driver->owner = THIS_MODULE; driver->driver_name = "ircomm"; driver->name = "ircomm"; driver->devfs_name = "ircomm"; @@ -363,10 +364,8 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp) IRDA_DEBUG(2, "%s()\n", __FUNCTION__ ); - MOD_INC_USE_COUNT; line = tty->index; if ((line < 0) || (line >= IRCOMM_TTY_PORTS)) { - MOD_DEC_USE_COUNT; return -ENODEV; } @@ -377,7 +376,6 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp) self = kmalloc(sizeof(struct ircomm_tty_cb), GFP_KERNEL); if (self == NULL) { ERROR("%s(), kmalloc failed!\n", __FUNCTION__); - MOD_DEC_USE_COUNT; return -ENOMEM; } memset(self, 0, sizeof(struct ircomm_tty_cb)); @@ -503,7 +501,6 @@ static void ircomm_tty_close(struct tty_struct *tty, struct file *filp) spin_lock_irqsave(&self->spinlock, flags); if (tty_hung_up_p(filp)) { - MOD_DEC_USE_COUNT; spin_unlock_irqrestore(&self->spinlock, flags); IRDA_DEBUG(0, "%s(), returning 1\n", __FUNCTION__ ); @@ -530,7 +527,6 @@ static void ircomm_tty_close(struct tty_struct *tty, struct file *filp) self->open_count = 0; } if (self->open_count) { - MOD_DEC_USE_COUNT; spin_unlock_irqrestore(&self->spinlock, flags); IRDA_DEBUG(0, "%s(), open count > 0\n", __FUNCTION__ ); @@ -572,8 +568,6 @@ static void ircomm_tty_close(struct tty_struct *tty, struct file *filp) self->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); wake_up_interruptible(&self->close_wait); - - MOD_DEC_USE_COUNT; } /* diff --git a/net/irda/irda_device.c b/net/irda/irda_device.c index 5f3f6feaad66..187356ed0c10 100644 --- a/net/irda/irda_device.c +++ b/net/irda/irda_device.c @@ -83,12 +83,6 @@ static const char *task_state[] = { static void irda_task_timer_expired(void *data); -#ifdef CONFIG_PROC_FS -int irda_device_proc_read(char *buf, char **start, off_t offset, int len, - int unused); - -#endif /* CONFIG_PROC_FS */ - int __init irda_device_init( void) { dongles = hashbin_new(HB_LOCK); @@ -372,11 +366,6 @@ static void irda_task_timer_expired(void *data) irda_task_kick(task); } -static void irda_device_destructor(struct net_device *dev) -{ - kfree(dev); -} - /* * Function irda_device_setup (dev) * @@ -388,7 +377,7 @@ void irda_device_setup(struct net_device *dev) dev->hard_header_len = 0; dev->addr_len = 0; - dev->destructor = irda_device_destructor; + dev->destructor = free_netdev; dev->type = ARPHRD_IRDA; dev->tx_queue_len = 8; /* Window size + 1 s-frame */ diff --git a/net/irda/irlan/irlan_client.c b/net/irda/irlan/irlan_client.c index e142dbb0172e..573907187208 100644 --- a/net/irda/irlan/irlan_client.c +++ b/net/irda/irlan/irlan_client.c @@ -154,7 +154,6 @@ void irlan_client_discovery_indication(discinfo_t *discovery, IRDA_DEBUG(1, "%s()\n", __FUNCTION__ ); - ASSERT(irlan != NULL, return;); ASSERT(discovery != NULL, return;); /* @@ -170,7 +169,8 @@ void irlan_client_discovery_indication(discinfo_t *discovery, daddr = discovery->daddr; /* Find instance */ - self = (struct irlan_cb *) hashbin_get_first(irlan); + rcu_read_lock(); + self = irlan_get_any(); if (self) { ASSERT(self->magic == IRLAN_MAGIC, return;); @@ -179,6 +179,7 @@ void irlan_client_discovery_indication(discinfo_t *discovery, irlan_client_wakeup(self, saddr, daddr); } + rcu_read_unlock(); } /* @@ -511,7 +512,7 @@ static void irlan_check_response_param(struct irlan_cb *self, char *param, bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5]); for (i = 0; i < 6; i++) - self->dev.dev_addr[i] = bytes[i]; + self->dev->dev_addr[i] = bytes[i]; } } diff --git a/net/irda/irlan/irlan_common.c b/net/irda/irlan/irlan_common.c index e9b7a7dd9176..b53d2b68de5d 100644 --- a/net/irda/irlan/irlan_common.c +++ b/net/irda/irlan/irlan_common.c @@ -31,8 +31,10 @@ #include <linux/init.h> #include <linux/errno.h> #include <linux/proc_fs.h> +#include <linux/seq_file.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> +#include <linux/rtnetlink.h> #include <asm/system.h> #include <asm/bitops.h> @@ -63,7 +65,8 @@ /* * Master structure */ -hashbin_t *irlan = NULL; +static LIST_HEAD(irlans); + static void *ckey; static void *skey; @@ -72,20 +75,6 @@ static int eth; /* Use "eth" or "irlan" name for devices */ static int access = ACCESS_PEER; /* PEER, DIRECT or HOSTED */ #ifdef CONFIG_PROC_FS -static char *irlan_state[] = { - "IRLAN_IDLE", - "IRLAN_QUERY", - "IRLAN_CONN", - "IRLAN_INFO", - "IRLAN_MEDIA", - "IRLAN_OPEN", - "IRLAN_WAIT", - "IRLAN_ARB", - "IRLAN_DATA", - "IRLAN_CLOSE", - "IRLAN_SYNC" -}; - static char *irlan_access[] = { "UNKNOWN", "DIRECT", @@ -98,6 +87,20 @@ static char *irlan_media[] = { "802.3", "802.5" }; + +extern struct proc_dir_entry *proc_irda; + +static int irlan_seq_open(struct inode *inode, struct file *file); + +static struct file_operations irlan_fops = { + .owner = THIS_MODULE, + .open = irlan_seq_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + +extern struct proc_dir_entry *proc_irda; #endif /* CONFIG_PROC_FS */ static void __irlan_close(struct irlan_cb *self); @@ -106,12 +109,6 @@ static int __irlan_insert_param(struct sk_buff *skb, char *param, int type, __u8 *value_array, __u16 value_len); void irlan_close_tsaps(struct irlan_cb *self); -#ifdef CONFIG_PROC_FS -static int irlan_proc_read(char *buf, char **start, off_t offset, int len); - -extern struct proc_dir_entry *proc_irda; -#endif /* CONFIG_PROC_FS */ - /* * Function irlan_init (void) * @@ -124,14 +121,17 @@ int __init irlan_init(void) __u16 hints; IRDA_DEBUG(0, "%s()\n", __FUNCTION__ ); - /* Allocate master structure */ - irlan = hashbin_new(HB_LOCK); /* protect from /proc */ - if (irlan == NULL) { - printk(KERN_WARNING "IrLAN: Can't allocate hashbin!\n"); - return -ENOMEM; - } + #ifdef CONFIG_PROC_FS - create_proc_info_entry("irlan", 0, proc_irda, irlan_proc_read); + { struct proc_dir_entry *proc; + proc = create_proc_entry("irlan", 0, proc_irda); + if (!proc) { + printk(KERN_ERR "irlan_init: can't create /proc entry!\n"); + return -ENODEV; + } + + proc->proc_fops = &irlan_fops; + } #endif /* CONFIG_PROC_FS */ IRDA_DEBUG(4, "%s()\n", __FUNCTION__ ); @@ -158,6 +158,8 @@ int __init irlan_init(void) void __exit irlan_cleanup(void) { + struct irlan_cb *self, *next; + IRDA_DEBUG(4, "%s()\n", __FUNCTION__ ); irlmp_unregister_client(ckey); @@ -166,37 +168,13 @@ void __exit irlan_cleanup(void) #ifdef CONFIG_PROC_FS remove_proc_entry("irlan", proc_irda); #endif /* CONFIG_PROC_FS */ - /* - * Delete hashbin and close all irlan client instances in it - */ - hashbin_delete(irlan, (FREE_FUNC) __irlan_close); -} - -/* - * Function irlan_register_netdev (self) - * - * Registers the network device to be used. We should don't register until - * we have been binded to a particular provider or client. - */ -int irlan_register_netdev(struct irlan_cb *self) -{ - int i=0; - - IRDA_DEBUG(0, "%s()\n", __FUNCTION__ ); - /* Check if we should call the device eth<x> or irlan<x> */ - if (!eth) { - /* Get the first free irlan<x> name */ - do { - sprintf(self->dev.name, "%s%d", "irlan", i++); - } while (dev_get(self->dev.name)); + /* Cleanup any leftover network devices */ + rtnl_lock(); + list_for_each_entry_safe(self, next, &irlans, dev_list) { + __irlan_close(self); } - - if (register_netdev(&self->dev) != 0) { - IRDA_DEBUG(2, "%s(), register_netdev() failed!\n", __FUNCTION__ ); - return -1; - } - return 0; + rtnl_unlock(); } /* @@ -207,31 +185,25 @@ int irlan_register_netdev(struct irlan_cb *self) */ struct irlan_cb *irlan_open(__u32 saddr, __u32 daddr) { + struct net_device *dev; struct irlan_cb *self; IRDA_DEBUG(2, "%s()\n", __FUNCTION__ ); - ASSERT(irlan != NULL, return NULL;); - /* - * Initialize the irlan structure. - */ - self = kmalloc(sizeof(struct irlan_cb), GFP_ATOMIC); - if (self == NULL) + /* Create network device with irlan */ + dev = alloc_netdev(sizeof(*self), + eth ? "eth%d" : "irlan%d", + irlan_eth_setup); + if (!dev) return NULL; - - memset(self, 0, sizeof(struct irlan_cb)); + + self = dev->priv; + self->dev = dev; /* * Initialize local device structure */ self->magic = IRLAN_MAGIC; - - sprintf(self->dev.name, "%s", "unknown"); - - self->dev.priv = (void *) self; - self->dev.next = NULL; - self->dev.init = irlan_eth_init; - self->saddr = saddr; self->daddr = daddr; @@ -242,15 +214,22 @@ struct irlan_cb *irlan_open(__u32 saddr, __u32 daddr) init_timer(&self->watchdog_timer); init_timer(&self->client.kick_timer); init_waitqueue_head(&self->open_wait); - - hashbin_insert(irlan, (irda_queue_t *) self, daddr, NULL); skb_queue_head_init(&self->client.txq); irlan_next_client_state(self, IRLAN_IDLE); irlan_next_provider_state(self, IRLAN_IDLE); - irlan_register_netdev(self); + if (register_netdev(dev)) { + IRDA_DEBUG(2, "%s(), register_netdev() failed!\n", + __FUNCTION__ ); + self = NULL; + kfree(dev); + } else { + rtnl_lock(); + list_add_rcu(&self->dev_list, &irlans); + rtnl_unlock(); + } return self; } @@ -258,8 +237,8 @@ struct irlan_cb *irlan_open(__u32 saddr, __u32 daddr) * Function __irlan_close (self) * * This function closes and deallocates the IrLAN client instances. Be - * aware that other functions which calles client_close() must call - * hashbin_remove() first!!! + * aware that other functions which calls client_close() must + * remove self from irlans list first. */ static void __irlan_close(struct irlan_cb *self) { @@ -267,6 +246,7 @@ static void __irlan_close(struct irlan_cb *self) IRDA_DEBUG(2, "%s()\n", __FUNCTION__ ); + ASSERT_RTNL(); ASSERT(self != NULL, return;); ASSERT(self->magic == IRLAN_MAGIC, return;); @@ -283,10 +263,19 @@ static void __irlan_close(struct irlan_cb *self) while ((skb = skb_dequeue(&self->client.txq))) dev_kfree_skb(skb); - unregister_netdev(&self->dev); - - self->magic = 0; - kfree(self); + /* Unregister and free self via destructor */ + unregister_netdevice(self->dev); +} + +/* Find any instance of irlan, used for client discovery wakeup */ +struct irlan_cb *irlan_get_any(void) +{ + struct irlan_cb *self; + + list_for_each_entry_rcu(self, &irlans, dev_list) { + return self; + } + return NULL; } /* @@ -337,7 +326,7 @@ void irlan_connect_indication(void *instance, void *sap, struct qos_info *qos, irlan_open_unicast_addr(self); } /* Ready to transfer Ethernet frames (at last) */ - netif_start_queue(&self->dev); /* Clear reason */ + netif_start_queue(self->dev); /* Clear reason */ } void irlan_connect_confirm(void *instance, void *sap, struct qos_info *qos, @@ -371,7 +360,7 @@ void irlan_connect_confirm(void *instance, void *sap, struct qos_info *qos, irlan_set_multicast_filter(self, TRUE); /* Ready to transfer Ethernet frames */ - netif_start_queue(&self->dev); + netif_start_queue(self->dev); self->disconnect_reason = 0; /* Clear reason */ #ifdef CONFIG_IRLAN_SEND_GRATUITOUS_ARP irlan_eth_send_gratuitous_arp(&self->dev); @@ -1079,59 +1068,104 @@ int irlan_extract_param(__u8 *buf, char *name, char *value, __u16 *len) } #ifdef CONFIG_PROC_FS +#define IRLAN_PROC_START_TOKEN ((void *)1) + /* - * Function irlan_client_proc_read (buf, start, offset, len, unused) - * - * Give some info to the /proc file system + * Start of reading /proc entries. + * Return entry at pos, + * or start_token to indicate print header line + * or NULL if end of file */ -static int irlan_proc_read(char *buf, char **start, off_t offset, int len) +static void *irlan_seq_start(struct seq_file *seq, loff_t *pos) { - struct irlan_cb *self; - unsigned long flags; - ASSERT(irlan != NULL, return 0;); - - len = 0; - - spin_lock_irqsave(&irlan->hb_spinlock, flags); + int i = 1; + struct irlan_cb *self; - len += sprintf(buf+len, "IrLAN instances:\n"); - - self = (struct irlan_cb *) hashbin_get_first(irlan); - while (self != NULL) { - ASSERT(self->magic == IRLAN_MAGIC, break;); + rcu_read_lock(); + if (*pos == 0) + return IRLAN_PROC_START_TOKEN; + + list_for_each_entry(self, &irlans, dev_list) { + if (*pos == i) + return self; + ++i; + } + return NULL; +} + +/* Return entry after v, and increment pos */ +static void *irlan_seq_next(struct seq_file *seq, void *v, loff_t *pos) +{ + struct list_head *nxt; + + ++*pos; + if (v == IRLAN_PROC_START_TOKEN) + nxt = irlans.next; + else + nxt = ((struct irlan_cb *)v)->dev_list.next; + + return (nxt == &irlans) ? NULL + : list_entry(nxt, struct irlan_cb, dev_list); +} + +/* End of reading /proc file */ +static void irlan_seq_stop(struct seq_file *seq, void *v) +{ + rcu_read_unlock(); +} + + +/* + * Show one entry in /proc file. + */ +static int irlan_seq_show(struct seq_file *seq, void *v) +{ + if (v == IRLAN_PROC_START_TOKEN) + seq_puts(seq, "IrLAN instances:\n"); + else { + struct irlan_cb *self = v; - len += sprintf(buf+len, "ifname: %s,\n", - self->dev.name); - len += sprintf(buf+len, "client state: %s, ", + ASSERT(self != NULL, return -1;); + ASSERT(self->magic == IRLAN_MAGIC, return -1;); + + seq_printf(seq,"ifname: %s,\n", + self->dev->name); + seq_printf(seq,"client state: %s, ", irlan_state[ self->client.state]); - len += sprintf(buf+len, "provider state: %s,\n", + seq_printf(seq,"provider state: %s,\n", irlan_state[ self->provider.state]); - len += sprintf(buf+len, "saddr: %#08x, ", + seq_printf(seq,"saddr: %#08x, ", self->saddr); - len += sprintf(buf+len, "daddr: %#08x\n", + seq_printf(seq,"daddr: %#08x\n", self->daddr); - len += sprintf(buf+len, "version: %d.%d,\n", + seq_printf(seq,"version: %d.%d,\n", self->version[1], self->version[0]); - len += sprintf(buf+len, "access type: %s\n", + seq_printf(seq,"access type: %s\n", irlan_access[self->client.access_type]); - len += sprintf(buf+len, "media: %s\n", + seq_printf(seq,"media: %s\n", irlan_media[self->media]); - len += sprintf(buf+len, "local filter:\n"); - len += sprintf(buf+len, "remote filter: "); - len += irlan_print_filter(self->client.filter_type, - buf+len); - - len += sprintf(buf+len, "tx busy: %s\n", - netif_queue_stopped(&self->dev) ? "TRUE" : "FALSE"); + seq_printf(seq,"local filter:\n"); + seq_printf(seq,"remote filter: "); + irlan_print_filter(seq, self->client.filter_type); + seq_printf(seq,"tx busy: %s\n", + netif_queue_stopped(self->dev) ? "TRUE" : "FALSE"); - len += sprintf(buf+len, "\n"); + seq_putc(seq,'\n'); + } + return 0; +} - self = (struct irlan_cb *) hashbin_get_next(irlan); - } - spin_unlock_irqrestore(&irlan->hb_spinlock, flags); +static struct seq_operations irlan_seq_ops = { + .start = irlan_seq_start, + .next = irlan_seq_next, + .stop = irlan_seq_stop, + .show = irlan_seq_show, +}; - return len; +static int irlan_seq_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &irlan_seq_ops); } #endif diff --git a/net/irda/irlan/irlan_eth.c b/net/irda/irlan/irlan_eth.c index 6ba413f5e82b..6a9c33f6ff31 100644 --- a/net/irda/irlan/irlan_eth.c +++ b/net/irda/irlan/irlan_eth.c @@ -47,14 +47,12 @@ * The network device initialization function. * */ -int irlan_eth_init(struct net_device *dev) +void irlan_eth_setup(struct net_device *dev) { struct irlan_cb *self; IRDA_DEBUG(2, "%s()\n", __FUNCTION__ ); - ASSERT(dev != NULL, return -1;); - self = (struct irlan_cb *) dev->priv; dev->open = irlan_eth_open; @@ -62,6 +60,8 @@ int irlan_eth_init(struct net_device *dev) dev->hard_start_xmit = irlan_eth_xmit; dev->get_stats = irlan_eth_get_stats; dev->set_multicast_list = irlan_eth_set_multicast_list; + dev->destructor = (void (*)(struct net_device *)) kfree; + SET_MODULE_OWNER(dev); ether_setup(dev); @@ -85,8 +85,6 @@ int irlan_eth_init(struct net_device *dev) get_random_bytes(dev->dev_addr+4, 1); get_random_bytes(dev->dev_addr+5, 1); } - - return 0; } /* @@ -237,7 +235,7 @@ int irlan_eth_receive(void *instance, void *sap, struct sk_buff *skb) * might have been previously set by the low level IrDA network * device driver */ - skb->dev = &self->dev; + skb->dev = self->dev; skb->protocol=eth_type_trans(skb, skb->dev); /* Remove eth header */ self->stats.rx_packets++; @@ -264,7 +262,7 @@ void irlan_eth_flow_indication(void *instance, void *sap, LOCAL_FLOW flow) ASSERT(self != NULL, return;); ASSERT(self->magic == IRLAN_MAGIC, return;); - dev = &self->dev; + dev = self->dev; ASSERT(dev != NULL, return;); diff --git a/net/irda/irlan/irlan_filter.c b/net/irda/irlan/irlan_filter.c index 66f4a842cc6c..87e4601231f6 100644 --- a/net/irda/irlan/irlan_filter.c +++ b/net/irda/irlan/irlan_filter.c @@ -24,6 +24,7 @@ #include <linux/skbuff.h> #include <linux/random.h> +#include <linux/seq_file.h> #include <net/irda/irlan_common.h> @@ -216,26 +217,30 @@ void irlan_check_command_param(struct irlan_cb *self, char *param, char *value) * Print status of filter. Used by /proc file system * */ -int irlan_print_filter(int filter_type, char *buf) +#ifdef CONFIG_PROC_FS +#define MASK2STR(m,s) { .mask = m, .str = s } + +void irlan_print_filter(struct seq_file *seq, int filter_type) { - int len = 0; - - if (filter_type & IRLAN_DIRECTED) - len += sprintf(buf+len, "%s", "DIRECTED "); - if (filter_type & IRLAN_FUNCTIONAL) - len += sprintf(buf+len, "%s", "FUNCTIONAL "); - if (filter_type & IRLAN_GROUP) - len += sprintf(buf+len, "%s", "GROUP "); - if (filter_type & IRLAN_MAC_FRAME) - len += sprintf(buf+len, "%s", "MAC_FRAME "); - if (filter_type & IRLAN_MULTICAST) - len += sprintf(buf+len, "%s", "MULTICAST "); - if (filter_type & IRLAN_BROADCAST) - len += sprintf(buf+len, "%s", "BROADCAST "); - if (filter_type & IRLAN_IPX_SOCKET) - len += sprintf(buf+len, "%s", "IPX_SOCKET"); - - len += sprintf(buf+len, "\n"); - - return len; + static struct { + int mask; + const char *str; + } filter_mask2str[] = { + MASK2STR(IRLAN_DIRECTED, "DIRECTED"), + MASK2STR(IRLAN_FUNCTIONAL, "FUNCTIONAL"), + MASK2STR(IRLAN_GROUP, "GROUP"), + MASK2STR(IRLAN_MAC_FRAME, "MAC_FRAME"), + MASK2STR(IRLAN_MULTICAST, "MULTICAST"), + MASK2STR(IRLAN_BROADCAST, "BROADCAST"), + MASK2STR(IRLAN_IPX_SOCKET, "IPX_SOCKET"), + MASK2STR(0, NULL) + }, *p; + + for (p = filter_mask2str; p->str; p++) { + if (filter_type & p->mask) + seq_printf(seq, "%s ", p->str); + } + seq_putc(seq, '\n'); } +#undef MASK2STR +#endif diff --git a/net/irda/irproc.c b/net/irda/irproc.c index aef346111238..6373aba599b1 100644 --- a/net/irda/irproc.c +++ b/net/irda/irproc.c @@ -62,14 +62,18 @@ static struct irda_entry dir[] = { void __init irda_proc_register(void) { int i; + struct proc_dir_entry *d; proc_irda = proc_mkdir("net/irda", NULL); if (proc_irda == NULL) return; proc_irda->owner = THIS_MODULE; - for (i=0; i<ARRAY_SIZE(dir); i++) - create_proc_info_entry(dir[i].name,0,proc_irda,dir[i].fn); + for (i=0; i<ARRAY_SIZE(dir); i++) { + d = create_proc_info_entry(dir[i].name,0,proc_irda,dir[i].fn); + if (d) + d->owner = THIS_MODULE; + } } /* diff --git a/net/netrom/nr_dev.c b/net/netrom/nr_dev.c index 1d126a109a9a..a86becaacc2a 100644 --- a/net/netrom/nr_dev.c +++ b/net/netrom/nr_dev.c @@ -204,7 +204,7 @@ void nr_setup(struct net_device *dev) dev->hard_start_xmit = nr_xmit; dev->open = nr_open; dev->stop = nr_close; - dev->destructor = (void (*)(struct net_device *))kfree; + dev->destructor = free_netdev; dev->hard_header = nr_header; dev->hard_header_len = NR_NETWORK_LEN + NR_TRANSPORT_LEN; diff --git a/net/netsyms.c b/net/netsyms.c index a1b61a2af1c9..660fe34f9e68 100644 --- a/net/netsyms.c +++ b/net/netsyms.c @@ -480,6 +480,7 @@ EXPORT_SYMBOL(call_netdevice_notifiers); EXPORT_SYMBOL(loopback_dev); EXPORT_SYMBOL(register_netdevice); EXPORT_SYMBOL(unregister_netdevice); +EXPORT_SYMBOL(free_netdev); EXPORT_SYMBOL(synchronize_net); EXPORT_SYMBOL(netdev_state_change); EXPORT_SYMBOL(netdev_boot_setup_check); diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index d540328896ab..59ef64968f0d 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c @@ -1580,7 +1580,7 @@ static void __exit rose_exit(void) if (dev) { unregister_netdev(dev); - kfree(dev); + free_netdev(dev); } } diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c index 5e54ef181e6d..0606b0eb140a 100644 --- a/net/sched/sch_teql.c +++ b/net/sched/sch_teql.c @@ -498,7 +498,7 @@ static void __exit teql_exit(void) unregister_qdisc(&master->qops); unregister_netdev(master->dev); - kfree(master->dev); + free_netdev(master->dev); } spin_unlock(&master_dev_lock); } diff --git a/net/wanrouter/wanmain.c b/net/wanrouter/wanmain.c index 34091a2f8a3f..2d8659709f36 100644 --- a/net/wanrouter/wanmain.c +++ b/net/wanrouter/wanmain.c @@ -908,7 +908,7 @@ static int wanrouter_delete_interface(struct wan_device *wandev, char *name) unregister_netdev(dev); - kfree(dev); + free_netdev(dev); return 0; } |
