Commit a953be53 authored by Michael Dalton's avatar Michael Dalton Committed by David S. Miller

net-sysfs: add support for device-specific rx queue sysfs attributes

Extend existing support for netdevice receive queue sysfs attributes to
permit a device-specific attribute group. Initial use case for this
support will be to allow the virtio-net device to export per-receive
queue mergeable receive buffer size.
Signed-off-by: default avatarMichael Dalton <mwdalton@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent ab7db917
...@@ -668,15 +668,28 @@ extern struct rps_sock_flow_table __rcu *rps_sock_flow_table; ...@@ -668,15 +668,28 @@ extern struct rps_sock_flow_table __rcu *rps_sock_flow_table;
bool rps_may_expire_flow(struct net_device *dev, u16 rxq_index, u32 flow_id, bool rps_may_expire_flow(struct net_device *dev, u16 rxq_index, u32 flow_id,
u16 filter_id); u16 filter_id);
#endif #endif
#endif /* CONFIG_RPS */
/* This structure contains an instance of an RX queue. */ /* This structure contains an instance of an RX queue. */
struct netdev_rx_queue { struct netdev_rx_queue {
#ifdef CONFIG_RPS
struct rps_map __rcu *rps_map; struct rps_map __rcu *rps_map;
struct rps_dev_flow_table __rcu *rps_flow_table; struct rps_dev_flow_table __rcu *rps_flow_table;
#endif
struct kobject kobj; struct kobject kobj;
struct net_device *dev; struct net_device *dev;
} ____cacheline_aligned_in_smp; } ____cacheline_aligned_in_smp;
#endif /* CONFIG_RPS */
/*
* RX queue sysfs structures and functions.
*/
struct rx_queue_attribute {
struct attribute attr;
ssize_t (*show)(struct netdev_rx_queue *queue,
struct rx_queue_attribute *attr, char *buf);
ssize_t (*store)(struct netdev_rx_queue *queue,
struct rx_queue_attribute *attr, const char *buf, size_t len);
};
#ifdef CONFIG_XPS #ifdef CONFIG_XPS
/* /*
...@@ -1313,7 +1326,7 @@ struct net_device { ...@@ -1313,7 +1326,7 @@ struct net_device {
unicast) */ unicast) */
#ifdef CONFIG_RPS #ifdef CONFIG_SYSFS
struct netdev_rx_queue *_rx; struct netdev_rx_queue *_rx;
/* Number of RX queues allocated at register_netdev() time */ /* Number of RX queues allocated at register_netdev() time */
...@@ -1424,6 +1437,8 @@ struct net_device { ...@@ -1424,6 +1437,8 @@ struct net_device {
struct device dev; struct device dev;
/* space for optional device, statistics, and wireless sysfs groups */ /* space for optional device, statistics, and wireless sysfs groups */
const struct attribute_group *sysfs_groups[4]; const struct attribute_group *sysfs_groups[4];
/* space for optional per-rx queue attributes */
const struct attribute_group *sysfs_rx_queue_group;
/* rtnetlink link ops */ /* rtnetlink link ops */
const struct rtnl_link_ops *rtnl_link_ops; const struct rtnl_link_ops *rtnl_link_ops;
...@@ -2375,7 +2390,7 @@ static inline bool netif_is_multiqueue(const struct net_device *dev) ...@@ -2375,7 +2390,7 @@ static inline bool netif_is_multiqueue(const struct net_device *dev)
int netif_set_real_num_tx_queues(struct net_device *dev, unsigned int txq); int netif_set_real_num_tx_queues(struct net_device *dev, unsigned int txq);
#ifdef CONFIG_RPS #ifdef CONFIG_SYSFS
int netif_set_real_num_rx_queues(struct net_device *dev, unsigned int rxq); int netif_set_real_num_rx_queues(struct net_device *dev, unsigned int rxq);
#else #else
static inline int netif_set_real_num_rx_queues(struct net_device *dev, static inline int netif_set_real_num_rx_queues(struct net_device *dev,
...@@ -2394,7 +2409,7 @@ static inline int netif_copy_real_num_queues(struct net_device *to_dev, ...@@ -2394,7 +2409,7 @@ static inline int netif_copy_real_num_queues(struct net_device *to_dev,
from_dev->real_num_tx_queues); from_dev->real_num_tx_queues);
if (err) if (err)
return err; return err;
#ifdef CONFIG_RPS #ifdef CONFIG_SYSFS
return netif_set_real_num_rx_queues(to_dev, return netif_set_real_num_rx_queues(to_dev,
from_dev->real_num_rx_queues); from_dev->real_num_rx_queues);
#else #else
...@@ -2402,6 +2417,18 @@ static inline int netif_copy_real_num_queues(struct net_device *to_dev, ...@@ -2402,6 +2417,18 @@ static inline int netif_copy_real_num_queues(struct net_device *to_dev,
#endif #endif
} }
#ifdef CONFIG_SYSFS
static inline unsigned int get_netdev_rx_queue_index(
struct netdev_rx_queue *queue)
{
struct net_device *dev = queue->dev;
int index = queue - dev->_rx;
BUG_ON(index >= dev->num_rx_queues);
return index;
}
#endif
#define DEFAULT_MAX_NUM_RSS_QUEUES (8) #define DEFAULT_MAX_NUM_RSS_QUEUES (8)
int netif_get_num_default_rss_queues(void); int netif_get_num_default_rss_queues(void);
......
...@@ -2083,7 +2083,7 @@ int netif_set_real_num_tx_queues(struct net_device *dev, unsigned int txq) ...@@ -2083,7 +2083,7 @@ int netif_set_real_num_tx_queues(struct net_device *dev, unsigned int txq)
} }
EXPORT_SYMBOL(netif_set_real_num_tx_queues); EXPORT_SYMBOL(netif_set_real_num_tx_queues);
#ifdef CONFIG_RPS #ifdef CONFIG_SYSFS
/** /**
* netif_set_real_num_rx_queues - set actual number of RX queues used * netif_set_real_num_rx_queues - set actual number of RX queues used
* @dev: Network device * @dev: Network device
...@@ -5764,7 +5764,7 @@ void netif_stacked_transfer_operstate(const struct net_device *rootdev, ...@@ -5764,7 +5764,7 @@ void netif_stacked_transfer_operstate(const struct net_device *rootdev,
} }
EXPORT_SYMBOL(netif_stacked_transfer_operstate); EXPORT_SYMBOL(netif_stacked_transfer_operstate);
#ifdef CONFIG_RPS #ifdef CONFIG_SYSFS
static int netif_alloc_rx_queues(struct net_device *dev) static int netif_alloc_rx_queues(struct net_device *dev)
{ {
unsigned int i, count = dev->num_rx_queues; unsigned int i, count = dev->num_rx_queues;
...@@ -6309,7 +6309,7 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name, ...@@ -6309,7 +6309,7 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
return NULL; return NULL;
} }
#ifdef CONFIG_RPS #ifdef CONFIG_SYSFS
if (rxqs < 1) { if (rxqs < 1) {
pr_err("alloc_netdev: Unable to allocate device with zero RX queues\n"); pr_err("alloc_netdev: Unable to allocate device with zero RX queues\n");
return NULL; return NULL;
...@@ -6365,7 +6365,7 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name, ...@@ -6365,7 +6365,7 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
if (netif_alloc_netdev_queues(dev)) if (netif_alloc_netdev_queues(dev))
goto free_all; goto free_all;
#ifdef CONFIG_RPS #ifdef CONFIG_SYSFS
dev->num_rx_queues = rxqs; dev->num_rx_queues = rxqs;
dev->real_num_rx_queues = rxqs; dev->real_num_rx_queues = rxqs;
if (netif_alloc_rx_queues(dev)) if (netif_alloc_rx_queues(dev))
...@@ -6385,7 +6385,7 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name, ...@@ -6385,7 +6385,7 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
free_pcpu: free_pcpu:
free_percpu(dev->pcpu_refcnt); free_percpu(dev->pcpu_refcnt);
netif_free_tx_queues(dev); netif_free_tx_queues(dev);
#ifdef CONFIG_RPS #ifdef CONFIG_SYSFS
kfree(dev->_rx); kfree(dev->_rx);
#endif #endif
...@@ -6410,7 +6410,7 @@ void free_netdev(struct net_device *dev) ...@@ -6410,7 +6410,7 @@ void free_netdev(struct net_device *dev)
release_net(dev_net(dev)); release_net(dev_net(dev));
netif_free_tx_queues(dev); netif_free_tx_queues(dev);
#ifdef CONFIG_RPS #ifdef CONFIG_SYSFS
kfree(dev->_rx); kfree(dev->_rx);
#endif #endif
......
...@@ -498,17 +498,7 @@ static struct attribute_group wireless_group = { ...@@ -498,17 +498,7 @@ static struct attribute_group wireless_group = {
#define net_class_groups NULL #define net_class_groups NULL
#endif /* CONFIG_SYSFS */ #endif /* CONFIG_SYSFS */
#ifdef CONFIG_RPS #ifdef CONFIG_SYSFS
/*
* RX queue sysfs structures and functions.
*/
struct rx_queue_attribute {
struct attribute attr;
ssize_t (*show)(struct netdev_rx_queue *queue,
struct rx_queue_attribute *attr, char *buf);
ssize_t (*store)(struct netdev_rx_queue *queue,
struct rx_queue_attribute *attr, const char *buf, size_t len);
};
#define to_rx_queue_attr(_attr) container_of(_attr, \ #define to_rx_queue_attr(_attr) container_of(_attr, \
struct rx_queue_attribute, attr) struct rx_queue_attribute, attr)
...@@ -543,6 +533,7 @@ static const struct sysfs_ops rx_queue_sysfs_ops = { ...@@ -543,6 +533,7 @@ static const struct sysfs_ops rx_queue_sysfs_ops = {
.store = rx_queue_attr_store, .store = rx_queue_attr_store,
}; };
#ifdef CONFIG_RPS
static ssize_t show_rps_map(struct netdev_rx_queue *queue, static ssize_t show_rps_map(struct netdev_rx_queue *queue,
struct rx_queue_attribute *attribute, char *buf) struct rx_queue_attribute *attribute, char *buf)
{ {
...@@ -718,16 +709,20 @@ static struct rx_queue_attribute rps_cpus_attribute = ...@@ -718,16 +709,20 @@ static struct rx_queue_attribute rps_cpus_attribute =
static struct rx_queue_attribute rps_dev_flow_table_cnt_attribute = static struct rx_queue_attribute rps_dev_flow_table_cnt_attribute =
__ATTR(rps_flow_cnt, S_IRUGO | S_IWUSR, __ATTR(rps_flow_cnt, S_IRUGO | S_IWUSR,
show_rps_dev_flow_table_cnt, store_rps_dev_flow_table_cnt); show_rps_dev_flow_table_cnt, store_rps_dev_flow_table_cnt);
#endif /* CONFIG_RPS */
static struct attribute *rx_queue_default_attrs[] = { static struct attribute *rx_queue_default_attrs[] = {
#ifdef CONFIG_RPS
&rps_cpus_attribute.attr, &rps_cpus_attribute.attr,
&rps_dev_flow_table_cnt_attribute.attr, &rps_dev_flow_table_cnt_attribute.attr,
#endif
NULL NULL
}; };
static void rx_queue_release(struct kobject *kobj) static void rx_queue_release(struct kobject *kobj)
{ {
struct netdev_rx_queue *queue = to_rx_queue(kobj); struct netdev_rx_queue *queue = to_rx_queue(kobj);
#ifdef CONFIG_RPS
struct rps_map *map; struct rps_map *map;
struct rps_dev_flow_table *flow_table; struct rps_dev_flow_table *flow_table;
...@@ -743,6 +738,7 @@ static void rx_queue_release(struct kobject *kobj) ...@@ -743,6 +738,7 @@ static void rx_queue_release(struct kobject *kobj)
RCU_INIT_POINTER(queue->rps_flow_table, NULL); RCU_INIT_POINTER(queue->rps_flow_table, NULL);
call_rcu(&flow_table->rcu, rps_dev_flow_table_release); call_rcu(&flow_table->rcu, rps_dev_flow_table_release);
} }
#endif
memset(kobj, 0, sizeof(*kobj)); memset(kobj, 0, sizeof(*kobj));
dev_put(queue->dev); dev_put(queue->dev);
...@@ -763,25 +759,36 @@ static int rx_queue_add_kobject(struct net_device *net, int index) ...@@ -763,25 +759,36 @@ static int rx_queue_add_kobject(struct net_device *net, int index)
kobj->kset = net->queues_kset; kobj->kset = net->queues_kset;
error = kobject_init_and_add(kobj, &rx_queue_ktype, NULL, error = kobject_init_and_add(kobj, &rx_queue_ktype, NULL,
"rx-%u", index); "rx-%u", index);
if (error) { if (error)
kobject_put(kobj); goto exit;
return error;
if (net->sysfs_rx_queue_group) {
error = sysfs_create_group(kobj, net->sysfs_rx_queue_group);
if (error)
goto exit;
} }
kobject_uevent(kobj, KOBJ_ADD); kobject_uevent(kobj, KOBJ_ADD);
dev_hold(queue->dev); dev_hold(queue->dev);
return error;
exit:
kobject_put(kobj);
return error; return error;
} }
#endif /* CONFIG_RPS */ #endif /* CONFIG_SYFS */
int int
net_rx_queue_update_kobjects(struct net_device *net, int old_num, int new_num) net_rx_queue_update_kobjects(struct net_device *net, int old_num, int new_num)
{ {
#ifdef CONFIG_RPS #ifdef CONFIG_SYSFS
int i; int i;
int error = 0; int error = 0;
#ifndef CONFIG_RPS
if (!net->sysfs_rx_queue_group)
return 0;
#endif
for (i = old_num; i < new_num; i++) { for (i = old_num; i < new_num; i++) {
error = rx_queue_add_kobject(net, i); error = rx_queue_add_kobject(net, i);
if (error) { if (error) {
...@@ -790,8 +797,12 @@ net_rx_queue_update_kobjects(struct net_device *net, int old_num, int new_num) ...@@ -790,8 +797,12 @@ net_rx_queue_update_kobjects(struct net_device *net, int old_num, int new_num)
} }
} }
while (--i >= new_num) while (--i >= new_num) {
if (net->sysfs_rx_queue_group)
sysfs_remove_group(&net->_rx[i].kobj,
net->sysfs_rx_queue_group);
kobject_put(&net->_rx[i].kobj); kobject_put(&net->_rx[i].kobj);
}
return error; return error;
#else #else
...@@ -1155,9 +1166,6 @@ static int register_queue_kobjects(struct net_device *net) ...@@ -1155,9 +1166,6 @@ static int register_queue_kobjects(struct net_device *net)
NULL, &net->dev.kobj); NULL, &net->dev.kobj);
if (!net->queues_kset) if (!net->queues_kset)
return -ENOMEM; return -ENOMEM;
#endif
#ifdef CONFIG_RPS
real_rx = net->real_num_rx_queues; real_rx = net->real_num_rx_queues;
#endif #endif
real_tx = net->real_num_tx_queues; real_tx = net->real_num_tx_queues;
...@@ -1184,7 +1192,7 @@ static void remove_queue_kobjects(struct net_device *net) ...@@ -1184,7 +1192,7 @@ static void remove_queue_kobjects(struct net_device *net)
{ {
int real_rx = 0, real_tx = 0; int real_rx = 0, real_tx = 0;
#ifdef CONFIG_RPS #ifdef CONFIG_SYSFS
real_rx = net->real_num_rx_queues; real_rx = net->real_num_rx_queues;
#endif #endif
real_tx = net->real_num_tx_queues; real_tx = net->real_num_tx_queues;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment