aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ifb.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-12 16:31:22 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-12 16:31:22 -0400
commite1bd2ac5a6b7a8b625e40c9e9f8b6dea4cf22f85 (patch)
tree9366e9fb481da2c7195ca3f2bafeffebbf001363 /drivers/net/ifb.c
parent0b9062f6b57a87f22309c6b920a51aaa66ce2a13 (diff)
parent15028aad00ddf241581fbe74a02ec89cbb28d35d (diff)
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
* 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6: (183 commits) [TG3]: Update version to 3.78. [TG3]: Add missing NVRAM strapping. [TG3]: Enable auto MDI. [TG3]: Fix the polarity bit. [TG3]: Fix irq_sync race condition. [NET_SCHED]: ematch: module autoloading [TCP]: tcp probe wraparound handling and other changes [RTNETLINK]: rtnl_link: allow specifying initial device address [RTNETLINK]: rtnl_link API simplification [VLAN]: Fix MAC address handling [ETH]: Validate address in eth_mac_addr [NET]: Fix races in net_rx_action vs netpoll. [AF_UNIX]: Rewrite garbage collector, fixes race. [NETFILTER]: {ip, nf}_conntrack_sctp: fix remotely triggerable NULL ptr dereference (CVE-2007-2876) [NET]: Make all initialized struct seq_operations const. [UDP]: Fix length check. [IPV6]: Remove unneeded pointer idev from addrconf_cleanup(). [DECNET]: Another unnecessary net/tcp.h inclusion in net/dn.h [IPV6]: Make IPV6_{RECV,2292}RTHDR boolean options. [IPV6]: Do not send RH0 anymore. ... Fixed up trivial conflict in Documentation/feature-removal-schedule.txt manually. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/net/ifb.c')
-rw-r--r--drivers/net/ifb.c78
1 files changed, 45 insertions, 33 deletions
diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c
index 07b4c0d7a75c..f5c3598e59af 100644
--- a/drivers/net/ifb.c
+++ b/drivers/net/ifb.c
@@ -136,13 +136,14 @@ resched:
136 136
137} 137}
138 138
139static void __init ifb_setup(struct net_device *dev) 139static void ifb_setup(struct net_device *dev)
140{ 140{
141 /* Initialize the device structure. */ 141 /* Initialize the device structure. */
142 dev->get_stats = ifb_get_stats; 142 dev->get_stats = ifb_get_stats;
143 dev->hard_start_xmit = ifb_xmit; 143 dev->hard_start_xmit = ifb_xmit;
144 dev->open = &ifb_open; 144 dev->open = &ifb_open;
145 dev->stop = &ifb_close; 145 dev->stop = &ifb_close;
146 dev->destructor = free_netdev;
146 147
147 /* Fill in device structure with ethernet-generic values. */ 148 /* Fill in device structure with ethernet-generic values. */
148 ether_setup(dev); 149 ether_setup(dev);
@@ -197,12 +198,6 @@ static struct net_device_stats *ifb_get_stats(struct net_device *dev)
197 return stats; 198 return stats;
198} 199}
199 200
200static struct net_device **ifbs;
201
202/* Number of ifb devices to be set up by this module. */
203module_param(numifbs, int, 0);
204MODULE_PARM_DESC(numifbs, "Number of ifb devices");
205
206static int ifb_close(struct net_device *dev) 201static int ifb_close(struct net_device *dev)
207{ 202{
208 struct ifb_private *dp = netdev_priv(dev); 203 struct ifb_private *dp = netdev_priv(dev);
@@ -226,6 +221,28 @@ static int ifb_open(struct net_device *dev)
226 return 0; 221 return 0;
227} 222}
228 223
224static int ifb_validate(struct nlattr *tb[], struct nlattr *data[])
225{
226 if (tb[IFLA_ADDRESS]) {
227 if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
228 return -EINVAL;
229 if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS])))
230 return -EADDRNOTAVAIL;
231 }
232 return 0;
233}
234
235static struct rtnl_link_ops ifb_link_ops __read_mostly = {
236 .kind = "ifb",
237 .priv_size = sizeof(struct ifb_private),
238 .setup = ifb_setup,
239 .validate = ifb_validate,
240};
241
242/* Number of ifb devices to be set up by this module. */
243module_param(numifbs, int, 0);
244MODULE_PARM_DESC(numifbs, "Number of ifb devices");
245
229static int __init ifb_init_one(int index) 246static int __init ifb_init_one(int index)
230{ 247{
231 struct net_device *dev_ifb; 248 struct net_device *dev_ifb;
@@ -237,49 +254,44 @@ static int __init ifb_init_one(int index)
237 if (!dev_ifb) 254 if (!dev_ifb)
238 return -ENOMEM; 255 return -ENOMEM;
239 256
240 if ((err = register_netdev(dev_ifb))) { 257 err = dev_alloc_name(dev_ifb, dev_ifb->name);
241 free_netdev(dev_ifb); 258 if (err < 0)
242 dev_ifb = NULL; 259 goto err;
243 } else {
244 ifbs[index] = dev_ifb;
245 }
246 260
247 return err; 261 dev_ifb->rtnl_link_ops = &ifb_link_ops;
248} 262 err = register_netdevice(dev_ifb);
263 if (err < 0)
264 goto err;
265 return 0;
249 266
250static void ifb_free_one(int index) 267err:
251{ 268 free_netdev(dev_ifb);
252 unregister_netdev(ifbs[index]); 269 return err;
253 free_netdev(ifbs[index]);
254} 270}
255 271
256static int __init ifb_init_module(void) 272static int __init ifb_init_module(void)
257{ 273{
258 int i, err = 0; 274 int i, err;
259 ifbs = kmalloc(numifbs * sizeof(void *), GFP_KERNEL); 275
260 if (!ifbs) 276 rtnl_lock();
261 return -ENOMEM; 277 err = __rtnl_link_register(&ifb_link_ops);
278
262 for (i = 0; i < numifbs && !err; i++) 279 for (i = 0; i < numifbs && !err; i++)
263 err = ifb_init_one(i); 280 err = ifb_init_one(i);
264 if (err) { 281 if (err)
265 i--; 282 __rtnl_link_unregister(&ifb_link_ops);
266 while (--i >= 0) 283 rtnl_unlock();
267 ifb_free_one(i);
268 }
269 284
270 return err; 285 return err;
271} 286}
272 287
273static void __exit ifb_cleanup_module(void) 288static void __exit ifb_cleanup_module(void)
274{ 289{
275 int i; 290 rtnl_link_unregister(&ifb_link_ops);
276
277 for (i = 0; i < numifbs; i++)
278 ifb_free_one(i);
279 kfree(ifbs);
280} 291}
281 292
282module_init(ifb_init_module); 293module_init(ifb_init_module);
283module_exit(ifb_cleanup_module); 294module_exit(ifb_cleanup_module);
284MODULE_LICENSE("GPL"); 295MODULE_LICENSE("GPL");
285MODULE_AUTHOR("Jamal Hadi Salim"); 296MODULE_AUTHOR("Jamal Hadi Salim");
297MODULE_ALIAS_RTNL_LINK("ifb");