提交 2b01888d 编写于 作者: S stephen hemminger 提交者: David S. Miller

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: NStephen Hemminger <sthemmin@microsoft.com>
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
上级 962f3fee
...@@ -628,6 +628,7 @@ struct nvsp_message { ...@@ -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
......
...@@ -47,8 +47,6 @@ static int ring_size = 128; ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册