aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ifb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ifb.c')
-rw-r--r--drivers/net/ifb.c36
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
41struct ifb_private { 42struct 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
200static struct net_device **ifbs; 203static 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. */
203module_param(numifbs, int, 0); 206module_param(numifbs, int, 0);
@@ -229,6 +232,7 @@ static int ifb_open(struct net_device *dev)
229static int __init ifb_init_one(int index) 232static 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
250static void ifb_free_one(int index) 256static 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
256static int __init ifb_init_module(void) 265static 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
273static void __exit ifb_cleanup_module(void) 280static 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
282module_init(ifb_init_module); 288module_init(ifb_init_module);