diff options
Diffstat (limited to 'drivers/net/hyperv/netvsc.c')
-rw-r--r-- | drivers/net/hyperv/netvsc.c | 33 |
1 files changed, 12 insertions, 21 deletions
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c index 17e529af79dc..0265d703eb03 100644 --- a/drivers/net/hyperv/netvsc.c +++ b/drivers/net/hyperv/netvsc.c | |||
@@ -852,13 +852,6 @@ int netvsc_send(struct net_device *ndev, | |||
852 | if (unlikely(!net_device || net_device->destroy)) | 852 | if (unlikely(!net_device || net_device->destroy)) |
853 | return -ENODEV; | 853 | return -ENODEV; |
854 | 854 | ||
855 | /* We may race with netvsc_connect_vsp()/netvsc_init_buf() and get | ||
856 | * here before the negotiation with the host is finished and | ||
857 | * send_section_map may not be allocated yet. | ||
858 | */ | ||
859 | if (unlikely(!net_device->send_section_map)) | ||
860 | return -EAGAIN; | ||
861 | |||
862 | nvchan = &net_device->chan_table[packet->q_idx]; | 855 | nvchan = &net_device->chan_table[packet->q_idx]; |
863 | packet->send_buf_index = NETVSC_INVALID_INDEX; | 856 | packet->send_buf_index = NETVSC_INVALID_INDEX; |
864 | packet->cp_partial = false; | 857 | packet->cp_partial = false; |
@@ -866,10 +859,8 @@ int netvsc_send(struct net_device *ndev, | |||
866 | /* Send control message directly without accessing msd (Multi-Send | 859 | /* Send control message directly without accessing msd (Multi-Send |
867 | * Data) field which may be changed during data packet processing. | 860 | * Data) field which may be changed during data packet processing. |
868 | */ | 861 | */ |
869 | if (!skb) { | 862 | if (!skb) |
870 | cur_send = packet; | 863 | return netvsc_send_pkt(device, packet, net_device, pb, skb); |
871 | goto send_now; | ||
872 | } | ||
873 | 864 | ||
874 | /* batch packets in send buffer if possible */ | 865 | /* batch packets in send buffer if possible */ |
875 | msdp = &nvchan->msd; | 866 | msdp = &nvchan->msd; |
@@ -953,7 +944,6 @@ int netvsc_send(struct net_device *ndev, | |||
953 | } | 944 | } |
954 | } | 945 | } |
955 | 946 | ||
956 | send_now: | ||
957 | if (cur_send) | 947 | if (cur_send) |
958 | ret = netvsc_send_pkt(device, cur_send, net_device, pb, skb); | 948 | ret = netvsc_send_pkt(device, cur_send, net_device, pb, skb); |
959 | 949 | ||
@@ -1217,9 +1207,10 @@ int netvsc_poll(struct napi_struct *napi, int budget) | |||
1217 | if (send_recv_completions(ndev, net_device, nvchan) == 0 && | 1207 | if (send_recv_completions(ndev, net_device, nvchan) == 0 && |
1218 | work_done < budget && | 1208 | work_done < budget && |
1219 | napi_complete_done(napi, work_done) && | 1209 | napi_complete_done(napi, work_done) && |
1220 | hv_end_read(&channel->inbound)) { | 1210 | hv_end_read(&channel->inbound) && |
1211 | napi_schedule_prep(napi)) { | ||
1221 | hv_begin_read(&channel->inbound); | 1212 | hv_begin_read(&channel->inbound); |
1222 | napi_reschedule(napi); | 1213 | __napi_schedule(napi); |
1223 | } | 1214 | } |
1224 | 1215 | ||
1225 | /* Driver may overshoot since multiple packets per descriptor */ | 1216 | /* Driver may overshoot since multiple packets per descriptor */ |
@@ -1242,7 +1233,7 @@ void netvsc_channel_cb(void *context) | |||
1242 | /* disable interupts from host */ | 1233 | /* disable interupts from host */ |
1243 | hv_begin_read(rbi); | 1234 | hv_begin_read(rbi); |
1244 | 1235 | ||
1245 | __napi_schedule(&nvchan->napi); | 1236 | __napi_schedule_irqoff(&nvchan->napi); |
1246 | } | 1237 | } |
1247 | } | 1238 | } |
1248 | 1239 | ||
@@ -1296,7 +1287,6 @@ struct netvsc_device *netvsc_device_add(struct hv_device *device, | |||
1296 | netvsc_channel_cb, net_device->chan_table); | 1287 | netvsc_channel_cb, net_device->chan_table); |
1297 | 1288 | ||
1298 | if (ret != 0) { | 1289 | if (ret != 0) { |
1299 | netif_napi_del(&net_device->chan_table[0].napi); | ||
1300 | netdev_err(ndev, "unable to open channel: %d\n", ret); | 1290 | netdev_err(ndev, "unable to open channel: %d\n", ret); |
1301 | goto cleanup; | 1291 | goto cleanup; |
1302 | } | 1292 | } |
@@ -1306,11 +1296,6 @@ struct netvsc_device *netvsc_device_add(struct hv_device *device, | |||
1306 | 1296 | ||
1307 | napi_enable(&net_device->chan_table[0].napi); | 1297 | napi_enable(&net_device->chan_table[0].napi); |
1308 | 1298 | ||
1309 | /* Writing nvdev pointer unlocks netvsc_send(), make sure chn_table is | ||
1310 | * populated. | ||
1311 | */ | ||
1312 | rcu_assign_pointer(net_device_ctx->nvdev, net_device); | ||
1313 | |||
1314 | /* Connect with the NetVsp */ | 1299 | /* Connect with the NetVsp */ |
1315 | ret = netvsc_connect_vsp(device, net_device, device_info); | 1300 | ret = netvsc_connect_vsp(device, net_device, device_info); |
1316 | if (ret != 0) { | 1301 | if (ret != 0) { |
@@ -1319,6 +1304,11 @@ struct netvsc_device *netvsc_device_add(struct hv_device *device, | |||
1319 | goto close; | 1304 | goto close; |
1320 | } | 1305 | } |
1321 | 1306 | ||
1307 | /* Writing nvdev pointer unlocks netvsc_send(), make sure chn_table is | ||
1308 | * populated. | ||
1309 | */ | ||
1310 | rcu_assign_pointer(net_device_ctx->nvdev, net_device); | ||
1311 | |||
1322 | return net_device; | 1312 | return net_device; |
1323 | 1313 | ||
1324 | close: | 1314 | close: |
@@ -1329,6 +1319,7 @@ close: | |||
1329 | vmbus_close(device->channel); | 1319 | vmbus_close(device->channel); |
1330 | 1320 | ||
1331 | cleanup: | 1321 | cleanup: |
1322 | netif_napi_del(&net_device->chan_table[0].napi); | ||
1332 | free_netvsc_device(&net_device->rcu); | 1323 | free_netvsc_device(&net_device->rcu); |
1333 | 1324 | ||
1334 | return ERR_PTR(ret); | 1325 | return ERR_PTR(ret); |