diff options
Diffstat (limited to 'net/core')
| -rw-r--r-- | net/core/ethtool.c | 9 | ||||
| -rw-r--r-- | net/core/netpoll.c | 22 | ||||
| -rw-r--r-- | net/core/rtnetlink.c | 41 |
3 files changed, 39 insertions, 33 deletions
diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 234a0ec2e932..0762aaf8e964 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c | |||
| @@ -1483,6 +1483,7 @@ static int ethtool_get_wol(struct net_device *dev, char __user *useraddr) | |||
| 1483 | static int ethtool_set_wol(struct net_device *dev, char __user *useraddr) | 1483 | static int ethtool_set_wol(struct net_device *dev, char __user *useraddr) |
| 1484 | { | 1484 | { |
| 1485 | struct ethtool_wolinfo wol; | 1485 | struct ethtool_wolinfo wol; |
| 1486 | int ret; | ||
| 1486 | 1487 | ||
| 1487 | if (!dev->ethtool_ops->set_wol) | 1488 | if (!dev->ethtool_ops->set_wol) |
| 1488 | return -EOPNOTSUPP; | 1489 | return -EOPNOTSUPP; |
| @@ -1490,7 +1491,13 @@ static int ethtool_set_wol(struct net_device *dev, char __user *useraddr) | |||
| 1490 | if (copy_from_user(&wol, useraddr, sizeof(wol))) | 1491 | if (copy_from_user(&wol, useraddr, sizeof(wol))) |
| 1491 | return -EFAULT; | 1492 | return -EFAULT; |
| 1492 | 1493 | ||
| 1493 | return dev->ethtool_ops->set_wol(dev, &wol); | 1494 | ret = dev->ethtool_ops->set_wol(dev, &wol); |
| 1495 | if (ret) | ||
| 1496 | return ret; | ||
| 1497 | |||
| 1498 | dev->wol_enabled = !!wol.wolopts; | ||
| 1499 | |||
| 1500 | return 0; | ||
| 1494 | } | 1501 | } |
| 1495 | 1502 | ||
| 1496 | static int ethtool_get_eee(struct net_device *dev, char __user *useraddr) | 1503 | static int ethtool_get_eee(struct net_device *dev, char __user *useraddr) |
diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 3219a2932463..de1d1ba92f2d 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c | |||
| @@ -135,27 +135,9 @@ static void queue_process(struct work_struct *work) | |||
| 135 | } | 135 | } |
| 136 | } | 136 | } |
| 137 | 137 | ||
| 138 | /* | ||
| 139 | * Check whether delayed processing was scheduled for our NIC. If so, | ||
| 140 | * we attempt to grab the poll lock and use ->poll() to pump the card. | ||
| 141 | * If this fails, either we've recursed in ->poll() or it's already | ||
| 142 | * running on another CPU. | ||
| 143 | * | ||
| 144 | * Note: we don't mask interrupts with this lock because we're using | ||
| 145 | * trylock here and interrupts are already disabled in the softirq | ||
| 146 | * case. Further, we test the poll_owner to avoid recursion on UP | ||
| 147 | * systems where the lock doesn't exist. | ||
| 148 | */ | ||
| 149 | static void poll_one_napi(struct napi_struct *napi) | 138 | static void poll_one_napi(struct napi_struct *napi) |
| 150 | { | 139 | { |
| 151 | int work = 0; | 140 | int work; |
| 152 | |||
| 153 | /* net_rx_action's ->poll() invocations and our's are | ||
| 154 | * synchronized by this test which is only made while | ||
| 155 | * holding the napi->poll_lock. | ||
| 156 | */ | ||
| 157 | if (!test_bit(NAPI_STATE_SCHED, &napi->state)) | ||
| 158 | return; | ||
| 159 | 141 | ||
| 160 | /* If we set this bit but see that it has already been set, | 142 | /* If we set this bit but see that it has already been set, |
| 161 | * that indicates that napi has been disabled and we need | 143 | * that indicates that napi has been disabled and we need |
| @@ -330,6 +312,7 @@ void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb, | |||
| 330 | /* It is up to the caller to keep npinfo alive. */ | 312 | /* It is up to the caller to keep npinfo alive. */ |
| 331 | struct netpoll_info *npinfo; | 313 | struct netpoll_info *npinfo; |
| 332 | 314 | ||
| 315 | rcu_read_lock_bh(); | ||
| 333 | lockdep_assert_irqs_disabled(); | 316 | lockdep_assert_irqs_disabled(); |
| 334 | 317 | ||
| 335 | npinfo = rcu_dereference_bh(np->dev->npinfo); | 318 | npinfo = rcu_dereference_bh(np->dev->npinfo); |
| @@ -374,6 +357,7 @@ void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb, | |||
| 374 | skb_queue_tail(&npinfo->txq, skb); | 357 | skb_queue_tail(&npinfo->txq, skb); |
| 375 | schedule_delayed_work(&npinfo->tx_work,0); | 358 | schedule_delayed_work(&npinfo->tx_work,0); |
| 376 | } | 359 | } |
| 360 | rcu_read_unlock_bh(); | ||
| 377 | } | 361 | } |
| 378 | EXPORT_SYMBOL(netpoll_send_skb_on_dev); | 362 | EXPORT_SYMBOL(netpoll_send_skb_on_dev); |
| 379 | 363 | ||
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 63ce2283a456..37c7936124e6 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
| @@ -1898,10 +1898,8 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) | |||
| 1898 | if (tb[IFLA_IF_NETNSID]) { | 1898 | if (tb[IFLA_IF_NETNSID]) { |
| 1899 | netnsid = nla_get_s32(tb[IFLA_IF_NETNSID]); | 1899 | netnsid = nla_get_s32(tb[IFLA_IF_NETNSID]); |
| 1900 | tgt_net = get_target_net(skb->sk, netnsid); | 1900 | tgt_net = get_target_net(skb->sk, netnsid); |
| 1901 | if (IS_ERR(tgt_net)) { | 1901 | if (IS_ERR(tgt_net)) |
| 1902 | tgt_net = net; | 1902 | return PTR_ERR(tgt_net); |
| 1903 | netnsid = -1; | ||
| 1904 | } | ||
| 1905 | } | 1903 | } |
| 1906 | 1904 | ||
| 1907 | if (tb[IFLA_EXT_MASK]) | 1905 | if (tb[IFLA_EXT_MASK]) |
| @@ -2837,6 +2835,12 @@ struct net_device *rtnl_create_link(struct net *net, | |||
| 2837 | else if (ops->get_num_rx_queues) | 2835 | else if (ops->get_num_rx_queues) |
| 2838 | num_rx_queues = ops->get_num_rx_queues(); | 2836 | num_rx_queues = ops->get_num_rx_queues(); |
| 2839 | 2837 | ||
| 2838 | if (num_tx_queues < 1 || num_tx_queues > 4096) | ||
| 2839 | return ERR_PTR(-EINVAL); | ||
| 2840 | |||
| 2841 | if (num_rx_queues < 1 || num_rx_queues > 4096) | ||
| 2842 | return ERR_PTR(-EINVAL); | ||
| 2843 | |||
| 2840 | dev = alloc_netdev_mqs(ops->priv_size, ifname, name_assign_type, | 2844 | dev = alloc_netdev_mqs(ops->priv_size, ifname, name_assign_type, |
| 2841 | ops->setup, num_tx_queues, num_rx_queues); | 2845 | ops->setup, num_tx_queues, num_rx_queues); |
| 2842 | if (!dev) | 2846 | if (!dev) |
| @@ -3744,16 +3748,27 @@ static int rtnl_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb) | |||
| 3744 | int err = 0; | 3748 | int err = 0; |
| 3745 | int fidx = 0; | 3749 | int fidx = 0; |
| 3746 | 3750 | ||
| 3747 | err = nlmsg_parse(cb->nlh, sizeof(struct ifinfomsg), tb, | 3751 | /* A hack to preserve kernel<->userspace interface. |
| 3748 | IFLA_MAX, ifla_policy, NULL); | 3752 | * Before Linux v4.12 this code accepted ndmsg since iproute2 v3.3.0. |
| 3749 | if (err < 0) { | 3753 | * However, ndmsg is shorter than ifinfomsg thus nlmsg_parse() bails. |
| 3750 | return -EINVAL; | 3754 | * So, check for ndmsg with an optional u32 attribute (not used here). |
| 3751 | } else if (err == 0) { | 3755 | * Fortunately these sizes don't conflict with the size of ifinfomsg |
| 3752 | if (tb[IFLA_MASTER]) | 3756 | * with an optional attribute. |
| 3753 | br_idx = nla_get_u32(tb[IFLA_MASTER]); | 3757 | */ |
| 3754 | } | 3758 | if (nlmsg_len(cb->nlh) != sizeof(struct ndmsg) && |
| 3759 | (nlmsg_len(cb->nlh) != sizeof(struct ndmsg) + | ||
| 3760 | nla_attr_size(sizeof(u32)))) { | ||
| 3761 | err = nlmsg_parse(cb->nlh, sizeof(struct ifinfomsg), tb, | ||
| 3762 | IFLA_MAX, ifla_policy, NULL); | ||
| 3763 | if (err < 0) { | ||
| 3764 | return -EINVAL; | ||
| 3765 | } else if (err == 0) { | ||
| 3766 | if (tb[IFLA_MASTER]) | ||
| 3767 | br_idx = nla_get_u32(tb[IFLA_MASTER]); | ||
| 3768 | } | ||
| 3755 | 3769 | ||
| 3756 | brport_idx = ifm->ifi_index; | 3770 | brport_idx = ifm->ifi_index; |
| 3771 | } | ||
| 3757 | 3772 | ||
| 3758 | if (br_idx) { | 3773 | if (br_idx) { |
| 3759 | br_dev = __dev_get_by_index(net, br_idx); | 3774 | br_dev = __dev_get_by_index(net, br_idx); |
