aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/hyperv/netvsc.c33
-rw-r--r--drivers/net/hyperv/netvsc_drv.c62
-rw-r--r--drivers/net/hyperv/rndis_filter.c23
3 files changed, 79 insertions, 39 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
956send_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
1324close: 1314close:
@@ -1329,6 +1319,7 @@ close:
1329 vmbus_close(device->channel); 1319 vmbus_close(device->channel);
1330 1320
1331cleanup: 1321cleanup:
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);
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index c5584c2d440e..cdb78eefab67 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -66,10 +66,36 @@ static int debug = -1;
66module_param(debug, int, S_IRUGO); 66module_param(debug, int, S_IRUGO);
67MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); 67MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
68 68
69static void netvsc_set_multicast_list(struct net_device *net) 69static void netvsc_change_rx_flags(struct net_device *net, int change)
70{ 70{
71 struct net_device_context *net_device_ctx = netdev_priv(net); 71 struct net_device_context *ndev_ctx = netdev_priv(net);
72 struct netvsc_device *nvdev = rtnl_dereference(net_device_ctx->nvdev); 72 struct net_device *vf_netdev = rtnl_dereference(ndev_ctx->vf_netdev);
73 int inc;
74
75 if (!vf_netdev)
76 return;
77
78 if (change & IFF_PROMISC) {
79 inc = (net->flags & IFF_PROMISC) ? 1 : -1;
80 dev_set_promiscuity(vf_netdev, inc);
81 }
82
83 if (change & IFF_ALLMULTI) {
84 inc = (net->flags & IFF_ALLMULTI) ? 1 : -1;
85 dev_set_allmulti(vf_netdev, inc);
86 }
87}
88
89static void netvsc_set_rx_mode(struct net_device *net)
90{
91 struct net_device_context *ndev_ctx = netdev_priv(net);
92 struct net_device *vf_netdev = rtnl_dereference(ndev_ctx->vf_netdev);
93 struct netvsc_device *nvdev = rtnl_dereference(ndev_ctx->nvdev);
94
95 if (vf_netdev) {
96 dev_uc_sync(vf_netdev, net);
97 dev_mc_sync(vf_netdev, net);
98 }
73 99
74 rndis_filter_update(nvdev); 100 rndis_filter_update(nvdev);
75} 101}
@@ -91,12 +117,11 @@ static int netvsc_open(struct net_device *net)
91 return ret; 117 return ret;
92 } 118 }
93 119
94 netif_tx_wake_all_queues(net);
95
96 rdev = nvdev->extension; 120 rdev = nvdev->extension;
97 121 if (!rdev->link_state) {
98 if (!rdev->link_state)
99 netif_carrier_on(net); 122 netif_carrier_on(net);
123 netif_tx_wake_all_queues(net);
124 }
100 125
101 if (vf_netdev) { 126 if (vf_netdev) {
102 /* Setting synthetic device up transparently sets 127 /* Setting synthetic device up transparently sets
@@ -299,8 +324,19 @@ static u16 netvsc_select_queue(struct net_device *ndev, struct sk_buff *skb,
299 rcu_read_lock(); 324 rcu_read_lock();
300 vf_netdev = rcu_dereference(ndc->vf_netdev); 325 vf_netdev = rcu_dereference(ndc->vf_netdev);
301 if (vf_netdev) { 326 if (vf_netdev) {
302 txq = skb_rx_queue_recorded(skb) ? skb_get_rx_queue(skb) : 0; 327 const struct net_device_ops *vf_ops = vf_netdev->netdev_ops;
303 qdisc_skb_cb(skb)->slave_dev_queue_mapping = skb->queue_mapping; 328
329 if (vf_ops->ndo_select_queue)
330 txq = vf_ops->ndo_select_queue(vf_netdev, skb,
331 accel_priv, fallback);
332 else
333 txq = fallback(vf_netdev, skb);
334
335 /* Record the queue selected by VF so that it can be
336 * used for common case where VF has more queues than
337 * the synthetic device.
338 */
339 qdisc_skb_cb(skb)->slave_dev_queue_mapping = txq;
304 } else { 340 } else {
305 txq = netvsc_pick_tx(ndev, skb); 341 txq = netvsc_pick_tx(ndev, skb);
306 } 342 }
@@ -1576,7 +1612,8 @@ static const struct net_device_ops device_ops = {
1576 .ndo_open = netvsc_open, 1612 .ndo_open = netvsc_open,
1577 .ndo_stop = netvsc_close, 1613 .ndo_stop = netvsc_close,
1578 .ndo_start_xmit = netvsc_start_xmit, 1614 .ndo_start_xmit = netvsc_start_xmit,
1579 .ndo_set_rx_mode = netvsc_set_multicast_list, 1615 .ndo_change_rx_flags = netvsc_change_rx_flags,
1616 .ndo_set_rx_mode = netvsc_set_rx_mode,
1580 .ndo_change_mtu = netvsc_change_mtu, 1617 .ndo_change_mtu = netvsc_change_mtu,
1581 .ndo_validate_addr = eth_validate_addr, 1618 .ndo_validate_addr = eth_validate_addr,
1582 .ndo_set_mac_address = netvsc_set_mac_addr, 1619 .ndo_set_mac_address = netvsc_set_mac_addr,
@@ -1807,6 +1844,11 @@ static void __netvsc_vf_setup(struct net_device *ndev,
1807 netdev_warn(vf_netdev, 1844 netdev_warn(vf_netdev,
1808 "unable to change mtu to %u\n", ndev->mtu); 1845 "unable to change mtu to %u\n", ndev->mtu);
1809 1846
1847 /* set multicast etc flags on VF */
1848 dev_change_flags(vf_netdev, ndev->flags | IFF_SLAVE);
1849 dev_uc_sync(vf_netdev, ndev);
1850 dev_mc_sync(vf_netdev, ndev);
1851
1810 if (netif_running(ndev)) { 1852 if (netif_running(ndev)) {
1811 ret = dev_open(vf_netdev); 1853 ret = dev_open(vf_netdev);
1812 if (ret) 1854 if (ret)
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
index c3ca191fea7f..8927c483c217 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -854,15 +854,19 @@ static void rndis_set_multicast(struct work_struct *w)
854{ 854{
855 struct rndis_device *rdev 855 struct rndis_device *rdev
856 = container_of(w, struct rndis_device, mcast_work); 856 = container_of(w, struct rndis_device, mcast_work);
857 u32 filter = NDIS_PACKET_TYPE_DIRECTED;
858 unsigned int flags = rdev->ndev->flags;
857 859
858 if (rdev->ndev->flags & IFF_PROMISC) 860 if (flags & IFF_PROMISC) {
859 rndis_filter_set_packet_filter(rdev, 861 filter = NDIS_PACKET_TYPE_PROMISCUOUS;
860 NDIS_PACKET_TYPE_PROMISCUOUS); 862 } else {
861 else 863 if (flags & IFF_ALLMULTI)
862 rndis_filter_set_packet_filter(rdev, 864 flags |= NDIS_PACKET_TYPE_ALL_MULTICAST;
863 NDIS_PACKET_TYPE_BROADCAST | 865 if (flags & IFF_BROADCAST)
864 NDIS_PACKET_TYPE_ALL_MULTICAST | 866 flags |= NDIS_PACKET_TYPE_BROADCAST;
865 NDIS_PACKET_TYPE_DIRECTED); 867 }
868
869 rndis_filter_set_packet_filter(rdev, filter);
866} 870}
867 871
868void rndis_filter_update(struct netvsc_device *nvdev) 872void rndis_filter_update(struct netvsc_device *nvdev)
@@ -1340,6 +1344,9 @@ void rndis_filter_device_remove(struct hv_device *dev,
1340{ 1344{
1341 struct rndis_device *rndis_dev = net_dev->extension; 1345 struct rndis_device *rndis_dev = net_dev->extension;
1342 1346
1347 /* Don't try and setup sub channels if about to halt */
1348 cancel_work_sync(&net_dev->subchan_work);
1349
1343 /* Halt and release the rndis device */ 1350 /* Halt and release the rndis device */
1344 rndis_filter_halt_device(rndis_dev); 1351 rndis_filter_halt_device(rndis_dev);
1345 1352