Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4f19c0d8 authored by stephen hemminger's avatar stephen hemminger Committed by David S. Miller
Browse files

netvsc: move filter setting to rndis_device



The work queue and handling of network filter parameters should
be in rndis_device. This gets rid of warning from RCU checks,
eliminates a race and cleans up code.

Signed-off-by: default avatarStephen Hemminger <sthemmin@microsoft.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a5ecd439
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -171,6 +171,8 @@ struct rndis_device {
	spinlock_t request_lock;
	struct list_head req_list;

	struct work_struct mcast_work;

	u8 hw_mac_adr[ETH_ALEN];
	u8 rss_key[NETVSC_HASH_KEYLEN];
	u16 ind_table[ITAB_NUM];
@@ -201,6 +203,7 @@ int rndis_filter_open(struct netvsc_device *nvdev);
int rndis_filter_close(struct netvsc_device *nvdev);
int rndis_filter_device_add(struct hv_device *dev,
			    struct netvsc_device_info *info);
void rndis_filter_update(struct netvsc_device *nvdev);
void rndis_filter_device_remove(struct hv_device *dev,
				struct netvsc_device *nvdev);
int rndis_filter_set_rss_param(struct rndis_device *rdev,
@@ -211,7 +214,6 @@ int rndis_filter_receive(struct net_device *ndev,
			 struct vmbus_channel *channel,
			 void *data, u32 buflen);

int rndis_filter_set_packet_filter(struct rndis_device *dev, u32 new_filter);
int rndis_filter_set_device_mac(struct net_device *ndev, char *mac);

void netvsc_switch_datapath(struct net_device *nv_dev, bool vf);
@@ -696,7 +698,6 @@ struct net_device_context {
	/* list protection */
	spinlock_t lock;

	struct work_struct work;
	u32 msg_enable; /* debug level */

	u32 tx_checksum_mask;
+2 −31
Original line number Diff line number Diff line
@@ -56,37 +56,12 @@ static int debug = -1;
module_param(debug, int, S_IRUGO);
MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");

static void do_set_multicast(struct work_struct *w)
{
	struct net_device_context *ndevctx =
		container_of(w, struct net_device_context, work);
	struct hv_device *device_obj = ndevctx->device_ctx;
	struct net_device *ndev = hv_get_drvdata(device_obj);
	struct netvsc_device *nvdev = rcu_dereference(ndevctx->nvdev);
	struct rndis_device *rdev;

	if (!nvdev)
		return;

	rdev = nvdev->extension;
	if (rdev == NULL)
		return;

	if (ndev->flags & IFF_PROMISC)
		rndis_filter_set_packet_filter(rdev,
			NDIS_PACKET_TYPE_PROMISCUOUS);
	else
		rndis_filter_set_packet_filter(rdev,
			NDIS_PACKET_TYPE_BROADCAST |
			NDIS_PACKET_TYPE_ALL_MULTICAST |
			NDIS_PACKET_TYPE_DIRECTED);
}

static void netvsc_set_multicast_list(struct net_device *net)
{
	struct net_device_context *net_device_ctx = netdev_priv(net);
	struct netvsc_device *nvdev = rtnl_dereference(net_device_ctx->nvdev);

	schedule_work(&net_device_ctx->work);
	rndis_filter_update(nvdev);
}

static int netvsc_open(struct net_device *net)
@@ -123,8 +98,6 @@ static int netvsc_close(struct net_device *net)

	netif_tx_disable(net);

	/* Make sure netvsc_set_multicast_list doesn't re-enable filter! */
	cancel_work_sync(&net_device_ctx->work);
	ret = rndis_filter_close(nvdev);
	if (ret != 0) {
		netdev_err(net, "unable to close device (ret %d).\n", ret);
@@ -1563,7 +1536,6 @@ static int netvsc_probe(struct hv_device *dev,
	hv_set_drvdata(dev, net);

	INIT_DELAYED_WORK(&net_device_ctx->dwork, netvsc_link_change);
	INIT_WORK(&net_device_ctx->work, do_set_multicast);

	spin_lock_init(&net_device_ctx->lock);
	INIT_LIST_HEAD(&net_device_ctx->reconfig_events);
@@ -1633,7 +1605,6 @@ static int netvsc_remove(struct hv_device *dev)
	netif_device_detach(net);

	cancel_delayed_work_sync(&ndev_ctx->dwork);
	cancel_work_sync(&ndev_ctx->work);

	/*
	 * Call to the vsc driver to let it know that the device is being
+29 −1
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@

#include "hyperv_net.h"

static void rndis_set_multicast(struct work_struct *w);

#define RNDIS_EXT_LEN PAGE_SIZE
struct rndis_request {
@@ -76,6 +77,7 @@ static struct rndis_device *get_rndis_device(void)
	spin_lock_init(&device->request_lock);

	INIT_LIST_HEAD(&device->req_list);
	INIT_WORK(&device->mcast_work, rndis_set_multicast);

	device->state = RNDIS_DEV_UNINITIALIZED;

@@ -815,7 +817,8 @@ static int rndis_filter_query_link_speed(struct rndis_device *dev)
	return ret;
}

int rndis_filter_set_packet_filter(struct rndis_device *dev, u32 new_filter)
static int rndis_filter_set_packet_filter(struct rndis_device *dev,
					  u32 new_filter)
{
	struct rndis_request *request;
	struct rndis_set_request *set;
@@ -846,6 +849,28 @@ int rndis_filter_set_packet_filter(struct rndis_device *dev, u32 new_filter)
	return ret;
}

static void rndis_set_multicast(struct work_struct *w)
{
	struct rndis_device *rdev
		= container_of(w, struct rndis_device, mcast_work);

	if (rdev->ndev->flags & IFF_PROMISC)
		rndis_filter_set_packet_filter(rdev,
					       NDIS_PACKET_TYPE_PROMISCUOUS);
	else
		rndis_filter_set_packet_filter(rdev,
					       NDIS_PACKET_TYPE_BROADCAST |
					       NDIS_PACKET_TYPE_ALL_MULTICAST |
					       NDIS_PACKET_TYPE_DIRECTED);
}

void rndis_filter_update(struct netvsc_device *nvdev)
{
	struct rndis_device *rdev = nvdev->extension;

	schedule_work(&rdev->mcast_work);
}

static int rndis_filter_init_device(struct rndis_device *dev)
{
	struct rndis_request *request;
@@ -973,6 +998,9 @@ static int rndis_filter_close_device(struct rndis_device *dev)
	if (dev->state != RNDIS_DEV_DATAINITIALIZED)
		return 0;

	/* Make sure rndis_set_multicast doesn't re-enable filter! */
	cancel_work_sync(&dev->mcast_work);

	ret = rndis_filter_set_packet_filter(dev, 0);
	if (ret == -ENODEV)
		ret = 0;