diff options
author | david decotigny <david.decotigny@google.com> | 2011-11-16 07:15:10 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-11-16 23:14:02 -0500 |
commit | ccf5ff69fbbd8d877377f5786369cf5aa78a15fc (patch) | |
tree | 2c9a7ca29d9b3052fb952ac52445cfb05742a32c /net | |
parent | 19b05f811341aaef3e5e22d2832aa2d8e0bad5ab (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>
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 a64382f201b8..602b1419998c 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c | |||
@@ -780,7 +780,7 @@ net_rx_queue_update_kobjects(struct net_device *net, int old_num, int new_num) | |||
780 | #endif | 780 | #endif |
781 | } | 781 | } |
782 | 782 | ||
783 | #ifdef CONFIG_XPS | 783 | #ifdef CONFIG_SYSFS |
784 | /* | 784 | /* |
785 | * netdev_queue sysfs structures and functions. | 785 | * netdev_queue sysfs structures and functions. |
786 | */ | 786 | */ |
@@ -826,6 +826,23 @@ static const struct sysfs_ops netdev_queue_sysfs_ops = { | |||
826 | .store = netdev_queue_attr_store, | 826 | .store = netdev_queue_attr_store, |
827 | }; | 827 | }; |
828 | 828 | ||
829 | static ssize_t show_trans_timeout(struct netdev_queue *queue, | ||
830 | struct netdev_queue_attribute *attribute, | ||
831 | char *buf) | ||
832 | { | ||
833 | unsigned long trans_timeout; | ||
834 | |||
835 | spin_lock_irq(&queue->_xmit_lock); | ||
836 | trans_timeout = queue->trans_timeout; | ||
837 | spin_unlock_irq(&queue->_xmit_lock); | ||
838 | |||
839 | return sprintf(buf, "%lu", trans_timeout); | ||
840 | } | ||
841 | |||
842 | static struct netdev_queue_attribute queue_trans_timeout = | ||
843 | __ATTR(tx_timeout, S_IRUGO, show_trans_timeout, NULL); | ||
844 | |||
845 | #ifdef CONFIG_XPS | ||
829 | static inline unsigned int get_netdev_queue_index(struct netdev_queue *queue) | 846 | static inline unsigned int get_netdev_queue_index(struct netdev_queue *queue) |
830 | { | 847 | { |
831 | struct net_device *dev = queue->dev; | 848 | struct net_device *dev = queue->dev; |
@@ -1020,12 +1037,17 @@ error: | |||
1020 | 1037 | ||
1021 | static struct netdev_queue_attribute xps_cpus_attribute = | 1038 | static struct netdev_queue_attribute xps_cpus_attribute = |
1022 | __ATTR(xps_cpus, S_IRUGO | S_IWUSR, show_xps_map, store_xps_map); | 1039 | __ATTR(xps_cpus, S_IRUGO | S_IWUSR, show_xps_map, store_xps_map); |
1040 | #endif /* CONFIG_XPS */ | ||
1023 | 1041 | ||
1024 | static struct attribute *netdev_queue_default_attrs[] = { | 1042 | static struct attribute *netdev_queue_default_attrs[] = { |
1043 | &queue_trans_timeout.attr, | ||
1044 | #ifdef CONFIG_XPS | ||
1025 | &xps_cpus_attribute.attr, | 1045 | &xps_cpus_attribute.attr, |
1046 | #endif | ||
1026 | NULL | 1047 | NULL |
1027 | }; | 1048 | }; |
1028 | 1049 | ||
1050 | #ifdef CONFIG_XPS | ||
1029 | static void netdev_queue_release(struct kobject *kobj) | 1051 | static void netdev_queue_release(struct kobject *kobj) |
1030 | { | 1052 | { |
1031 | struct netdev_queue *queue = to_netdev_queue(kobj); | 1053 | struct netdev_queue *queue = to_netdev_queue(kobj); |
@@ -1076,10 +1098,13 @@ static void netdev_queue_release(struct kobject *kobj) | |||
1076 | memset(kobj, 0, sizeof(*kobj)); | 1098 | memset(kobj, 0, sizeof(*kobj)); |
1077 | dev_put(queue->dev); | 1099 | dev_put(queue->dev); |
1078 | } | 1100 | } |
1101 | #endif /* CONFIG_XPS */ | ||
1079 | 1102 | ||
1080 | static struct kobj_type netdev_queue_ktype = { | 1103 | static struct kobj_type netdev_queue_ktype = { |
1081 | .sysfs_ops = &netdev_queue_sysfs_ops, | 1104 | .sysfs_ops = &netdev_queue_sysfs_ops, |
1105 | #ifdef CONFIG_XPS | ||
1082 | .release = netdev_queue_release, | 1106 | .release = netdev_queue_release, |
1107 | #endif | ||
1083 | .default_attrs = netdev_queue_default_attrs, | 1108 | .default_attrs = netdev_queue_default_attrs, |
1084 | }; | 1109 | }; |
1085 | 1110 | ||
@@ -1102,12 +1127,12 @@ static int netdev_queue_add_kobject(struct net_device *net, int index) | |||
1102 | 1127 | ||
1103 | return error; | 1128 | return error; |
1104 | } | 1129 | } |
1105 | #endif /* CONFIG_XPS */ | 1130 | #endif /* CONFIG_SYSFS */ |
1106 | 1131 | ||
1107 | int | 1132 | int |
1108 | netdev_queue_update_kobjects(struct net_device *net, int old_num, int new_num) | 1133 | netdev_queue_update_kobjects(struct net_device *net, int old_num, int new_num) |
1109 | { | 1134 | { |
1110 | #ifdef CONFIG_XPS | 1135 | #ifdef CONFIG_SYSFS |
1111 | int i; | 1136 | int i; |
1112 | int error = 0; | 1137 | int error = 0; |
1113 | 1138 | ||
@@ -1125,14 +1150,14 @@ netdev_queue_update_kobjects(struct net_device *net, int old_num, int new_num) | |||
1125 | return error; | 1150 | return error; |
1126 | #else | 1151 | #else |
1127 | return 0; | 1152 | return 0; |
1128 | #endif | 1153 | #endif /* CONFIG_SYSFS */ |
1129 | } | 1154 | } |
1130 | 1155 | ||
1131 | static int register_queue_kobjects(struct net_device *net) | 1156 | static int register_queue_kobjects(struct net_device *net) |
1132 | { | 1157 | { |
1133 | int error = 0, txq = 0, rxq = 0, real_rx = 0, real_tx = 0; | 1158 | int error = 0, txq = 0, rxq = 0, real_rx = 0, real_tx = 0; |
1134 | 1159 | ||
1135 | #if defined(CONFIG_RPS) || defined(CONFIG_XPS) | 1160 | #ifdef CONFIG_SYSFS |
1136 | net->queues_kset = kset_create_and_add("queues", | 1161 | net->queues_kset = kset_create_and_add("queues", |
1137 | NULL, &net->dev.kobj); | 1162 | NULL, &net->dev.kobj); |
1138 | if (!net->queues_kset) | 1163 | if (!net->queues_kset) |
@@ -1173,7 +1198,7 @@ static void remove_queue_kobjects(struct net_device *net) | |||
1173 | 1198 | ||
1174 | net_rx_queue_update_kobjects(net, real_rx, 0); | 1199 | net_rx_queue_update_kobjects(net, real_rx, 0); |
1175 | netdev_queue_update_kobjects(net, real_tx, 0); | 1200 | netdev_queue_update_kobjects(net, real_tx, 0); |
1176 | #if defined(CONFIG_RPS) || defined(CONFIG_XPS) | 1201 | #ifdef CONFIG_SYSFS |
1177 | kset_unregister(net->queues_kset); | 1202 | kset_unregister(net->queues_kset); |
1178 | #endif | 1203 | #endif |
1179 | } | 1204 | } |
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index 69fca2798804..79ac1458c2ba 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 | } |