at v4.5-rc4 406 lines 11 kB view raw
1/* 2 * Intel MIC Platform Software Stack (MPSS) 3 * 4 * Copyright(c) 2013 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 MIC Host driver. 19 * 20 */ 21#include <linux/debugfs.h> 22#include <linux/pci.h> 23#include <linux/seq_file.h> 24 25#include <linux/mic_common.h> 26#include "../common/mic_dev.h" 27#include "mic_device.h" 28#include "mic_smpt.h" 29#include "mic_virtio.h" 30 31/* Debugfs parent dir */ 32static struct dentry *mic_dbg; 33 34static int mic_smpt_show(struct seq_file *s, void *pos) 35{ 36 int i; 37 struct mic_device *mdev = s->private; 38 unsigned long flags; 39 40 seq_printf(s, "MIC %-2d |%-10s| %-14s %-10s\n", 41 mdev->id, "SMPT entry", "SW DMA addr", "RefCount"); 42 seq_puts(s, "====================================================\n"); 43 44 if (mdev->smpt) { 45 struct mic_smpt_info *smpt_info = mdev->smpt; 46 spin_lock_irqsave(&smpt_info->smpt_lock, flags); 47 for (i = 0; i < smpt_info->info.num_reg; i++) { 48 seq_printf(s, "%9s|%-10d| %-#14llx %-10lld\n", 49 " ", i, smpt_info->entry[i].dma_addr, 50 smpt_info->entry[i].ref_count); 51 } 52 spin_unlock_irqrestore(&smpt_info->smpt_lock, flags); 53 } 54 seq_puts(s, "====================================================\n"); 55 return 0; 56} 57 58static int mic_smpt_debug_open(struct inode *inode, struct file *file) 59{ 60 return single_open(file, mic_smpt_show, inode->i_private); 61} 62 63static int mic_smpt_debug_release(struct inode *inode, struct file *file) 64{ 65 return single_release(inode, file); 66} 67 68static const struct file_operations smpt_file_ops = { 69 .owner = THIS_MODULE, 70 .open = mic_smpt_debug_open, 71 .read = seq_read, 72 .llseek = seq_lseek, 73 .release = mic_smpt_debug_release 74}; 75 76static int mic_post_code_show(struct seq_file *s, void *pos) 77{ 78 struct mic_device *mdev = s->private; 79 u32 reg = mdev->ops->get_postcode(mdev); 80 81 seq_printf(s, "%c%c", reg & 0xff, (reg >> 8) & 0xff); 82 return 0; 83} 84 85static int mic_post_code_debug_open(struct inode *inode, struct file *file) 86{ 87 return single_open(file, mic_post_code_show, inode->i_private); 88} 89 90static int mic_post_code_debug_release(struct inode *inode, struct file *file) 91{ 92 return single_release(inode, file); 93} 94 95static const struct file_operations post_code_ops = { 96 .owner = THIS_MODULE, 97 .open = mic_post_code_debug_open, 98 .read = seq_read, 99 .llseek = seq_lseek, 100 .release = mic_post_code_debug_release 101}; 102 103static int mic_dp_show(struct seq_file *s, void *pos) 104{ 105 struct mic_device *mdev = s->private; 106 struct mic_device_desc *d; 107 struct mic_device_ctrl *dc; 108 struct mic_vqconfig *vqconfig; 109 __u32 *features; 110 __u8 *config; 111 struct mic_bootparam *bootparam = mdev->dp; 112 int i, j; 113 114 seq_printf(s, "Bootparam: magic 0x%x\n", 115 bootparam->magic); 116 seq_printf(s, "Bootparam: h2c_config_db %d\n", 117 bootparam->h2c_config_db); 118 seq_printf(s, "Bootparam: node_id %d\n", 119 bootparam->node_id); 120 seq_printf(s, "Bootparam: c2h_scif_db %d\n", 121 bootparam->c2h_scif_db); 122 seq_printf(s, "Bootparam: h2c_scif_db %d\n", 123 bootparam->h2c_scif_db); 124 seq_printf(s, "Bootparam: scif_host_dma_addr 0x%llx\n", 125 bootparam->scif_host_dma_addr); 126 seq_printf(s, "Bootparam: scif_card_dma_addr 0x%llx\n", 127 bootparam->scif_card_dma_addr); 128 129 130 for (i = sizeof(*bootparam); i < MIC_DP_SIZE; 131 i += mic_total_desc_size(d)) { 132 d = mdev->dp + i; 133 dc = (void *)d + mic_aligned_desc_size(d); 134 135 /* end of list */ 136 if (d->type == 0) 137 break; 138 139 if (d->type == -1) 140 continue; 141 142 seq_printf(s, "Type %d ", d->type); 143 seq_printf(s, "Num VQ %d ", d->num_vq); 144 seq_printf(s, "Feature Len %d\n", d->feature_len); 145 seq_printf(s, "Config Len %d ", d->config_len); 146 seq_printf(s, "Shutdown Status %d\n", d->status); 147 148 for (j = 0; j < d->num_vq; j++) { 149 vqconfig = mic_vq_config(d) + j; 150 seq_printf(s, "vqconfig[%d]: ", j); 151 seq_printf(s, "address 0x%llx ", vqconfig->address); 152 seq_printf(s, "num %d ", vqconfig->num); 153 seq_printf(s, "used address 0x%llx\n", 154 vqconfig->used_address); 155 } 156 157 features = (__u32 *)mic_vq_features(d); 158 seq_printf(s, "Features: Host 0x%x ", features[0]); 159 seq_printf(s, "Guest 0x%x\n", features[1]); 160 161 config = mic_vq_configspace(d); 162 for (j = 0; j < d->config_len; j++) 163 seq_printf(s, "config[%d]=%d\n", j, config[j]); 164 165 seq_puts(s, "Device control:\n"); 166 seq_printf(s, "Config Change %d ", dc->config_change); 167 seq_printf(s, "Vdev reset %d\n", dc->vdev_reset); 168 seq_printf(s, "Guest Ack %d ", dc->guest_ack); 169 seq_printf(s, "Host ack %d\n", dc->host_ack); 170 seq_printf(s, "Used address updated %d ", 171 dc->used_address_updated); 172 seq_printf(s, "Vdev 0x%llx\n", dc->vdev); 173 seq_printf(s, "c2h doorbell %d ", dc->c2h_vdev_db); 174 seq_printf(s, "h2c doorbell %d\n", dc->h2c_vdev_db); 175 } 176 177 return 0; 178} 179 180static int mic_dp_debug_open(struct inode *inode, struct file *file) 181{ 182 return single_open(file, mic_dp_show, inode->i_private); 183} 184 185static int mic_dp_debug_release(struct inode *inode, struct file *file) 186{ 187 return single_release(inode, file); 188} 189 190static const struct file_operations dp_ops = { 191 .owner = THIS_MODULE, 192 .open = mic_dp_debug_open, 193 .read = seq_read, 194 .llseek = seq_lseek, 195 .release = mic_dp_debug_release 196}; 197 198static int mic_vdev_info_show(struct seq_file *s, void *unused) 199{ 200 struct mic_device *mdev = s->private; 201 struct list_head *pos, *tmp; 202 struct mic_vdev *mvdev; 203 int i, j; 204 205 mutex_lock(&mdev->mic_mutex); 206 list_for_each_safe(pos, tmp, &mdev->vdev_list) { 207 mvdev = list_entry(pos, struct mic_vdev, list); 208 seq_printf(s, "VDEV type %d state %s in %ld out %ld\n", 209 mvdev->virtio_id, 210 mic_vdevup(mvdev) ? "UP" : "DOWN", 211 mvdev->in_bytes, 212 mvdev->out_bytes); 213 for (i = 0; i < MIC_MAX_VRINGS; i++) { 214 struct vring_desc *desc; 215 struct vring_avail *avail; 216 struct vring_used *used; 217 struct mic_vringh *mvr = &mvdev->mvr[i]; 218 struct vringh *vrh = &mvr->vrh; 219 int num = vrh->vring.num; 220 if (!num) 221 continue; 222 desc = vrh->vring.desc; 223 seq_printf(s, "vring i %d avail_idx %d", 224 i, mvr->vring.info->avail_idx & (num - 1)); 225 seq_printf(s, " vring i %d avail_idx %d\n", 226 i, mvr->vring.info->avail_idx); 227 seq_printf(s, "vrh i %d weak_barriers %d", 228 i, vrh->weak_barriers); 229 seq_printf(s, " last_avail_idx %d last_used_idx %d", 230 vrh->last_avail_idx, vrh->last_used_idx); 231 seq_printf(s, " completed %d\n", vrh->completed); 232 for (j = 0; j < num; j++) { 233 seq_printf(s, "desc[%d] addr 0x%llx len %d", 234 j, desc->addr, desc->len); 235 seq_printf(s, " flags 0x%x next %d\n", 236 desc->flags, desc->next); 237 desc++; 238 } 239 avail = vrh->vring.avail; 240 seq_printf(s, "avail flags 0x%x idx %d\n", 241 vringh16_to_cpu(vrh, avail->flags), 242 vringh16_to_cpu(vrh, avail->idx) & (num - 1)); 243 seq_printf(s, "avail flags 0x%x idx %d\n", 244 vringh16_to_cpu(vrh, avail->flags), 245 vringh16_to_cpu(vrh, avail->idx)); 246 for (j = 0; j < num; j++) 247 seq_printf(s, "avail ring[%d] %d\n", 248 j, avail->ring[j]); 249 used = vrh->vring.used; 250 seq_printf(s, "used flags 0x%x idx %d\n", 251 vringh16_to_cpu(vrh, used->flags), 252 vringh16_to_cpu(vrh, used->idx) & (num - 1)); 253 seq_printf(s, "used flags 0x%x idx %d\n", 254 vringh16_to_cpu(vrh, used->flags), 255 vringh16_to_cpu(vrh, used->idx)); 256 for (j = 0; j < num; j++) 257 seq_printf(s, "used ring[%d] id %d len %d\n", 258 j, vringh32_to_cpu(vrh, 259 used->ring[j].id), 260 vringh32_to_cpu(vrh, 261 used->ring[j].len)); 262 } 263 } 264 mutex_unlock(&mdev->mic_mutex); 265 266 return 0; 267} 268 269static int mic_vdev_info_debug_open(struct inode *inode, struct file *file) 270{ 271 return single_open(file, mic_vdev_info_show, inode->i_private); 272} 273 274static int mic_vdev_info_debug_release(struct inode *inode, struct file *file) 275{ 276 return single_release(inode, file); 277} 278 279static const struct file_operations vdev_info_ops = { 280 .owner = THIS_MODULE, 281 .open = mic_vdev_info_debug_open, 282 .read = seq_read, 283 .llseek = seq_lseek, 284 .release = mic_vdev_info_debug_release 285}; 286 287static int mic_msi_irq_info_show(struct seq_file *s, void *pos) 288{ 289 struct mic_device *mdev = s->private; 290 int reg; 291 int i, j; 292 u16 entry; 293 u16 vector; 294 struct pci_dev *pdev = mdev->pdev; 295 296 if (pci_dev_msi_enabled(pdev)) { 297 for (i = 0; i < mdev->irq_info.num_vectors; i++) { 298 if (pdev->msix_enabled) { 299 entry = mdev->irq_info.msix_entries[i].entry; 300 vector = mdev->irq_info.msix_entries[i].vector; 301 } else { 302 entry = 0; 303 vector = pdev->irq; 304 } 305 306 reg = mdev->intr_ops->read_msi_to_src_map(mdev, entry); 307 308 seq_printf(s, "%s %-10d %s %-10d MXAR[%d]: %08X\n", 309 "IRQ:", vector, "Entry:", entry, i, reg); 310 311 seq_printf(s, "%-10s", "offset:"); 312 for (j = (MIC_NUM_OFFSETS - 1); j >= 0; j--) 313 seq_printf(s, "%4d ", j); 314 seq_puts(s, "\n"); 315 316 317 seq_printf(s, "%-10s", "count:"); 318 for (j = (MIC_NUM_OFFSETS - 1); j >= 0; j--) 319 seq_printf(s, "%4d ", 320 (mdev->irq_info.mic_msi_map[i] & 321 BIT(j)) ? 1 : 0); 322 seq_puts(s, "\n\n"); 323 } 324 } else { 325 seq_puts(s, "MSI/MSIx interrupts not enabled\n"); 326 } 327 328 return 0; 329} 330 331static int mic_msi_irq_info_debug_open(struct inode *inode, struct file *file) 332{ 333 return single_open(file, mic_msi_irq_info_show, inode->i_private); 334} 335 336static int 337mic_msi_irq_info_debug_release(struct inode *inode, struct file *file) 338{ 339 return single_release(inode, file); 340} 341 342static const struct file_operations msi_irq_info_ops = { 343 .owner = THIS_MODULE, 344 .open = mic_msi_irq_info_debug_open, 345 .read = seq_read, 346 .llseek = seq_lseek, 347 .release = mic_msi_irq_info_debug_release 348}; 349 350/** 351 * mic_create_debug_dir - Initialize MIC debugfs entries. 352 */ 353void mic_create_debug_dir(struct mic_device *mdev) 354{ 355 char name[16]; 356 357 if (!mic_dbg) 358 return; 359 360 scnprintf(name, sizeof(name), "mic%d", mdev->id); 361 mdev->dbg_dir = debugfs_create_dir(name, mic_dbg); 362 if (!mdev->dbg_dir) 363 return; 364 365 debugfs_create_file("smpt", 0444, mdev->dbg_dir, mdev, &smpt_file_ops); 366 367 debugfs_create_file("post_code", 0444, mdev->dbg_dir, mdev, 368 &post_code_ops); 369 370 debugfs_create_file("dp", 0444, mdev->dbg_dir, mdev, &dp_ops); 371 372 debugfs_create_file("vdev_info", 0444, mdev->dbg_dir, mdev, 373 &vdev_info_ops); 374 375 debugfs_create_file("msi_irq_info", 0444, mdev->dbg_dir, mdev, 376 &msi_irq_info_ops); 377} 378 379/** 380 * mic_delete_debug_dir - Uninitialize MIC debugfs entries. 381 */ 382void mic_delete_debug_dir(struct mic_device *mdev) 383{ 384 if (!mdev->dbg_dir) 385 return; 386 387 debugfs_remove_recursive(mdev->dbg_dir); 388} 389 390/** 391 * mic_init_debugfs - Initialize global debugfs entry. 392 */ 393void __init mic_init_debugfs(void) 394{ 395 mic_dbg = debugfs_create_dir(KBUILD_MODNAME, NULL); 396 if (!mic_dbg) 397 pr_err("can't create debugfs dir\n"); 398} 399 400/** 401 * mic_exit_debugfs - Uninitialize global debugfs entry 402 */ 403void mic_exit_debugfs(void) 404{ 405 debugfs_remove(mic_dbg); 406}