at v4.13 232 lines 7.0 kB view raw
1/* 2 * Intel MIC Platform Software Stack (MPSS) 3 * 4 * Copyright(c) 2016 Intel Corporation. 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License, version 2, as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, but 11 * WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * General Public License for more details. 14 * 15 * The full GNU General Public License is included in this distribution in 16 * the file called "COPYING". 17 * 18 * Intel Virtio Over PCIe (VOP) driver. 19 * 20 */ 21#include <linux/debugfs.h> 22#include <linux/seq_file.h> 23 24#include "vop_main.h" 25 26static int vop_dp_show(struct seq_file *s, void *pos) 27{ 28 struct mic_device_desc *d; 29 struct mic_device_ctrl *dc; 30 struct mic_vqconfig *vqconfig; 31 __u32 *features; 32 __u8 *config; 33 struct vop_info *vi = s->private; 34 struct vop_device *vpdev = vi->vpdev; 35 struct mic_bootparam *bootparam = vpdev->hw_ops->get_dp(vpdev); 36 int j, k; 37 38 seq_printf(s, "Bootparam: magic 0x%x\n", 39 bootparam->magic); 40 seq_printf(s, "Bootparam: h2c_config_db %d\n", 41 bootparam->h2c_config_db); 42 seq_printf(s, "Bootparam: node_id %d\n", 43 bootparam->node_id); 44 seq_printf(s, "Bootparam: c2h_scif_db %d\n", 45 bootparam->c2h_scif_db); 46 seq_printf(s, "Bootparam: h2c_scif_db %d\n", 47 bootparam->h2c_scif_db); 48 seq_printf(s, "Bootparam: scif_host_dma_addr 0x%llx\n", 49 bootparam->scif_host_dma_addr); 50 seq_printf(s, "Bootparam: scif_card_dma_addr 0x%llx\n", 51 bootparam->scif_card_dma_addr); 52 53 for (j = sizeof(*bootparam); 54 j < MIC_DP_SIZE; j += mic_total_desc_size(d)) { 55 d = (void *)bootparam + j; 56 dc = (void *)d + mic_aligned_desc_size(d); 57 58 /* end of list */ 59 if (d->type == 0) 60 break; 61 62 if (d->type == -1) 63 continue; 64 65 seq_printf(s, "Type %d ", d->type); 66 seq_printf(s, "Num VQ %d ", d->num_vq); 67 seq_printf(s, "Feature Len %d\n", d->feature_len); 68 seq_printf(s, "Config Len %d ", d->config_len); 69 seq_printf(s, "Shutdown Status %d\n", d->status); 70 71 for (k = 0; k < d->num_vq; k++) { 72 vqconfig = mic_vq_config(d) + k; 73 seq_printf(s, "vqconfig[%d]: ", k); 74 seq_printf(s, "address 0x%llx ", 75 vqconfig->address); 76 seq_printf(s, "num %d ", vqconfig->num); 77 seq_printf(s, "used address 0x%llx\n", 78 vqconfig->used_address); 79 } 80 81 features = (__u32 *)mic_vq_features(d); 82 seq_printf(s, "Features: Host 0x%x ", features[0]); 83 seq_printf(s, "Guest 0x%x\n", features[1]); 84 85 config = mic_vq_configspace(d); 86 for (k = 0; k < d->config_len; k++) 87 seq_printf(s, "config[%d]=%d\n", k, config[k]); 88 89 seq_puts(s, "Device control:\n"); 90 seq_printf(s, "Config Change %d ", dc->config_change); 91 seq_printf(s, "Vdev reset %d\n", dc->vdev_reset); 92 seq_printf(s, "Guest Ack %d ", dc->guest_ack); 93 seq_printf(s, "Host ack %d\n", dc->host_ack); 94 seq_printf(s, "Used address updated %d ", 95 dc->used_address_updated); 96 seq_printf(s, "Vdev 0x%llx\n", dc->vdev); 97 seq_printf(s, "c2h doorbell %d ", dc->c2h_vdev_db); 98 seq_printf(s, "h2c doorbell %d\n", dc->h2c_vdev_db); 99 } 100 schedule_work(&vi->hotplug_work); 101 return 0; 102} 103 104static int vop_dp_debug_open(struct inode *inode, struct file *file) 105{ 106 return single_open(file, vop_dp_show, inode->i_private); 107} 108 109static int vop_dp_debug_release(struct inode *inode, struct file *file) 110{ 111 return single_release(inode, file); 112} 113 114static const struct file_operations dp_ops = { 115 .owner = THIS_MODULE, 116 .open = vop_dp_debug_open, 117 .read = seq_read, 118 .llseek = seq_lseek, 119 .release = vop_dp_debug_release 120}; 121 122static int vop_vdev_info_show(struct seq_file *s, void *unused) 123{ 124 struct vop_info *vi = s->private; 125 struct list_head *pos, *tmp; 126 struct vop_vdev *vdev; 127 int i, j; 128 129 mutex_lock(&vi->vop_mutex); 130 list_for_each_safe(pos, tmp, &vi->vdev_list) { 131 vdev = list_entry(pos, struct vop_vdev, list); 132 seq_printf(s, "VDEV type %d state %s in %ld out %ld in_dma %ld out_dma %ld\n", 133 vdev->virtio_id, 134 vop_vdevup(vdev) ? "UP" : "DOWN", 135 vdev->in_bytes, 136 vdev->out_bytes, 137 vdev->in_bytes_dma, 138 vdev->out_bytes_dma); 139 for (i = 0; i < MIC_MAX_VRINGS; i++) { 140 struct vring_desc *desc; 141 struct vring_avail *avail; 142 struct vring_used *used; 143 struct vop_vringh *vvr = &vdev->vvr[i]; 144 struct vringh *vrh = &vvr->vrh; 145 int num = vrh->vring.num; 146 147 if (!num) 148 continue; 149 desc = vrh->vring.desc; 150 seq_printf(s, "vring i %d avail_idx %d", 151 i, vvr->vring.info->avail_idx & (num - 1)); 152 seq_printf(s, " vring i %d avail_idx %d\n", 153 i, vvr->vring.info->avail_idx); 154 seq_printf(s, "vrh i %d weak_barriers %d", 155 i, vrh->weak_barriers); 156 seq_printf(s, " last_avail_idx %d last_used_idx %d", 157 vrh->last_avail_idx, vrh->last_used_idx); 158 seq_printf(s, " completed %d\n", vrh->completed); 159 for (j = 0; j < num; j++) { 160 seq_printf(s, "desc[%d] addr 0x%llx len %d", 161 j, desc->addr, desc->len); 162 seq_printf(s, " flags 0x%x next %d\n", 163 desc->flags, desc->next); 164 desc++; 165 } 166 avail = vrh->vring.avail; 167 seq_printf(s, "avail flags 0x%x idx %d\n", 168 vringh16_to_cpu(vrh, avail->flags), 169 vringh16_to_cpu(vrh, 170 avail->idx) & (num - 1)); 171 seq_printf(s, "avail flags 0x%x idx %d\n", 172 vringh16_to_cpu(vrh, avail->flags), 173 vringh16_to_cpu(vrh, avail->idx)); 174 for (j = 0; j < num; j++) 175 seq_printf(s, "avail ring[%d] %d\n", 176 j, avail->ring[j]); 177 used = vrh->vring.used; 178 seq_printf(s, "used flags 0x%x idx %d\n", 179 vringh16_to_cpu(vrh, used->flags), 180 vringh16_to_cpu(vrh, used->idx) & (num - 1)); 181 seq_printf(s, "used flags 0x%x idx %d\n", 182 vringh16_to_cpu(vrh, used->flags), 183 vringh16_to_cpu(vrh, used->idx)); 184 for (j = 0; j < num; j++) 185 seq_printf(s, "used ring[%d] id %d len %d\n", 186 j, vringh32_to_cpu(vrh, 187 used->ring[j].id), 188 vringh32_to_cpu(vrh, 189 used->ring[j].len)); 190 } 191 } 192 mutex_unlock(&vi->vop_mutex); 193 194 return 0; 195} 196 197static int vop_vdev_info_debug_open(struct inode *inode, struct file *file) 198{ 199 return single_open(file, vop_vdev_info_show, inode->i_private); 200} 201 202static int vop_vdev_info_debug_release(struct inode *inode, struct file *file) 203{ 204 return single_release(inode, file); 205} 206 207static const struct file_operations vdev_info_ops = { 208 .owner = THIS_MODULE, 209 .open = vop_vdev_info_debug_open, 210 .read = seq_read, 211 .llseek = seq_lseek, 212 .release = vop_vdev_info_debug_release 213}; 214 215void vop_init_debugfs(struct vop_info *vi) 216{ 217 char name[16]; 218 219 snprintf(name, sizeof(name), "%s%d", KBUILD_MODNAME, vi->vpdev->dnode); 220 vi->dbg = debugfs_create_dir(name, NULL); 221 if (!vi->dbg) { 222 pr_err("can't create debugfs dir vop\n"); 223 return; 224 } 225 debugfs_create_file("dp", 0444, vi->dbg, vi, &dp_ops); 226 debugfs_create_file("vdev_info", 0444, vi->dbg, vi, &vdev_info_ops); 227} 228 229void vop_exit_debugfs(struct vop_info *vi) 230{ 231 debugfs_remove_recursive(vi->dbg); 232}