aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/netdevice.h52
-rw-r--r--net/Kconfig5
-rw-r--r--net/core/dev.c9
-rw-r--r--net/core/net-sysfs.c47
-rw-r--r--net/core/net-sysfs.h3
5 files changed, 73 insertions, 43 deletions
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 7c6ae2f4b9ab..9ae4544f0cf0 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -536,30 +536,6 @@ struct rps_map {
536#define RPS_MAP_SIZE(_num) (sizeof(struct rps_map) + (_num * sizeof(u16))) 536#define RPS_MAP_SIZE(_num) (sizeof(struct rps_map) + (_num * sizeof(u16)))
537 537
538/* 538/*
539 * This structure holds an XPS map which can be of variable length. The
540 * map is an array of queues.
541 */
542struct xps_map {
543 unsigned int len;
544 unsigned int alloc_len;
545 struct rcu_head rcu;
546 u16 queues[0];
547};
548#define XPS_MAP_SIZE(_num) (sizeof(struct xps_map) + (_num * sizeof(u16)))
549#define XPS_MIN_MAP_ALLOC ((L1_CACHE_BYTES - sizeof(struct xps_map)) \
550 / sizeof(u16))
551
552/*
553 * This structure holds all XPS maps for device. Maps are indexed by CPU.
554 */
555struct xps_dev_maps {
556 struct rcu_head rcu;
557 struct xps_map *cpu_map[0];
558};
559#define XPS_DEV_MAPS_SIZE (sizeof(struct xps_dev_maps) + \
560 (nr_cpu_ids * sizeof(struct xps_map *)))
561
562/*
563 * The rps_dev_flow structure contains the mapping of a flow to a CPU and the 539 * The rps_dev_flow structure contains the mapping of a flow to a CPU and the
564 * tail pointer for that CPU's input queue at the time of last enqueue. 540 * tail pointer for that CPU's input queue at the time of last enqueue.
565 */ 541 */
@@ -626,6 +602,32 @@ struct netdev_rx_queue {
626} ____cacheline_aligned_in_smp; 602} ____cacheline_aligned_in_smp;
627#endif /* CONFIG_RPS */ 603#endif /* CONFIG_RPS */
628 604
605#ifdef CONFIG_XPS
606/*
607 * This structure holds an XPS map which can be of variable length. The
608 * map is an array of queues.
609 */
610struct xps_map {
611 unsigned int len;
612 unsigned int alloc_len;
613 struct rcu_head rcu;
614 u16 queues[0];
615};
616#define XPS_MAP_SIZE(_num) (sizeof(struct xps_map) + (_num * sizeof(u16)))
617#define XPS_MIN_MAP_ALLOC ((L1_CACHE_BYTES - sizeof(struct xps_map)) \
618 / sizeof(u16))
619
620/*
621 * This structure holds all XPS maps for device. Maps are indexed by CPU.
622 */
623struct xps_dev_maps {
624 struct rcu_head rcu;
625 struct xps_map *cpu_map[0];
626};
627#define XPS_DEV_MAPS_SIZE (sizeof(struct xps_dev_maps) + \
628 (nr_cpu_ids * sizeof(struct xps_map *)))
629#endif /* CONFIG_XPS */
630
629/* 631/*
630 * This structure defines the management hooks for network devices. 632 * This structure defines the management hooks for network devices.
631 * The following hooks can be defined; unless noted otherwise, they are 633 * The following hooks can be defined; unless noted otherwise, they are
@@ -1046,7 +1048,9 @@ struct net_device {
1046 unsigned long tx_queue_len; /* Max frames per queue allowed */ 1048 unsigned long tx_queue_len; /* Max frames per queue allowed */
1047 spinlock_t tx_global_lock; 1049 spinlock_t tx_global_lock;
1048 1050
1051#ifdef CONFIG_XPS
1049 struct xps_dev_maps *xps_maps; 1052 struct xps_dev_maps *xps_maps;
1053#endif
1050 1054
1051 /* These may be needed for future network-power-down code. */ 1055 /* These may be needed for future network-power-down code. */
1052 1056
diff --git a/net/Kconfig b/net/Kconfig
index 55fd82e9ffd9..126c2af0fc1f 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -220,6 +220,11 @@ config RPS
220 depends on SMP && SYSFS && USE_GENERIC_SMP_HELPERS 220 depends on SMP && SYSFS && USE_GENERIC_SMP_HELPERS
221 default y 221 default y
222 222
223config XPS
224 boolean
225 depends on SMP && SYSFS && USE_GENERIC_SMP_HELPERS
226 default y
227
223menu "Network testing" 228menu "Network testing"
224 229
225config NET_PKTGEN 230config NET_PKTGEN
diff --git a/net/core/dev.c b/net/core/dev.c
index c852f0038a08..3259d2c323a6 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1567,6 +1567,9 @@ int netif_set_real_num_tx_queues(struct net_device *dev, unsigned int txq)
1567 1567
1568 rc = netdev_queue_update_kobjects(dev, dev->real_num_tx_queues, 1568 rc = netdev_queue_update_kobjects(dev, dev->real_num_tx_queues,
1569 txq); 1569 txq);
1570 if (rc)
1571 return rc;
1572
1570 if (txq < dev->real_num_tx_queues) 1573 if (txq < dev->real_num_tx_queues)
1571 qdisc_reset_all_tx_gt(dev, txq); 1574 qdisc_reset_all_tx_gt(dev, txq);
1572 } 1575 }
@@ -2148,7 +2151,7 @@ static inline u16 dev_cap_txqueue(struct net_device *dev, u16 queue_index)
2148 2151
2149static inline int get_xps_queue(struct net_device *dev, struct sk_buff *skb) 2152static inline int get_xps_queue(struct net_device *dev, struct sk_buff *skb)
2150{ 2153{
2151#ifdef CONFIG_RPS 2154#ifdef CONFIG_XPS
2152 struct xps_dev_maps *dev_maps; 2155 struct xps_dev_maps *dev_maps;
2153 struct xps_map *map; 2156 struct xps_map *map;
2154 int queue_index = -1; 2157 int queue_index = -1;
@@ -5085,9 +5088,9 @@ void netif_stacked_transfer_operstate(const struct net_device *rootdev,
5085} 5088}
5086EXPORT_SYMBOL(netif_stacked_transfer_operstate); 5089EXPORT_SYMBOL(netif_stacked_transfer_operstate);
5087 5090
5091#ifdef CONFIG_RPS
5088static int netif_alloc_rx_queues(struct net_device *dev) 5092static int netif_alloc_rx_queues(struct net_device *dev)
5089{ 5093{
5090#ifdef CONFIG_RPS
5091 unsigned int i, count = dev->num_rx_queues; 5094 unsigned int i, count = dev->num_rx_queues;
5092 struct netdev_rx_queue *rx; 5095 struct netdev_rx_queue *rx;
5093 5096
@@ -5102,9 +5105,9 @@ static int netif_alloc_rx_queues(struct net_device *dev)
5102 5105
5103 for (i = 0; i < count; i++) 5106 for (i = 0; i < count; i++)
5104 rx[i].dev = dev; 5107 rx[i].dev = dev;
5105#endif
5106 return 0; 5108 return 0;
5107} 5109}
5110#endif
5108 5111
5109static int netif_alloc_netdev_queues(struct net_device *dev) 5112static int netif_alloc_netdev_queues(struct net_device *dev)
5110{ 5113{
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index 68dbbfdee274..99c11294623f 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -751,10 +751,12 @@ static int rx_queue_add_kobject(struct net_device *net, int index)
751 751
752 return error; 752 return error;
753} 753}
754#endif /* CONFIG_RPS */
754 755
755int 756int
756net_rx_queue_update_kobjects(struct net_device *net, int old_num, int new_num) 757net_rx_queue_update_kobjects(struct net_device *net, int old_num, int new_num)
757{ 758{
759#ifdef CONFIG_RPS
758 int i; 760 int i;
759 int error = 0; 761 int error = 0;
760 762
@@ -770,8 +772,12 @@ net_rx_queue_update_kobjects(struct net_device *net, int old_num, int new_num)
770 kobject_put(&net->_rx[i].kobj); 772 kobject_put(&net->_rx[i].kobj);
771 773
772 return error; 774 return error;
775#else
776 return 0;
777#endif
773} 778}
774 779
780#ifdef CONFIG_XPS
775/* 781/*
776 * netdev_queue sysfs structures and functions. 782 * netdev_queue sysfs structures and functions.
777 */ 783 */
@@ -1090,10 +1096,12 @@ static int netdev_queue_add_kobject(struct net_device *net, int index)
1090 1096
1091 return error; 1097 return error;
1092} 1098}
1099#endif /* CONFIG_XPS */
1093 1100
1094int 1101int
1095netdev_queue_update_kobjects(struct net_device *net, int old_num, int new_num) 1102netdev_queue_update_kobjects(struct net_device *net, int old_num, int new_num)
1096{ 1103{
1104#ifdef CONFIG_XPS
1097 int i; 1105 int i;
1098 int error = 0; 1106 int error = 0;
1099 1107
@@ -1109,27 +1117,36 @@ netdev_queue_update_kobjects(struct net_device *net, int old_num, int new_num)
1109 kobject_put(&net->_tx[i].kobj); 1117 kobject_put(&net->_tx[i].kobj);
1110 1118
1111 return error; 1119 return error;
1120#else
1121 return 0;
1122#endif
1112} 1123}
1113 1124
1114static int register_queue_kobjects(struct net_device *net) 1125static int register_queue_kobjects(struct net_device *net)
1115{ 1126{
1116 int error = 0, txq = 0, rxq = 0; 1127 int error = 0, txq = 0, rxq = 0, real_rx = 0, real_tx = 0;
1117 1128
1129#if defined(CONFIG_RPS) || defined(CONFIG_XPS)
1118 net->queues_kset = kset_create_and_add("queues", 1130 net->queues_kset = kset_create_and_add("queues",
1119 NULL, &net->dev.kobj); 1131 NULL, &net->dev.kobj);
1120 if (!net->queues_kset) 1132 if (!net->queues_kset)
1121 return -ENOMEM; 1133 return -ENOMEM;
1134#endif
1135
1136#ifdef CONFIG_RPS
1137 real_rx = net->real_num_rx_queues;
1138#endif
1139 real_tx = net->real_num_tx_queues;
1122 1140
1123 error = net_rx_queue_update_kobjects(net, 0, net->real_num_rx_queues); 1141 error = net_rx_queue_update_kobjects(net, 0, real_rx);
1124 if (error) 1142 if (error)
1125 goto error; 1143 goto error;
1126 rxq = net->real_num_rx_queues; 1144 rxq = real_rx;
1127 1145
1128 error = netdev_queue_update_kobjects(net, 0, 1146 error = netdev_queue_update_kobjects(net, 0, real_tx);
1129 net->real_num_tx_queues);
1130 if (error) 1147 if (error)
1131 goto error; 1148 goto error;
1132 txq = net->real_num_tx_queues; 1149 txq = real_tx;
1133 1150
1134 return 0; 1151 return 0;
1135 1152
@@ -1141,11 +1158,19 @@ error:
1141 1158
1142static void remove_queue_kobjects(struct net_device *net) 1159static void remove_queue_kobjects(struct net_device *net)
1143{ 1160{
1144 net_rx_queue_update_kobjects(net, net->real_num_rx_queues, 0); 1161 int real_rx = 0, real_tx = 0;
1145 netdev_queue_update_kobjects(net, net->real_num_tx_queues, 0); 1162
1163#ifdef CONFIG_RPS
1164 real_rx = net->real_num_rx_queues;
1165#endif
1166 real_tx = net->real_num_tx_queues;
1167
1168 net_rx_queue_update_kobjects(net, real_rx, 0);
1169 netdev_queue_update_kobjects(net, real_tx, 0);
1170#if defined(CONFIG_RPS) || defined(CONFIG_XPS)
1146 kset_unregister(net->queues_kset); 1171 kset_unregister(net->queues_kset);
1172#endif
1147} 1173}
1148#endif /* CONFIG_RPS */
1149 1174
1150static const void *net_current_ns(void) 1175static const void *net_current_ns(void)
1151{ 1176{
@@ -1244,9 +1269,7 @@ void netdev_unregister_kobject(struct net_device * net)
1244 1269
1245 kobject_get(&dev->kobj); 1270 kobject_get(&dev->kobj);
1246 1271
1247#ifdef CONFIG_RPS
1248 remove_queue_kobjects(net); 1272 remove_queue_kobjects(net);
1249#endif
1250 1273
1251 device_del(dev); 1274 device_del(dev);
1252} 1275}
@@ -1285,13 +1308,11 @@ int netdev_register_kobject(struct net_device *net)
1285 if (error) 1308 if (error)
1286 return error; 1309 return error;
1287 1310
1288#ifdef CONFIG_RPS
1289 error = register_queue_kobjects(net); 1311 error = register_queue_kobjects(net);
1290 if (error) { 1312 if (error) {
1291 device_del(dev); 1313 device_del(dev);
1292 return error; 1314 return error;
1293 } 1315 }
1294#endif
1295 1316
1296 return error; 1317 return error;
1297} 1318}
diff --git a/net/core/net-sysfs.h b/net/core/net-sysfs.h
index 25ec2ee57df7..bd7751ec1c4d 100644
--- a/net/core/net-sysfs.h
+++ b/net/core/net-sysfs.h
@@ -4,11 +4,8 @@
4int netdev_kobject_init(void); 4int netdev_kobject_init(void);
5int netdev_register_kobject(struct net_device *); 5int netdev_register_kobject(struct net_device *);
6void netdev_unregister_kobject(struct net_device *); 6void netdev_unregister_kobject(struct net_device *);
7#ifdef CONFIG_RPS
8int net_rx_queue_update_kobjects(struct net_device *, int old_num, int new_num); 7int net_rx_queue_update_kobjects(struct net_device *, int old_num, int new_num);
9int netdev_queue_update_kobjects(struct net_device *net, 8int netdev_queue_update_kobjects(struct net_device *net,
10 int old_num, int new_num); 9 int old_num, int new_num);
11 10
12#endif 11#endif
13
14#endif