diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/core/netpoll.c | 24 |
1 files changed, 10 insertions, 14 deletions
diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 9f0506726101..a5ad1c1c4b18 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c | |||
@@ -1048,11 +1048,13 @@ int netpoll_setup(struct netpoll *np) | |||
1048 | struct in_device *in_dev; | 1048 | struct in_device *in_dev; |
1049 | int err; | 1049 | int err; |
1050 | 1050 | ||
1051 | rtnl_lock(); | ||
1051 | if (np->dev_name) | 1052 | if (np->dev_name) |
1052 | ndev = dev_get_by_name(&init_net, np->dev_name); | 1053 | ndev = __dev_get_by_name(&init_net, np->dev_name); |
1053 | if (!ndev) { | 1054 | if (!ndev) { |
1054 | np_err(np, "%s doesn't exist, aborting\n", np->dev_name); | 1055 | np_err(np, "%s doesn't exist, aborting\n", np->dev_name); |
1055 | return -ENODEV; | 1056 | err = -ENODEV; |
1057 | goto unlock; | ||
1056 | } | 1058 | } |
1057 | 1059 | ||
1058 | if (netdev_master_upper_dev_get(ndev)) { | 1060 | if (netdev_master_upper_dev_get(ndev)) { |
@@ -1066,15 +1068,14 @@ int netpoll_setup(struct netpoll *np) | |||
1066 | 1068 | ||
1067 | np_info(np, "device %s not up yet, forcing it\n", np->dev_name); | 1069 | np_info(np, "device %s not up yet, forcing it\n", np->dev_name); |
1068 | 1070 | ||
1069 | rtnl_lock(); | ||
1070 | err = dev_open(ndev); | 1071 | err = dev_open(ndev); |
1071 | rtnl_unlock(); | ||
1072 | 1072 | ||
1073 | if (err) { | 1073 | if (err) { |
1074 | np_err(np, "failed to open %s\n", ndev->name); | 1074 | np_err(np, "failed to open %s\n", ndev->name); |
1075 | goto put; | 1075 | goto put; |
1076 | } | 1076 | } |
1077 | 1077 | ||
1078 | rtnl_unlock(); | ||
1078 | atleast = jiffies + HZ/10; | 1079 | atleast = jiffies + HZ/10; |
1079 | atmost = jiffies + carrier_timeout * HZ; | 1080 | atmost = jiffies + carrier_timeout * HZ; |
1080 | while (!netif_carrier_ok(ndev)) { | 1081 | while (!netif_carrier_ok(ndev)) { |
@@ -1094,16 +1095,14 @@ int netpoll_setup(struct netpoll *np) | |||
1094 | np_notice(np, "carrier detect appears untrustworthy, waiting 4 seconds\n"); | 1095 | np_notice(np, "carrier detect appears untrustworthy, waiting 4 seconds\n"); |
1095 | msleep(4000); | 1096 | msleep(4000); |
1096 | } | 1097 | } |
1098 | rtnl_lock(); | ||
1097 | } | 1099 | } |
1098 | 1100 | ||
1099 | if (!np->local_ip.ip) { | 1101 | if (!np->local_ip.ip) { |
1100 | if (!np->ipv6) { | 1102 | if (!np->ipv6) { |
1101 | rcu_read_lock(); | 1103 | in_dev = __in_dev_get_rtnl(ndev); |
1102 | in_dev = __in_dev_get_rcu(ndev); | ||
1103 | |||
1104 | 1104 | ||
1105 | if (!in_dev || !in_dev->ifa_list) { | 1105 | if (!in_dev || !in_dev->ifa_list) { |
1106 | rcu_read_unlock(); | ||
1107 | np_err(np, "no IP address for %s, aborting\n", | 1106 | np_err(np, "no IP address for %s, aborting\n", |
1108 | np->dev_name); | 1107 | np->dev_name); |
1109 | err = -EDESTADDRREQ; | 1108 | err = -EDESTADDRREQ; |
@@ -1111,14 +1110,12 @@ int netpoll_setup(struct netpoll *np) | |||
1111 | } | 1110 | } |
1112 | 1111 | ||
1113 | np->local_ip.ip = in_dev->ifa_list->ifa_local; | 1112 | np->local_ip.ip = in_dev->ifa_list->ifa_local; |
1114 | rcu_read_unlock(); | ||
1115 | np_info(np, "local IP %pI4\n", &np->local_ip.ip); | 1113 | np_info(np, "local IP %pI4\n", &np->local_ip.ip); |
1116 | } else { | 1114 | } else { |
1117 | #if IS_ENABLED(CONFIG_IPV6) | 1115 | #if IS_ENABLED(CONFIG_IPV6) |
1118 | struct inet6_dev *idev; | 1116 | struct inet6_dev *idev; |
1119 | 1117 | ||
1120 | err = -EDESTADDRREQ; | 1118 | err = -EDESTADDRREQ; |
1121 | rcu_read_lock(); | ||
1122 | idev = __in6_dev_get(ndev); | 1119 | idev = __in6_dev_get(ndev); |
1123 | if (idev) { | 1120 | if (idev) { |
1124 | struct inet6_ifaddr *ifp; | 1121 | struct inet6_ifaddr *ifp; |
@@ -1133,7 +1130,6 @@ int netpoll_setup(struct netpoll *np) | |||
1133 | } | 1130 | } |
1134 | read_unlock_bh(&idev->lock); | 1131 | read_unlock_bh(&idev->lock); |
1135 | } | 1132 | } |
1136 | rcu_read_unlock(); | ||
1137 | if (err) { | 1133 | if (err) { |
1138 | np_err(np, "no IPv6 address for %s, aborting\n", | 1134 | np_err(np, "no IPv6 address for %s, aborting\n", |
1139 | np->dev_name); | 1135 | np->dev_name); |
@@ -1151,17 +1147,17 @@ int netpoll_setup(struct netpoll *np) | |||
1151 | /* fill up the skb queue */ | 1147 | /* fill up the skb queue */ |
1152 | refill_skbs(); | 1148 | refill_skbs(); |
1153 | 1149 | ||
1154 | rtnl_lock(); | ||
1155 | err = __netpoll_setup(np, ndev, GFP_KERNEL); | 1150 | err = __netpoll_setup(np, ndev, GFP_KERNEL); |
1156 | rtnl_unlock(); | ||
1157 | |||
1158 | if (err) | 1151 | if (err) |
1159 | goto put; | 1152 | goto put; |
1160 | 1153 | ||
1154 | rtnl_unlock(); | ||
1161 | return 0; | 1155 | return 0; |
1162 | 1156 | ||
1163 | put: | 1157 | put: |
1164 | dev_put(ndev); | 1158 | dev_put(ndev); |
1159 | unlock: | ||
1160 | rtnl_unlock(); | ||
1165 | return err; | 1161 | return err; |
1166 | } | 1162 | } |
1167 | EXPORT_SYMBOL(netpoll_setup); | 1163 | EXPORT_SYMBOL(netpoll_setup); |