diff options
author | Patrick McHardy <kaber@trash.net> | 2007-07-11 22:42:13 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-07-11 22:45:33 -0400 |
commit | 2d85cba2b272a5201a60966a65a4f8c0bcc0bb71 (patch) | |
tree | f8dd1ca6d7c963eade714a4ecc7aec4d7751f55a /drivers/net/ifb.c | |
parent | 8c979c26a0f093c13290320edda799d8335e50ae (diff) |
[RTNETLINK]: rtnl_link API simplification
All drivers need to unregister their devices in the module unload function.
While doing so they must hold the rtnl and atomically unregister the
rtnl_link ops as well. This makes the rtnl_link_unregister function that
takes the rtnl itself completely useless.
Provide default newlink/dellink functions, make __rtnl_link_unregister and
rtnl_link_unregister unregister all devices with matching rtnl_link_ops and
change the existing users to take advantage of that.
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ifb.c')
-rw-r--r-- | drivers/net/ifb.c | 58 |
1 files changed, 6 insertions, 52 deletions
diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c index 669ee1a1b284..c8e7c8f6ba3e 100644 --- a/drivers/net/ifb.c +++ b/drivers/net/ifb.c | |||
@@ -33,15 +33,12 @@ | |||
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> | ||
37 | #include <net/pkt_sched.h> | 36 | #include <net/pkt_sched.h> |
38 | 37 | ||
39 | #define TX_TIMEOUT (2*HZ) | 38 | #define TX_TIMEOUT (2*HZ) |
40 | 39 | ||
41 | #define TX_Q_LIMIT 32 | 40 | #define TX_Q_LIMIT 32 |
42 | struct ifb_private { | 41 | struct ifb_private { |
43 | struct list_head list; | ||
44 | struct net_device *dev; | ||
45 | struct net_device_stats stats; | 42 | struct net_device_stats stats; |
46 | struct tasklet_struct ifb_tasklet; | 43 | struct tasklet_struct ifb_tasklet; |
47 | int tasklet_pending; | 44 | int tasklet_pending; |
@@ -201,12 +198,6 @@ static struct net_device_stats *ifb_get_stats(struct net_device *dev) | |||
201 | return stats; | 198 | return stats; |
202 | } | 199 | } |
203 | 200 | ||
204 | static LIST_HEAD(ifbs); | ||
205 | |||
206 | /* Number of ifb devices to be set up by this module. */ | ||
207 | module_param(numifbs, int, 0); | ||
208 | MODULE_PARM_DESC(numifbs, "Number of ifb devices"); | ||
209 | |||
210 | static int ifb_close(struct net_device *dev) | 201 | static int ifb_close(struct net_device *dev) |
211 | { | 202 | { |
212 | struct ifb_private *dp = netdev_priv(dev); | 203 | struct ifb_private *dp = netdev_priv(dev); |
@@ -230,41 +221,19 @@ static int ifb_open(struct net_device *dev) | |||
230 | return 0; | 221 | return 0; |
231 | } | 222 | } |
232 | 223 | ||
233 | static int ifb_newlink(struct net_device *dev, | ||
234 | struct nlattr *tb[], struct nlattr *data[]) | ||
235 | { | ||
236 | struct ifb_private *priv = netdev_priv(dev); | ||
237 | int err; | ||
238 | |||
239 | err = register_netdevice(dev); | ||
240 | if (err < 0) | ||
241 | return err; | ||
242 | |||
243 | priv->dev = dev; | ||
244 | list_add_tail(&priv->list, &ifbs); | ||
245 | return 0; | ||
246 | } | ||
247 | |||
248 | static void ifb_dellink(struct net_device *dev) | ||
249 | { | ||
250 | struct ifb_private *priv = netdev_priv(dev); | ||
251 | |||
252 | list_del(&priv->list); | ||
253 | unregister_netdevice(dev); | ||
254 | } | ||
255 | |||
256 | static struct rtnl_link_ops ifb_link_ops __read_mostly = { | 224 | static struct rtnl_link_ops ifb_link_ops __read_mostly = { |
257 | .kind = "ifb", | 225 | .kind = "ifb", |
258 | .priv_size = sizeof(struct ifb_private), | 226 | .priv_size = sizeof(struct ifb_private), |
259 | .setup = ifb_setup, | 227 | .setup = ifb_setup, |
260 | .newlink = ifb_newlink, | ||
261 | .dellink = ifb_dellink, | ||
262 | }; | 228 | }; |
263 | 229 | ||
230 | /* Number of ifb devices to be set up by this module. */ | ||
231 | module_param(numifbs, int, 0); | ||
232 | MODULE_PARM_DESC(numifbs, "Number of ifb devices"); | ||
233 | |||
264 | static int __init ifb_init_one(int index) | 234 | static int __init ifb_init_one(int index) |
265 | { | 235 | { |
266 | struct net_device *dev_ifb; | 236 | struct net_device *dev_ifb; |
267 | struct ifb_private *priv; | ||
268 | int err; | 237 | int err; |
269 | 238 | ||
270 | dev_ifb = alloc_netdev(sizeof(struct ifb_private), | 239 | dev_ifb = alloc_netdev(sizeof(struct ifb_private), |
@@ -281,10 +250,6 @@ static int __init ifb_init_one(int index) | |||
281 | err = register_netdevice(dev_ifb); | 250 | err = register_netdevice(dev_ifb); |
282 | if (err < 0) | 251 | if (err < 0) |
283 | goto err; | 252 | goto err; |
284 | |||
285 | priv = netdev_priv(dev_ifb); | ||
286 | priv->dev = dev_ifb; | ||
287 | list_add_tail(&priv->list, &ifbs); | ||
288 | return 0; | 253 | return 0; |
289 | 254 | ||
290 | err: | 255 | err: |
@@ -294,7 +259,6 @@ err: | |||
294 | 259 | ||
295 | static int __init ifb_init_module(void) | 260 | static int __init ifb_init_module(void) |
296 | { | 261 | { |
297 | struct ifb_private *priv, *next; | ||
298 | int i, err; | 262 | int i, err; |
299 | 263 | ||
300 | rtnl_lock(); | 264 | rtnl_lock(); |
@@ -302,11 +266,8 @@ static int __init ifb_init_module(void) | |||
302 | 266 | ||
303 | for (i = 0; i < numifbs && !err; i++) | 267 | for (i = 0; i < numifbs && !err; i++) |
304 | err = ifb_init_one(i); | 268 | err = ifb_init_one(i); |
305 | if (err) { | 269 | if (err) |
306 | list_for_each_entry_safe(priv, next, &ifbs, list) | ||
307 | ifb_dellink(priv->dev); | ||
308 | __rtnl_link_unregister(&ifb_link_ops); | 270 | __rtnl_link_unregister(&ifb_link_ops); |
309 | } | ||
310 | rtnl_unlock(); | 271 | rtnl_unlock(); |
311 | 272 | ||
312 | return err; | 273 | return err; |
@@ -314,14 +275,7 @@ static int __init ifb_init_module(void) | |||
314 | 275 | ||
315 | static void __exit ifb_cleanup_module(void) | 276 | static void __exit ifb_cleanup_module(void) |
316 | { | 277 | { |
317 | struct ifb_private *priv, *next; | 278 | rtnl_link_unregister(&ifb_link_ops); |
318 | |||
319 | rtnl_lock(); | ||
320 | list_for_each_entry_safe(priv, next, &ifbs, list) | ||
321 | ifb_dellink(priv->dev); | ||
322 | |||
323 | __rtnl_link_unregister(&ifb_link_ops); | ||
324 | rtnl_unlock(); | ||
325 | } | 279 | } |
326 | 280 | ||
327 | module_init(ifb_init_module); | 281 | module_init(ifb_init_module); |