aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/dummy.c82
1 files changed, 62 insertions, 20 deletions
diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c
index 2f2cf3c04bc7..91126b9ce453 100644
--- a/drivers/net/dummy.c
+++ b/drivers/net/dummy.c
@@ -35,6 +35,7 @@
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> 37#include <linux/rtnetlink.h>
38#include <net/rtnetlink.h>
38 39
39struct dummy_priv { 40struct dummy_priv {
40 struct net_device *dev; 41 struct net_device *dev;
@@ -61,12 +62,13 @@ static void set_multicast_list(struct net_device *dev)
61{ 62{
62} 63}
63 64
64static void __init dummy_setup(struct net_device *dev) 65static void dummy_setup(struct net_device *dev)
65{ 66{
66 /* Initialize the device structure. */ 67 /* Initialize the device structure. */
67 dev->hard_start_xmit = dummy_xmit; 68 dev->hard_start_xmit = dummy_xmit;
68 dev->set_multicast_list = set_multicast_list; 69 dev->set_multicast_list = set_multicast_list;
69 dev->set_mac_address = dummy_set_address; 70 dev->set_mac_address = dummy_set_address;
71 dev->destructor = free_netdev;
70 72
71 /* Fill in device structure with ethernet-generic values. */ 73 /* Fill in device structure with ethernet-generic values. */
72 ether_setup(dev); 74 ether_setup(dev);
@@ -89,6 +91,37 @@ static int dummy_xmit(struct sk_buff *skb, struct net_device *dev)
89 91
90static LIST_HEAD(dummies); 92static LIST_HEAD(dummies);
91 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 = {
118 .kind = "dummy",
119 .priv_size = sizeof(struct dummy_priv),
120 .setup = dummy_setup,
121 .newlink = dummy_newlink,
122 .dellink = dummy_dellink,
123};
124
92/* Number of dummy devices to be set up by this module. */ 125/* Number of dummy devices to be set up by this module. */
93module_param(numdummies, int, 0); 126module_param(numdummies, int, 0);
94MODULE_PARM_DESC(numdummies, "Number of dummy pseudo devices"); 127MODULE_PARM_DESC(numdummies, "Number of dummy pseudo devices");
@@ -105,25 +138,23 @@ static int __init dummy_init_one(void)
105 if (!dev_dummy) 138 if (!dev_dummy)
106 return -ENOMEM; 139 return -ENOMEM;
107 140
108 if ((err = register_netdev(dev_dummy))) { 141 err = dev_alloc_name(dev_dummy, dev_dummy->name);
109 free_netdev(dev_dummy); 142 if (err < 0)
110 dev_dummy = NULL; 143 goto err;
111 } else {
112 priv = netdev_priv(dev_dummy);
113 priv->dev = dev_dummy;
114 list_add_tail(&priv->list, &dummies);
115 }
116 144
117 return err; 145 dev_dummy->rtnl_link_ops = &dummy_link_ops;
118} 146 err = register_netdevice(dev_dummy);
147 if (err < 0)
148 goto err;
119 149
120static void dummy_free_one(struct net_device *dev) 150 priv = netdev_priv(dev_dummy);
121{ 151 priv->dev = dev_dummy;
122 struct dummy_priv *priv = netdev_priv(dev); 152 list_add_tail(&priv->list, &dummies);
153 return 0;
123 154
124 list_del(&priv->list); 155err:
125 unregister_netdev(dev); 156 free_netdev(dev_dummy);
126 free_netdev(dev); 157 return err;
127} 158}
128 159
129static int __init dummy_init_module(void) 160static int __init dummy_init_module(void)
@@ -131,12 +162,18 @@ static int __init dummy_init_module(void)
131 struct dummy_priv *priv, *next; 162 struct dummy_priv *priv, *next;
132 int i, err = 0; 163 int i, err = 0;
133 164
165 rtnl_lock();
166 err = __rtnl_link_register(&dummy_link_ops);
167
134 for (i = 0; i < numdummies && !err; i++) 168 for (i = 0; i < numdummies && !err; i++)
135 err = dummy_init_one(); 169 err = dummy_init_one();
136 if (err) { 170 if (err < 0) {
137 list_for_each_entry_safe(priv, next, &dummies, list) 171 list_for_each_entry_safe(priv, next, &dummies, list)
138 dummy_free_one(priv->dev); 172 dummy_dellink(priv->dev);
173 __rtnl_link_unregister(&dummy_link_ops);
139 } 174 }
175 rtnl_unlock();
176
140 return err; 177 return err;
141} 178}
142 179
@@ -144,10 +181,15 @@ static void __exit dummy_cleanup_module(void)
144{ 181{
145 struct dummy_priv *priv, *next; 182 struct dummy_priv *priv, *next;
146 183
184 rtnl_lock();
147 list_for_each_entry_safe(priv, next, &dummies, list) 185 list_for_each_entry_safe(priv, next, &dummies, list)
148 dummy_free_one(priv->dev); 186 dummy_dellink(priv->dev);
187
188 __rtnl_link_unregister(&dummy_link_ops);
189 rtnl_unlock();
149} 190}
150 191
151module_init(dummy_init_module); 192module_init(dummy_init_module);
152module_exit(dummy_cleanup_module); 193module_exit(dummy_cleanup_module);
153MODULE_LICENSE("GPL"); 194MODULE_LICENSE("GPL");
195MODULE_ALIAS_RTNL_LINK("dummy");