Commit 7f7f6262 authored by David S. Miller's avatar David S. Miller

Merge branch 'hv_netvsc-fix-multicast-flags-and-sync'

Stephen Hemminger says:

====================
hv_netvsc: fix multicast flags and sync

This set of patches deals with the handling of multicast flags
and addresses in transparent VF mode. The recent set of patches
(in linux-net) had a couple of bugs.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 652dfb2b b0dee791
...@@ -173,6 +173,7 @@ struct rndis_device { ...@@ -173,6 +173,7 @@ struct rndis_device {
struct list_head req_list; struct list_head req_list;
struct work_struct mcast_work; struct work_struct mcast_work;
u32 filter;
bool link_state; /* 0 - link up, 1 - link down */ bool link_state; /* 0 - link up, 1 - link down */
......
...@@ -89,15 +89,20 @@ static void netvsc_change_rx_flags(struct net_device *net, int change) ...@@ -89,15 +89,20 @@ static void netvsc_change_rx_flags(struct net_device *net, int change)
static void netvsc_set_rx_mode(struct net_device *net) static void netvsc_set_rx_mode(struct net_device *net)
{ {
struct net_device_context *ndev_ctx = netdev_priv(net); struct net_device_context *ndev_ctx = netdev_priv(net);
struct net_device *vf_netdev = rtnl_dereference(ndev_ctx->vf_netdev); struct net_device *vf_netdev;
struct netvsc_device *nvdev = rtnl_dereference(ndev_ctx->nvdev); struct netvsc_device *nvdev;
rcu_read_lock();
vf_netdev = rcu_dereference(ndev_ctx->vf_netdev);
if (vf_netdev) { if (vf_netdev) {
dev_uc_sync(vf_netdev, net); dev_uc_sync(vf_netdev, net);
dev_mc_sync(vf_netdev, net); dev_mc_sync(vf_netdev, net);
} }
rndis_filter_update(nvdev); nvdev = rcu_dereference(ndev_ctx->nvdev);
if (nvdev)
rndis_filter_update(nvdev);
rcu_read_unlock();
} }
static int netvsc_open(struct net_device *net) static int netvsc_open(struct net_device *net)
...@@ -1846,8 +1851,12 @@ static void __netvsc_vf_setup(struct net_device *ndev, ...@@ -1846,8 +1851,12 @@ static void __netvsc_vf_setup(struct net_device *ndev,
/* set multicast etc flags on VF */ /* set multicast etc flags on VF */
dev_change_flags(vf_netdev, ndev->flags | IFF_SLAVE); dev_change_flags(vf_netdev, ndev->flags | IFF_SLAVE);
/* sync address list from ndev to VF */
netif_addr_lock_bh(ndev);
dev_uc_sync(vf_netdev, ndev); dev_uc_sync(vf_netdev, ndev);
dev_mc_sync(vf_netdev, ndev); dev_mc_sync(vf_netdev, ndev);
netif_addr_unlock_bh(ndev);
if (netif_running(ndev)) { if (netif_running(ndev)) {
ret = dev_open(vf_netdev); ret = dev_open(vf_netdev);
......
...@@ -825,13 +825,15 @@ static int rndis_filter_set_packet_filter(struct rndis_device *dev, ...@@ -825,13 +825,15 @@ static int rndis_filter_set_packet_filter(struct rndis_device *dev,
struct rndis_set_request *set; struct rndis_set_request *set;
int ret; int ret;
if (dev->filter == new_filter)
return 0;
request = get_rndis_request(dev, RNDIS_MSG_SET, request = get_rndis_request(dev, RNDIS_MSG_SET,
RNDIS_MESSAGE_SIZE(struct rndis_set_request) + RNDIS_MESSAGE_SIZE(struct rndis_set_request) +
sizeof(u32)); sizeof(u32));
if (!request) if (!request)
return -ENOMEM; return -ENOMEM;
/* Setup the rndis set */ /* Setup the rndis set */
set = &request->request_msg.msg.set_req; set = &request->request_msg.msg.set_req;
set->oid = RNDIS_OID_GEN_CURRENT_PACKET_FILTER; set->oid = RNDIS_OID_GEN_CURRENT_PACKET_FILTER;
...@@ -842,8 +844,10 @@ static int rndis_filter_set_packet_filter(struct rndis_device *dev, ...@@ -842,8 +844,10 @@ static int rndis_filter_set_packet_filter(struct rndis_device *dev,
&new_filter, sizeof(u32)); &new_filter, sizeof(u32));
ret = rndis_filter_send_request(dev, request); ret = rndis_filter_send_request(dev, request);
if (ret == 0) if (ret == 0) {
wait_for_completion(&request->wait_event); wait_for_completion(&request->wait_event);
dev->filter = new_filter;
}
put_rndis_request(dev, request); put_rndis_request(dev, request);
...@@ -861,9 +865,9 @@ static void rndis_set_multicast(struct work_struct *w) ...@@ -861,9 +865,9 @@ static void rndis_set_multicast(struct work_struct *w)
filter = NDIS_PACKET_TYPE_PROMISCUOUS; filter = NDIS_PACKET_TYPE_PROMISCUOUS;
} else { } else {
if (flags & IFF_ALLMULTI) if (flags & IFF_ALLMULTI)
flags |= NDIS_PACKET_TYPE_ALL_MULTICAST; filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
if (flags & IFF_BROADCAST) if (flags & IFF_BROADCAST)
flags |= NDIS_PACKET_TYPE_BROADCAST; filter |= NDIS_PACKET_TYPE_BROADCAST;
} }
rndis_filter_set_packet_filter(rdev, filter); rndis_filter_set_packet_filter(rdev, filter);
......
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