Commit 9cbcc428 authored by Stephen Hemminger's avatar Stephen Hemminger Committed by David S. Miller

hv_netvsc: remove VF in flight counters

Since VF reference is now protected by RCU, no longer need the VF usage
counter and can use device flags to see whether to inject or not.
Signed-off-by: default avatarStephen Hemminger <sthemmin@microsoft.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent f207c10d
...@@ -696,8 +696,7 @@ struct net_device_context { ...@@ -696,8 +696,7 @@ struct net_device_context {
/* State to manage the associated VF interface. */ /* State to manage the associated VF interface. */
struct net_device __rcu *vf_netdev; struct net_device __rcu *vf_netdev;
bool vf_inject;
atomic_t vf_use_cnt;
/* 1: allocated, serial number is valid. 0: not allocated */ /* 1: allocated, serial number is valid. 0: not allocated */
u32 vf_alloc; u32 vf_alloc;
/* Serial number of the VF to team with */ /* Serial number of the VF to team with */
......
...@@ -670,50 +670,20 @@ int netvsc_recv_callback(struct hv_device *device_obj, ...@@ -670,50 +670,20 @@ int netvsc_recv_callback(struct hv_device *device_obj,
struct net_device *vf_netdev; struct net_device *vf_netdev;
struct sk_buff *skb; struct sk_buff *skb;
struct netvsc_stats *rx_stats; struct netvsc_stats *rx_stats;
u32 bytes_recvd = packet->total_data_buflen;
int ret = 0;
if (!net || net->reg_state != NETREG_REGISTERED) if (net->reg_state != NETREG_REGISTERED)
return NVSP_STAT_FAIL; return NVSP_STAT_FAIL;
/*
* If necessary, inject this packet into the VF interface.
* On Hyper-V, multicast and brodcast packets are only delivered
* to the synthetic interface (after subjecting these to
* policy filters on the host). Deliver these via the VF
* interface in the guest.
*/
vf_netdev = rcu_dereference(net_device_ctx->vf_netdev); vf_netdev = rcu_dereference(net_device_ctx->vf_netdev);
if (vf_netdev) { if (vf_netdev && (vf_netdev->flags & IFF_UP))
struct sk_buff *vf_skb; net = vf_netdev;
atomic_inc(&net_device_ctx->vf_use_cnt);
if (!net_device_ctx->vf_inject) {
/*
* We raced; just move on.
*/
atomic_dec(&net_device_ctx->vf_use_cnt);
goto vf_injection_done;
}
/*
* Inject this packet into the VF inerface.
* On Hyper-V, multicast and brodcast packets
* are only delivered on the synthetic interface
* (after subjecting these to policy filters on
* the host). Deliver these via the VF interface
* in the guest.
*/
vf_skb = netvsc_alloc_recv_skb(vf_netdev,
packet, csum_info, *data,
vlan_tci);
if (vf_skb != NULL) {
++vf_netdev->stats.rx_packets;
vf_netdev->stats.rx_bytes += bytes_recvd;
netif_receive_skb(vf_skb);
} else {
++net->stats.rx_dropped;
ret = NVSP_STAT_FAIL;
}
atomic_dec(&net_device_ctx->vf_use_cnt);
return ret;
}
vf_injection_done:
rx_stats = this_cpu_ptr(net_device_ctx->rx_stats);
/* Allocate a skb - TODO direct I/O to pages? */ /* Allocate a skb - TODO direct I/O to pages? */
skb = netvsc_alloc_recv_skb(net, packet, csum_info, *data, vlan_tci); skb = netvsc_alloc_recv_skb(net, packet, csum_info, *data, vlan_tci);
...@@ -721,9 +691,17 @@ int netvsc_recv_callback(struct hv_device *device_obj, ...@@ -721,9 +691,17 @@ int netvsc_recv_callback(struct hv_device *device_obj,
++net->stats.rx_dropped; ++net->stats.rx_dropped;
return NVSP_STAT_FAIL; return NVSP_STAT_FAIL;
} }
skb_record_rx_queue(skb, channel->
offermsg.offer.sub_channel_index);
if (net != vf_netdev)
skb_record_rx_queue(skb,
channel->offermsg.offer.sub_channel_index);
/*
* Even if injecting the packet, record the statistics
* on the synthetic device because modifying the VF device
* statistics will not work correctly.
*/
rx_stats = this_cpu_ptr(net_device_ctx->rx_stats);
u64_stats_update_begin(&rx_stats->syncp); u64_stats_update_begin(&rx_stats->syncp);
rx_stats->packets++; rx_stats->packets++;
rx_stats->bytes += packet->total_data_buflen; rx_stats->bytes += packet->total_data_buflen;
...@@ -1291,20 +1269,6 @@ static int netvsc_register_vf(struct net_device *vf_netdev) ...@@ -1291,20 +1269,6 @@ static int netvsc_register_vf(struct net_device *vf_netdev)
return NOTIFY_OK; return NOTIFY_OK;
} }
static void netvsc_inject_enable(struct net_device_context *net_device_ctx)
{
net_device_ctx->vf_inject = true;
}
static void netvsc_inject_disable(struct net_device_context *net_device_ctx)
{
net_device_ctx->vf_inject = false;
/* Wait for currently active users to drain out. */
while (atomic_read(&net_device_ctx->vf_use_cnt) != 0)
udelay(50);
}
static int netvsc_vf_up(struct net_device *vf_netdev) static int netvsc_vf_up(struct net_device *vf_netdev)
{ {
struct net_device *ndev; struct net_device *ndev;
...@@ -1319,7 +1283,6 @@ static int netvsc_vf_up(struct net_device *vf_netdev) ...@@ -1319,7 +1283,6 @@ static int netvsc_vf_up(struct net_device *vf_netdev)
netvsc_dev = net_device_ctx->nvdev; netvsc_dev = net_device_ctx->nvdev;
netdev_info(ndev, "VF up: %s\n", vf_netdev->name); netdev_info(ndev, "VF up: %s\n", vf_netdev->name);
netvsc_inject_enable(net_device_ctx);
/* /*
* Open the device before switching data path. * Open the device before switching data path.
...@@ -1354,7 +1317,6 @@ static int netvsc_vf_down(struct net_device *vf_netdev) ...@@ -1354,7 +1317,6 @@ static int netvsc_vf_down(struct net_device *vf_netdev)
netvsc_dev = net_device_ctx->nvdev; netvsc_dev = net_device_ctx->nvdev;
netdev_info(ndev, "VF down: %s\n", vf_netdev->name); netdev_info(ndev, "VF down: %s\n", vf_netdev->name);
netvsc_inject_disable(net_device_ctx);
netvsc_switch_datapath(ndev, false); netvsc_switch_datapath(ndev, false);
netdev_info(ndev, "Data path switched from VF: %s\n", vf_netdev->name); netdev_info(ndev, "Data path switched from VF: %s\n", vf_netdev->name);
rndis_filter_close(netvsc_dev); rndis_filter_close(netvsc_dev);
...@@ -1380,7 +1342,6 @@ static int netvsc_unregister_vf(struct net_device *vf_netdev) ...@@ -1380,7 +1342,6 @@ static int netvsc_unregister_vf(struct net_device *vf_netdev)
netvsc_dev = net_device_ctx->nvdev; netvsc_dev = net_device_ctx->nvdev;
netdev_info(ndev, "VF unregistering: %s\n", vf_netdev->name); netdev_info(ndev, "VF unregistering: %s\n", vf_netdev->name);
netvsc_inject_disable(net_device_ctx);
RCU_INIT_POINTER(net_device_ctx->vf_netdev, NULL); RCU_INIT_POINTER(net_device_ctx->vf_netdev, NULL);
dev_put(vf_netdev); dev_put(vf_netdev);
...@@ -1435,8 +1396,6 @@ static int netvsc_probe(struct hv_device *dev, ...@@ -1435,8 +1396,6 @@ static int netvsc_probe(struct hv_device *dev,
spin_lock_init(&net_device_ctx->lock); spin_lock_init(&net_device_ctx->lock);
INIT_LIST_HEAD(&net_device_ctx->reconfig_events); INIT_LIST_HEAD(&net_device_ctx->reconfig_events);
atomic_set(&net_device_ctx->vf_use_cnt, 0);
net->netdev_ops = &device_ops; net->netdev_ops = &device_ops;
net->hw_features = NETVSC_HW_FEATURES; net->hw_features = NETVSC_HW_FEATURES;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment