mirror of https://gitee.com/openkylin/linux.git
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: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
7f7f6262a5
|
@ -173,6 +173,7 @@ struct rndis_device {
|
|||
struct list_head req_list;
|
||||
|
||||
struct work_struct mcast_work;
|
||||
u32 filter;
|
||||
|
||||
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)
|
|||
static void netvsc_set_rx_mode(struct net_device *net)
|
||||
{
|
||||
struct net_device_context *ndev_ctx = netdev_priv(net);
|
||||
struct net_device *vf_netdev = rtnl_dereference(ndev_ctx->vf_netdev);
|
||||
struct netvsc_device *nvdev = rtnl_dereference(ndev_ctx->nvdev);
|
||||
struct net_device *vf_netdev;
|
||||
struct netvsc_device *nvdev;
|
||||
|
||||
rcu_read_lock();
|
||||
vf_netdev = rcu_dereference(ndev_ctx->vf_netdev);
|
||||
if (vf_netdev) {
|
||||
dev_uc_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)
|
||||
|
@ -1846,8 +1851,12 @@ static void __netvsc_vf_setup(struct net_device *ndev,
|
|||
|
||||
/* set multicast etc flags on VF */
|
||||
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_mc_sync(vf_netdev, ndev);
|
||||
netif_addr_unlock_bh(ndev);
|
||||
|
||||
if (netif_running(ndev)) {
|
||||
ret = dev_open(vf_netdev);
|
||||
|
|
|
@ -825,13 +825,15 @@ static int rndis_filter_set_packet_filter(struct rndis_device *dev,
|
|||
struct rndis_set_request *set;
|
||||
int ret;
|
||||
|
||||
if (dev->filter == new_filter)
|
||||
return 0;
|
||||
|
||||
request = get_rndis_request(dev, RNDIS_MSG_SET,
|
||||
RNDIS_MESSAGE_SIZE(struct rndis_set_request) +
|
||||
sizeof(u32));
|
||||
if (!request)
|
||||
return -ENOMEM;
|
||||
|
||||
|
||||
/* Setup the rndis set */
|
||||
set = &request->request_msg.msg.set_req;
|
||||
set->oid = RNDIS_OID_GEN_CURRENT_PACKET_FILTER;
|
||||
|
@ -842,8 +844,10 @@ static int rndis_filter_set_packet_filter(struct rndis_device *dev,
|
|||
&new_filter, sizeof(u32));
|
||||
|
||||
ret = rndis_filter_send_request(dev, request);
|
||||
if (ret == 0)
|
||||
if (ret == 0) {
|
||||
wait_for_completion(&request->wait_event);
|
||||
dev->filter = new_filter;
|
||||
}
|
||||
|
||||
put_rndis_request(dev, request);
|
||||
|
||||
|
@ -861,9 +865,9 @@ static void rndis_set_multicast(struct work_struct *w)
|
|||
filter = NDIS_PACKET_TYPE_PROMISCUOUS;
|
||||
} else {
|
||||
if (flags & IFF_ALLMULTI)
|
||||
flags |= NDIS_PACKET_TYPE_ALL_MULTICAST;
|
||||
filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
|
||||
if (flags & IFF_BROADCAST)
|
||||
flags |= NDIS_PACKET_TYPE_BROADCAST;
|
||||
filter |= NDIS_PACKET_TYPE_BROADCAST;
|
||||
}
|
||||
|
||||
rndis_filter_set_packet_filter(rdev, filter);
|
||||
|
|
Loading…
Reference in New Issue