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