diff options
author | Patrick McHardy <kaber@trash.net> | 2007-06-13 15:04:20 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-07-11 01:14:25 -0400 |
commit | 206c9fb26f5df2ea6d440fb64159faf4d8665398 (patch) | |
tree | feb0240bfe4c87f21d74dc16e897cc5e043e3acb | |
parent | 58651b24acfd9a6fd3b217b52e577ce34b0932af (diff) |
[DUMMY]: Keep dummy devices on list
Use a list instead of an array to allow creating new devices.
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/dummy.c | 47 |
1 files changed, 29 insertions, 18 deletions
diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c index 91b474c9bba0..2f2cf3c04bc7 100644 --- a/drivers/net/dummy.c +++ b/drivers/net/dummy.c | |||
@@ -34,6 +34,12 @@ | |||
34 | #include <linux/etherdevice.h> | 34 | #include <linux/etherdevice.h> |
35 | #include <linux/init.h> | 35 | #include <linux/init.h> |
36 | #include <linux/moduleparam.h> | 36 | #include <linux/moduleparam.h> |
37 | #include <linux/rtnetlink.h> | ||
38 | |||
39 | struct dummy_priv { | ||
40 | struct net_device *dev; | ||
41 | struct list_head list; | ||
42 | }; | ||
37 | 43 | ||
38 | static int numdummies = 1; | 44 | static int numdummies = 1; |
39 | 45 | ||
@@ -81,18 +87,20 @@ static int dummy_xmit(struct sk_buff *skb, struct net_device *dev) | |||
81 | return 0; | 87 | return 0; |
82 | } | 88 | } |
83 | 89 | ||
84 | static struct net_device **dummies; | 90 | static LIST_HEAD(dummies); |
85 | 91 | ||
86 | /* Number of dummy devices to be set up by this module. */ | 92 | /* Number of dummy devices to be set up by this module. */ |
87 | module_param(numdummies, int, 0); | 93 | module_param(numdummies, int, 0); |
88 | MODULE_PARM_DESC(numdummies, "Number of dummy pseudo devices"); | 94 | MODULE_PARM_DESC(numdummies, "Number of dummy pseudo devices"); |
89 | 95 | ||
90 | static int __init dummy_init_one(int index) | 96 | static int __init dummy_init_one(void) |
91 | { | 97 | { |
92 | struct net_device *dev_dummy; | 98 | struct net_device *dev_dummy; |
99 | struct dummy_priv *priv; | ||
93 | int err; | 100 | int err; |
94 | 101 | ||
95 | dev_dummy = alloc_netdev(0, "dummy%d", dummy_setup); | 102 | dev_dummy = alloc_netdev(sizeof(struct dummy_priv), "dummy%d", |
103 | dummy_setup); | ||
96 | 104 | ||
97 | if (!dev_dummy) | 105 | if (!dev_dummy) |
98 | return -ENOMEM; | 106 | return -ENOMEM; |
@@ -101,40 +109,43 @@ static int __init dummy_init_one(int index) | |||
101 | free_netdev(dev_dummy); | 109 | free_netdev(dev_dummy); |
102 | dev_dummy = NULL; | 110 | dev_dummy = NULL; |
103 | } else { | 111 | } else { |
104 | dummies[index] = dev_dummy; | 112 | priv = netdev_priv(dev_dummy); |
113 | priv->dev = dev_dummy; | ||
114 | list_add_tail(&priv->list, &dummies); | ||
105 | } | 115 | } |
106 | 116 | ||
107 | return err; | 117 | return err; |
108 | } | 118 | } |
109 | 119 | ||
110 | static void dummy_free_one(int index) | 120 | static void dummy_free_one(struct net_device *dev) |
111 | { | 121 | { |
112 | unregister_netdev(dummies[index]); | 122 | struct dummy_priv *priv = netdev_priv(dev); |
113 | free_netdev(dummies[index]); | 123 | |
124 | list_del(&priv->list); | ||
125 | unregister_netdev(dev); | ||
126 | free_netdev(dev); | ||
114 | } | 127 | } |
115 | 128 | ||
116 | static int __init dummy_init_module(void) | 129 | static int __init dummy_init_module(void) |
117 | { | 130 | { |
131 | struct dummy_priv *priv, *next; | ||
118 | int i, err = 0; | 132 | int i, err = 0; |
119 | dummies = kmalloc(numdummies * sizeof(void *), GFP_KERNEL); | 133 | |
120 | if (!dummies) | ||
121 | return -ENOMEM; | ||
122 | for (i = 0; i < numdummies && !err; i++) | 134 | for (i = 0; i < numdummies && !err; i++) |
123 | err = dummy_init_one(i); | 135 | err = dummy_init_one(); |
124 | if (err) { | 136 | if (err) { |
125 | i--; | 137 | list_for_each_entry_safe(priv, next, &dummies, list) |
126 | while (--i >= 0) | 138 | dummy_free_one(priv->dev); |
127 | dummy_free_one(i); | ||
128 | } | 139 | } |
129 | return err; | 140 | return err; |
130 | } | 141 | } |
131 | 142 | ||
132 | static void __exit dummy_cleanup_module(void) | 143 | static void __exit dummy_cleanup_module(void) |
133 | { | 144 | { |
134 | int i; | 145 | struct dummy_priv *priv, *next; |
135 | for (i = 0; i < numdummies; i++) | 146 | |
136 | dummy_free_one(i); | 147 | list_for_each_entry_safe(priv, next, &dummies, list) |
137 | kfree(dummies); | 148 | dummy_free_one(priv->dev); |
138 | } | 149 | } |
139 | 150 | ||
140 | module_init(dummy_init_module); | 151 | module_init(dummy_init_module); |