diff options
author | david decotigny <david.decotigny@google.com> | 2011-11-16 07:15:10 -0500 |
---|---|---|
committer | Christopher Kenna <cjk@cs.unc.edu> | 2012-09-29 13:32:06 -0400 |
commit | 611926edc62a15f77b891658ac70cb66e7a638f2 (patch) | |
tree | c3753e114e0073b8231cb657a0ee080678b4ca3c /net | |
parent | 4241502af7a01ec64a5cae23c46bde5458b01b67 (diff) |
net: new counter for tx_timeout errors in sysfs
This adds the /sys/class/net/DEV/queues/Q/tx_timeout attribute
containing the total number of timeout events on the given queue. It
is always available with CONFIG_SYSFS, independently of
CONFIG_RPS/XPS.
Credits to Stephen Hemminger for a preliminary version of this patch.
Tested:
without CONFIG_SYSFS (compilation only)
with sysfs and without CONFIG_RPS & CONFIG_XPS
with sysfs and without CONFIG_RPS
with sysfs and without CONFIG_XPS
with defaults
Signed-off-by: David Decotigny <david.decotigny@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Conflicts:
include/linux/netdevice.h
Signed-off-by: Christopher Kenna <cjk@cs.unc.edu>
Diffstat (limited to 'net')
-rw-r--r-- | net/core/net-sysfs.c | 37 | ||||
-rw-r--r-- | net/sched/sch_generic.c | 1 |
2 files changed, 32 insertions, 6 deletions
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index 33d2a1fba13..ec4eae35330 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c | |||
@@ -781,7 +781,7 @@ net_rx_queue_update_kobjects(struct net_device *net, int old_num, int new_num) | |||
781 | #endif | 781 | #endif |
782 | } | 782 | } |
783 | 783 | ||
784 | #ifdef CONFIG_XPS | 784 | #ifdef CONFIG_SYSFS |
785 | /* | 785 | /* |
786 | * netdev_queue sysfs structures and functions. | 786 | * netdev_queue sysfs structures and functions. |
787 | */ | 787 | */ |
@@ -827,6 +827,23 @@ static const struct sysfs_ops netdev_queue_sysfs_ops = { | |||
827 | .store = netdev_queue_attr_store, | 827 | .store = netdev_queue_attr_store, |
828 | }; | 828 | }; |
829 | 829 | ||
830 | static ssize_t show_trans_timeout(struct netdev_queue *queue, | ||
831 | struct netdev_queue_attribute *attribute, | ||
832 | char *buf) | ||
833 | { | ||
834 | unsigned long trans_timeout; | ||
835 | |||
836 | spin_lock_irq(&queue->_xmit_lock); | ||
837 | trans_timeout = queue->trans_timeout; | ||
838 | spin_unlock_irq(&queue->_xmit_lock); | ||
839 | |||
840 | return sprintf(buf, "%lu", trans_timeout); | ||
841 | } | ||
842 | |||
843 | static struct netdev_queue_attribute queue_trans_timeout = | ||
844 | __ATTR(tx_timeout, S_IRUGO, show_trans_timeout, NULL); | ||
845 | |||
846 | #ifdef CONFIG_XPS | ||
830 | static inline unsigned int get_netdev_queue_index(struct netdev_queue *queue) | 847 | static inline unsigned int get_netdev_queue_index(struct netdev_queue *queue) |
831 | { | 848 | { |
832 | struct net_device *dev = queue->dev; | 849 | struct net_device *dev = queue->dev; |
@@ -1021,12 +1038,17 @@ error: | |||
1021 | 1038 | ||
1022 | static struct netdev_queue_attribute xps_cpus_attribute = | 1039 | static struct netdev_queue_attribute xps_cpus_attribute = |
1023 | __ATTR(xps_cpus, S_IRUGO | S_IWUSR, show_xps_map, store_xps_map); | 1040 | __ATTR(xps_cpus, S_IRUGO | S_IWUSR, show_xps_map, store_xps_map); |
1041 | #endif /* CONFIG_XPS */ | ||
1024 | 1042 | ||
1025 | static struct attribute *netdev_queue_default_attrs[] = { | 1043 | static struct attribute *netdev_queue_default_attrs[] = { |
1044 | &queue_trans_timeout.attr, | ||
1045 | #ifdef CONFIG_XPS | ||
1026 | &xps_cpus_attribute.attr, | 1046 | &xps_cpus_attribute.attr, |
1047 | #endif | ||
1027 | NULL | 1048 | NULL |
1028 | }; | 1049 | }; |
1029 | 1050 | ||
1051 | #ifdef CONFIG_XPS | ||
1030 | static void netdev_queue_release(struct kobject *kobj) | 1052 | static void netdev_queue_release(struct kobject *kobj) |
1031 | { | 1053 | { |
1032 | struct netdev_queue *queue = to_netdev_queue(kobj); | 1054 | struct netdev_queue *queue = to_netdev_queue(kobj); |
@@ -1077,10 +1099,13 @@ static void netdev_queue_release(struct kobject *kobj) | |||
1077 | memset(kobj, 0, sizeof(*kobj)); | 1099 | memset(kobj, 0, sizeof(*kobj)); |
1078 | dev_put(queue->dev); | 1100 | dev_put(queue->dev); |
1079 | } | 1101 | } |
1102 | #endif /* CONFIG_XPS */ | ||
1080 | 1103 | ||
1081 | static struct kobj_type netdev_queue_ktype = { | 1104 | static struct kobj_type netdev_queue_ktype = { |
1082 | .sysfs_ops = &netdev_queue_sysfs_ops, | 1105 | .sysfs_ops = &netdev_queue_sysfs_ops, |
1106 | #ifdef CONFIG_XPS | ||
1083 | .release = netdev_queue_release, | 1107 | .release = netdev_queue_release, |
1108 | #endif | ||
1084 | .default_attrs = netdev_queue_default_attrs, | 1109 | .default_attrs = netdev_queue_default_attrs, |
1085 | }; | 1110 | }; |
1086 | 1111 | ||
@@ -1103,12 +1128,12 @@ static int netdev_queue_add_kobject(struct net_device *net, int index) | |||
1103 | 1128 | ||
1104 | return error; | 1129 | return error; |
1105 | } | 1130 | } |
1106 | #endif /* CONFIG_XPS */ | 1131 | #endif /* CONFIG_SYSFS */ |
1107 | 1132 | ||
1108 | int | 1133 | int |
1109 | netdev_queue_update_kobjects(struct net_device *net, int old_num, int new_num) | 1134 | netdev_queue_update_kobjects(struct net_device *net, int old_num, int new_num) |
1110 | { | 1135 | { |
1111 | #ifdef CONFIG_XPS | 1136 | #ifdef CONFIG_SYSFS |
1112 | int i; | 1137 | int i; |
1113 | int error = 0; | 1138 | int error = 0; |
1114 | 1139 | ||
@@ -1126,14 +1151,14 @@ netdev_queue_update_kobjects(struct net_device *net, int old_num, int new_num) | |||
1126 | return error; | 1151 | return error; |
1127 | #else | 1152 | #else |
1128 | return 0; | 1153 | return 0; |
1129 | #endif | 1154 | #endif /* CONFIG_SYSFS */ |
1130 | } | 1155 | } |
1131 | 1156 | ||
1132 | static int register_queue_kobjects(struct net_device *net) | 1157 | static int register_queue_kobjects(struct net_device *net) |
1133 | { | 1158 | { |
1134 | int error = 0, txq = 0, rxq = 0, real_rx = 0, real_tx = 0; | 1159 | int error = 0, txq = 0, rxq = 0, real_rx = 0, real_tx = 0; |
1135 | 1160 | ||
1136 | #if defined(CONFIG_RPS) || defined(CONFIG_XPS) | 1161 | #ifdef CONFIG_SYSFS |
1137 | net->queues_kset = kset_create_and_add("queues", | 1162 | net->queues_kset = kset_create_and_add("queues", |
1138 | NULL, &net->dev.kobj); | 1163 | NULL, &net->dev.kobj); |
1139 | if (!net->queues_kset) | 1164 | if (!net->queues_kset) |
@@ -1174,7 +1199,7 @@ static void remove_queue_kobjects(struct net_device *net) | |||
1174 | 1199 | ||
1175 | net_rx_queue_update_kobjects(net, real_rx, 0); | 1200 | net_rx_queue_update_kobjects(net, real_rx, 0); |
1176 | netdev_queue_update_kobjects(net, real_tx, 0); | 1201 | netdev_queue_update_kobjects(net, real_tx, 0); |
1177 | #if defined(CONFIG_RPS) || defined(CONFIG_XPS) | 1202 | #ifdef CONFIG_SYSFS |
1178 | kset_unregister(net->queues_kset); | 1203 | kset_unregister(net->queues_kset); |
1179 | #endif | 1204 | #endif |
1180 | } | 1205 | } |
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index b4c680900d7..06d8a8fec68 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c | |||
@@ -246,6 +246,7 @@ static void dev_watchdog(unsigned long arg) | |||
246 | time_after(jiffies, (trans_start + | 246 | time_after(jiffies, (trans_start + |
247 | dev->watchdog_timeo))) { | 247 | dev->watchdog_timeo))) { |
248 | some_queue_timedout = 1; | 248 | some_queue_timedout = 1; |
249 | txq->trans_timeout++; | ||
249 | break; | 250 | break; |
250 | } | 251 | } |
251 | } | 252 | } |