diff options
| -rw-r--r-- | drivers/net/veth.c | 70 |
1 files changed, 33 insertions, 37 deletions
diff --git a/drivers/net/veth.c b/drivers/net/veth.c index e3202af72df5..8d679c8b7f25 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c | |||
| @@ -789,16 +789,48 @@ static int is_valid_veth_mtu(int mtu) | |||
| 789 | return mtu >= ETH_MIN_MTU && mtu <= ETH_MAX_MTU; | 789 | return mtu >= ETH_MIN_MTU && mtu <= ETH_MAX_MTU; |
| 790 | } | 790 | } |
| 791 | 791 | ||
| 792 | static int veth_alloc_queues(struct net_device *dev) | ||
| 793 | { | ||
| 794 | struct veth_priv *priv = netdev_priv(dev); | ||
| 795 | int i; | ||
| 796 | |||
| 797 | priv->rq = kcalloc(dev->num_rx_queues, sizeof(*priv->rq), GFP_KERNEL); | ||
| 798 | if (!priv->rq) | ||
| 799 | return -ENOMEM; | ||
| 800 | |||
| 801 | for (i = 0; i < dev->num_rx_queues; i++) | ||
| 802 | priv->rq[i].dev = dev; | ||
| 803 | |||
| 804 | return 0; | ||
| 805 | } | ||
| 806 | |||
| 807 | static void veth_free_queues(struct net_device *dev) | ||
| 808 | { | ||
| 809 | struct veth_priv *priv = netdev_priv(dev); | ||
| 810 | |||
| 811 | kfree(priv->rq); | ||
| 812 | } | ||
| 813 | |||
| 792 | static int veth_dev_init(struct net_device *dev) | 814 | static int veth_dev_init(struct net_device *dev) |
| 793 | { | 815 | { |
| 816 | int err; | ||
| 817 | |||
| 794 | dev->vstats = netdev_alloc_pcpu_stats(struct pcpu_vstats); | 818 | dev->vstats = netdev_alloc_pcpu_stats(struct pcpu_vstats); |
| 795 | if (!dev->vstats) | 819 | if (!dev->vstats) |
| 796 | return -ENOMEM; | 820 | return -ENOMEM; |
| 821 | |||
| 822 | err = veth_alloc_queues(dev); | ||
| 823 | if (err) { | ||
| 824 | free_percpu(dev->vstats); | ||
| 825 | return err; | ||
| 826 | } | ||
| 827 | |||
| 797 | return 0; | 828 | return 0; |
| 798 | } | 829 | } |
| 799 | 830 | ||
| 800 | static void veth_dev_free(struct net_device *dev) | 831 | static void veth_dev_free(struct net_device *dev) |
| 801 | { | 832 | { |
| 833 | veth_free_queues(dev); | ||
| 802 | free_percpu(dev->vstats); | 834 | free_percpu(dev->vstats); |
| 803 | } | 835 | } |
| 804 | 836 | ||
| @@ -1040,31 +1072,13 @@ static int veth_validate(struct nlattr *tb[], struct nlattr *data[], | |||
| 1040 | return 0; | 1072 | return 0; |
| 1041 | } | 1073 | } |
| 1042 | 1074 | ||
| 1043 | static int veth_alloc_queues(struct net_device *dev) | ||
| 1044 | { | ||
| 1045 | struct veth_priv *priv = netdev_priv(dev); | ||
| 1046 | |||
| 1047 | priv->rq = kcalloc(dev->num_rx_queues, sizeof(*priv->rq), GFP_KERNEL); | ||
| 1048 | if (!priv->rq) | ||
| 1049 | return -ENOMEM; | ||
| 1050 | |||
| 1051 | return 0; | ||
| 1052 | } | ||
| 1053 | |||
| 1054 | static void veth_free_queues(struct net_device *dev) | ||
| 1055 | { | ||
| 1056 | struct veth_priv *priv = netdev_priv(dev); | ||
| 1057 | |||
| 1058 | kfree(priv->rq); | ||
| 1059 | } | ||
| 1060 | |||
| 1061 | static struct rtnl_link_ops veth_link_ops; | 1075 | static struct rtnl_link_ops veth_link_ops; |
| 1062 | 1076 | ||
| 1063 | static int veth_newlink(struct net *src_net, struct net_device *dev, | 1077 | static int veth_newlink(struct net *src_net, struct net_device *dev, |
| 1064 | struct nlattr *tb[], struct nlattr *data[], | 1078 | struct nlattr *tb[], struct nlattr *data[], |
| 1065 | struct netlink_ext_ack *extack) | 1079 | struct netlink_ext_ack *extack) |
| 1066 | { | 1080 | { |
| 1067 | int err, i; | 1081 | int err; |
| 1068 | struct net_device *peer; | 1082 | struct net_device *peer; |
| 1069 | struct veth_priv *priv; | 1083 | struct veth_priv *priv; |
| 1070 | char ifname[IFNAMSIZ]; | 1084 | char ifname[IFNAMSIZ]; |
| @@ -1117,12 +1131,6 @@ static int veth_newlink(struct net *src_net, struct net_device *dev, | |||
| 1117 | return PTR_ERR(peer); | 1131 | return PTR_ERR(peer); |
| 1118 | } | 1132 | } |
| 1119 | 1133 | ||
| 1120 | err = veth_alloc_queues(peer); | ||
| 1121 | if (err) { | ||
| 1122 | put_net(net); | ||
| 1123 | goto err_peer_alloc_queues; | ||
| 1124 | } | ||
| 1125 | |||
| 1126 | if (!ifmp || !tbp[IFLA_ADDRESS]) | 1134 | if (!ifmp || !tbp[IFLA_ADDRESS]) |
| 1127 | eth_hw_addr_random(peer); | 1135 | eth_hw_addr_random(peer); |
| 1128 | 1136 | ||
| @@ -1151,10 +1159,6 @@ static int veth_newlink(struct net *src_net, struct net_device *dev, | |||
| 1151 | * should be re-allocated | 1159 | * should be re-allocated |
| 1152 | */ | 1160 | */ |
| 1153 | 1161 | ||
| 1154 | err = veth_alloc_queues(dev); | ||
| 1155 | if (err) | ||
| 1156 | goto err_alloc_queues; | ||
| 1157 | |||
| 1158 | if (tb[IFLA_ADDRESS] == NULL) | 1162 | if (tb[IFLA_ADDRESS] == NULL) |
| 1159 | eth_hw_addr_random(dev); | 1163 | eth_hw_addr_random(dev); |
| 1160 | 1164 | ||
| @@ -1174,28 +1178,20 @@ static int veth_newlink(struct net *src_net, struct net_device *dev, | |||
| 1174 | */ | 1178 | */ |
| 1175 | 1179 | ||
| 1176 | priv = netdev_priv(dev); | 1180 | priv = netdev_priv(dev); |
| 1177 | for (i = 0; i < dev->real_num_rx_queues; i++) | ||
| 1178 | priv->rq[i].dev = dev; | ||
| 1179 | rcu_assign_pointer(priv->peer, peer); | 1181 | rcu_assign_pointer(priv->peer, peer); |
| 1180 | 1182 | ||
| 1181 | priv = netdev_priv(peer); | 1183 | priv = netdev_priv(peer); |
| 1182 | for (i = 0; i < peer->real_num_rx_queues; i++) | ||
| 1183 | priv->rq[i].dev = peer; | ||
| 1184 | rcu_assign_pointer(priv->peer, dev); | 1184 | rcu_assign_pointer(priv->peer, dev); |
| 1185 | 1185 | ||
| 1186 | return 0; | 1186 | return 0; |
| 1187 | 1187 | ||
| 1188 | err_register_dev: | 1188 | err_register_dev: |
| 1189 | veth_free_queues(dev); | ||
| 1190 | err_alloc_queues: | ||
| 1191 | /* nothing to do */ | 1189 | /* nothing to do */ |
| 1192 | err_configure_peer: | 1190 | err_configure_peer: |
| 1193 | unregister_netdevice(peer); | 1191 | unregister_netdevice(peer); |
| 1194 | return err; | 1192 | return err; |
| 1195 | 1193 | ||
| 1196 | err_register_peer: | 1194 | err_register_peer: |
| 1197 | veth_free_queues(peer); | ||
| 1198 | err_peer_alloc_queues: | ||
| 1199 | free_netdev(peer); | 1195 | free_netdev(peer); |
| 1200 | return err; | 1196 | return err; |
| 1201 | } | 1197 | } |
