File Index
Files and directories
Sign in
FILE

pci_debug.c

File preview with syntax highlighting.

linux-6.19.14/arch/s390/pci/pci_debug.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 *  Copyright IBM Corp. 2012,2015
  4 *
  5 *  Author(s):
  6 *    Jan Glauber <jang@linux.vnet.ibm.com>
  7 */
  8
  9#define pr_fmt(fmt) "zpci: " fmt
 10
 11#include <linux/kernel.h>
 12#include <linux/seq_file.h>
 13#include <linux/debugfs.h>
 14#include <linux/export.h>
 15#include <linux/pci.h>
 16#include <asm/debug.h>
 17
 18#include <asm/pci_dma.h>
 19
 20static struct dentry *debugfs_root;
 21debug_info_t *pci_debug_msg_id;
 22EXPORT_SYMBOL_GPL(pci_debug_msg_id);
 23debug_info_t *pci_debug_err_id;
 24EXPORT_SYMBOL_GPL(pci_debug_err_id);
 25
 26static char *pci_common_names[] = {
 27	"Load operations",
 28	"Store operations",
 29	"Store block operations",
 30	"Refresh operations",
 31};
 32
 33static char *pci_fmt0_names[] = {
 34	"DMA read bytes",
 35	"DMA write bytes",
 36};
 37
 38static char *pci_fmt1_names[] = {
 39	"Received bytes",
 40	"Received packets",
 41	"Transmitted bytes",
 42	"Transmitted packets",
 43};
 44
 45static char *pci_fmt2_names[] = {
 46	"Consumed work units",
 47	"Maximum work units",
 48};
 49
 50static char *pci_fmt3_names[] = {
 51	"Transmitted bytes",
 52};
 53
 54static char *pci_sw_names[] = {
 55	"Mapped pages",
 56	"Unmapped pages",
 57	"Global RPCITs",
 58	"Sync Map RPCITs",
 59	"Sync RPCITs",
 60};
 61
 62static void pci_fmb_show(struct seq_file *m, char *name[], int length,
 63			 u64 *data)
 64{
 65	int i;
 66
 67	for (i = 0; i < length; i++, data++)
 68		seq_printf(m, "%26s:\t%llu\n", name[i], *data);
 69}
 70
 71static void pci_sw_counter_show(struct seq_file *m)
 72{
 73	struct zpci_dev *zdev = m->private;
 74	struct zpci_iommu_ctrs *ctrs;
 75	atomic64_t *counter;
 76	unsigned long flags;
 77	int i;
 78
 79	spin_lock_irqsave(&zdev->dom_lock, flags);
 80	ctrs = zpci_get_iommu_ctrs(m->private);
 81	if (!ctrs)
 82		goto unlock;
 83
 84	counter = &ctrs->mapped_pages;
 85	for (i = 0; i < ARRAY_SIZE(pci_sw_names); i++, counter++)
 86		seq_printf(m, "%26s:\t%llu\n", pci_sw_names[i],
 87			   atomic64_read(counter));
 88unlock:
 89	spin_unlock_irqrestore(&zdev->dom_lock, flags);
 90}
 91
 92static int pci_perf_show(struct seq_file *m, void *v)
 93{
 94	struct zpci_dev *zdev = m->private;
 95
 96	if (!zdev)
 97		return 0;
 98
 99	mutex_lock(&zdev->fmb_lock);
100	if (!zdev->fmb) {
101		mutex_unlock(&zdev->fmb_lock);
102		seq_puts(m, "FMB statistics disabled\n");
103		return 0;
104	}
105
106	/* header */
107	seq_printf(m, "Update interval: %u ms\n", zdev->fmb_update);
108	seq_printf(m, "Samples: %u\n", zdev->fmb->samples);
109	seq_printf(m, "Last update TOD: %Lx\n", zdev->fmb->last_update);
110
111	pci_fmb_show(m, pci_common_names, ARRAY_SIZE(pci_common_names),
112		     &zdev->fmb->ld_ops);
113
114	switch (zdev->fmb->format) {
115	case 0:
116		if (!(zdev->fmb->fmt_ind & ZPCI_FMB_DMA_COUNTER_VALID))
117			break;
118		pci_fmb_show(m, pci_fmt0_names, ARRAY_SIZE(pci_fmt0_names),
119			     &zdev->fmb->fmt0.dma_rbytes);
120		break;
121	case 1:
122		pci_fmb_show(m, pci_fmt1_names, ARRAY_SIZE(pci_fmt1_names),
123			     &zdev->fmb->fmt1.rx_bytes);
124		break;
125	case 2:
126		pci_fmb_show(m, pci_fmt2_names, ARRAY_SIZE(pci_fmt2_names),
127			     &zdev->fmb->fmt2.consumed_work_units);
128		break;
129	case 3:
130		pci_fmb_show(m, pci_fmt3_names, ARRAY_SIZE(pci_fmt3_names),
131			     &zdev->fmb->fmt3.tx_bytes);
132		break;
133	default:
134		seq_puts(m, "Unknown format\n");
135	}
136
137	pci_sw_counter_show(m);
138	mutex_unlock(&zdev->fmb_lock);
139	return 0;
140}
141
142static ssize_t pci_perf_seq_write(struct file *file, const char __user *ubuf,
143				  size_t count, loff_t *off)
144{
145	struct zpci_dev *zdev = ((struct seq_file *) file->private_data)->private;
146	unsigned long val;
147	int rc;
148
149	if (!zdev)
150		return 0;
151
152	rc = kstrtoul_from_user(ubuf, count, 10, &val);
153	if (rc)
154		return rc;
155
156	mutex_lock(&zdev->fmb_lock);
157	switch (val) {
158	case 0:
159		rc = zpci_fmb_disable_device(zdev);
160		break;
161	case 1:
162		rc = zpci_fmb_enable_device(zdev);
163		break;
164	}
165	mutex_unlock(&zdev->fmb_lock);
166	return rc ? rc : count;
167}
168
169static int pci_perf_seq_open(struct inode *inode, struct file *filp)
170{
171	return single_open(filp, pci_perf_show,
172			   file_inode(filp)->i_private);
173}
174
175static const struct file_operations debugfs_pci_perf_fops = {
176	.open	 = pci_perf_seq_open,
177	.read	 = seq_read,
178	.write	 = pci_perf_seq_write,
179	.llseek  = seq_lseek,
180	.release = single_release,
181};
182
183void zpci_debug_init_device(struct zpci_dev *zdev, const char *name)
184{
185	zdev->debugfs_dev = debugfs_create_dir(name, debugfs_root);
186
187	debugfs_create_file("statistics", S_IFREG | S_IRUGO | S_IWUSR,
188			    zdev->debugfs_dev, zdev, &debugfs_pci_perf_fops);
189}
190
191void zpci_debug_exit_device(struct zpci_dev *zdev)
192{
193	debugfs_remove_recursive(zdev->debugfs_dev);
194}
195
196int __init zpci_debug_init(void)
197{
198	/* event trace buffer */
199	pci_debug_msg_id = debug_register("pci_msg", 8, 1, 8 * sizeof(long));
200	if (!pci_debug_msg_id)
201		return -EINVAL;
202	debug_register_view(pci_debug_msg_id, &debug_sprintf_view);
203	debug_set_level(pci_debug_msg_id, 3);
204
205	/* error log */
206	pci_debug_err_id = debug_register("pci_error", 2, 1, 16);
207	if (!pci_debug_err_id)
208		return -EINVAL;
209	debug_register_view(pci_debug_err_id, &debug_hex_ascii_view);
210	debug_set_level(pci_debug_err_id, 3);
211
212	debugfs_root = debugfs_create_dir("pci", NULL);
213	return 0;
214}
215
216void zpci_debug_exit(void)
217{
218	debug_unregister(pci_debug_msg_id);
219	debug_unregister(pci_debug_err_id);
220	debugfs_remove(debugfs_root);
221}
~/ Read-only file preview.