summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/networking/driver.txt10
-rw-r--r--Documentation/networking/netdevices.txt12
-rw-r--r--arch/um/drivers/net_kern.c2
-rw-r--r--drivers/atm/ambassador.c28
-rw-r--r--drivers/atm/eni.c10
-rw-r--r--drivers/atm/firestream.c10
-rw-r--r--drivers/atm/he.c12
-rw-r--r--drivers/atm/horizon.c13
-rw-r--r--drivers/atm/idt77252.c2
-rw-r--r--drivers/atm/iphase.c9
-rw-r--r--drivers/atm/lanai.c3
-rw-r--r--drivers/atm/zatm.c44
-rw-r--r--drivers/ieee1394/eth1394.c2
-rw-r--r--drivers/isdn/hysdn/hysdn_net.c2
-rw-r--r--drivers/message/fusion/mptlan.c2
-rw-r--r--drivers/net/3c509.c2
-rw-r--r--drivers/net/3c515.c2
-rw-r--r--drivers/net/3c59x.c6
-rw-r--r--drivers/net/8139cp.c2
-rw-r--r--drivers/net/8139too.c2
-rw-r--r--drivers/net/a2065.c2
-rw-r--r--drivers/net/acenic.c2
-rwxr-xr-xdrivers/net/amd8111e.c2
-rw-r--r--drivers/net/arcnet/arc-rimi.c2
-rw-r--r--drivers/net/arcnet/com20020.c2
-rw-r--r--drivers/net/arcnet/com90io.c2
-rw-r--r--drivers/net/arcnet/com90xx.c2
-rw-r--r--drivers/net/ariadne.c2
-rw-r--r--drivers/net/arm/ether00.c2
-rw-r--r--drivers/net/arm/ether1.c2
-rw-r--r--drivers/net/arm/ether3.c2
-rw-r--r--drivers/net/arm/etherh.c2
-rw-r--r--drivers/net/atp.c2
-rw-r--r--drivers/net/au1000_eth.c2
-rw-r--r--drivers/net/b44.c2
-rw-r--r--drivers/net/bmac.c2
-rw-r--r--drivers/net/bonding/bond_main.c2
-rw-r--r--drivers/net/declance.c4
-rw-r--r--drivers/net/defxx.c2
-rw-r--r--drivers/net/dgrs.c4
-rw-r--r--drivers/net/dl2k.c2
-rw-r--r--drivers/net/dummy.c2
-rw-r--r--drivers/net/e100/e100_main.c2
-rw-r--r--drivers/net/e1000/e1000_main.c2
-rw-r--r--drivers/net/eepro100.c2
-rw-r--r--drivers/net/epic100.c2
-rw-r--r--drivers/net/eql.c2
-rw-r--r--drivers/net/ewrk3.c2
-rw-r--r--drivers/net/fc/iph5526.c2
-rw-r--r--drivers/net/fealnx.c2
-rw-r--r--drivers/net/gt96100eth.c4
-rw-r--r--drivers/net/hamachi.c2
-rw-r--r--drivers/net/hamradio/bpqether.c2
-rw-r--r--drivers/net/hamradio/scc.c4
-rw-r--r--drivers/net/hamradio/yam.c2
-rw-r--r--drivers/net/hp100.c2
-rw-r--r--drivers/net/hplance.c2
-rw-r--r--drivers/net/hydra.c2
-rw-r--r--drivers/net/ioc3-eth.c2
-rw-r--r--drivers/net/irda/Kconfig14
-rw-r--r--drivers/net/irda/Makefile3
-rw-r--r--drivers/net/irda/irtty.c1077
-rw-r--r--drivers/net/ixgb/ixgb_main.c2
-rw-r--r--drivers/net/lasi_82596.c2
-rw-r--r--drivers/net/lp486e.c2
-rw-r--r--drivers/net/mace.c2
-rw-r--r--drivers/net/mvme147.c2
-rw-r--r--drivers/net/myri_sbus.c2
-rw-r--r--drivers/net/natsemi.c2
-rw-r--r--drivers/net/ne2k-pci.c2
-rw-r--r--drivers/net/ns83820.c4
-rw-r--r--drivers/net/oaknet.c2
-rw-r--r--drivers/net/pci-skeleton.c2
-rw-r--r--drivers/net/pcmcia/3c574_cs.c6
-rw-r--r--drivers/net/pcmcia/3c589_cs.c6
-rw-r--r--drivers/net/pcmcia/axnet_cs.c6
-rw-r--r--drivers/net/pcmcia/com20020_cs.c2
-rw-r--r--drivers/net/pcmcia/fmvj18x_cs.c6
-rw-r--r--drivers/net/pcmcia/ibmtr_cs.c2
-rw-r--r--drivers/net/pcmcia/nmclan_cs.c6
-rw-r--r--drivers/net/pcmcia/pcnet_cs.c6
-rw-r--r--drivers/net/pcmcia/smc91c92_cs.c6
-rw-r--r--drivers/net/pcmcia/xirc2ps_cs.c6
-rw-r--r--drivers/net/pcnet32.c2
-rw-r--r--drivers/net/plip.c2
-rw-r--r--drivers/net/ppp_generic.c7
-rw-r--r--drivers/net/r8169.c2
-rw-r--r--drivers/net/rcpci45.c2
-rw-r--r--drivers/net/rrunner.c2
-rw-r--r--drivers/net/sb1000.c2
-rw-r--r--drivers/net/sb1250-mac.c2
-rw-r--r--drivers/net/sgiseeq.c2
-rw-r--r--drivers/net/shaper.c2
-rw-r--r--drivers/net/sis190.c2
-rw-r--r--drivers/net/sis900.c2
-rw-r--r--drivers/net/sk98lin/skge.c2
-rw-r--r--drivers/net/sk_g16.c2
-rw-r--r--drivers/net/skfp/skfddi.c2
-rw-r--r--drivers/net/slip.c2
-rw-r--r--drivers/net/starfire.c2
-rw-r--r--drivers/net/sunbmac.c2
-rw-r--r--drivers/net/sundance.c2
-rw-r--r--drivers/net/sungem.c2
-rw-r--r--drivers/net/sunhme.c2
-rw-r--r--drivers/net/sunlance.c2
-rw-r--r--drivers/net/sunqe.c2
-rw-r--r--drivers/net/tc35815.c2
-rw-r--r--drivers/net/tg3.c2
-rw-r--r--drivers/net/tlan.c2
-rw-r--r--drivers/net/tokenring/3c359.c2
-rw-r--r--drivers/net/tokenring/abyss.c2
-rw-r--r--drivers/net/tokenring/ibmtr.c2
-rw-r--r--drivers/net/tokenring/lanstreamer.c2
-rw-r--r--drivers/net/tokenring/madgemc.c2
-rw-r--r--drivers/net/tokenring/olympic.c2
-rw-r--r--drivers/net/tokenring/proteon.c2
-rw-r--r--drivers/net/tokenring/skisa.c2
-rw-r--r--drivers/net/tokenring/smctr.c2
-rw-r--r--drivers/net/tokenring/tmspci.c2
-rw-r--r--drivers/net/tulip/de2104x.c2
-rw-r--r--drivers/net/tulip/de4x5.c2
-rw-r--r--drivers/net/tulip/dmfe.c2
-rw-r--r--drivers/net/tulip/tulip_core.c2
-rw-r--r--drivers/net/tulip/winbond-840.c2
-rw-r--r--drivers/net/tulip/xircom_cb.c2
-rw-r--r--drivers/net/tulip/xircom_tulip_cb.c2
-rw-r--r--drivers/net/tun.c2
-rw-r--r--drivers/net/typhoon.c2
-rw-r--r--drivers/net/via-rhine.c2
-rw-r--r--drivers/net/wan/comx.c2
-rw-r--r--drivers/net/wan/cosa.c1
-rw-r--r--drivers/net/wan/dlci.c2
-rw-r--r--drivers/net/wan/hdlc_fr.c2
-rw-r--r--drivers/net/wan/lapbether.c2
-rw-r--r--drivers/net/wan/lmc/lmc_main.c2
-rw-r--r--drivers/net/wan/sbni.c2
-rw-r--r--drivers/net/wan/x25_asy.c2
-rw-r--r--drivers/net/wireless/airo.c4
-rw-r--r--drivers/net/wireless/airport.c2
-rw-r--r--drivers/net/wireless/arlan.c2
-rw-r--r--drivers/net/wireless/atmel.c2
-rw-r--r--drivers/net/wireless/netwave_cs.c4
-rw-r--r--drivers/net/wireless/orinoco_cs.c2
-rw-r--r--drivers/net/wireless/orinoco_pci.c2
-rw-r--r--drivers/net/wireless/orinoco_plx.c2
-rw-r--r--drivers/net/wireless/orinoco_tmd.c2
-rw-r--r--drivers/net/wireless/strip.c411
-rw-r--r--drivers/net/wireless/wavelan.c2
-rw-r--r--drivers/net/yellowfin.c2
-rw-r--r--drivers/net/znet.c2
-rw-r--r--drivers/net/zorro8390.c2
-rw-r--r--drivers/s390/net/ctcmain.c2
-rw-r--r--drivers/s390/net/netiucv.c2
-rw-r--r--drivers/usb/gadget/ether.c1
-rw-r--r--drivers/usb/net/catc.c2
-rw-r--r--drivers/usb/net/kaweth.c2
-rw-r--r--drivers/usb/net/pegasus.c2
-rw-r--r--drivers/usb/net/rtl8150.c2
-rw-r--r--include/linux/atmdev.h22
-rw-r--r--include/linux/netdevice.h3
-rw-r--r--include/net/irda/irlan_common.h9
-rw-r--r--include/net/irda/irlan_eth.h2
-rw-r--r--include/net/irda/irlan_filter.h2
-rw-r--r--include/net/neighbour.h1
-rw-r--r--net/802/tr.c137
-rw-r--r--net/8021q/vlan.c2
-rw-r--r--net/Kconfig1
-rw-r--r--net/atm/br2684.c222
-rw-r--r--net/atm/clip.c2
-rw-r--r--net/atm/common.c3
-rw-r--r--net/atm/lec.c2
-rw-r--r--net/atm/pppoatm.c8
-rw-r--r--net/bridge/br_device.c18
-rw-r--r--net/core/dev.c34
-rw-r--r--net/core/neighbour.c28
-rw-r--r--net/core/net-sysfs.c15
-rw-r--r--net/ipv4/arp.c21
-rw-r--r--net/ipv4/ip_gre.c2
-rw-r--r--net/ipv4/ipip.c2
-rw-r--r--net/ipv4/ipmr.c2
-rw-r--r--net/ipv6/ndisc.c21
-rw-r--r--net/ipv6/sit.c2
-rw-r--r--net/irda/ircomm/ircomm_tty.c8
-rw-r--r--net/irda/irda_device.c13
-rw-r--r--net/irda/irlan/irlan_client.c7
-rw-r--r--net/irda/irlan/irlan_common.c274
-rw-r--r--net/irda/irlan/irlan_eth.c12
-rw-r--r--net/irda/irlan/irlan_filter.c47
-rw-r--r--net/irda/irproc.c8
-rw-r--r--net/netrom/nr_dev.c2
-rw-r--r--net/netsyms.c1
-rw-r--r--net/rose/af_rose.c2
-rw-r--r--net/sched/sch_teql.c2
-rw-r--r--net/wanrouter/wanmain.c2
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;
}