aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/xen-netback
diff options
context:
space:
mode:
authorZoltan Kiss <zoltan.kiss@citrix.com>2014-07-08 14:49:14 -0400
committerDavid S. Miller <davem@davemloft.net>2014-07-08 23:48:36 -0400
commitf51de24356e49e4dcb5095e87717065580912120 (patch)
tree33439ff1f49a3d2d61455f0c6585b3369088b25c /drivers/net/xen-netback
parenta37934fc0d0c087dd120dba229077048f1abfd37 (diff)
xen-netback: Adding debugfs "io_ring_qX" files
This patch adds debugfs capabilities to netback. There used to be a similar patch floating around for classic kernel, but it used procfs. It is based on a very similar blkback patch. It creates xen-netback/[vifname]/io_ring_q[queueno] files, reading them output various ring variables etc. Writing "kick" into it imitates an interrupt happened, it can be useful to check whether the ring is just stalled due to a missed interrupt. Signed-off-by: Zoltan Kiss <zoltan.kiss@citrix.com> Cc: netdev@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: xen-devel@lists.xenproject.org Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/xen-netback')
-rw-r--r--drivers/net/xen-netback/common.h11
-rw-r--r--drivers/net/xen-netback/interface.c2
-rw-r--r--drivers/net/xen-netback/netback.c11
-rw-r--r--drivers/net/xen-netback/xenbus.c178
4 files changed, 200 insertions, 2 deletions
diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h
index 2532ce85d718..28c98229e95f 100644
--- a/drivers/net/xen-netback/common.h
+++ b/drivers/net/xen-netback/common.h
@@ -44,6 +44,7 @@
44#include <xen/interface/grant_table.h> 44#include <xen/interface/grant_table.h>
45#include <xen/grant_table.h> 45#include <xen/grant_table.h>
46#include <xen/xenbus.h> 46#include <xen/xenbus.h>
47#include <linux/debugfs.h>
47 48
48typedef unsigned int pending_ring_idx_t; 49typedef unsigned int pending_ring_idx_t;
49#define INVALID_PENDING_RING_IDX (~0U) 50#define INVALID_PENDING_RING_IDX (~0U)
@@ -224,6 +225,10 @@ struct xenvif {
224 struct xenvif_queue *queues; 225 struct xenvif_queue *queues;
225 unsigned int num_queues; /* active queues, resource allocated */ 226 unsigned int num_queues; /* active queues, resource allocated */
226 227
228#ifdef CONFIG_DEBUG_FS
229 struct dentry *xenvif_dbg_root;
230#endif
231
227 /* Miscellaneous private stuff. */ 232 /* Miscellaneous private stuff. */
228 struct net_device *dev; 233 struct net_device *dev;
229}; 234};
@@ -297,10 +302,16 @@ static inline pending_ring_idx_t nr_pending_reqs(struct xenvif_queue *queue)
297/* Callback from stack when TX packet can be released */ 302/* Callback from stack when TX packet can be released */
298void xenvif_zerocopy_callback(struct ubuf_info *ubuf, bool zerocopy_success); 303void xenvif_zerocopy_callback(struct ubuf_info *ubuf, bool zerocopy_success);
299 304
305irqreturn_t xenvif_interrupt(int irq, void *dev_id);
306
300extern bool separate_tx_rx_irq; 307extern bool separate_tx_rx_irq;
301 308
302extern unsigned int rx_drain_timeout_msecs; 309extern unsigned int rx_drain_timeout_msecs;
303extern unsigned int rx_drain_timeout_jiffies; 310extern unsigned int rx_drain_timeout_jiffies;
304extern unsigned int xenvif_max_queues; 311extern unsigned int xenvif_max_queues;
305 312
313#ifdef CONFIG_DEBUG_FS
314extern struct dentry *xen_netback_dbg_root;
315#endif
316
306#endif /* __XEN_NETBACK__COMMON_H__ */ 317#endif /* __XEN_NETBACK__COMMON_H__ */
diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c
index 9e97c7ca0ddd..ef75b45e5085 100644
--- a/drivers/net/xen-netback/interface.c
+++ b/drivers/net/xen-netback/interface.c
@@ -102,7 +102,7 @@ static irqreturn_t xenvif_rx_interrupt(int irq, void *dev_id)
102 return IRQ_HANDLED; 102 return IRQ_HANDLED;
103} 103}
104 104
105static irqreturn_t xenvif_interrupt(int irq, void *dev_id) 105irqreturn_t xenvif_interrupt(int irq, void *dev_id)
106{ 106{
107 xenvif_tx_interrupt(irq, dev_id); 107 xenvif_tx_interrupt(irq, dev_id);
108 xenvif_rx_interrupt(irq, dev_id); 108 xenvif_rx_interrupt(irq, dev_id);
diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
index 1844a47636b6..77127ca08ca4 100644
--- a/drivers/net/xen-netback/netback.c
+++ b/drivers/net/xen-netback/netback.c
@@ -1987,6 +1987,13 @@ static int __init netback_init(void)
1987 1987
1988 rx_drain_timeout_jiffies = msecs_to_jiffies(rx_drain_timeout_msecs); 1988 rx_drain_timeout_jiffies = msecs_to_jiffies(rx_drain_timeout_msecs);
1989 1989
1990#ifdef CONFIG_DEBUG_FS
1991 xen_netback_dbg_root = debugfs_create_dir("xen-netback", NULL);
1992 if (IS_ERR_OR_NULL(xen_netback_dbg_root))
1993 pr_warn("Init of debugfs returned %ld!\n",
1994 PTR_ERR(xen_netback_dbg_root));
1995#endif /* CONFIG_DEBUG_FS */
1996
1990 return 0; 1997 return 0;
1991 1998
1992failed_init: 1999failed_init:
@@ -1997,6 +2004,10 @@ module_init(netback_init);
1997 2004
1998static void __exit netback_fini(void) 2005static void __exit netback_fini(void)
1999{ 2006{
2007#ifdef CONFIG_DEBUG_FS
2008 if (!IS_ERR_OR_NULL(xen_netback_dbg_root))
2009 debugfs_remove_recursive(xen_netback_dbg_root);
2010#endif /* CONFIG_DEBUG_FS */
2000 xenvif_xenbus_fini(); 2011 xenvif_xenbus_fini();
2001} 2012}
2002module_exit(netback_fini); 2013module_exit(netback_fini);
diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c
index 3d85acd84bad..580517d857bf 100644
--- a/drivers/net/xen-netback/xenbus.c
+++ b/drivers/net/xen-netback/xenbus.c
@@ -44,6 +44,175 @@ static void unregister_hotplug_status_watch(struct backend_info *be);
44static void set_backend_state(struct backend_info *be, 44static void set_backend_state(struct backend_info *be,
45 enum xenbus_state state); 45 enum xenbus_state state);
46 46
47#ifdef CONFIG_DEBUG_FS
48struct dentry *xen_netback_dbg_root = NULL;
49
50static int xenvif_read_io_ring(struct seq_file *m, void *v)
51{
52 struct xenvif_queue *queue = m->private;
53 struct xen_netif_tx_back_ring *tx_ring = &queue->tx;
54 struct xen_netif_rx_back_ring *rx_ring = &queue->rx;
55
56 if (tx_ring->sring) {
57 struct xen_netif_tx_sring *sring = tx_ring->sring;
58
59 seq_printf(m, "Queue %d\nTX: nr_ents %u\n", queue->id,
60 tx_ring->nr_ents);
61 seq_printf(m, "req prod %u (%d) cons %u (%d) event %u (%d)\n",
62 sring->req_prod,
63 sring->req_prod - sring->rsp_prod,
64 tx_ring->req_cons,
65 tx_ring->req_cons - sring->rsp_prod,
66 sring->req_event,
67 sring->req_event - sring->rsp_prod);
68 seq_printf(m, "rsp prod %u (base) pvt %u (%d) event %u (%d)\n",
69 sring->rsp_prod,
70 tx_ring->rsp_prod_pvt,
71 tx_ring->rsp_prod_pvt - sring->rsp_prod,
72 sring->rsp_event,
73 sring->rsp_event - sring->rsp_prod);
74 seq_printf(m, "pending prod %u pending cons %u nr_pending_reqs %u\n",
75 queue->pending_prod,
76 queue->pending_cons,
77 nr_pending_reqs(queue));
78 seq_printf(m, "dealloc prod %u dealloc cons %u dealloc_queue %u\n\n",
79 queue->dealloc_prod,
80 queue->dealloc_cons,
81 queue->dealloc_prod - queue->dealloc_cons);
82 }
83
84 if (rx_ring->sring) {
85 struct xen_netif_rx_sring *sring = rx_ring->sring;
86
87 seq_printf(m, "RX: nr_ents %u\n", rx_ring->nr_ents);
88 seq_printf(m, "req prod %u (%d) cons %u (%d) event %u (%d)\n",
89 sring->req_prod,
90 sring->req_prod - sring->rsp_prod,
91 rx_ring->req_cons,
92 rx_ring->req_cons - sring->rsp_prod,
93 sring->req_event,
94 sring->req_event - sring->rsp_prod);
95 seq_printf(m, "rsp prod %u (base) pvt %u (%d) event %u (%d)\n\n",
96 sring->rsp_prod,
97 rx_ring->rsp_prod_pvt,
98 rx_ring->rsp_prod_pvt - sring->rsp_prod,
99 sring->rsp_event,
100 sring->rsp_event - sring->rsp_prod);
101 }
102
103 seq_printf(m, "NAPI state: %lx NAPI weight: %d TX queue len %u\n"
104 "Credit timer_pending: %d, credit: %lu, usec: %lu\n"
105 "remaining: %lu, expires: %lu, now: %lu\n",
106 queue->napi.state, queue->napi.weight,
107 skb_queue_len(&queue->tx_queue),
108 timer_pending(&queue->credit_timeout),
109 queue->credit_bytes,
110 queue->credit_usec,
111 queue->remaining_credit,
112 queue->credit_timeout.expires,
113 jiffies);
114
115 return 0;
116}
117
118#define XENVIF_KICK_STR "kick"
119
120static ssize_t
121xenvif_write_io_ring(struct file *filp, const char __user *buf, size_t count,
122 loff_t *ppos)
123{
124 struct xenvif_queue *queue =
125 ((struct seq_file *)filp->private_data)->private;
126 int len;
127 char write[sizeof(XENVIF_KICK_STR)];
128
129 /* don't allow partial writes and check the length */
130 if (*ppos != 0)
131 return 0;
132 if (count < sizeof(XENVIF_KICK_STR) - 1)
133 return -ENOSPC;
134
135 len = simple_write_to_buffer(write,
136 sizeof(write),
137 ppos,
138 buf,
139 count);
140 if (len < 0)
141 return len;
142
143 if (!strncmp(write, XENVIF_KICK_STR, sizeof(XENVIF_KICK_STR) - 1))
144 xenvif_interrupt(0, (void *)queue);
145 else {
146 pr_warn("Unknown command to io_ring_q%d. Available: kick\n",
147 queue->id);
148 count = -EINVAL;
149 }
150 return count;
151}
152
153static int xenvif_dump_open(struct inode *inode, struct file *filp)
154{
155 int ret;
156 void *queue = NULL;
157
158 if (inode->i_private)
159 queue = inode->i_private;
160 ret = single_open(filp, xenvif_read_io_ring, queue);
161 filp->f_mode |= FMODE_PWRITE;
162 return ret;
163}
164
165static const struct file_operations xenvif_dbg_io_ring_ops_fops = {
166 .owner = THIS_MODULE,
167 .open = xenvif_dump_open,
168 .read = seq_read,
169 .llseek = seq_lseek,
170 .release = single_release,
171 .write = xenvif_write_io_ring,
172};
173
174static void xenvif_debugfs_addif(struct xenvif_queue *queue)
175{
176 struct dentry *pfile;
177 struct xenvif *vif = queue->vif;
178 int i;
179
180 if (IS_ERR_OR_NULL(xen_netback_dbg_root))
181 return;
182
183 vif->xenvif_dbg_root = debugfs_create_dir(vif->dev->name,
184 xen_netback_dbg_root);
185 if (!IS_ERR_OR_NULL(vif->xenvif_dbg_root)) {
186 for (i = 0; i < vif->num_queues; ++i) {
187 char filename[sizeof("io_ring_q") + 4];
188
189 snprintf(filename, sizeof(filename), "io_ring_q%d", i);
190 pfile = debugfs_create_file(filename,
191 S_IRUSR | S_IWUSR,
192 vif->xenvif_dbg_root,
193 &vif->queues[i],
194 &xenvif_dbg_io_ring_ops_fops);
195 if (IS_ERR_OR_NULL(pfile))
196 pr_warn("Creation of io_ring file returned %ld!\n",
197 PTR_ERR(pfile));
198 }
199 } else
200 netdev_warn(vif->dev,
201 "Creation of vif debugfs dir returned %ld!\n",
202 PTR_ERR(vif->xenvif_dbg_root));
203}
204
205static void xenvif_debugfs_delif(struct xenvif *vif)
206{
207 if (IS_ERR_OR_NULL(xen_netback_dbg_root))
208 return;
209
210 if (!IS_ERR_OR_NULL(vif->xenvif_dbg_root))
211 debugfs_remove_recursive(vif->xenvif_dbg_root);
212 vif->xenvif_dbg_root = NULL;
213}
214#endif /* CONFIG_DEBUG_FS */
215
47static int netback_remove(struct xenbus_device *dev) 216static int netback_remove(struct xenbus_device *dev)
48{ 217{
49 struct backend_info *be = dev_get_drvdata(&dev->dev); 218 struct backend_info *be = dev_get_drvdata(&dev->dev);
@@ -246,8 +415,12 @@ static void backend_create_xenvif(struct backend_info *be)
246 415
247static void backend_disconnect(struct backend_info *be) 416static void backend_disconnect(struct backend_info *be)
248{ 417{
249 if (be->vif) 418 if (be->vif) {
419#ifdef CONFIG_DEBUG_FS
420 xenvif_debugfs_delif(be->vif);
421#endif /* CONFIG_DEBUG_FS */
250 xenvif_disconnect(be->vif); 422 xenvif_disconnect(be->vif);
423 }
251} 424}
252 425
253static void backend_connect(struct backend_info *be) 426static void backend_connect(struct backend_info *be)
@@ -560,6 +733,9 @@ static void connect(struct backend_info *be)
560 be->vif->num_queues = queue_index; 733 be->vif->num_queues = queue_index;
561 goto err; 734 goto err;
562 } 735 }
736#ifdef CONFIG_DEBUG_FS
737 xenvif_debugfs_addif(queue);
738#endif /* CONFIG_DEBUG_FS */
563 } 739 }
564 740
565 /* Initialisation completed, tell core driver the number of 741 /* Initialisation completed, tell core driver the number of