diff options
| author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-12 13:31:22 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-12 13:31:22 -0700 |
| commit | e1bd2ac5a6b7a8b625e40c9e9f8b6dea4cf22f85 (patch) | |
| tree | 9366e9fb481da2c7195ca3f2bafeffebbf001363 /drivers/net/ifb.c | |
| parent | 0b9062f6b57a87f22309c6b920a51aaa66ce2a13 (diff) | |
| parent | 15028aad00ddf241581fbe74a02ec89cbb28d35d (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.c | 78 |
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: } -static void __init ifb_setup(struct net_device *dev) +static void ifb_setup(struct net_device *dev) { /* Initialize the device structure. */ dev->get_stats = ifb_get_stats; dev->hard_start_xmit = ifb_xmit; dev->open = &ifb_open; dev->stop = &ifb_close; + dev->destructor = free_netdev; /* Fill in device structure with ethernet-generic values. */ ether_setup(dev); @@ -197,12 +198,6 @@ static struct net_device_stats *ifb_get_stats(struct net_device *dev) return stats; } -static struct net_device **ifbs; - -/* Number of ifb devices to be set up by this module. */ -module_param(numifbs, int, 0); -MODULE_PARM_DESC(numifbs, "Number of ifb devices"); - static int ifb_close(struct net_device *dev) { struct ifb_private *dp = netdev_priv(dev); @@ -226,6 +221,28 @@ static int ifb_open(struct net_device *dev) return 0; } +static int ifb_validate(struct nlattr *tb[], struct nlattr *data[]) +{ + if (tb[IFLA_ADDRESS]) { + if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN) + return -EINVAL; + if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS]))) + return -EADDRNOTAVAIL; + } + return 0; +} + +static struct rtnl_link_ops ifb_link_ops __read_mostly = { + .kind = "ifb", + .priv_size = sizeof(struct ifb_private), + .setup = ifb_setup, + .validate = ifb_validate, +}; + +/* Number of ifb devices to be set up by this module. */ +module_param(numifbs, int, 0); +MODULE_PARM_DESC(numifbs, "Number of ifb devices"); + static int __init ifb_init_one(int index) { struct net_device *dev_ifb; @@ -237,49 +254,44 @@ static int __init ifb_init_one(int index) if (!dev_ifb) return -ENOMEM; - if ((err = register_netdev(dev_ifb))) { - free_netdev(dev_ifb); - dev_ifb = NULL; - } else { - ifbs[index] = dev_ifb; - } + err = dev_alloc_name(dev_ifb, dev_ifb->name); + if (err < 0) + goto err; - return err; -} + dev_ifb->rtnl_link_ops = &ifb_link_ops; + err = register_netdevice(dev_ifb); + if (err < 0) + goto err; + return 0; -static void ifb_free_one(int index) -{ - unregister_netdev(ifbs[index]); - free_netdev(ifbs[index]); +err: + free_netdev(dev_ifb); + return err; } static int __init ifb_init_module(void) { - int i, err = 0; - ifbs = kmalloc(numifbs * sizeof(void *), GFP_KERNEL); - if (!ifbs) - return -ENOMEM; + int i, err; + + rtnl_lock(); + err = __rtnl_link_register(&ifb_link_ops); + for (i = 0; i < numifbs && !err; i++) err = ifb_init_one(i); - if (err) { - i--; - while (--i >= 0) - ifb_free_one(i); - } + if (err) + __rtnl_link_unregister(&ifb_link_ops); + rtnl_unlock(); return err; } static void __exit ifb_cleanup_module(void) { - int i; - - for (i = 0; i < numifbs; i++) - ifb_free_one(i); - kfree(ifbs); + rtnl_link_unregister(&ifb_link_ops); } module_init(ifb_init_module); module_exit(ifb_cleanup_module); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Jamal Hadi Salim"); +MODULE_ALIAS_RTNL_LINK("ifb"); |
