1d0b08853SJan Glauber /* 2d0b08853SJan Glauber * Copyright IBM Corp. 2012 3d0b08853SJan Glauber * 4d0b08853SJan Glauber * Author(s): 5d0b08853SJan Glauber * Jan Glauber <jang@linux.vnet.ibm.com> 6d0b08853SJan Glauber */ 7d0b08853SJan Glauber 8d0b08853SJan Glauber #define COMPONENT "zPCI" 9d0b08853SJan Glauber #define pr_fmt(fmt) COMPONENT ": " fmt 10d0b08853SJan Glauber 11d0b08853SJan Glauber #include <linux/kernel.h> 12d0b08853SJan Glauber #include <linux/seq_file.h> 13d0b08853SJan Glauber #include <linux/debugfs.h> 14*a2ab8333SSebastian Ott #include <linux/export.h> 15d0b08853SJan Glauber #include <linux/pci.h> 16d0b08853SJan Glauber #include <asm/debug.h> 17d0b08853SJan Glauber 18d0b08853SJan Glauber #include <asm/pci_dma.h> 19d0b08853SJan Glauber 20d0b08853SJan Glauber static struct dentry *debugfs_root; 21*a2ab8333SSebastian Ott debug_info_t *pci_debug_msg_id; 22*a2ab8333SSebastian Ott EXPORT_SYMBOL_GPL(pci_debug_msg_id); 23*a2ab8333SSebastian Ott debug_info_t *pci_debug_err_id; 24*a2ab8333SSebastian Ott EXPORT_SYMBOL_GPL(pci_debug_err_id); 25d0b08853SJan Glauber 26d0b08853SJan Glauber static char *pci_perf_names[] = { 27d0b08853SJan Glauber /* hardware counters */ 28d0b08853SJan Glauber "Load operations", 29d0b08853SJan Glauber "Store operations", 30d0b08853SJan Glauber "Store block operations", 31d0b08853SJan Glauber "Refresh operations", 32d0b08853SJan Glauber "DMA read bytes", 33d0b08853SJan Glauber "DMA write bytes", 34d0b08853SJan Glauber /* software counters */ 35d0b08853SJan Glauber "Allocated pages", 36d0b08853SJan Glauber "Mapped pages", 37d0b08853SJan Glauber "Unmapped pages", 38d0b08853SJan Glauber }; 39d0b08853SJan Glauber 40d0b08853SJan Glauber static int pci_perf_show(struct seq_file *m, void *v) 41d0b08853SJan Glauber { 42d0b08853SJan Glauber struct zpci_dev *zdev = m->private; 43d0b08853SJan Glauber u64 *stat; 44d0b08853SJan Glauber int i; 45d0b08853SJan Glauber 46d0b08853SJan Glauber if (!zdev) 47d0b08853SJan Glauber return 0; 48d0b08853SJan Glauber if (!zdev->fmb) 49d0b08853SJan Glauber return seq_printf(m, "FMB statistics disabled\n"); 50d0b08853SJan Glauber 51d0b08853SJan Glauber /* header */ 52d0b08853SJan Glauber seq_printf(m, "FMB @ %p\n", zdev->fmb); 53d0b08853SJan Glauber seq_printf(m, "Update interval: %u ms\n", zdev->fmb_update); 54d0b08853SJan Glauber seq_printf(m, "Samples: %u\n", zdev->fmb->samples); 55d0b08853SJan Glauber seq_printf(m, "Last update TOD: %Lx\n", zdev->fmb->last_update); 56d0b08853SJan Glauber 57d0b08853SJan Glauber /* hardware counters */ 58d0b08853SJan Glauber stat = (u64 *) &zdev->fmb->ld_ops; 59d0b08853SJan Glauber for (i = 0; i < 4; i++) 60d0b08853SJan Glauber seq_printf(m, "%26s:\t%llu\n", 61d0b08853SJan Glauber pci_perf_names[i], *(stat + i)); 62d0b08853SJan Glauber if (zdev->fmb->dma_valid) 63d0b08853SJan Glauber for (i = 4; i < 6; i++) 64d0b08853SJan Glauber seq_printf(m, "%26s:\t%llu\n", 65d0b08853SJan Glauber pci_perf_names[i], *(stat + i)); 66d0b08853SJan Glauber /* software counters */ 67d0b08853SJan Glauber for (i = 6; i < ARRAY_SIZE(pci_perf_names); i++) 68d0b08853SJan Glauber seq_printf(m, "%26s:\t%llu\n", 69d0b08853SJan Glauber pci_perf_names[i], 70d0b08853SJan Glauber atomic64_read((atomic64_t *) (stat + i))); 71d0b08853SJan Glauber 72d0b08853SJan Glauber return 0; 73d0b08853SJan Glauber } 74d0b08853SJan Glauber 75d0b08853SJan Glauber static ssize_t pci_perf_seq_write(struct file *file, const char __user *ubuf, 76d0b08853SJan Glauber size_t count, loff_t *off) 77d0b08853SJan Glauber { 78d0b08853SJan Glauber struct zpci_dev *zdev = ((struct seq_file *) file->private_data)->private; 79d0b08853SJan Glauber unsigned long val; 80d0b08853SJan Glauber int rc; 81d0b08853SJan Glauber 82d0b08853SJan Glauber if (!zdev) 83d0b08853SJan Glauber return 0; 84d0b08853SJan Glauber 85d0b08853SJan Glauber rc = kstrtoul_from_user(ubuf, count, 10, &val); 86d0b08853SJan Glauber if (rc) 87d0b08853SJan Glauber return rc; 88d0b08853SJan Glauber 89d0b08853SJan Glauber switch (val) { 90d0b08853SJan Glauber case 0: 91d0b08853SJan Glauber rc = zpci_fmb_disable_device(zdev); 92d0b08853SJan Glauber if (rc) 93d0b08853SJan Glauber return rc; 94d0b08853SJan Glauber break; 95d0b08853SJan Glauber case 1: 96d0b08853SJan Glauber rc = zpci_fmb_enable_device(zdev); 97d0b08853SJan Glauber if (rc) 98d0b08853SJan Glauber return rc; 99d0b08853SJan Glauber break; 100d0b08853SJan Glauber } 101d0b08853SJan Glauber return count; 102d0b08853SJan Glauber } 103d0b08853SJan Glauber 104d0b08853SJan Glauber static int pci_perf_seq_open(struct inode *inode, struct file *filp) 105d0b08853SJan Glauber { 106d0b08853SJan Glauber return single_open(filp, pci_perf_show, 107496ad9aaSAl Viro file_inode(filp)->i_private); 108d0b08853SJan Glauber } 109d0b08853SJan Glauber 110d0b08853SJan Glauber static const struct file_operations debugfs_pci_perf_fops = { 111d0b08853SJan Glauber .open = pci_perf_seq_open, 112d0b08853SJan Glauber .read = seq_read, 113d0b08853SJan Glauber .write = pci_perf_seq_write, 114d0b08853SJan Glauber .llseek = seq_lseek, 115d0b08853SJan Glauber .release = single_release, 116d0b08853SJan Glauber }; 117d0b08853SJan Glauber 118d0b08853SJan Glauber static int pci_debug_show(struct seq_file *m, void *v) 119d0b08853SJan Glauber { 120d0b08853SJan Glauber struct zpci_dev *zdev = m->private; 121d0b08853SJan Glauber 122d0b08853SJan Glauber zpci_debug_info(zdev, m); 123d0b08853SJan Glauber return 0; 124d0b08853SJan Glauber } 125d0b08853SJan Glauber 126d0b08853SJan Glauber static int pci_debug_seq_open(struct inode *inode, struct file *filp) 127d0b08853SJan Glauber { 128d0b08853SJan Glauber return single_open(filp, pci_debug_show, 129496ad9aaSAl Viro file_inode(filp)->i_private); 130d0b08853SJan Glauber } 131d0b08853SJan Glauber 132d0b08853SJan Glauber static const struct file_operations debugfs_pci_debug_fops = { 133d0b08853SJan Glauber .open = pci_debug_seq_open, 134d0b08853SJan Glauber .read = seq_read, 135d0b08853SJan Glauber .llseek = seq_lseek, 136d0b08853SJan Glauber .release = single_release, 137d0b08853SJan Glauber }; 138d0b08853SJan Glauber 139d0b08853SJan Glauber void zpci_debug_init_device(struct zpci_dev *zdev) 140d0b08853SJan Glauber { 141d0b08853SJan Glauber zdev->debugfs_dev = debugfs_create_dir(dev_name(&zdev->pdev->dev), 142d0b08853SJan Glauber debugfs_root); 143d0b08853SJan Glauber if (IS_ERR(zdev->debugfs_dev)) 144d0b08853SJan Glauber zdev->debugfs_dev = NULL; 145d0b08853SJan Glauber 146d0b08853SJan Glauber zdev->debugfs_perf = debugfs_create_file("statistics", 147d0b08853SJan Glauber S_IFREG | S_IRUGO | S_IWUSR, 148d0b08853SJan Glauber zdev->debugfs_dev, zdev, 149d0b08853SJan Glauber &debugfs_pci_perf_fops); 150d0b08853SJan Glauber if (IS_ERR(zdev->debugfs_perf)) 151d0b08853SJan Glauber zdev->debugfs_perf = NULL; 152d0b08853SJan Glauber 153d0b08853SJan Glauber zdev->debugfs_debug = debugfs_create_file("debug", 154d0b08853SJan Glauber S_IFREG | S_IRUGO | S_IWUSR, 155d0b08853SJan Glauber zdev->debugfs_dev, zdev, 156d0b08853SJan Glauber &debugfs_pci_debug_fops); 157d0b08853SJan Glauber if (IS_ERR(zdev->debugfs_debug)) 158d0b08853SJan Glauber zdev->debugfs_debug = NULL; 159d0b08853SJan Glauber } 160d0b08853SJan Glauber 161d0b08853SJan Glauber void zpci_debug_exit_device(struct zpci_dev *zdev) 162d0b08853SJan Glauber { 163d0b08853SJan Glauber debugfs_remove(zdev->debugfs_perf); 164d0b08853SJan Glauber debugfs_remove(zdev->debugfs_debug); 165d0b08853SJan Glauber debugfs_remove(zdev->debugfs_dev); 166d0b08853SJan Glauber } 167d0b08853SJan Glauber 168d0b08853SJan Glauber int __init zpci_debug_init(void) 169d0b08853SJan Glauber { 170d0b08853SJan Glauber /* event trace buffer */ 171d0b08853SJan Glauber pci_debug_msg_id = debug_register("pci_msg", 16, 1, 16 * sizeof(long)); 172d0b08853SJan Glauber if (!pci_debug_msg_id) 173d0b08853SJan Glauber return -EINVAL; 174d0b08853SJan Glauber debug_register_view(pci_debug_msg_id, &debug_sprintf_view); 175d0b08853SJan Glauber debug_set_level(pci_debug_msg_id, 3); 176d0b08853SJan Glauber 177d0b08853SJan Glauber /* error log */ 178d0b08853SJan Glauber pci_debug_err_id = debug_register("pci_error", 2, 1, 16); 179d0b08853SJan Glauber if (!pci_debug_err_id) 180d0b08853SJan Glauber return -EINVAL; 181d0b08853SJan Glauber debug_register_view(pci_debug_err_id, &debug_hex_ascii_view); 182d0b08853SJan Glauber debug_set_level(pci_debug_err_id, 6); 183d0b08853SJan Glauber 184d0b08853SJan Glauber debugfs_root = debugfs_create_dir("pci", NULL); 185d0b08853SJan Glauber return 0; 186d0b08853SJan Glauber } 187d0b08853SJan Glauber 188d0b08853SJan Glauber void zpci_debug_exit(void) 189d0b08853SJan Glauber { 190d0b08853SJan Glauber if (pci_debug_msg_id) 191d0b08853SJan Glauber debug_unregister(pci_debug_msg_id); 192d0b08853SJan Glauber if (pci_debug_err_id) 193d0b08853SJan Glauber debug_unregister(pci_debug_err_id); 194d0b08853SJan Glauber 195d0b08853SJan Glauber debugfs_remove(debugfs_root); 196d0b08853SJan Glauber } 197