summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@osdl.org>2003-08-07 06:28:33 +1000
committerStephen Hemminger <shemminger@osdl.org>2003-08-07 06:28:33 +1000
commit6ae0b08d7fb678751ec27a2b22f38c771e9eed8f (patch)
tree4d749d78ac128d6f1ca14543a9c2c4b9a90c0600
parentcd5221688ad84366dfcb9dd7286ecd4766f9d6e6 (diff)
[NET] Dynamically allocate net_device structures for ROSE
This patch changes the ROSE protocol to allocate an array of pointers and each network device separately. This sets up later change where network_device object's are released on last use which may be after the module is unloaded. The patch is against 2.6.0-test2 (though this code hasn't changed in a long time). Allocation is done via alloc_netdev so the dev->priv area is already reserved and doesn't need to be allocated separately.
-rw-r--r--include/net/rose.h2
-rw-r--r--net/rose/af_rose.c47
-rw-r--r--net/rose/rose_dev.c12
3 files changed, 38 insertions, 23 deletions
diff --git a/include/net/rose.h b/include/net/rose.h
index 96d561e15a26..37e8176ee7d2 100644
--- a/include/net/rose.h
+++ b/include/net/rose.h
@@ -163,7 +163,7 @@ extern void rose_destroy_socket(struct sock *);
/* rose_dev.c */
extern int rose_rx_ip(struct sk_buff *, struct net_device *);
-extern int rose_init(struct net_device *);
+extern void rose_setup(struct net_device *);
/* rose_in.c */
extern int rose_process_rx_frame(struct sock *, struct sk_buff *);
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c
index 4beee50e18ff..96fc7d9a087d 100644
--- a/net/rose/af_rose.c
+++ b/net/rose/af_rose.c
@@ -43,7 +43,7 @@
#include <net/ip.h>
#include <net/arp.h>
-int rose_ndevs = 10;
+static int rose_ndevs = 10;
int sysctl_rose_restart_request_timeout = ROSE_DEFAULT_T0;
int sysctl_rose_call_request_timeout = ROSE_DEFAULT_T1;
@@ -56,7 +56,7 @@ int sysctl_rose_link_fail_timeout = ROSE_DEFAULT_FAIL_TIMEOUT;
int sysctl_rose_maximum_vcs = ROSE_DEFAULT_MAXVC;
int sysctl_rose_window_size = ROSE_DEFAULT_WINDOW_SIZE;
-HLIST_HEAD(rose_list);
+static HLIST_HEAD(rose_list);
static spinlock_t rose_list_lock = SPIN_LOCK_UNLOCKED;
static struct proto_ops rose_proto_ops;
@@ -1435,7 +1435,7 @@ static struct notifier_block rose_dev_notifier = {
.notifier_call = rose_device_event,
};
-static struct net_device *dev_rose;
+static struct net_device **dev_rose;
static const char banner[] = KERN_INFO "F6FBB/G4KLX ROSE for Linux. Version 0.62 for AX25.037 Linux 2.4\n";
@@ -1450,17 +1450,39 @@ static int __init rose_proto_init(void)
return -1;
}
- if ((dev_rose = kmalloc(rose_ndevs * sizeof(struct net_device), GFP_KERNEL)) == NULL) {
+ dev_rose = kmalloc(rose_ndevs * sizeof(struct net_device *), GFP_KERNEL);
+ if (dev_rose == NULL) {
printk(KERN_ERR "ROSE: rose_proto_init - unable to allocate device structure\n");
return -1;
}
- memset(dev_rose, 0x00, rose_ndevs * sizeof(struct net_device));
+ memset(dev_rose, 0x00, rose_ndevs * sizeof(struct net_device*));
+ for (i = 0; i < rose_ndevs; i++) {
+ struct net_device *dev;
+ char name[IFNAMSIZ];
+
+ sprintf(name, "rose%d", i);
+ dev = alloc_netdev(sizeof(struct net_device_stats),
+ name, rose_setup);
+ if (!dev) {
+ printk(KERN_ERR "ROSE: rose_proto_init - unable to allocate memory\n");
+ while (--i >= 0)
+ kfree(dev_rose[i]);
+ return -ENOMEM;
+ }
+ dev_rose[i] = dev;
+ }
for (i = 0; i < rose_ndevs; i++) {
- sprintf(dev_rose[i].name, "rose%d", i);
- dev_rose[i].init = rose_init;
- register_netdev(&dev_rose[i]);
+ if (register_netdev(dev_rose[i])) {
+ printk(KERN_ERR "ROSE: netdevice regeistration failed\n");
+ while (--i >= 0) {
+ unregister_netdev(dev_rose[i]);
+ kfree(dev_rose[i]);
+ return -EIO;
+ }
+ }
+
}
sock_register(&rose_family_ops);
@@ -1518,10 +1540,11 @@ static void __exit rose_exit(void)
sock_unregister(PF_ROSE);
for (i = 0; i < rose_ndevs; i++) {
- if (dev_rose[i].priv != NULL) {
- kfree(dev_rose[i].priv);
- dev_rose[i].priv = NULL;
- unregister_netdev(&dev_rose[i]);
+ struct net_device *dev = dev_rose[i];
+
+ if (dev) {
+ unregister_netdev(dev);
+ kfree(dev);
}
}
diff --git a/net/rose/rose_dev.c b/net/rose/rose_dev.c
index 45adce6ea28e..d779e071b97d 100644
--- a/net/rose/rose_dev.c
+++ b/net/rose/rose_dev.c
@@ -165,7 +165,7 @@ static struct net_device_stats *rose_get_stats(struct net_device *dev)
return (struct net_device_stats *)dev->priv;
}
-int rose_init(struct net_device *dev)
+void rose_setup(struct net_device *dev)
{
SET_MODULE_OWNER(dev);
dev->mtu = ROSE_MAX_PACKET_SIZE - 2;
@@ -182,13 +182,5 @@ int rose_init(struct net_device *dev)
/* New-style flags. */
dev->flags = 0;
-
- if ((dev->priv = kmalloc(sizeof(struct net_device_stats), GFP_KERNEL)) == NULL)
- return -ENOMEM;
-
- memset(dev->priv, 0, sizeof(struct net_device_stats));
-
dev->get_stats = rose_get_stats;
-
- return 0;
-};
+}