Commit ea383bf1 authored by stephen hemminger's avatar stephen hemminger Committed by David S. Miller

netvsc: change logic for change mtu and set_queues

Use device detach/attach to ensure that no packets are handed
to device during state changes. Call rndis_filter_open/close
directly as part of later VF related changes.
Signed-off-by: default avatarStephen Hemminger <sthemmin@microsoft.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a5e1ec38
...@@ -200,6 +200,7 @@ int netvsc_recv_callback(struct net_device *net, ...@@ -200,6 +200,7 @@ int netvsc_recv_callback(struct net_device *net,
const struct ndis_pkt_8021q_info *vlan); const struct ndis_pkt_8021q_info *vlan);
void netvsc_channel_cb(void *context); void netvsc_channel_cb(void *context);
int netvsc_poll(struct napi_struct *napi, int budget); int netvsc_poll(struct napi_struct *napi, int budget);
bool rndis_filter_opened(const struct netvsc_device *nvdev);
int rndis_filter_open(struct netvsc_device *nvdev); int rndis_filter_open(struct netvsc_device *nvdev);
int rndis_filter_close(struct netvsc_device *nvdev); int rndis_filter_close(struct netvsc_device *nvdev);
int rndis_filter_device_add(struct hv_device *dev, int rndis_filter_device_add(struct hv_device *dev,
......
...@@ -742,7 +742,7 @@ static int netvsc_set_channels(struct net_device *net, ...@@ -742,7 +742,7 @@ static int netvsc_set_channels(struct net_device *net,
struct hv_device *dev = net_device_ctx->device_ctx; struct hv_device *dev = net_device_ctx->device_ctx;
struct netvsc_device *nvdev = rtnl_dereference(net_device_ctx->nvdev); struct netvsc_device *nvdev = rtnl_dereference(net_device_ctx->nvdev);
unsigned int count = channels->combined_count; unsigned int count = channels->combined_count;
bool was_running; bool was_opened;
int ret; int ret;
/* We do not support separate count for rx, tx, or other */ /* We do not support separate count for rx, tx, or other */
...@@ -762,12 +762,9 @@ static int netvsc_set_channels(struct net_device *net, ...@@ -762,12 +762,9 @@ static int netvsc_set_channels(struct net_device *net,
if (count > nvdev->max_chn) if (count > nvdev->max_chn)
return -EINVAL; return -EINVAL;
was_running = netif_running(net); was_opened = rndis_filter_opened(nvdev);
if (was_running) { if (was_opened)
ret = netvsc_close(net); rndis_filter_close(nvdev);
if (ret)
return ret;
}
rndis_filter_device_remove(dev, nvdev); rndis_filter_device_remove(dev, nvdev);
...@@ -777,8 +774,9 @@ static int netvsc_set_channels(struct net_device *net, ...@@ -777,8 +774,9 @@ static int netvsc_set_channels(struct net_device *net,
else else
netvsc_set_queues(net, dev, nvdev->num_chn); netvsc_set_queues(net, dev, nvdev->num_chn);
if (was_running) nvdev = rtnl_dereference(net_device_ctx->nvdev);
ret = netvsc_open(net); if (was_opened)
rndis_filter_open(nvdev);
/* We may have missed link change notifications */ /* We may have missed link change notifications */
net_device_ctx->last_reconfig = 0; net_device_ctx->last_reconfig = 0;
...@@ -848,18 +846,15 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu) ...@@ -848,18 +846,15 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu)
struct netvsc_device *nvdev = rtnl_dereference(ndevctx->nvdev); struct netvsc_device *nvdev = rtnl_dereference(ndevctx->nvdev);
struct hv_device *hdev = ndevctx->device_ctx; struct hv_device *hdev = ndevctx->device_ctx;
struct netvsc_device_info device_info; struct netvsc_device_info device_info;
bool was_running; bool was_opened;
int ret = 0;
if (!nvdev || nvdev->destroy) if (!nvdev || nvdev->destroy)
return -ENODEV; return -ENODEV;
was_running = netif_running(ndev); netif_device_detach(ndev);
if (was_running) { was_opened = rndis_filter_opened(nvdev);
ret = netvsc_close(ndev); if (was_opened)
if (ret) rndis_filter_close(nvdev);
return ret;
}
memset(&device_info, 0, sizeof(device_info)); memset(&device_info, 0, sizeof(device_info));
device_info.ring_size = ring_size; device_info.ring_size = ring_size;
...@@ -877,14 +872,17 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu) ...@@ -877,14 +872,17 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu)
ndev->mtu = mtu; ndev->mtu = mtu;
rndis_filter_device_add(hdev, &device_info); rndis_filter_device_add(hdev, &device_info);
nvdev = rtnl_dereference(ndevctx->nvdev);
if (was_running) if (was_opened)
ret = netvsc_open(ndev); rndis_filter_open(nvdev);
netif_device_attach(ndev);
/* We may have missed link change notifications */ /* We may have missed link change notifications */
schedule_delayed_work(&ndevctx->dwork, 0); schedule_delayed_work(&ndevctx->dwork, 0);
return ret; return 0;
} }
static void netvsc_get_stats64(struct net_device *net, static void netvsc_get_stats64(struct net_device *net,
......
...@@ -1302,3 +1302,8 @@ int rndis_filter_close(struct netvsc_device *nvdev) ...@@ -1302,3 +1302,8 @@ int rndis_filter_close(struct netvsc_device *nvdev)
return rndis_filter_close_device(nvdev->extension); return rndis_filter_close_device(nvdev->extension);
} }
bool rndis_filter_opened(const struct netvsc_device *nvdev)
{
return atomic_read(&nvdev->open_cnt) > 0;
}
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