Ashutosh Dixit | f8487a2 | 2015-09-29 18:12:27 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Intel MIC Platform Software Stack (MPSS) |
| 3 | * |
| 4 | * Copyright(c) 2015 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 Coprocessor State Management (COSM) Driver |
| 19 | * |
| 20 | */ |
| 21 | |
| 22 | #include <linux/debugfs.h> |
| 23 | #include <linux/slab.h> |
Ashutosh Dixit | f8bf0de | 2015-10-07 16:34:34 -0700 | [diff] [blame] | 24 | #include <linux/io.h> |
Ashutosh Dixit | f8487a2 | 2015-09-29 18:12:27 -0700 | [diff] [blame] | 25 | #include "cosm_main.h" |
| 26 | |
| 27 | /* Debugfs parent dir */ |
| 28 | static struct dentry *cosm_dbg; |
| 29 | |
| 30 | /** |
| 31 | * cosm_log_buf_show - Display MIC kernel log buffer |
| 32 | * |
| 33 | * log_buf addr/len is read from System.map by user space |
| 34 | * and populated in sysfs entries. |
| 35 | */ |
| 36 | static int cosm_log_buf_show(struct seq_file *s, void *unused) |
| 37 | { |
| 38 | void __iomem *log_buf_va; |
| 39 | int __iomem *log_buf_len_va; |
| 40 | struct cosm_device *cdev = s->private; |
| 41 | void *kva; |
| 42 | int size; |
| 43 | u64 aper_offset; |
| 44 | |
| 45 | if (!cdev || !cdev->log_buf_addr || !cdev->log_buf_len) |
| 46 | goto done; |
| 47 | |
| 48 | mutex_lock(&cdev->cosm_mutex); |
| 49 | switch (cdev->state) { |
| 50 | case MIC_BOOTING: |
| 51 | case MIC_ONLINE: |
| 52 | case MIC_SHUTTING_DOWN: |
| 53 | break; |
| 54 | default: |
| 55 | goto unlock; |
| 56 | } |
| 57 | |
| 58 | /* |
| 59 | * Card kernel will never be relocated and any kernel text/data mapping |
| 60 | * can be translated to phys address by subtracting __START_KERNEL_map. |
| 61 | */ |
| 62 | aper_offset = (u64)cdev->log_buf_len - __START_KERNEL_map; |
| 63 | log_buf_len_va = cdev->hw_ops->aper(cdev)->va + aper_offset; |
| 64 | aper_offset = (u64)cdev->log_buf_addr - __START_KERNEL_map; |
| 65 | log_buf_va = cdev->hw_ops->aper(cdev)->va + aper_offset; |
| 66 | |
| 67 | size = ioread32(log_buf_len_va); |
| 68 | kva = kmalloc(size, GFP_KERNEL); |
| 69 | if (!kva) |
| 70 | goto unlock; |
| 71 | |
| 72 | memcpy_fromio(kva, log_buf_va, size); |
| 73 | seq_write(s, kva, size); |
| 74 | kfree(kva); |
| 75 | unlock: |
| 76 | mutex_unlock(&cdev->cosm_mutex); |
| 77 | done: |
| 78 | return 0; |
| 79 | } |
| 80 | |
| 81 | static int cosm_log_buf_open(struct inode *inode, struct file *file) |
| 82 | { |
| 83 | return single_open(file, cosm_log_buf_show, inode->i_private); |
| 84 | } |
| 85 | |
| 86 | static const struct file_operations log_buf_ops = { |
| 87 | .owner = THIS_MODULE, |
| 88 | .open = cosm_log_buf_open, |
| 89 | .read = seq_read, |
| 90 | .llseek = seq_lseek, |
| 91 | .release = single_release |
| 92 | }; |
| 93 | |
| 94 | /** |
| 95 | * cosm_force_reset_show - Force MIC reset |
| 96 | * |
| 97 | * Invokes the force_reset COSM bus op instead of the standard reset |
| 98 | * op in case a force reset of the MIC device is required |
| 99 | */ |
| 100 | static int cosm_force_reset_show(struct seq_file *s, void *pos) |
| 101 | { |
| 102 | struct cosm_device *cdev = s->private; |
| 103 | |
| 104 | cosm_stop(cdev, true); |
| 105 | return 0; |
| 106 | } |
| 107 | |
| 108 | static int cosm_force_reset_debug_open(struct inode *inode, struct file *file) |
| 109 | { |
| 110 | return single_open(file, cosm_force_reset_show, inode->i_private); |
| 111 | } |
| 112 | |
| 113 | static const struct file_operations force_reset_ops = { |
| 114 | .owner = THIS_MODULE, |
| 115 | .open = cosm_force_reset_debug_open, |
| 116 | .read = seq_read, |
| 117 | .llseek = seq_lseek, |
| 118 | .release = single_release |
| 119 | }; |
| 120 | |
| 121 | void cosm_create_debug_dir(struct cosm_device *cdev) |
| 122 | { |
| 123 | char name[16]; |
| 124 | |
| 125 | if (!cosm_dbg) |
| 126 | return; |
| 127 | |
| 128 | scnprintf(name, sizeof(name), "mic%d", cdev->index); |
| 129 | cdev->dbg_dir = debugfs_create_dir(name, cosm_dbg); |
| 130 | if (!cdev->dbg_dir) |
| 131 | return; |
| 132 | |
| 133 | debugfs_create_file("log_buf", 0444, cdev->dbg_dir, cdev, &log_buf_ops); |
| 134 | debugfs_create_file("force_reset", 0444, cdev->dbg_dir, cdev, |
| 135 | &force_reset_ops); |
| 136 | } |
| 137 | |
| 138 | void cosm_delete_debug_dir(struct cosm_device *cdev) |
| 139 | { |
| 140 | if (!cdev->dbg_dir) |
| 141 | return; |
| 142 | |
| 143 | debugfs_remove_recursive(cdev->dbg_dir); |
| 144 | } |
| 145 | |
| 146 | void cosm_init_debugfs(void) |
| 147 | { |
| 148 | cosm_dbg = debugfs_create_dir(KBUILD_MODNAME, NULL); |
| 149 | if (!cosm_dbg) |
| 150 | pr_err("can't create debugfs dir\n"); |
| 151 | } |
| 152 | |
| 153 | void cosm_exit_debugfs(void) |
| 154 | { |
| 155 | debugfs_remove(cosm_dbg); |
| 156 | } |