diff options
author | Patrick McHardy <kaber@trash.net> | 2007-06-13 15:04:51 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-07-11 01:14:36 -0400 |
commit | 62b7ffcaaa4e91ed547fc55758076ac536bd5571 (patch) | |
tree | d383b7834d1faceb10b4b33c6c55c150cddd7864 /drivers/net | |
parent | 5d5cb173d85ebf6dfb16f456a8148ecb4b1cecbc (diff) |
[IFB]: Keep ifb 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>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/ifb.c | 36 |
1 files changed, 21 insertions, 15 deletions
diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c index 07b4c0d7a75c..819945e3b330 100644 --- a/drivers/net/ifb.c +++ b/drivers/net/ifb.c | |||
@@ -33,12 +33,15 @@ | |||
33 | #include <linux/etherdevice.h> | 33 | #include <linux/etherdevice.h> |
34 | #include <linux/init.h> | 34 | #include <linux/init.h> |
35 | #include <linux/moduleparam.h> | 35 | #include <linux/moduleparam.h> |
36 | #include <linux/list.h> | ||
36 | #include <net/pkt_sched.h> | 37 | #include <net/pkt_sched.h> |
37 | 38 | ||
38 | #define TX_TIMEOUT (2*HZ) | 39 | #define TX_TIMEOUT (2*HZ) |
39 | 40 | ||
40 | #define TX_Q_LIMIT 32 | 41 | #define TX_Q_LIMIT 32 |
41 | struct ifb_private { | 42 | struct ifb_private { |
43 | struct list_head list; | ||
44 | struct net_device *dev; | ||
42 | struct net_device_stats stats; | 45 | struct net_device_stats stats; |
43 | struct tasklet_struct ifb_tasklet; | 46 | struct tasklet_struct ifb_tasklet; |
44 | int tasklet_pending; | 47 | int tasklet_pending; |
@@ -197,7 +200,7 @@ static struct net_device_stats *ifb_get_stats(struct net_device *dev) | |||
197 | return stats; | 200 | return stats; |
198 | } | 201 | } |
199 | 202 | ||
200 | static struct net_device **ifbs; | 203 | static LIST_HEAD(ifbs); |
201 | 204 | ||
202 | /* Number of ifb devices to be set up by this module. */ | 205 | /* Number of ifb devices to be set up by this module. */ |
203 | module_param(numifbs, int, 0); | 206 | module_param(numifbs, int, 0); |
@@ -229,6 +232,7 @@ static int ifb_open(struct net_device *dev) | |||
229 | static int __init ifb_init_one(int index) | 232 | static int __init ifb_init_one(int index) |
230 | { | 233 | { |
231 | struct net_device *dev_ifb; | 234 | struct net_device *dev_ifb; |
235 | struct ifb_private *priv; | ||
232 | int err; | 236 | int err; |
233 | 237 | ||
234 | dev_ifb = alloc_netdev(sizeof(struct ifb_private), | 238 | dev_ifb = alloc_netdev(sizeof(struct ifb_private), |
@@ -241,30 +245,33 @@ static int __init ifb_init_one(int index) | |||
241 | free_netdev(dev_ifb); | 245 | free_netdev(dev_ifb); |
242 | dev_ifb = NULL; | 246 | dev_ifb = NULL; |
243 | } else { | 247 | } else { |
244 | ifbs[index] = dev_ifb; | 248 | priv = netdev_priv(dev_ifb); |
249 | priv->dev = dev_ifb; | ||
250 | list_add_tail(&priv->list, &ifbs); | ||
245 | } | 251 | } |
246 | 252 | ||
247 | return err; | 253 | return err; |
248 | } | 254 | } |
249 | 255 | ||
250 | static void ifb_free_one(int index) | 256 | static void ifb_free_one(struct net_device *dev) |
251 | { | 257 | { |
252 | unregister_netdev(ifbs[index]); | 258 | struct ifb_private *priv = netdev_priv(dev); |
253 | free_netdev(ifbs[index]); | 259 | |
260 | list_del(&priv->list); | ||
261 | unregister_netdev(dev); | ||
262 | free_netdev(dev); | ||
254 | } | 263 | } |
255 | 264 | ||
256 | static int __init ifb_init_module(void) | 265 | static int __init ifb_init_module(void) |
257 | { | 266 | { |
267 | struct ifb_private *priv, *next; | ||
258 | int i, err = 0; | 268 | int i, err = 0; |
259 | ifbs = kmalloc(numifbs * sizeof(void *), GFP_KERNEL); | 269 | |
260 | if (!ifbs) | ||
261 | return -ENOMEM; | ||
262 | for (i = 0; i < numifbs && !err; i++) | 270 | for (i = 0; i < numifbs && !err; i++) |
263 | err = ifb_init_one(i); | 271 | err = ifb_init_one(i); |
264 | if (err) { | 272 | if (err) { |
265 | i--; | 273 | list_for_each_entry_safe(priv, next, &ifbs, list) |
266 | while (--i >= 0) | 274 | ifb_free_one(priv->dev); |
267 | ifb_free_one(i); | ||
268 | } | 275 | } |
269 | 276 | ||
270 | return err; | 277 | return err; |
@@ -272,11 +279,10 @@ static int __init ifb_init_module(void) | |||
272 | 279 | ||
273 | static void __exit ifb_cleanup_module(void) | 280 | static void __exit ifb_cleanup_module(void) |
274 | { | 281 | { |
275 | int i; | 282 | struct ifb_private *priv, *next; |
276 | 283 | ||
277 | for (i = 0; i < numifbs; i++) | 284 | list_for_each_entry_safe(priv, next, &ifbs, list) |
278 | ifb_free_one(i); | 285 | ifb_free_one(priv->dev); |
279 | kfree(ifbs); | ||
280 | } | 286 | } |
281 | 287 | ||
282 | module_init(ifb_init_module); | 288 | module_init(ifb_init_module); |