|
@@ -47,8 +47,6 @@ static int ring_size = 128;
|
|
|
module_param(ring_size, int, S_IRUGO);
|
|
|
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 |
|
|
|
NETIF_MSG_LINK | NETIF_MSG_IFUP |
|
|
|
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,
|
|
|
struct ethtool_channels *channels)
|
|
|
{
|
|
|
struct net_device_context *net_device_ctx = netdev_priv(net);
|
|
|
struct hv_device *dev = net_device_ctx->device_ctx;
|
|
|
struct netvsc_device *nvdev = net_device_ctx->nvdev;
|
|
|
- struct netvsc_device_info device_info;
|
|
|
- u32 num_chn;
|
|
|
- u32 max_chn;
|
|
|
- int ret = 0;
|
|
|
- bool recovering = false;
|
|
|
+ unsigned int count = channels->combined_count;
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ /* We do not support separate count for rx, tx, or other */
|
|
|
+ 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)
|
|
|
return -ENODEV;
|
|
|
|
|
|
- num_chn = nvdev->num_chn;
|
|
|
- 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");
|
|
|
+ if (nvdev->nvsp_version < NVSP_PROTOCOL_VERSION_5)
|
|
|
return -EINVAL;
|
|
|
- }
|
|
|
|
|
|
- /* We do not support rx, tx, or other */
|
|
|
- if (!channels ||
|
|
|
- channels->rx_count ||
|
|
|
- channels->tx_count ||
|
|
|
- channels->other_count ||
|
|
|
- (channels->combined_count < 1))
|
|
|
+ if (count > nvdev->max_chn)
|
|
|
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);
|
|
|
if (ret)
|
|
|
- goto out;
|
|
|
+ return ret;
|
|
|
|
|
|
- do_set:
|
|
|
net_device_ctx->start_remove = true;
|
|
|
rndis_filter_device_remove(dev);
|
|
|
|
|
|
- nvdev->num_chn = channels->combined_count;
|
|
|
-
|
|
|
- memset(&device_info, 0, sizeof(device_info));
|
|
|
- device_info.num_chn = nvdev->num_chn; /* passed to RNDIS */
|
|
|
- device_info.ring_size = ring_size;
|
|
|
- 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;
|
|
|
- }
|
|
|
+ ret = netvsc_set_queues(net, dev, count);
|
|
|
+ if (ret == 0)
|
|
|
+ nvdev->num_chn = count;
|
|
|
+ else
|
|
|
+ netvsc_set_queues(net, dev, nvdev->num_chn);
|
|
|
|
|
|
- out:
|
|
|
netvsc_open(net);
|
|
|
net_device_ctx->start_remove = false;
|
|
|
+
|
|
|
/* We may have missed link change notifications */
|
|
|
schedule_delayed_work(&net_device_ctx->dwork, 0);
|
|
|
|
|
|
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)
|
|
@@ -865,8 +837,7 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu)
|
|
|
struct netvsc_device *nvdev = ndevctx->nvdev;
|
|
|
struct hv_device *hdev = ndevctx->device_ctx;
|
|
|
struct netvsc_device_info device_info;
|
|
|
- u32 num_chn;
|
|
|
- int ret = 0;
|
|
|
+ int ret;
|
|
|
|
|
|
if (ndevctx->start_remove || !nvdev || nvdev->destroy)
|
|
|
return -ENODEV;
|
|
@@ -875,8 +846,6 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu)
|
|
|
if (ret)
|
|
|
goto out;
|
|
|
|
|
|
- num_chn = nvdev->num_chn;
|
|
|
-
|
|
|
ndevctx->start_remove = true;
|
|
|
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));
|
|
|
device_info.ring_size = ring_size;
|
|
|
- device_info.num_chn = num_chn;
|
|
|
- device_info.max_num_vrss_chns = max_num_vrss_chns;
|
|
|
+ device_info.num_chn = nvdev->num_chn;
|
|
|
+ device_info.max_num_vrss_chns = nvdev->num_chn;
|
|
|
rndis_filter_device_add(hdev, &device_info);
|
|
|
|
|
|
out:
|
|
@@ -1410,7 +1379,7 @@ static int netvsc_probe(struct hv_device *dev,
|
|
|
int ret;
|
|
|
|
|
|
net = alloc_etherdev_mq(sizeof(struct net_device_context),
|
|
|
- num_online_cpus());
|
|
|
+ VRSS_CHANNEL_MAX);
|
|
|
if (!net)
|
|
|
return -ENOMEM;
|
|
|
|
|
@@ -1457,7 +1426,8 @@ static int netvsc_probe(struct hv_device *dev,
|
|
|
/* Notify the netvsc driver of the new device */
|
|
|
memset(&device_info, 0, sizeof(device_info));
|
|
|
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);
|
|
|
if (ret != 0) {
|
|
|
netdev_err(net, "unable to add netvsc device (ret %d)\n", ret);
|