summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--net/ethtool/channels.c28
-rw-r--r--net/ethtool/ioctl.c21
2 files changed, 29 insertions, 20 deletions
diff --git a/net/ethtool/channels.c b/net/ethtool/channels.c
index 45232cf1c144..64ef8cff2005 100644
--- a/net/ethtool/channels.c
+++ b/net/ethtool/channels.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
-#include <net/xdp_sock_drv.h>
+#include <net/netdev_queues.h>
#include "common.h"
#include "netlink.h"
@@ -109,7 +109,7 @@ ethnl_set_channels_validate(struct ethnl_req_info *req_info,
static int
ethnl_set_channels(struct ethnl_req_info *req_info, struct genl_info *info)
{
- unsigned int from_channel, old_total, i;
+ unsigned int old_combined, old_rx, old_tx, i;
bool mod = false, mod_combined = false;
struct net_device *dev = req_info->dev;
struct ethtool_channels channels = {};
@@ -118,8 +118,9 @@ ethnl_set_channels(struct ethnl_req_info *req_info, struct genl_info *info)
int ret;
dev->ethtool_ops->get_channels(dev, &channels);
- old_total = channels.combined_count +
- max(channels.rx_count, channels.tx_count);
+ old_combined = channels.combined_count;
+ old_rx = channels.rx_count;
+ old_tx = channels.tx_count;
ethnl_update_u32(&channels.rx_count, tb[ETHTOOL_A_CHANNELS_RX_COUNT],
&mod);
@@ -169,14 +170,19 @@ ethnl_set_channels(struct ethnl_req_info *req_info, struct genl_info *info)
if (ret)
return ret;
- /* Disabling channels, query zero-copy AF_XDP sockets */
- from_channel = channels.combined_count +
- min(channels.rx_count, channels.tx_count);
- for (i = from_channel; i < old_total; i++)
- if (xsk_get_pool_from_qid(dev, i)) {
- GENL_SET_ERR_MSG(info, "requested channel counts are too low for existing zerocopy AF_XDP sockets");
+ /* ensure channels are not busy at the moment */
+ for (i = channels.combined_count + channels.rx_count;
+ i < old_combined + old_rx; i++) {
+ if (netdev_queue_busy(dev, i, NETDEV_QUEUE_TYPE_RX,
+ info->extack))
return -EINVAL;
- }
+ }
+ for (i = channels.combined_count + channels.tx_count;
+ i < old_combined + old_tx; i++) {
+ if (netdev_queue_busy(dev, i, NETDEV_QUEUE_TYPE_TX,
+ info->extack))
+ return -EINVAL;
+ }
ret = dev->ethtool_ops->set_channels(dev, &channels);
return ret < 0 ? ret : 1;
diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c
index 3c713a91ad0d..bd97f9b9bf18 100644
--- a/net/ethtool/ioctl.c
+++ b/net/ethtool/ioctl.c
@@ -27,12 +27,12 @@
#include <linux/net.h>
#include <linux/pm_runtime.h>
#include <linux/utsname.h>
+#include <linux/ethtool_netlink.h>
#include <net/devlink.h>
#include <net/ipv6.h>
-#include <net/xdp_sock_drv.h>
#include <net/flow_offload.h>
#include <net/netdev_lock.h>
-#include <linux/ethtool_netlink.h>
+#include <net/netdev_queues.h>
#include "common.h"
@@ -2250,7 +2250,6 @@ static noinline_for_stack int ethtool_set_channels(struct net_device *dev,
void __user *useraddr)
{
struct ethtool_channels channels, curr = { .cmd = ETHTOOL_GCHANNELS };
- u16 from_channel, to_channel;
unsigned int i;
int ret;
@@ -2284,13 +2283,17 @@ static noinline_for_stack int ethtool_set_channels(struct net_device *dev,
if (ret)
return ret;
- /* Disabling channels, query zero-copy AF_XDP sockets */
- from_channel = channels.combined_count +
- min(channels.rx_count, channels.tx_count);
- to_channel = curr.combined_count + max(curr.rx_count, curr.tx_count);
- for (i = from_channel; i < to_channel; i++)
- if (xsk_get_pool_from_qid(dev, i))
+ /* Disabling channels, query busy queues (AF_XDP, queue leasing) */
+ for (i = channels.combined_count + channels.rx_count;
+ i < curr.combined_count + curr.rx_count; i++) {
+ if (netdev_queue_busy(dev, i, NETDEV_QUEUE_TYPE_RX, NULL))
return -EINVAL;
+ }
+ for (i = channels.combined_count + channels.tx_count;
+ i < curr.combined_count + curr.tx_count; i++) {
+ if (netdev_queue_busy(dev, i, NETDEV_QUEUE_TYPE_TX, NULL))
+ return -EINVAL;
+ }
ret = dev->ethtool_ops->set_channels(dev, &channels);
if (!ret)