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

Commit 2b01888d authored by stephen hemminger's avatar stephen hemminger Committed by David S. Miller
Browse files

netvsc: allow more flexible setting of number of channels



This allows for number of channels to be managed in a manner similar
to existing hardware drivers. It also removes the restriction of
maximum 8 channels and allows as many as the host will allow.

Signed-off-by: default avatarStephen Hemminger <sthemmin@microsoft.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 962f3fee
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -628,6 +628,7 @@ struct nvsp_message {


#define VRSS_SEND_TAB_SIZE 16
#define VRSS_SEND_TAB_SIZE 16
#define VRSS_CHANNEL_MAX 64
#define VRSS_CHANNEL_MAX 64
#define VRSS_CHANNEL_DEFAULT 8


#define RNDIS_MAX_PKT_DEFAULT 8
#define RNDIS_MAX_PKT_DEFAULT 8
#define RNDIS_PKT_ALIGN_DEFAULT 8
#define RNDIS_PKT_ALIGN_DEFAULT 8
+49 −79
Original line number Original line Diff line number Diff line
@@ -47,8 +47,6 @@ static int ring_size = 128;
module_param(ring_size, int, S_IRUGO);
module_param(ring_size, int, S_IRUGO);
MODULE_PARM_DESC(ring_size, "Ring buffer size (# of pages)");
MODULE_PARM_DESC(ring_size, "Ring buffer size (# of pages)");


static int max_num_vrss_chns = 8;

static const u32 default_msg = NETIF_MSG_DRV | NETIF_MSG_PROBE |
static const u32 default_msg = NETIF_MSG_DRV | NETIF_MSG_PROBE |
				NETIF_MSG_LINK | NETIF_MSG_IFUP |
				NETIF_MSG_LINK | NETIF_MSG_IFUP |
				NETIF_MSG_IFDOWN | NETIF_MSG_RX_ERR |
				NETIF_MSG_IFDOWN | NETIF_MSG_RX_ERR |
@@ -709,102 +707,76 @@ static void netvsc_get_channels(struct net_device *net,
	}
	}
}
}


static int netvsc_set_queues(struct net_device *net, struct hv_device *dev,
			     u32 num_chn)
{
	struct netvsc_device_info device_info;
	int ret;

	memset(&device_info, 0, sizeof(device_info));
	device_info.num_chn = num_chn;
	device_info.ring_size = ring_size;
	device_info.max_num_vrss_chns = num_chn;

	ret = rndis_filter_device_add(dev, &device_info);
	if (ret)
		return ret;

	ret = netif_set_real_num_tx_queues(net, num_chn);
	if (ret)
		return ret;

	ret = netif_set_real_num_rx_queues(net, num_chn);

	return ret;
}

static int netvsc_set_channels(struct net_device *net,
static int netvsc_set_channels(struct net_device *net,
			       struct ethtool_channels *channels)
			       struct ethtool_channels *channels)
{
{
	struct net_device_context *net_device_ctx = netdev_priv(net);
	struct net_device_context *net_device_ctx = netdev_priv(net);
	struct hv_device *dev = net_device_ctx->device_ctx;
	struct hv_device *dev = net_device_ctx->device_ctx;
	struct netvsc_device *nvdev = net_device_ctx->nvdev;
	struct netvsc_device *nvdev = net_device_ctx->nvdev;
	struct netvsc_device_info device_info;
	unsigned int count = channels->combined_count;
	u32 num_chn;
	int ret;
	u32 max_chn;

	int ret = 0;
	/* We do not support separate count for rx, tx, or other */
	bool recovering = false;
	if (count == 0 ||
	    channels->rx_count || channels->tx_count || channels->other_count)
		return -EINVAL;

	if (count > net->num_tx_queues || count > net->num_rx_queues)
		return -EINVAL;


	if (net_device_ctx->start_remove || !nvdev || nvdev->destroy)
	if (net_device_ctx->start_remove || !nvdev || nvdev->destroy)
		return -ENODEV;
		return -ENODEV;


	num_chn = nvdev->num_chn;
	if (nvdev->nvsp_version < NVSP_PROTOCOL_VERSION_5)
	max_chn = min_t(u32, nvdev->max_chn, num_online_cpus());

	if (nvdev->nvsp_version < NVSP_PROTOCOL_VERSION_5) {
		pr_info("vRSS unsupported before NVSP Version 5\n");
		return -EINVAL;
		return -EINVAL;
	}


	/* We do not support rx, tx, or other */
	if (count > nvdev->max_chn)
	if (!channels ||
	    channels->rx_count ||
	    channels->tx_count ||
	    channels->other_count ||
	    (channels->combined_count < 1))
		return -EINVAL;
		return -EINVAL;


	if (channels->combined_count > max_chn) {
		pr_info("combined channels too high, using %d\n", max_chn);
		channels->combined_count = max_chn;
	}

	ret = netvsc_close(net);
	ret = netvsc_close(net);
	if (ret)
	if (ret)
		goto out;
		return ret;


 do_set:
	net_device_ctx->start_remove = true;
	net_device_ctx->start_remove = true;
	rndis_filter_device_remove(dev);
	rndis_filter_device_remove(dev);


	nvdev->num_chn = channels->combined_count;
	ret = netvsc_set_queues(net, dev, count);

	if (ret == 0)
	memset(&device_info, 0, sizeof(device_info));
		nvdev->num_chn = count;
	device_info.num_chn = nvdev->num_chn; /* passed to RNDIS */
	else
	device_info.ring_size = ring_size;
		netvsc_set_queues(net, dev, nvdev->num_chn);
	device_info.max_num_vrss_chns = max_num_vrss_chns;

	ret = rndis_filter_device_add(dev, &device_info);
	if (ret) {
		if (recovering) {
			netdev_err(net, "unable to add netvsc device (ret %d)\n", ret);
			return ret;
		}
		goto recover;
	}

	nvdev = net_device_ctx->nvdev;

	ret = netif_set_real_num_tx_queues(net, nvdev->num_chn);
	if (ret) {
		if (recovering) {
			netdev_err(net, "could not set tx queue count (ret %d)\n", ret);
			return ret;
		}
		goto recover;
	}

	ret = netif_set_real_num_rx_queues(net, nvdev->num_chn);
	if (ret) {
		if (recovering) {
			netdev_err(net, "could not set rx queue count (ret %d)\n", ret);
			return ret;
		}
		goto recover;
	}


 out:
	netvsc_open(net);
	netvsc_open(net);
	net_device_ctx->start_remove = false;
	net_device_ctx->start_remove = false;

	/* We may have missed link change notifications */
	/* We may have missed link change notifications */
	schedule_delayed_work(&net_device_ctx->dwork, 0);
	schedule_delayed_work(&net_device_ctx->dwork, 0);


	return ret;
	return ret;

 recover:
	/* If the above failed, we attempt to recover through the same
	 * process but with the original number of channels.
	 */
	netdev_err(net, "could not set channels, recovering\n");
	recovering = true;
	channels->combined_count = num_chn;
	goto do_set;
}
}


static bool netvsc_validate_ethtool_ss_cmd(const struct ethtool_cmd *cmd)
static bool netvsc_validate_ethtool_ss_cmd(const struct ethtool_cmd *cmd)
@@ -865,8 +837,7 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu)
	struct netvsc_device *nvdev = ndevctx->nvdev;
	struct netvsc_device *nvdev = 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;
	u32 num_chn;
	int ret;
	int ret = 0;


	if (ndevctx->start_remove || !nvdev || nvdev->destroy)
	if (ndevctx->start_remove || !nvdev || nvdev->destroy)
		return -ENODEV;
		return -ENODEV;
@@ -875,8 +846,6 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu)
	if (ret)
	if (ret)
		goto out;
		goto out;


	num_chn = nvdev->num_chn;

	ndevctx->start_remove = true;
	ndevctx->start_remove = true;
	rndis_filter_device_remove(hdev);
	rndis_filter_device_remove(hdev);


@@ -884,8 +853,8 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu)


	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;
	device_info.num_chn = num_chn;
	device_info.num_chn = nvdev->num_chn;
	device_info.max_num_vrss_chns = max_num_vrss_chns;
	device_info.max_num_vrss_chns = nvdev->num_chn;
	rndis_filter_device_add(hdev, &device_info);
	rndis_filter_device_add(hdev, &device_info);


out:
out:
@@ -1410,7 +1379,7 @@ static int netvsc_probe(struct hv_device *dev,
	int ret;
	int ret;


	net = alloc_etherdev_mq(sizeof(struct net_device_context),
	net = alloc_etherdev_mq(sizeof(struct net_device_context),
				num_online_cpus());
				VRSS_CHANNEL_MAX);
	if (!net)
	if (!net)
		return -ENOMEM;
		return -ENOMEM;


@@ -1457,7 +1426,8 @@ static int netvsc_probe(struct hv_device *dev,
	/* Notify the netvsc driver of the new device */
	/* Notify the netvsc driver of the new device */
	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;
	device_info.max_num_vrss_chns = max_num_vrss_chns;
	device_info.max_num_vrss_chns = min_t(u32, VRSS_CHANNEL_DEFAULT,
					      num_online_cpus());
	ret = rndis_filter_device_add(dev, &device_info);
	ret = rndis_filter_device_add(dev, &device_info);
	if (ret != 0) {
	if (ret != 0) {
		netdev_err(net, "unable to add netvsc device (ret %d)\n", ret);
		netdev_err(net, "unable to add netvsc device (ret %d)\n", ret);