aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/net-sysfs.c
diff options
context:
space:
mode:
authorTom Herbert <therbert@google.com>2011-11-28 11:33:09 -0500
committerDavid S. Miller <davem@davemloft.net>2011-11-29 12:46:19 -0500
commit114cf5802165ee93e3ab461c9c505cd94a08b800 (patch)
tree88208dddd7c1e90f5e1a840ad0ad7afcea991050 /net/core/net-sysfs.c
parent927fbec13e40648d3c87cbb1daaac5b1fb9c8775 (diff)
bql: Byte queue limits
Networking stack support for byte queue limits, uses dynamic queue limits library. Byte queue limits are maintained per transmit queue, and a dql structure has been added to netdev_queue structure for this purpose. Configuration of bql is in the tx-<n> sysfs directory for the queue under the byte_queue_limits directory. Configuration includes: limit_min, bql minimum limit limit_max, bql maximum limit hold_time, bql slack hold time Also under the directory are: limit, current byte limit inflight, current number of bytes on the queue Signed-off-by: Tom Herbert <therbert@google.com> Acked-by: Eric Dumazet <eric.dumazet@gmail.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.c140
1 files changed, 132 insertions, 8 deletions
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index b17c14a0fce9..3bf72b638d34 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -21,6 +21,7 @@
21#include <linux/wireless.h> 21#include <linux/wireless.h>
22#include <linux/vmalloc.h> 22#include <linux/vmalloc.h>
23#include <linux/export.h> 23#include <linux/export.h>
24#include <linux/jiffies.h>
24#include <net/wext.h> 25#include <net/wext.h>
25 26
26#include "net-sysfs.h" 27#include "net-sysfs.h"
@@ -845,6 +846,116 @@ static ssize_t show_trans_timeout(struct netdev_queue *queue,
845static struct netdev_queue_attribute queue_trans_timeout = 846static struct netdev_queue_attribute queue_trans_timeout =
846 __ATTR(tx_timeout, S_IRUGO, show_trans_timeout, NULL); 847 __ATTR(tx_timeout, S_IRUGO, show_trans_timeout, NULL);
847 848
849#ifdef CONFIG_BQL
850/*
851 * Byte queue limits sysfs structures and functions.
852 */
853static ssize_t bql_show(char *buf, unsigned int value)
854{
855 return sprintf(buf, "%u\n", value);
856}
857
858static ssize_t bql_set(const char *buf, const size_t count,
859 unsigned int *pvalue)
860{
861 unsigned int value;
862 int err;
863
864 if (!strcmp(buf, "max") || !strcmp(buf, "max\n"))
865 value = DQL_MAX_LIMIT;
866 else {
867 err = kstrtouint(buf, 10, &value);
868 if (err < 0)
869 return err;
870 if (value > DQL_MAX_LIMIT)
871 return -EINVAL;
872 }
873
874 *pvalue = value;
875
876 return count;
877}
878
879static ssize_t bql_show_hold_time(struct netdev_queue *queue,
880 struct netdev_queue_attribute *attr,
881 char *buf)
882{
883 struct dql *dql = &queue->dql;
884
885 return sprintf(buf, "%u\n", jiffies_to_msecs(dql->slack_hold_time));
886}
887
888static ssize_t bql_set_hold_time(struct netdev_queue *queue,
889 struct netdev_queue_attribute *attribute,
890 const char *buf, size_t len)
891{
892 struct dql *dql = &queue->dql;
893 unsigned value;
894 int err;
895
896 err = kstrtouint(buf, 10, &value);
897 if (err < 0)
898 return err;
899
900 dql->slack_hold_time = msecs_to_jiffies(value);
901
902 return len;
903}
904
905static struct netdev_queue_attribute bql_hold_time_attribute =
906 __ATTR(hold_time, S_IRUGO | S_IWUSR, bql_show_hold_time,
907 bql_set_hold_time);
908
909static ssize_t bql_show_inflight(struct netdev_queue *queue,
910 struct netdev_queue_attribute *attr,
911 char *buf)
912{
913 struct dql *dql = &queue->dql;
914
915 return sprintf(buf, "%u\n", dql->num_queued - dql->num_completed);
916}
917
918static struct netdev_queue_attribute bql_inflight_attribute =
919 __ATTR(inflight, S_IRUGO | S_IWUSR, bql_show_inflight, NULL);
920
921#define BQL_ATTR(NAME, FIELD) \
922static ssize_t bql_show_ ## NAME(struct netdev_queue *queue, \
923 struct netdev_queue_attribute *attr, \
924 char *buf) \
925{ \
926 return bql_show(buf, queue->dql.FIELD); \
927} \
928 \
929static ssize_t bql_set_ ## NAME(struct netdev_queue *queue, \
930 struct netdev_queue_attribute *attr, \
931 const char *buf, size_t len) \
932{ \
933 return bql_set(buf, len, &queue->dql.FIELD); \
934} \
935 \
936static struct netdev_queue_attribute bql_ ## NAME ## _attribute = \
937 __ATTR(NAME, S_IRUGO | S_IWUSR, bql_show_ ## NAME, \
938 bql_set_ ## NAME);
939
940BQL_ATTR(limit, limit)
941BQL_ATTR(limit_max, max_limit)
942BQL_ATTR(limit_min, min_limit)
943
944static struct attribute *dql_attrs[] = {
945 &bql_limit_attribute.attr,
946 &bql_limit_max_attribute.attr,
947 &bql_limit_min_attribute.attr,
948 &bql_hold_time_attribute.attr,
949 &bql_inflight_attribute.attr,
950 NULL
951};
952
953static struct attribute_group dql_group = {
954 .name = "byte_queue_limits",
955 .attrs = dql_attrs,
956};
957#endif /* CONFIG_BQL */
958
848#ifdef CONFIG_XPS 959#ifdef CONFIG_XPS
849static inline unsigned int get_netdev_queue_index(struct netdev_queue *queue) 960static inline unsigned int get_netdev_queue_index(struct netdev_queue *queue)
850{ 961{
@@ -1096,17 +1207,17 @@ static struct attribute *netdev_queue_default_attrs[] = {
1096 NULL 1207 NULL
1097}; 1208};
1098 1209
1099#ifdef CONFIG_XPS
1100static void netdev_queue_release(struct kobject *kobj) 1210static void netdev_queue_release(struct kobject *kobj)
1101{ 1211{
1102 struct netdev_queue *queue = to_netdev_queue(kobj); 1212 struct netdev_queue *queue = to_netdev_queue(kobj);
1103 1213
1214#ifdef CONFIG_XPS
1104 xps_queue_release(queue); 1215 xps_queue_release(queue);
1216#endif
1105 1217
1106 memset(kobj, 0, sizeof(*kobj)); 1218 memset(kobj, 0, sizeof(*kobj));
1107 dev_put(queue->dev); 1219 dev_put(queue->dev);
1108} 1220}
1109#endif /* CONFIG_XPS */
1110 1221
1111static struct kobj_type netdev_queue_ktype = { 1222static struct kobj_type netdev_queue_ktype = {
1112 .sysfs_ops = &netdev_queue_sysfs_ops, 1223 .sysfs_ops = &netdev_queue_sysfs_ops,
@@ -1125,14 +1236,21 @@ static int netdev_queue_add_kobject(struct net_device *net, int index)
1125 kobj->kset = net->queues_kset; 1236 kobj->kset = net->queues_kset;
1126 error = kobject_init_and_add(kobj, &netdev_queue_ktype, NULL, 1237 error = kobject_init_and_add(kobj, &netdev_queue_ktype, NULL,
1127 "tx-%u", index); 1238 "tx-%u", index);
1128 if (error) { 1239 if (error)
1129 kobject_put(kobj); 1240 goto exit;
1130 return error; 1241
1131 } 1242#ifdef CONFIG_BQL
1243 error = sysfs_create_group(kobj, &dql_group);
1244 if (error)
1245 goto exit;
1246#endif
1132 1247
1133 kobject_uevent(kobj, KOBJ_ADD); 1248 kobject_uevent(kobj, KOBJ_ADD);
1134 dev_hold(queue->dev); 1249 dev_hold(queue->dev);
1135 1250
1251 return 0;
1252exit:
1253 kobject_put(kobj);
1136 return error; 1254 return error;
1137} 1255}
1138#endif /* CONFIG_SYSFS */ 1256#endif /* CONFIG_SYSFS */
@@ -1152,8 +1270,14 @@ netdev_queue_update_kobjects(struct net_device *net, int old_num, int new_num)
1152 } 1270 }
1153 } 1271 }
1154 1272
1155 while (--i >= new_num) 1273 while (--i >= new_num) {
1156 kobject_put(&net->_tx[i].kobj); 1274 struct netdev_queue *queue = net->_tx + i;
1275
1276#ifdef CONFIG_BQL
1277 sysfs_remove_group(&queue->kobj, &dql_group);
1278#endif
1279 kobject_put(&queue->kobj);
1280 }
1157 1281
1158 return error; 1282 return error;
1159#else 1283#else