Merge branch 'cpufreq/arm/fixes' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6-microblaze.git] / net / core / rtnetlink.c
index ec931b0..f6af3e7 100644 (file)
@@ -9,7 +9,7 @@
  * Authors:    Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
  *
  *     Fixes:
- *     Vitaly E. Lavrov                RTA_OK arithmetics was wrong.
+ *     Vitaly E. Lavrov                RTA_OK arithmetic was wrong.
  */
 
 #include <linux/bitops.h>
@@ -234,7 +234,7 @@ unlock:
  * @msgtype: rtnetlink message type
  * @doit: Function pointer called for each request message
  * @dumpit: Function pointer called for each dump request (NLM_F_DUMP) message
- * @flags: rtnl_link_flags to modifiy behaviour of doit/dumpit functions
+ * @flags: rtnl_link_flags to modify behaviour of doit/dumpit functions
  *
  * Like rtnl_register, but for use by removable modules.
  */
@@ -254,7 +254,7 @@ EXPORT_SYMBOL_GPL(rtnl_register_module);
  * @msgtype: rtnetlink message type
  * @doit: Function pointer called for each request message
  * @dumpit: Function pointer called for each dump request (NLM_F_DUMP) message
- * @flags: rtnl_link_flags to modifiy behaviour of doit/dumpit functions
+ * @flags: rtnl_link_flags to modify behaviour of doit/dumpit functions
  *
  * Registers the specified function pointers (at least one of them has
  * to be non-NULL) to be called whenever a request message for the
@@ -376,12 +376,12 @@ int __rtnl_link_register(struct rtnl_link_ops *ops)
        if (rtnl_link_ops_get(ops->kind))
                return -EEXIST;
 
-       /* The check for setup is here because if ops
+       /* The check for alloc/setup is here because if ops
         * does not have that filled up, it is not possible
         * to use the ops for creating device. So do not
         * fill up dellink as well. That disables rtnl_dellink.
         */
-       if (ops->setup && !ops->dellink)
+       if ((ops->alloc || ops->setup) && !ops->dellink)
                ops->dellink = unregister_netdevice_queue;
 
        list_add_tail(&ops->list, &link_ops);
@@ -543,7 +543,9 @@ static const struct rtnl_af_ops *rtnl_af_lookup(const int family)
 {
        const struct rtnl_af_ops *ops;
 
-       list_for_each_entry_rcu(ops, &rtnl_af_ops, list) {
+       ASSERT_RTNL();
+
+       list_for_each_entry(ops, &rtnl_af_ops, list) {
                if (ops->family == family)
                        return ops;
        }
@@ -1819,6 +1821,16 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb,
        if (rtnl_fill_prop_list(skb, dev))
                goto nla_put_failure;
 
+       if (dev->dev.parent &&
+           nla_put_string(skb, IFLA_PARENT_DEV_NAME,
+                          dev_name(dev->dev.parent)))
+               goto nla_put_failure;
+
+       if (dev->dev.parent && dev->dev.parent->bus &&
+           nla_put_string(skb, IFLA_PARENT_DEV_BUS_NAME,
+                          dev->dev.parent->bus->name))
+               goto nla_put_failure;
+
        nlmsg_end(skb, nlh);
        return 0;
 
@@ -1878,6 +1890,7 @@ static const struct nla_policy ifla_policy[IFLA_MAX+1] = {
        [IFLA_PERM_ADDRESS]     = { .type = NLA_REJECT },
        [IFLA_PROTO_DOWN_REASON] = { .type = NLA_NESTED },
        [IFLA_NEW_IFINDEX]      = NLA_POLICY_MIN(NLA_S32, 1),
+       [IFLA_PARENT_DEV_NAME]  = { .type = NLA_NUL_STRING },
 };
 
 static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = {
@@ -2274,27 +2287,18 @@ static int validate_linkmsg(struct net_device *dev, struct nlattr *tb[])
                nla_for_each_nested(af, tb[IFLA_AF_SPEC], rem) {
                        const struct rtnl_af_ops *af_ops;
 
-                       rcu_read_lock();
                        af_ops = rtnl_af_lookup(nla_type(af));
-                       if (!af_ops) {
-                               rcu_read_unlock();
+                       if (!af_ops)
                                return -EAFNOSUPPORT;
-                       }
 
-                       if (!af_ops->set_link_af) {
-                               rcu_read_unlock();
+                       if (!af_ops->set_link_af)
                                return -EOPNOTSUPP;
-                       }
 
                        if (af_ops->validate_link_af) {
                                err = af_ops->validate_link_af(dev, af);
-                               if (err < 0) {
-                                       rcu_read_unlock();
+                               if (err < 0)
                                        return err;
-                               }
                        }
-
-                       rcu_read_unlock();
                }
        }
 
@@ -2574,7 +2578,7 @@ static int do_set_proto_down(struct net_device *dev,
        if (nl_proto_down) {
                proto_down = nla_get_u8(nl_proto_down);
 
-               /* Dont turn off protodown if there are active reasons */
+               /* Don't turn off protodown if there are active reasons */
                if (!proto_down && dev->proto_down_reason) {
                        NL_SET_ERR_MSG(extack, "Cannot clear protodown, active reasons");
                        return -EBUSY;
@@ -2868,17 +2872,12 @@ static int do_setlink(const struct sk_buff *skb,
                nla_for_each_nested(af, tb[IFLA_AF_SPEC], rem) {
                        const struct rtnl_af_ops *af_ops;
 
-                       rcu_read_lock();
-
                        BUG_ON(!(af_ops = rtnl_af_lookup(nla_type(af))));
 
                        err = af_ops->set_link_af(dev, af, extack);
-                       if (err < 0) {
-                               rcu_read_unlock();
+                       if (err < 0)
                                goto errout;
-                       }
 
-                       rcu_read_unlock();
                        status |= DO_SETLINK_NOTIFY;
                }
        }
@@ -3177,8 +3176,17 @@ struct net_device *rtnl_create_link(struct net *net, const char *ifname,
                return ERR_PTR(-EINVAL);
        }
 
-       dev = alloc_netdev_mqs(ops->priv_size, ifname, name_assign_type,
-                              ops->setup, num_tx_queues, num_rx_queues);
+       if (ops->alloc) {
+               dev = ops->alloc(tb, ifname, name_assign_type,
+                                num_tx_queues, num_rx_queues);
+               if (IS_ERR(dev))
+                       return dev;
+       } else {
+               dev = alloc_netdev_mqs(ops->priv_size, ifname,
+                                      name_assign_type, ops->setup,
+                                      num_tx_queues, num_rx_queues);
+       }
+
        if (!dev)
                return ERR_PTR(-ENOMEM);
 
@@ -3411,7 +3419,7 @@ replay:
                return -EOPNOTSUPP;
        }
 
-       if (!ops->setup)
+       if (!ops->alloc && !ops->setup)
                return -EOPNOTSUPP;
 
        if (!ifname[0]) {
@@ -3939,12 +3947,12 @@ int ndo_dflt_fdb_add(struct ndmsg *ndm,
         * implement its own handler for this.
         */
        if (ndm->ndm_state && !(ndm->ndm_state & NUD_PERMANENT)) {
-               pr_info("%s: FDB only supports static addresses\n", dev->name);
+               netdev_info(dev, "default FDB implementation only supports local addresses\n");
                return err;
        }
 
        if (vid) {
-               pr_info("%s: vlans aren't supported yet for dev_uc|mc_add()\n", dev->name);
+               netdev_info(dev, "vlans aren't supported yet for dev_uc|mc_add()\n");
                return err;
        }
 
@@ -4078,7 +4086,7 @@ int ndo_dflt_fdb_del(struct ndmsg *ndm,
         * implement its own handler for this.
         */
        if (!(ndm->ndm_state & NUD_PERMANENT)) {
-               pr_info("%s: FDB only supports static addresses\n", dev->name);
+               netdev_info(dev, "default FDB implementation only supports local addresses\n");
                return err;
        }