aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/net-sysfs.c
diff options
context:
space:
mode:
authorAmritha Nambiar <amritha.nambiar@intel.com>2018-06-30 00:27:07 -0400
committerDavid S. Miller <davem@davemloft.net>2018-07-01 20:06:24 -0400
commit8af2c06ff4b144064b51b7f688194474123d9c9c (patch)
tree34329bd3aad1391e24ff9a4555894e289bdf2a3c /net/core/net-sysfs.c
parentfc9bab24e9c654f62f3d411fc0b041be9e487e9d (diff)
net-sysfs: Add interface for Rx queue(s) map per Tx queue
Extend transmit queue sysfs attribute to configure Rx queue(s) map per Tx queue. By default no receive queues are configured for the Tx queue. - /sys/class/net/eth0/queues/tx-*/xps_rxqs Signed-off-by: Amritha Nambiar <amritha.nambiar@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core/net-sysfs.c')
-rw-r--r--net/core/net-sysfs.c83
1 files changed, 83 insertions, 0 deletions
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index b39987c81d53..f25ac5ff48a6 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -1283,6 +1283,88 @@ static ssize_t xps_cpus_store(struct netdev_queue *queue,
1283 1283
1284static struct netdev_queue_attribute xps_cpus_attribute __ro_after_init 1284static struct netdev_queue_attribute xps_cpus_attribute __ro_after_init
1285 = __ATTR_RW(xps_cpus); 1285 = __ATTR_RW(xps_cpus);
1286
1287static ssize_t xps_rxqs_show(struct netdev_queue *queue, char *buf)
1288{
1289 struct net_device *dev = queue->dev;
1290 struct xps_dev_maps *dev_maps;
1291 unsigned long *mask, index;
1292 int j, len, num_tc = 1, tc = 0;
1293
1294 index = get_netdev_queue_index(queue);
1295
1296 if (dev->num_tc) {
1297 num_tc = dev->num_tc;
1298 tc = netdev_txq_to_tc(dev, index);
1299 if (tc < 0)
1300 return -EINVAL;
1301 }
1302 mask = kcalloc(BITS_TO_LONGS(dev->num_rx_queues), sizeof(long),
1303 GFP_KERNEL);
1304 if (!mask)
1305 return -ENOMEM;
1306
1307 rcu_read_lock();
1308 dev_maps = rcu_dereference(dev->xps_rxqs_map);
1309 if (!dev_maps)
1310 goto out_no_maps;
1311
1312 for (j = -1; j = netif_attrmask_next(j, NULL, dev->num_rx_queues),
1313 j < dev->num_rx_queues;) {
1314 int i, tci = j * num_tc + tc;
1315 struct xps_map *map;
1316
1317 map = rcu_dereference(dev_maps->attr_map[tci]);
1318 if (!map)
1319 continue;
1320
1321 for (i = map->len; i--;) {
1322 if (map->queues[i] == index) {
1323 set_bit(j, mask);
1324 break;
1325 }
1326 }
1327 }
1328out_no_maps:
1329 rcu_read_unlock();
1330
1331 len = bitmap_print_to_pagebuf(false, buf, mask, dev->num_rx_queues);
1332 kfree(mask);
1333
1334 return len < PAGE_SIZE ? len : -EINVAL;
1335}
1336
1337static ssize_t xps_rxqs_store(struct netdev_queue *queue, const char *buf,
1338 size_t len)
1339{
1340 struct net_device *dev = queue->dev;
1341 struct net *net = dev_net(dev);
1342 unsigned long *mask, index;
1343 int err;
1344
1345 if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
1346 return -EPERM;
1347
1348 mask = kcalloc(BITS_TO_LONGS(dev->num_rx_queues), sizeof(long),
1349 GFP_KERNEL);
1350 if (!mask)
1351 return -ENOMEM;
1352
1353 index = get_netdev_queue_index(queue);
1354
1355 err = bitmap_parse(buf, len, mask, dev->num_rx_queues);
1356 if (err) {
1357 kfree(mask);
1358 return err;
1359 }
1360
1361 err = __netif_set_xps_queue(dev, mask, index, true);
1362 kfree(mask);
1363 return err ? : len;
1364}
1365
1366static struct netdev_queue_attribute xps_rxqs_attribute __ro_after_init
1367 = __ATTR_RW(xps_rxqs);
1286#endif /* CONFIG_XPS */ 1368#endif /* CONFIG_XPS */
1287 1369
1288static struct attribute *netdev_queue_default_attrs[] __ro_after_init = { 1370static struct attribute *netdev_queue_default_attrs[] __ro_after_init = {
@@ -1290,6 +1372,7 @@ static struct attribute *netdev_queue_default_attrs[] __ro_after_init = {
1290 &queue_traffic_class.attr, 1372 &queue_traffic_class.attr,
1291#ifdef CONFIG_XPS 1373#ifdef CONFIG_XPS
1292 &xps_cpus_attribute.attr, 1374 &xps_cpus_attribute.attr,
1375 &xps_rxqs_attribute.attr,
1293 &queue_tx_maxrate.attr, 1376 &queue_tx_maxrate.attr,
1294#endif 1377#endif
1295 NULL 1378 NULL