aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2007-07-11 22:42:13 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-07-11 22:45:33 -0400
commit2d85cba2b272a5201a60966a65a4f8c0bcc0bb71 (patch)
treef8dd1ca6d7c963eade714a4ecc7aec4d7751f55a
parent8c979c26a0f093c13290320edda799d8335e50ae (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>
-rw-r--r--drivers/net/dummy.c57
-rw-r--r--drivers/net/ifb.c58
-rw-r--r--net/8021q/vlan.c21
-rw-r--r--net/core/rtnetlink.c18
4 files changed, 23 insertions, 131 deletions
diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c
index 91126b9ce453..373ff700404f 100644
--- a/drivers/net/dummy.c
+++ b/drivers/net/dummy.c
@@ -37,11 +37,6 @@
37#include <linux/rtnetlink.h> 37#include <linux/rtnetlink.h>
38#include <net/rtnetlink.h> 38#include <net/rtnetlink.h>
39 39
40struct dummy_priv {
41 struct net_device *dev;
42 struct list_head list;
43};
44
45static int numdummies = 1; 40static int numdummies = 1;
46 41
47static int dummy_xmit(struct sk_buff *skb, struct net_device *dev); 42static int dummy_xmit(struct sk_buff *skb, struct net_device *dev);
@@ -89,37 +84,9 @@ static int dummy_xmit(struct sk_buff *skb, struct net_device *dev)
89 return 0; 84 return 0;
90} 85}
91 86
92static LIST_HEAD(dummies);
93
94static int dummy_newlink(struct net_device *dev,
95 struct nlattr *tb[], struct nlattr *data[])
96{
97 struct dummy_priv *priv = netdev_priv(dev);
98 int err;
99
100 err = register_netdevice(dev);
101 if (err < 0)
102 return err;
103
104 priv->dev = dev;
105 list_add_tail(&priv->list, &dummies);
106 return 0;
107}
108
109static void dummy_dellink(struct net_device *dev)
110{
111 struct dummy_priv *priv = netdev_priv(dev);
112
113 list_del(&priv->list);
114 unregister_netdevice(dev);
115}
116
117static struct rtnl_link_ops dummy_link_ops __read_mostly = { 87static struct rtnl_link_ops dummy_link_ops __read_mostly = {
118 .kind = "dummy", 88 .kind = "dummy",
119 .priv_size = sizeof(struct dummy_priv),
120 .setup = dummy_setup, 89 .setup = dummy_setup,
121 .newlink = dummy_newlink,
122 .dellink = dummy_dellink,
123}; 90};
124 91
125/* Number of dummy devices to be set up by this module. */ 92/* Number of dummy devices to be set up by this module. */
@@ -129,12 +96,9 @@ MODULE_PARM_DESC(numdummies, "Number of dummy pseudo devices");
129static int __init dummy_init_one(void) 96static int __init dummy_init_one(void)
130{ 97{
131 struct net_device *dev_dummy; 98 struct net_device *dev_dummy;
132 struct dummy_priv *priv;
133 int err; 99 int err;
134 100
135 dev_dummy = alloc_netdev(sizeof(struct dummy_priv), "dummy%d", 101 dev_dummy = alloc_netdev(0, "dummy%d", dummy_setup);
136 dummy_setup);
137
138 if (!dev_dummy) 102 if (!dev_dummy)
139 return -ENOMEM; 103 return -ENOMEM;
140 104
@@ -146,10 +110,6 @@ static int __init dummy_init_one(void)
146 err = register_netdevice(dev_dummy); 110 err = register_netdevice(dev_dummy);
147 if (err < 0) 111 if (err < 0)
148 goto err; 112 goto err;
149
150 priv = netdev_priv(dev_dummy);
151 priv->dev = dev_dummy;
152 list_add_tail(&priv->list, &dummies);
153 return 0; 113 return 0;
154 114
155err: 115err:
@@ -159,7 +119,6 @@ err:
159 119
160static int __init dummy_init_module(void) 120static int __init dummy_init_module(void)
161{ 121{
162 struct dummy_priv *priv, *next;
163 int i, err = 0; 122 int i, err = 0;
164 123
165 rtnl_lock(); 124 rtnl_lock();
@@ -167,11 +126,8 @@ static int __init dummy_init_module(void)
167 126
168 for (i = 0; i < numdummies && !err; i++) 127 for (i = 0; i < numdummies && !err; i++)
169 err = dummy_init_one(); 128 err = dummy_init_one();
170 if (err < 0) { 129 if (err < 0)
171 list_for_each_entry_safe(priv, next, &dummies, list)
172 dummy_dellink(priv->dev);
173 __rtnl_link_unregister(&dummy_link_ops); 130 __rtnl_link_unregister(&dummy_link_ops);
174 }
175 rtnl_unlock(); 131 rtnl_unlock();
176 132
177 return err; 133 return err;
@@ -179,14 +135,7 @@ static int __init dummy_init_module(void)
179 135
180static void __exit dummy_cleanup_module(void) 136static void __exit dummy_cleanup_module(void)
181{ 137{
182 struct dummy_priv *priv, *next; 138 rtnl_link_unregister(&dummy_link_ops);
183
184 rtnl_lock();
185 list_for_each_entry_safe(priv, next, &dummies, list)
186 dummy_dellink(priv->dev);
187
188 __rtnl_link_unregister(&dummy_link_ops);
189 rtnl_unlock();
190} 139}
191 140
192module_init(dummy_init_module); 141module_init(dummy_init_module);
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
42struct ifb_private { 41struct 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
204static LIST_HEAD(ifbs);
205
206/* Number of ifb devices to be set up by this module. */
207module_param(numifbs, int, 0);
208MODULE_PARM_DESC(numifbs, "Number of ifb devices");
209
210static int ifb_close(struct net_device *dev) 201static 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
233static 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
248static 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
256static struct rtnl_link_ops ifb_link_ops __read_mostly = { 224static 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. */
231module_param(numifbs, int, 0);
232MODULE_PARM_DESC(numifbs, "Number of ifb devices");
233
264static int __init ifb_init_one(int index) 234static 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
290err: 255err:
@@ -294,7 +259,6 @@ err:
294 259
295static int __init ifb_init_module(void) 260static 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
315static void __exit ifb_cleanup_module(void) 276static 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
327module_init(ifb_init_module); 281module_init(ifb_init_module);
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index b463ba47024d..34c1d0b241ca 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -115,26 +115,6 @@ err1:
115 return err; 115 return err;
116} 116}
117 117
118/* Cleanup all vlan devices
119 * Note: devices that have been registered that but not
120 * brought up will exist but have no module ref count.
121 */
122static void __exit vlan_cleanup_devices(void)
123{
124 struct net_device *dev, *nxt;
125
126 rtnl_lock();
127 for_each_netdev_safe(dev, nxt) {
128 if (dev->priv_flags & IFF_802_1Q_VLAN) {
129 unregister_vlan_dev(VLAN_DEV_INFO(dev)->real_dev,
130 VLAN_DEV_INFO(dev)->vlan_id);
131
132 unregister_netdevice(dev);
133 }
134 }
135 rtnl_unlock();
136}
137
138/* 118/*
139 * Module 'remove' entry point. 119 * Module 'remove' entry point.
140 * o delete /proc/net/router directory and static entries. 120 * o delete /proc/net/router directory and static entries.
@@ -150,7 +130,6 @@ static void __exit vlan_cleanup_module(void)
150 unregister_netdevice_notifier(&vlan_notifier_block); 130 unregister_netdevice_notifier(&vlan_notifier_block);
151 131
152 dev_remove_pack(&vlan_packet_type); 132 dev_remove_pack(&vlan_packet_type);
153 vlan_cleanup_devices();
154 133
155 /* This table must be empty if there are no module 134 /* This table must be empty if there are no module
156 * references left. 135 * references left.
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 54c17e4cd28f..7b6b16396745 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -270,6 +270,9 @@ static LIST_HEAD(link_ops);
270 */ 270 */
271int __rtnl_link_register(struct rtnl_link_ops *ops) 271int __rtnl_link_register(struct rtnl_link_ops *ops)
272{ 272{
273 if (!ops->dellink)
274 ops->dellink = unregister_netdevice;
275
273 list_add_tail(&ops->list, &link_ops); 276 list_add_tail(&ops->list, &link_ops);
274 return 0; 277 return 0;
275} 278}
@@ -298,12 +301,16 @@ EXPORT_SYMBOL_GPL(rtnl_link_register);
298 * __rtnl_link_unregister - Unregister rtnl_link_ops from rtnetlink. 301 * __rtnl_link_unregister - Unregister rtnl_link_ops from rtnetlink.
299 * @ops: struct rtnl_link_ops * to unregister 302 * @ops: struct rtnl_link_ops * to unregister
300 * 303 *
301 * The caller must hold the rtnl_mutex. This function should be used 304 * The caller must hold the rtnl_mutex.
302 * by drivers that unregister devices during module unloading. It must
303 * be called after unregistering the devices.
304 */ 305 */
305void __rtnl_link_unregister(struct rtnl_link_ops *ops) 306void __rtnl_link_unregister(struct rtnl_link_ops *ops)
306{ 307{
308 struct net_device *dev, *n;
309
310 for_each_netdev_safe(dev, n) {
311 if (dev->rtnl_link_ops == ops)
312 ops->dellink(dev);
313 }
307 list_del(&ops->list); 314 list_del(&ops->list);
308} 315}
309 316
@@ -1067,7 +1074,10 @@ replay:
1067 if (tb[IFLA_LINKMODE]) 1074 if (tb[IFLA_LINKMODE])
1068 dev->link_mode = nla_get_u8(tb[IFLA_LINKMODE]); 1075 dev->link_mode = nla_get_u8(tb[IFLA_LINKMODE]);
1069 1076
1070 err = ops->newlink(dev, tb, data); 1077 if (ops->newlink)
1078 err = ops->newlink(dev, tb, data);
1079 else
1080 err = register_netdevice(dev);
1071err_free: 1081err_free:
1072 if (err < 0) 1082 if (err < 0)
1073 free_netdev(dev); 1083 free_netdev(dev);