aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaolo Abeni <pabeni@redhat.com>2016-05-10 16:11:54 +0200
committerJakub Kicinski <kuba@kernel.org>2020-08-18 10:21:11 -0700
commitfdf93d4de9278aba58f3c3290d52c51a3074c184 (patch)
tree018e00692c41fadf372e4a886cdd13923ac1b53a
parentd7ba4cd12bd5d9c60c33e6555575ae3456d2856d (diff)
downloadlinux-fdf93d4de9278aba58f3c3290d52c51a3074c184.tar.gz
net: add sysfs attribute to control napi threaded mode
this patch addis a new sysfs attribute to the network device class. Said attribute is a bitmask that allows controlling the threaded mode for all the napi instances of the given network device. The threaded mode can be switched only if related network device is down. Signed-off-by: Paolo Abeni <pabeni@redhat.com> Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
-rw-r--r--include/linux/netdevice.h1
-rw-r--r--net/core/net-sysfs.c53
2 files changed, 54 insertions, 0 deletions
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index fa40bdc0e2c45..9e8a886ab8be0 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1961,6 +1961,7 @@ struct net_device {
spinlock_t addr_list_lock;
unsigned char name_assign_type;
bool uc_promisc;
+ bool napi_threaded;
struct netdev_hw_addr_list uc;
struct netdev_hw_addr_list mc;
struct netdev_hw_addr_list dev_addrs;
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index 7bd6440c63bf5..9c97cdb09f308 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -537,6 +537,58 @@ static ssize_t phys_switch_id_show(struct device *dev,
}
static DEVICE_ATTR_RO(phys_switch_id);
+static ssize_t threaded_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct net_device *netdev = to_net_dev(dev);
+ size_t count = 0;
+
+ if (!rtnl_trylock())
+ return restart_syscall();
+
+ if (dev_isalive(netdev))
+ count = snprintf(buf, PAGE_SIZE, "%u\n", netdev->napi_threaded);
+ rtnl_unlock();
+
+ return count;
+}
+
+static ssize_t threaded_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ struct net_device *netdev = to_net_dev(dev);
+ size_t ret;
+ bool val;
+
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+
+ if (!rtnl_trylock())
+ return restart_syscall();
+
+ if (!dev_isalive(netdev)) {
+ ret = len;
+ goto unlock;
+ }
+
+ if (netdev->flags & IFF_UP) {
+ ret = -EBUSY;
+ goto unlock;
+ }
+
+ ret = kstrtobool(buf, &val);
+ if (ret < 0)
+ goto unlock;
+ netdev->napi_threaded = val;
+ ret = len;
+
+unlock:
+ rtnl_unlock();
+ return ret;
+}
+static DEVICE_ATTR_RW(threaded);
+
static struct attribute *net_class_attrs[] __ro_after_init = {
&dev_attr_netdev_group.attr,
&dev_attr_type.attr,
@@ -569,6 +621,7 @@ static struct attribute *net_class_attrs[] __ro_after_init = {
&dev_attr_proto_down.attr,
&dev_attr_carrier_up_count.attr,
&dev_attr_carrier_down_count.attr,
+ &dev_attr_threaded.attr,
NULL,
};
ATTRIBUTE_GROUPS(net_class);