diff options
Diffstat (limited to 'drivers/net/xen-netback/xenbus.c')
| -rw-r--r-- | drivers/net/xen-netback/xenbus.c | 178 |
1 files changed, 177 insertions, 1 deletions
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); | |||
| 44 | static void set_backend_state(struct backend_info *be, | 44 | static 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 | ||
| 48 | struct dentry *xen_netback_dbg_root = NULL; | ||
| 49 | |||
| 50 | static 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 | |||
| 120 | static ssize_t | ||
| 121 | xenvif_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 | |||
| 153 | static 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 | |||
| 165 | static 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 | |||
| 174 | static 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 | |||
| 205 | static 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 | |||
| 47 | static int netback_remove(struct xenbus_device *dev) | 216 | static 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 | ||
| 247 | static void backend_disconnect(struct backend_info *be) | 416 | static 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 | ||
| 253 | static void backend_connect(struct backend_info *be) | 426 | static 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 |
