aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordavid decotigny <david.decotigny@google.com>2011-11-16 07:15:10 -0500
committerChristopher Kenna <cjk@cs.unc.edu>2012-09-29 13:32:06 -0400
commit611926edc62a15f77b891658ac70cb66e7a638f2 (patch)
treec3753e114e0073b8231cb657a0ee080678b4ca3c
parent4241502af7a01ec64a5cae23c46bde5458b01b67 (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>
-rw-r--r--include/linux/netdevice.h12
-rw-r--r--net/core/net-sysfs.c37
-rw-r--r--net/sched/sch_generic.c1
3 files changed, 42 insertions, 8 deletions
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index c6d6d486d31..a672989daa2 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -556,7 +556,7 @@ struct netdev_queue {
556 struct Qdisc *qdisc; 556 struct Qdisc *qdisc;
557 unsigned long state; 557 unsigned long state;
558 struct Qdisc *qdisc_sleeping; 558 struct Qdisc *qdisc_sleeping;
559#ifdef CONFIG_RPS 559#ifdef CONFIG_SYSFS
560 struct kobject kobj; 560 struct kobject kobj;
561#endif 561#endif
562#if defined(CONFIG_XPS) && defined(CONFIG_NUMA) 562#if defined(CONFIG_XPS) && defined(CONFIG_NUMA)
@@ -571,6 +571,12 @@ struct netdev_queue {
571 * please use this field instead of dev->trans_start 571 * please use this field instead of dev->trans_start
572 */ 572 */
573 unsigned long trans_start; 573 unsigned long trans_start;
574
575 /*
576 * Number of TX timeouts for this queue
577 * (/sys/class/net/DEV/Q/trans_timeout)
578 */
579 unsigned long trans_timeout;
574} ____cacheline_aligned_in_smp; 580} ____cacheline_aligned_in_smp;
575 581
576static inline int netdev_queue_numa_node_read(const struct netdev_queue *q) 582static inline int netdev_queue_numa_node_read(const struct netdev_queue *q)
@@ -1214,9 +1220,11 @@ struct net_device {
1214 1220
1215 unsigned char broadcast[MAX_ADDR_LEN]; /* hw bcast add */ 1221 unsigned char broadcast[MAX_ADDR_LEN]; /* hw bcast add */
1216 1222
1217#ifdef CONFIG_RPS 1223#ifdef CONFIG_SYSFS
1218 struct kset *queues_kset; 1224 struct kset *queues_kset;
1225#endif
1219 1226
1227#ifdef CONFIG_RPS
1220 struct netdev_rx_queue *_rx; 1228 struct netdev_rx_queue *_rx;
1221 1229
1222 /* Number of RX queues allocated at register_netdev() time */ 1230 /* Number of RX queues allocated at register_netdev() time */
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
830static 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
843static struct netdev_queue_attribute queue_trans_timeout =
844 __ATTR(tx_timeout, S_IRUGO, show_trans_timeout, NULL);
845
846#ifdef CONFIG_XPS
830static inline unsigned int get_netdev_queue_index(struct netdev_queue *queue) 847static 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
1022static struct netdev_queue_attribute xps_cpus_attribute = 1039static 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
1025static struct attribute *netdev_queue_default_attrs[] = { 1043static 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
1030static void netdev_queue_release(struct kobject *kobj) 1052static 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
1081static struct kobj_type netdev_queue_ktype = { 1104static 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
1108int 1133int
1109netdev_queue_update_kobjects(struct net_device *net, int old_num, int new_num) 1134netdev_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
1132static int register_queue_kobjects(struct net_device *net) 1157static 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 }