diff options
author | Tom Herbert <therbert@google.com> | 2011-11-28 11:33:09 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-11-29 12:46:19 -0500 |
commit | 114cf5802165ee93e3ab461c9c505cd94a08b800 (patch) | |
tree | 88208dddd7c1e90f5e1a840ad0ad7afcea991050 /net/core/net-sysfs.c | |
parent | 927fbec13e40648d3c87cbb1daaac5b1fb9c8775 (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.c | 140 |
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, | |||
845 | static struct netdev_queue_attribute queue_trans_timeout = | 846 | static 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 | */ | ||
853 | static ssize_t bql_show(char *buf, unsigned int value) | ||
854 | { | ||
855 | return sprintf(buf, "%u\n", value); | ||
856 | } | ||
857 | |||
858 | static 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 | |||
879 | static 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 | |||
888 | static 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 | |||
905 | static 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 | |||
909 | static 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 | |||
918 | static 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) \ | ||
922 | static 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 | \ | ||
929 | static 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 | \ | ||
936 | static struct netdev_queue_attribute bql_ ## NAME ## _attribute = \ | ||
937 | __ATTR(NAME, S_IRUGO | S_IWUSR, bql_show_ ## NAME, \ | ||
938 | bql_set_ ## NAME); | ||
939 | |||
940 | BQL_ATTR(limit, limit) | ||
941 | BQL_ATTR(limit_max, max_limit) | ||
942 | BQL_ATTR(limit_min, min_limit) | ||
943 | |||
944 | static 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 | |||
953 | static 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 |
849 | static inline unsigned int get_netdev_queue_index(struct netdev_queue *queue) | 960 | static 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 | ||
1100 | static void netdev_queue_release(struct kobject *kobj) | 1210 | static 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 | ||
1111 | static struct kobj_type netdev_queue_ktype = { | 1222 | static 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; | ||
1252 | exit: | ||
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 |