1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright(c) 2015-2018 Intel Corporation.
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * This file is provided under a dual BSD/GPLv2 license. When using or
5*4882a593Smuzhiyun * redistributing this file, you may do so under either license.
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * GPL LICENSE SUMMARY
8*4882a593Smuzhiyun *
9*4882a593Smuzhiyun * This program is free software; you can redistribute it and/or modify
10*4882a593Smuzhiyun * it under the terms of version 2 of the GNU General Public License as
11*4882a593Smuzhiyun * published by the Free Software Foundation.
12*4882a593Smuzhiyun *
13*4882a593Smuzhiyun * This program is distributed in the hope that it will be useful, but
14*4882a593Smuzhiyun * WITHOUT ANY WARRANTY; without even the implied warranty of
15*4882a593Smuzhiyun * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16*4882a593Smuzhiyun * General Public License for more details.
17*4882a593Smuzhiyun *
18*4882a593Smuzhiyun * BSD LICENSE
19*4882a593Smuzhiyun *
20*4882a593Smuzhiyun * Redistribution and use in source and binary forms, with or without
21*4882a593Smuzhiyun * modification, are permitted provided that the following conditions
22*4882a593Smuzhiyun * are met:
23*4882a593Smuzhiyun *
24*4882a593Smuzhiyun * - Redistributions of source code must retain the above copyright
25*4882a593Smuzhiyun * notice, this list of conditions and the following disclaimer.
26*4882a593Smuzhiyun * - Redistributions in binary form must reproduce the above copyright
27*4882a593Smuzhiyun * notice, this list of conditions and the following disclaimer in
28*4882a593Smuzhiyun * the documentation and/or other materials provided with the
29*4882a593Smuzhiyun * distribution.
30*4882a593Smuzhiyun * - Neither the name of Intel Corporation nor the names of its
31*4882a593Smuzhiyun * contributors may be used to endorse or promote products derived
32*4882a593Smuzhiyun * from this software without specific prior written permission.
33*4882a593Smuzhiyun *
34*4882a593Smuzhiyun * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
35*4882a593Smuzhiyun * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
36*4882a593Smuzhiyun * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
37*4882a593Smuzhiyun * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
38*4882a593Smuzhiyun * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
39*4882a593Smuzhiyun * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
40*4882a593Smuzhiyun * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
41*4882a593Smuzhiyun * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
42*4882a593Smuzhiyun * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
43*4882a593Smuzhiyun * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
44*4882a593Smuzhiyun * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
45*4882a593Smuzhiyun *
46*4882a593Smuzhiyun */
47*4882a593Smuzhiyun #include <linux/debugfs.h>
48*4882a593Smuzhiyun #include <linux/seq_file.h>
49*4882a593Smuzhiyun #include <linux/kernel.h>
50*4882a593Smuzhiyun #include <linux/export.h>
51*4882a593Smuzhiyun #include <linux/module.h>
52*4882a593Smuzhiyun #include <linux/string.h>
53*4882a593Smuzhiyun #include <linux/types.h>
54*4882a593Smuzhiyun #include <linux/ratelimit.h>
55*4882a593Smuzhiyun #include <linux/fault-inject.h>
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun #include "hfi.h"
58*4882a593Smuzhiyun #include "trace.h"
59*4882a593Smuzhiyun #include "debugfs.h"
60*4882a593Smuzhiyun #include "device.h"
61*4882a593Smuzhiyun #include "qp.h"
62*4882a593Smuzhiyun #include "sdma.h"
63*4882a593Smuzhiyun #include "fault.h"
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun static struct dentry *hfi1_dbg_root;
66*4882a593Smuzhiyun
67*4882a593Smuzhiyun /* wrappers to enforce srcu in seq file */
hfi1_seq_read(struct file * file,char __user * buf,size_t size,loff_t * ppos)68*4882a593Smuzhiyun ssize_t hfi1_seq_read(struct file *file, char __user *buf, size_t size,
69*4882a593Smuzhiyun loff_t *ppos)
70*4882a593Smuzhiyun {
71*4882a593Smuzhiyun struct dentry *d = file->f_path.dentry;
72*4882a593Smuzhiyun ssize_t r;
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun r = debugfs_file_get(d);
75*4882a593Smuzhiyun if (unlikely(r))
76*4882a593Smuzhiyun return r;
77*4882a593Smuzhiyun r = seq_read(file, buf, size, ppos);
78*4882a593Smuzhiyun debugfs_file_put(d);
79*4882a593Smuzhiyun return r;
80*4882a593Smuzhiyun }
81*4882a593Smuzhiyun
hfi1_seq_lseek(struct file * file,loff_t offset,int whence)82*4882a593Smuzhiyun loff_t hfi1_seq_lseek(struct file *file, loff_t offset, int whence)
83*4882a593Smuzhiyun {
84*4882a593Smuzhiyun struct dentry *d = file->f_path.dentry;
85*4882a593Smuzhiyun loff_t r;
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun r = debugfs_file_get(d);
88*4882a593Smuzhiyun if (unlikely(r))
89*4882a593Smuzhiyun return r;
90*4882a593Smuzhiyun r = seq_lseek(file, offset, whence);
91*4882a593Smuzhiyun debugfs_file_put(d);
92*4882a593Smuzhiyun return r;
93*4882a593Smuzhiyun }
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun #define private2dd(file) (file_inode(file)->i_private)
96*4882a593Smuzhiyun #define private2ppd(file) (file_inode(file)->i_private)
97*4882a593Smuzhiyun
_opcode_stats_seq_start(struct seq_file * s,loff_t * pos)98*4882a593Smuzhiyun static void *_opcode_stats_seq_start(struct seq_file *s, loff_t *pos)
99*4882a593Smuzhiyun {
100*4882a593Smuzhiyun struct hfi1_opcode_stats_perctx *opstats;
101*4882a593Smuzhiyun
102*4882a593Smuzhiyun if (*pos >= ARRAY_SIZE(opstats->stats))
103*4882a593Smuzhiyun return NULL;
104*4882a593Smuzhiyun return pos;
105*4882a593Smuzhiyun }
106*4882a593Smuzhiyun
_opcode_stats_seq_next(struct seq_file * s,void * v,loff_t * pos)107*4882a593Smuzhiyun static void *_opcode_stats_seq_next(struct seq_file *s, void *v, loff_t *pos)
108*4882a593Smuzhiyun {
109*4882a593Smuzhiyun struct hfi1_opcode_stats_perctx *opstats;
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun ++*pos;
112*4882a593Smuzhiyun if (*pos >= ARRAY_SIZE(opstats->stats))
113*4882a593Smuzhiyun return NULL;
114*4882a593Smuzhiyun return pos;
115*4882a593Smuzhiyun }
116*4882a593Smuzhiyun
_opcode_stats_seq_stop(struct seq_file * s,void * v)117*4882a593Smuzhiyun static void _opcode_stats_seq_stop(struct seq_file *s, void *v)
118*4882a593Smuzhiyun {
119*4882a593Smuzhiyun }
120*4882a593Smuzhiyun
opcode_stats_show(struct seq_file * s,u8 i,u64 packets,u64 bytes)121*4882a593Smuzhiyun static int opcode_stats_show(struct seq_file *s, u8 i, u64 packets, u64 bytes)
122*4882a593Smuzhiyun {
123*4882a593Smuzhiyun if (!packets && !bytes)
124*4882a593Smuzhiyun return SEQ_SKIP;
125*4882a593Smuzhiyun seq_printf(s, "%02x %llu/%llu\n", i,
126*4882a593Smuzhiyun (unsigned long long)packets,
127*4882a593Smuzhiyun (unsigned long long)bytes);
128*4882a593Smuzhiyun
129*4882a593Smuzhiyun return 0;
130*4882a593Smuzhiyun }
131*4882a593Smuzhiyun
_opcode_stats_seq_show(struct seq_file * s,void * v)132*4882a593Smuzhiyun static int _opcode_stats_seq_show(struct seq_file *s, void *v)
133*4882a593Smuzhiyun {
134*4882a593Smuzhiyun loff_t *spos = v;
135*4882a593Smuzhiyun loff_t i = *spos, j;
136*4882a593Smuzhiyun u64 n_packets = 0, n_bytes = 0;
137*4882a593Smuzhiyun struct hfi1_ibdev *ibd = (struct hfi1_ibdev *)s->private;
138*4882a593Smuzhiyun struct hfi1_devdata *dd = dd_from_dev(ibd);
139*4882a593Smuzhiyun struct hfi1_ctxtdata *rcd;
140*4882a593Smuzhiyun
141*4882a593Smuzhiyun for (j = 0; j < dd->first_dyn_alloc_ctxt; j++) {
142*4882a593Smuzhiyun rcd = hfi1_rcd_get_by_index(dd, j);
143*4882a593Smuzhiyun if (rcd) {
144*4882a593Smuzhiyun n_packets += rcd->opstats->stats[i].n_packets;
145*4882a593Smuzhiyun n_bytes += rcd->opstats->stats[i].n_bytes;
146*4882a593Smuzhiyun }
147*4882a593Smuzhiyun hfi1_rcd_put(rcd);
148*4882a593Smuzhiyun }
149*4882a593Smuzhiyun return opcode_stats_show(s, i, n_packets, n_bytes);
150*4882a593Smuzhiyun }
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun DEBUGFS_SEQ_FILE_OPS(opcode_stats);
153*4882a593Smuzhiyun DEBUGFS_SEQ_FILE_OPEN(opcode_stats)
154*4882a593Smuzhiyun DEBUGFS_FILE_OPS(opcode_stats);
155*4882a593Smuzhiyun
_tx_opcode_stats_seq_start(struct seq_file * s,loff_t * pos)156*4882a593Smuzhiyun static void *_tx_opcode_stats_seq_start(struct seq_file *s, loff_t *pos)
157*4882a593Smuzhiyun {
158*4882a593Smuzhiyun return _opcode_stats_seq_start(s, pos);
159*4882a593Smuzhiyun }
160*4882a593Smuzhiyun
_tx_opcode_stats_seq_next(struct seq_file * s,void * v,loff_t * pos)161*4882a593Smuzhiyun static void *_tx_opcode_stats_seq_next(struct seq_file *s, void *v, loff_t *pos)
162*4882a593Smuzhiyun {
163*4882a593Smuzhiyun return _opcode_stats_seq_next(s, v, pos);
164*4882a593Smuzhiyun }
165*4882a593Smuzhiyun
_tx_opcode_stats_seq_stop(struct seq_file * s,void * v)166*4882a593Smuzhiyun static void _tx_opcode_stats_seq_stop(struct seq_file *s, void *v)
167*4882a593Smuzhiyun {
168*4882a593Smuzhiyun }
169*4882a593Smuzhiyun
_tx_opcode_stats_seq_show(struct seq_file * s,void * v)170*4882a593Smuzhiyun static int _tx_opcode_stats_seq_show(struct seq_file *s, void *v)
171*4882a593Smuzhiyun {
172*4882a593Smuzhiyun loff_t *spos = v;
173*4882a593Smuzhiyun loff_t i = *spos;
174*4882a593Smuzhiyun int j;
175*4882a593Smuzhiyun u64 n_packets = 0, n_bytes = 0;
176*4882a593Smuzhiyun struct hfi1_ibdev *ibd = (struct hfi1_ibdev *)s->private;
177*4882a593Smuzhiyun struct hfi1_devdata *dd = dd_from_dev(ibd);
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun for_each_possible_cpu(j) {
180*4882a593Smuzhiyun struct hfi1_opcode_stats_perctx *s =
181*4882a593Smuzhiyun per_cpu_ptr(dd->tx_opstats, j);
182*4882a593Smuzhiyun n_packets += s->stats[i].n_packets;
183*4882a593Smuzhiyun n_bytes += s->stats[i].n_bytes;
184*4882a593Smuzhiyun }
185*4882a593Smuzhiyun return opcode_stats_show(s, i, n_packets, n_bytes);
186*4882a593Smuzhiyun }
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun DEBUGFS_SEQ_FILE_OPS(tx_opcode_stats);
189*4882a593Smuzhiyun DEBUGFS_SEQ_FILE_OPEN(tx_opcode_stats)
190*4882a593Smuzhiyun DEBUGFS_FILE_OPS(tx_opcode_stats);
191*4882a593Smuzhiyun
_ctx_stats_seq_start(struct seq_file * s,loff_t * pos)192*4882a593Smuzhiyun static void *_ctx_stats_seq_start(struct seq_file *s, loff_t *pos)
193*4882a593Smuzhiyun {
194*4882a593Smuzhiyun struct hfi1_ibdev *ibd = (struct hfi1_ibdev *)s->private;
195*4882a593Smuzhiyun struct hfi1_devdata *dd = dd_from_dev(ibd);
196*4882a593Smuzhiyun
197*4882a593Smuzhiyun if (!*pos)
198*4882a593Smuzhiyun return SEQ_START_TOKEN;
199*4882a593Smuzhiyun if (*pos >= dd->first_dyn_alloc_ctxt)
200*4882a593Smuzhiyun return NULL;
201*4882a593Smuzhiyun return pos;
202*4882a593Smuzhiyun }
203*4882a593Smuzhiyun
_ctx_stats_seq_next(struct seq_file * s,void * v,loff_t * pos)204*4882a593Smuzhiyun static void *_ctx_stats_seq_next(struct seq_file *s, void *v, loff_t *pos)
205*4882a593Smuzhiyun {
206*4882a593Smuzhiyun struct hfi1_ibdev *ibd = (struct hfi1_ibdev *)s->private;
207*4882a593Smuzhiyun struct hfi1_devdata *dd = dd_from_dev(ibd);
208*4882a593Smuzhiyun
209*4882a593Smuzhiyun if (v == SEQ_START_TOKEN)
210*4882a593Smuzhiyun return pos;
211*4882a593Smuzhiyun
212*4882a593Smuzhiyun ++*pos;
213*4882a593Smuzhiyun if (*pos >= dd->first_dyn_alloc_ctxt)
214*4882a593Smuzhiyun return NULL;
215*4882a593Smuzhiyun return pos;
216*4882a593Smuzhiyun }
217*4882a593Smuzhiyun
_ctx_stats_seq_stop(struct seq_file * s,void * v)218*4882a593Smuzhiyun static void _ctx_stats_seq_stop(struct seq_file *s, void *v)
219*4882a593Smuzhiyun {
220*4882a593Smuzhiyun /* nothing allocated */
221*4882a593Smuzhiyun }
222*4882a593Smuzhiyun
_ctx_stats_seq_show(struct seq_file * s,void * v)223*4882a593Smuzhiyun static int _ctx_stats_seq_show(struct seq_file *s, void *v)
224*4882a593Smuzhiyun {
225*4882a593Smuzhiyun loff_t *spos;
226*4882a593Smuzhiyun loff_t i, j;
227*4882a593Smuzhiyun u64 n_packets = 0;
228*4882a593Smuzhiyun struct hfi1_ibdev *ibd = (struct hfi1_ibdev *)s->private;
229*4882a593Smuzhiyun struct hfi1_devdata *dd = dd_from_dev(ibd);
230*4882a593Smuzhiyun struct hfi1_ctxtdata *rcd;
231*4882a593Smuzhiyun
232*4882a593Smuzhiyun if (v == SEQ_START_TOKEN) {
233*4882a593Smuzhiyun seq_puts(s, "Ctx:npkts\n");
234*4882a593Smuzhiyun return 0;
235*4882a593Smuzhiyun }
236*4882a593Smuzhiyun
237*4882a593Smuzhiyun spos = v;
238*4882a593Smuzhiyun i = *spos;
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun rcd = hfi1_rcd_get_by_index_safe(dd, i);
241*4882a593Smuzhiyun if (!rcd)
242*4882a593Smuzhiyun return SEQ_SKIP;
243*4882a593Smuzhiyun
244*4882a593Smuzhiyun for (j = 0; j < ARRAY_SIZE(rcd->opstats->stats); j++)
245*4882a593Smuzhiyun n_packets += rcd->opstats->stats[j].n_packets;
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun hfi1_rcd_put(rcd);
248*4882a593Smuzhiyun
249*4882a593Smuzhiyun if (!n_packets)
250*4882a593Smuzhiyun return SEQ_SKIP;
251*4882a593Smuzhiyun
252*4882a593Smuzhiyun seq_printf(s, " %llu:%llu\n", i, n_packets);
253*4882a593Smuzhiyun return 0;
254*4882a593Smuzhiyun }
255*4882a593Smuzhiyun
256*4882a593Smuzhiyun DEBUGFS_SEQ_FILE_OPS(ctx_stats);
257*4882a593Smuzhiyun DEBUGFS_SEQ_FILE_OPEN(ctx_stats)
258*4882a593Smuzhiyun DEBUGFS_FILE_OPS(ctx_stats);
259*4882a593Smuzhiyun
_qp_stats_seq_start(struct seq_file * s,loff_t * pos)260*4882a593Smuzhiyun static void *_qp_stats_seq_start(struct seq_file *s, loff_t *pos)
261*4882a593Smuzhiyun __acquires(RCU)
262*4882a593Smuzhiyun {
263*4882a593Smuzhiyun struct rvt_qp_iter *iter;
264*4882a593Smuzhiyun loff_t n = *pos;
265*4882a593Smuzhiyun
266*4882a593Smuzhiyun iter = rvt_qp_iter_init(s->private, 0, NULL);
267*4882a593Smuzhiyun
268*4882a593Smuzhiyun /* stop calls rcu_read_unlock */
269*4882a593Smuzhiyun rcu_read_lock();
270*4882a593Smuzhiyun
271*4882a593Smuzhiyun if (!iter)
272*4882a593Smuzhiyun return NULL;
273*4882a593Smuzhiyun
274*4882a593Smuzhiyun do {
275*4882a593Smuzhiyun if (rvt_qp_iter_next(iter)) {
276*4882a593Smuzhiyun kfree(iter);
277*4882a593Smuzhiyun return NULL;
278*4882a593Smuzhiyun }
279*4882a593Smuzhiyun } while (n--);
280*4882a593Smuzhiyun
281*4882a593Smuzhiyun return iter;
282*4882a593Smuzhiyun }
283*4882a593Smuzhiyun
_qp_stats_seq_next(struct seq_file * s,void * iter_ptr,loff_t * pos)284*4882a593Smuzhiyun static void *_qp_stats_seq_next(struct seq_file *s, void *iter_ptr,
285*4882a593Smuzhiyun loff_t *pos)
286*4882a593Smuzhiyun __must_hold(RCU)
287*4882a593Smuzhiyun {
288*4882a593Smuzhiyun struct rvt_qp_iter *iter = iter_ptr;
289*4882a593Smuzhiyun
290*4882a593Smuzhiyun (*pos)++;
291*4882a593Smuzhiyun
292*4882a593Smuzhiyun if (rvt_qp_iter_next(iter)) {
293*4882a593Smuzhiyun kfree(iter);
294*4882a593Smuzhiyun return NULL;
295*4882a593Smuzhiyun }
296*4882a593Smuzhiyun
297*4882a593Smuzhiyun return iter;
298*4882a593Smuzhiyun }
299*4882a593Smuzhiyun
_qp_stats_seq_stop(struct seq_file * s,void * iter_ptr)300*4882a593Smuzhiyun static void _qp_stats_seq_stop(struct seq_file *s, void *iter_ptr)
301*4882a593Smuzhiyun __releases(RCU)
302*4882a593Smuzhiyun {
303*4882a593Smuzhiyun rcu_read_unlock();
304*4882a593Smuzhiyun }
305*4882a593Smuzhiyun
_qp_stats_seq_show(struct seq_file * s,void * iter_ptr)306*4882a593Smuzhiyun static int _qp_stats_seq_show(struct seq_file *s, void *iter_ptr)
307*4882a593Smuzhiyun {
308*4882a593Smuzhiyun struct rvt_qp_iter *iter = iter_ptr;
309*4882a593Smuzhiyun
310*4882a593Smuzhiyun if (!iter)
311*4882a593Smuzhiyun return 0;
312*4882a593Smuzhiyun
313*4882a593Smuzhiyun qp_iter_print(s, iter);
314*4882a593Smuzhiyun
315*4882a593Smuzhiyun return 0;
316*4882a593Smuzhiyun }
317*4882a593Smuzhiyun
318*4882a593Smuzhiyun DEBUGFS_SEQ_FILE_OPS(qp_stats);
319*4882a593Smuzhiyun DEBUGFS_SEQ_FILE_OPEN(qp_stats)
320*4882a593Smuzhiyun DEBUGFS_FILE_OPS(qp_stats);
321*4882a593Smuzhiyun
_sdes_seq_start(struct seq_file * s,loff_t * pos)322*4882a593Smuzhiyun static void *_sdes_seq_start(struct seq_file *s, loff_t *pos)
323*4882a593Smuzhiyun {
324*4882a593Smuzhiyun struct hfi1_ibdev *ibd;
325*4882a593Smuzhiyun struct hfi1_devdata *dd;
326*4882a593Smuzhiyun
327*4882a593Smuzhiyun ibd = (struct hfi1_ibdev *)s->private;
328*4882a593Smuzhiyun dd = dd_from_dev(ibd);
329*4882a593Smuzhiyun if (!dd->per_sdma || *pos >= dd->num_sdma)
330*4882a593Smuzhiyun return NULL;
331*4882a593Smuzhiyun return pos;
332*4882a593Smuzhiyun }
333*4882a593Smuzhiyun
_sdes_seq_next(struct seq_file * s,void * v,loff_t * pos)334*4882a593Smuzhiyun static void *_sdes_seq_next(struct seq_file *s, void *v, loff_t *pos)
335*4882a593Smuzhiyun {
336*4882a593Smuzhiyun struct hfi1_ibdev *ibd = (struct hfi1_ibdev *)s->private;
337*4882a593Smuzhiyun struct hfi1_devdata *dd = dd_from_dev(ibd);
338*4882a593Smuzhiyun
339*4882a593Smuzhiyun ++*pos;
340*4882a593Smuzhiyun if (!dd->per_sdma || *pos >= dd->num_sdma)
341*4882a593Smuzhiyun return NULL;
342*4882a593Smuzhiyun return pos;
343*4882a593Smuzhiyun }
344*4882a593Smuzhiyun
_sdes_seq_stop(struct seq_file * s,void * v)345*4882a593Smuzhiyun static void _sdes_seq_stop(struct seq_file *s, void *v)
346*4882a593Smuzhiyun {
347*4882a593Smuzhiyun }
348*4882a593Smuzhiyun
_sdes_seq_show(struct seq_file * s,void * v)349*4882a593Smuzhiyun static int _sdes_seq_show(struct seq_file *s, void *v)
350*4882a593Smuzhiyun {
351*4882a593Smuzhiyun struct hfi1_ibdev *ibd = (struct hfi1_ibdev *)s->private;
352*4882a593Smuzhiyun struct hfi1_devdata *dd = dd_from_dev(ibd);
353*4882a593Smuzhiyun loff_t *spos = v;
354*4882a593Smuzhiyun loff_t i = *spos;
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun sdma_seqfile_dump_sde(s, &dd->per_sdma[i]);
357*4882a593Smuzhiyun return 0;
358*4882a593Smuzhiyun }
359*4882a593Smuzhiyun
360*4882a593Smuzhiyun DEBUGFS_SEQ_FILE_OPS(sdes);
361*4882a593Smuzhiyun DEBUGFS_SEQ_FILE_OPEN(sdes)
362*4882a593Smuzhiyun DEBUGFS_FILE_OPS(sdes);
363*4882a593Smuzhiyun
_rcds_seq_start(struct seq_file * s,loff_t * pos)364*4882a593Smuzhiyun static void *_rcds_seq_start(struct seq_file *s, loff_t *pos)
365*4882a593Smuzhiyun {
366*4882a593Smuzhiyun struct hfi1_ibdev *ibd;
367*4882a593Smuzhiyun struct hfi1_devdata *dd;
368*4882a593Smuzhiyun
369*4882a593Smuzhiyun ibd = (struct hfi1_ibdev *)s->private;
370*4882a593Smuzhiyun dd = dd_from_dev(ibd);
371*4882a593Smuzhiyun if (!dd->rcd || *pos >= dd->n_krcv_queues)
372*4882a593Smuzhiyun return NULL;
373*4882a593Smuzhiyun return pos;
374*4882a593Smuzhiyun }
375*4882a593Smuzhiyun
_rcds_seq_next(struct seq_file * s,void * v,loff_t * pos)376*4882a593Smuzhiyun static void *_rcds_seq_next(struct seq_file *s, void *v, loff_t *pos)
377*4882a593Smuzhiyun {
378*4882a593Smuzhiyun struct hfi1_ibdev *ibd = (struct hfi1_ibdev *)s->private;
379*4882a593Smuzhiyun struct hfi1_devdata *dd = dd_from_dev(ibd);
380*4882a593Smuzhiyun
381*4882a593Smuzhiyun ++*pos;
382*4882a593Smuzhiyun if (!dd->rcd || *pos >= dd->num_rcv_contexts)
383*4882a593Smuzhiyun return NULL;
384*4882a593Smuzhiyun return pos;
385*4882a593Smuzhiyun }
386*4882a593Smuzhiyun
_rcds_seq_stop(struct seq_file * s,void * v)387*4882a593Smuzhiyun static void _rcds_seq_stop(struct seq_file *s, void *v)
388*4882a593Smuzhiyun {
389*4882a593Smuzhiyun }
390*4882a593Smuzhiyun
_rcds_seq_show(struct seq_file * s,void * v)391*4882a593Smuzhiyun static int _rcds_seq_show(struct seq_file *s, void *v)
392*4882a593Smuzhiyun {
393*4882a593Smuzhiyun struct hfi1_ibdev *ibd = (struct hfi1_ibdev *)s->private;
394*4882a593Smuzhiyun struct hfi1_devdata *dd = dd_from_dev(ibd);
395*4882a593Smuzhiyun struct hfi1_ctxtdata *rcd;
396*4882a593Smuzhiyun loff_t *spos = v;
397*4882a593Smuzhiyun loff_t i = *spos;
398*4882a593Smuzhiyun
399*4882a593Smuzhiyun rcd = hfi1_rcd_get_by_index_safe(dd, i);
400*4882a593Smuzhiyun if (rcd)
401*4882a593Smuzhiyun seqfile_dump_rcd(s, rcd);
402*4882a593Smuzhiyun hfi1_rcd_put(rcd);
403*4882a593Smuzhiyun return 0;
404*4882a593Smuzhiyun }
405*4882a593Smuzhiyun
406*4882a593Smuzhiyun DEBUGFS_SEQ_FILE_OPS(rcds);
407*4882a593Smuzhiyun DEBUGFS_SEQ_FILE_OPEN(rcds)
408*4882a593Smuzhiyun DEBUGFS_FILE_OPS(rcds);
409*4882a593Smuzhiyun
_pios_seq_start(struct seq_file * s,loff_t * pos)410*4882a593Smuzhiyun static void *_pios_seq_start(struct seq_file *s, loff_t *pos)
411*4882a593Smuzhiyun {
412*4882a593Smuzhiyun struct hfi1_ibdev *ibd;
413*4882a593Smuzhiyun struct hfi1_devdata *dd;
414*4882a593Smuzhiyun
415*4882a593Smuzhiyun ibd = (struct hfi1_ibdev *)s->private;
416*4882a593Smuzhiyun dd = dd_from_dev(ibd);
417*4882a593Smuzhiyun if (!dd->send_contexts || *pos >= dd->num_send_contexts)
418*4882a593Smuzhiyun return NULL;
419*4882a593Smuzhiyun return pos;
420*4882a593Smuzhiyun }
421*4882a593Smuzhiyun
_pios_seq_next(struct seq_file * s,void * v,loff_t * pos)422*4882a593Smuzhiyun static void *_pios_seq_next(struct seq_file *s, void *v, loff_t *pos)
423*4882a593Smuzhiyun {
424*4882a593Smuzhiyun struct hfi1_ibdev *ibd = (struct hfi1_ibdev *)s->private;
425*4882a593Smuzhiyun struct hfi1_devdata *dd = dd_from_dev(ibd);
426*4882a593Smuzhiyun
427*4882a593Smuzhiyun ++*pos;
428*4882a593Smuzhiyun if (!dd->send_contexts || *pos >= dd->num_send_contexts)
429*4882a593Smuzhiyun return NULL;
430*4882a593Smuzhiyun return pos;
431*4882a593Smuzhiyun }
432*4882a593Smuzhiyun
_pios_seq_stop(struct seq_file * s,void * v)433*4882a593Smuzhiyun static void _pios_seq_stop(struct seq_file *s, void *v)
434*4882a593Smuzhiyun {
435*4882a593Smuzhiyun }
436*4882a593Smuzhiyun
_pios_seq_show(struct seq_file * s,void * v)437*4882a593Smuzhiyun static int _pios_seq_show(struct seq_file *s, void *v)
438*4882a593Smuzhiyun {
439*4882a593Smuzhiyun struct hfi1_ibdev *ibd = (struct hfi1_ibdev *)s->private;
440*4882a593Smuzhiyun struct hfi1_devdata *dd = dd_from_dev(ibd);
441*4882a593Smuzhiyun struct send_context_info *sci;
442*4882a593Smuzhiyun loff_t *spos = v;
443*4882a593Smuzhiyun loff_t i = *spos;
444*4882a593Smuzhiyun unsigned long flags;
445*4882a593Smuzhiyun
446*4882a593Smuzhiyun spin_lock_irqsave(&dd->sc_lock, flags);
447*4882a593Smuzhiyun sci = &dd->send_contexts[i];
448*4882a593Smuzhiyun if (sci && sci->type != SC_USER && sci->allocated && sci->sc)
449*4882a593Smuzhiyun seqfile_dump_sci(s, i, sci);
450*4882a593Smuzhiyun spin_unlock_irqrestore(&dd->sc_lock, flags);
451*4882a593Smuzhiyun return 0;
452*4882a593Smuzhiyun }
453*4882a593Smuzhiyun
454*4882a593Smuzhiyun DEBUGFS_SEQ_FILE_OPS(pios);
455*4882a593Smuzhiyun DEBUGFS_SEQ_FILE_OPEN(pios)
456*4882a593Smuzhiyun DEBUGFS_FILE_OPS(pios);
457*4882a593Smuzhiyun
458*4882a593Smuzhiyun /* read the per-device counters */
dev_counters_read(struct file * file,char __user * buf,size_t count,loff_t * ppos)459*4882a593Smuzhiyun static ssize_t dev_counters_read(struct file *file, char __user *buf,
460*4882a593Smuzhiyun size_t count, loff_t *ppos)
461*4882a593Smuzhiyun {
462*4882a593Smuzhiyun u64 *counters;
463*4882a593Smuzhiyun size_t avail;
464*4882a593Smuzhiyun struct hfi1_devdata *dd;
465*4882a593Smuzhiyun ssize_t rval;
466*4882a593Smuzhiyun
467*4882a593Smuzhiyun dd = private2dd(file);
468*4882a593Smuzhiyun avail = hfi1_read_cntrs(dd, NULL, &counters);
469*4882a593Smuzhiyun rval = simple_read_from_buffer(buf, count, ppos, counters, avail);
470*4882a593Smuzhiyun return rval;
471*4882a593Smuzhiyun }
472*4882a593Smuzhiyun
473*4882a593Smuzhiyun /* read the per-device counters */
dev_names_read(struct file * file,char __user * buf,size_t count,loff_t * ppos)474*4882a593Smuzhiyun static ssize_t dev_names_read(struct file *file, char __user *buf,
475*4882a593Smuzhiyun size_t count, loff_t *ppos)
476*4882a593Smuzhiyun {
477*4882a593Smuzhiyun char *names;
478*4882a593Smuzhiyun size_t avail;
479*4882a593Smuzhiyun struct hfi1_devdata *dd;
480*4882a593Smuzhiyun ssize_t rval;
481*4882a593Smuzhiyun
482*4882a593Smuzhiyun dd = private2dd(file);
483*4882a593Smuzhiyun avail = hfi1_read_cntrs(dd, &names, NULL);
484*4882a593Smuzhiyun rval = simple_read_from_buffer(buf, count, ppos, names, avail);
485*4882a593Smuzhiyun return rval;
486*4882a593Smuzhiyun }
487*4882a593Smuzhiyun
488*4882a593Smuzhiyun struct counter_info {
489*4882a593Smuzhiyun char *name;
490*4882a593Smuzhiyun const struct file_operations ops;
491*4882a593Smuzhiyun };
492*4882a593Smuzhiyun
493*4882a593Smuzhiyun /*
494*4882a593Smuzhiyun * Could use file_inode(file)->i_ino to figure out which file,
495*4882a593Smuzhiyun * instead of separate routine for each, but for now, this works...
496*4882a593Smuzhiyun */
497*4882a593Smuzhiyun
498*4882a593Smuzhiyun /* read the per-port names (same for each port) */
portnames_read(struct file * file,char __user * buf,size_t count,loff_t * ppos)499*4882a593Smuzhiyun static ssize_t portnames_read(struct file *file, char __user *buf,
500*4882a593Smuzhiyun size_t count, loff_t *ppos)
501*4882a593Smuzhiyun {
502*4882a593Smuzhiyun char *names;
503*4882a593Smuzhiyun size_t avail;
504*4882a593Smuzhiyun struct hfi1_devdata *dd;
505*4882a593Smuzhiyun ssize_t rval;
506*4882a593Smuzhiyun
507*4882a593Smuzhiyun dd = private2dd(file);
508*4882a593Smuzhiyun avail = hfi1_read_portcntrs(dd->pport, &names, NULL);
509*4882a593Smuzhiyun rval = simple_read_from_buffer(buf, count, ppos, names, avail);
510*4882a593Smuzhiyun return rval;
511*4882a593Smuzhiyun }
512*4882a593Smuzhiyun
513*4882a593Smuzhiyun /* read the per-port counters */
portcntrs_debugfs_read(struct file * file,char __user * buf,size_t count,loff_t * ppos)514*4882a593Smuzhiyun static ssize_t portcntrs_debugfs_read(struct file *file, char __user *buf,
515*4882a593Smuzhiyun size_t count, loff_t *ppos)
516*4882a593Smuzhiyun {
517*4882a593Smuzhiyun u64 *counters;
518*4882a593Smuzhiyun size_t avail;
519*4882a593Smuzhiyun struct hfi1_pportdata *ppd;
520*4882a593Smuzhiyun ssize_t rval;
521*4882a593Smuzhiyun
522*4882a593Smuzhiyun ppd = private2ppd(file);
523*4882a593Smuzhiyun avail = hfi1_read_portcntrs(ppd, NULL, &counters);
524*4882a593Smuzhiyun rval = simple_read_from_buffer(buf, count, ppos, counters, avail);
525*4882a593Smuzhiyun return rval;
526*4882a593Smuzhiyun }
527*4882a593Smuzhiyun
check_dyn_flag(u64 scratch0,char * p,int size,int * used,int this_hfi,int hfi,u32 flag,const char * what)528*4882a593Smuzhiyun static void check_dyn_flag(u64 scratch0, char *p, int size, int *used,
529*4882a593Smuzhiyun int this_hfi, int hfi, u32 flag, const char *what)
530*4882a593Smuzhiyun {
531*4882a593Smuzhiyun u32 mask;
532*4882a593Smuzhiyun
533*4882a593Smuzhiyun mask = flag << (hfi ? CR_DYN_SHIFT : 0);
534*4882a593Smuzhiyun if (scratch0 & mask) {
535*4882a593Smuzhiyun *used += scnprintf(p + *used, size - *used,
536*4882a593Smuzhiyun " 0x%08x - HFI%d %s in use, %s device\n",
537*4882a593Smuzhiyun mask, hfi, what,
538*4882a593Smuzhiyun this_hfi == hfi ? "this" : "other");
539*4882a593Smuzhiyun }
540*4882a593Smuzhiyun }
541*4882a593Smuzhiyun
asic_flags_read(struct file * file,char __user * buf,size_t count,loff_t * ppos)542*4882a593Smuzhiyun static ssize_t asic_flags_read(struct file *file, char __user *buf,
543*4882a593Smuzhiyun size_t count, loff_t *ppos)
544*4882a593Smuzhiyun {
545*4882a593Smuzhiyun struct hfi1_pportdata *ppd;
546*4882a593Smuzhiyun struct hfi1_devdata *dd;
547*4882a593Smuzhiyun u64 scratch0;
548*4882a593Smuzhiyun char *tmp;
549*4882a593Smuzhiyun int ret = 0;
550*4882a593Smuzhiyun int size;
551*4882a593Smuzhiyun int used;
552*4882a593Smuzhiyun int i;
553*4882a593Smuzhiyun
554*4882a593Smuzhiyun ppd = private2ppd(file);
555*4882a593Smuzhiyun dd = ppd->dd;
556*4882a593Smuzhiyun size = PAGE_SIZE;
557*4882a593Smuzhiyun used = 0;
558*4882a593Smuzhiyun tmp = kmalloc(size, GFP_KERNEL);
559*4882a593Smuzhiyun if (!tmp)
560*4882a593Smuzhiyun return -ENOMEM;
561*4882a593Smuzhiyun
562*4882a593Smuzhiyun scratch0 = read_csr(dd, ASIC_CFG_SCRATCH);
563*4882a593Smuzhiyun used += scnprintf(tmp + used, size - used,
564*4882a593Smuzhiyun "Resource flags: 0x%016llx\n", scratch0);
565*4882a593Smuzhiyun
566*4882a593Smuzhiyun /* check permanent flag */
567*4882a593Smuzhiyun if (scratch0 & CR_THERM_INIT) {
568*4882a593Smuzhiyun used += scnprintf(tmp + used, size - used,
569*4882a593Smuzhiyun " 0x%08x - thermal monitoring initialized\n",
570*4882a593Smuzhiyun (u32)CR_THERM_INIT);
571*4882a593Smuzhiyun }
572*4882a593Smuzhiyun
573*4882a593Smuzhiyun /* check each dynamic flag on each HFI */
574*4882a593Smuzhiyun for (i = 0; i < 2; i++) {
575*4882a593Smuzhiyun check_dyn_flag(scratch0, tmp, size, &used, dd->hfi1_id, i,
576*4882a593Smuzhiyun CR_SBUS, "SBus");
577*4882a593Smuzhiyun check_dyn_flag(scratch0, tmp, size, &used, dd->hfi1_id, i,
578*4882a593Smuzhiyun CR_EPROM, "EPROM");
579*4882a593Smuzhiyun check_dyn_flag(scratch0, tmp, size, &used, dd->hfi1_id, i,
580*4882a593Smuzhiyun CR_I2C1, "i2c chain 1");
581*4882a593Smuzhiyun check_dyn_flag(scratch0, tmp, size, &used, dd->hfi1_id, i,
582*4882a593Smuzhiyun CR_I2C2, "i2c chain 2");
583*4882a593Smuzhiyun }
584*4882a593Smuzhiyun used += scnprintf(tmp + used, size - used, "Write bits to clear\n");
585*4882a593Smuzhiyun
586*4882a593Smuzhiyun ret = simple_read_from_buffer(buf, count, ppos, tmp, used);
587*4882a593Smuzhiyun kfree(tmp);
588*4882a593Smuzhiyun return ret;
589*4882a593Smuzhiyun }
590*4882a593Smuzhiyun
asic_flags_write(struct file * file,const char __user * buf,size_t count,loff_t * ppos)591*4882a593Smuzhiyun static ssize_t asic_flags_write(struct file *file, const char __user *buf,
592*4882a593Smuzhiyun size_t count, loff_t *ppos)
593*4882a593Smuzhiyun {
594*4882a593Smuzhiyun struct hfi1_pportdata *ppd;
595*4882a593Smuzhiyun struct hfi1_devdata *dd;
596*4882a593Smuzhiyun char *buff;
597*4882a593Smuzhiyun int ret;
598*4882a593Smuzhiyun unsigned long long value;
599*4882a593Smuzhiyun u64 scratch0;
600*4882a593Smuzhiyun u64 clear;
601*4882a593Smuzhiyun
602*4882a593Smuzhiyun ppd = private2ppd(file);
603*4882a593Smuzhiyun dd = ppd->dd;
604*4882a593Smuzhiyun
605*4882a593Smuzhiyun /* zero terminate and read the expected integer */
606*4882a593Smuzhiyun buff = memdup_user_nul(buf, count);
607*4882a593Smuzhiyun if (IS_ERR(buff))
608*4882a593Smuzhiyun return PTR_ERR(buff);
609*4882a593Smuzhiyun
610*4882a593Smuzhiyun ret = kstrtoull(buff, 0, &value);
611*4882a593Smuzhiyun if (ret)
612*4882a593Smuzhiyun goto do_free;
613*4882a593Smuzhiyun clear = value;
614*4882a593Smuzhiyun
615*4882a593Smuzhiyun /* obtain exclusive access */
616*4882a593Smuzhiyun mutex_lock(&dd->asic_data->asic_resource_mutex);
617*4882a593Smuzhiyun acquire_hw_mutex(dd);
618*4882a593Smuzhiyun
619*4882a593Smuzhiyun scratch0 = read_csr(dd, ASIC_CFG_SCRATCH);
620*4882a593Smuzhiyun scratch0 &= ~clear;
621*4882a593Smuzhiyun write_csr(dd, ASIC_CFG_SCRATCH, scratch0);
622*4882a593Smuzhiyun /* force write to be visible to other HFI on another OS */
623*4882a593Smuzhiyun (void)read_csr(dd, ASIC_CFG_SCRATCH);
624*4882a593Smuzhiyun
625*4882a593Smuzhiyun release_hw_mutex(dd);
626*4882a593Smuzhiyun mutex_unlock(&dd->asic_data->asic_resource_mutex);
627*4882a593Smuzhiyun
628*4882a593Smuzhiyun /* return the number of bytes written */
629*4882a593Smuzhiyun ret = count;
630*4882a593Smuzhiyun
631*4882a593Smuzhiyun do_free:
632*4882a593Smuzhiyun kfree(buff);
633*4882a593Smuzhiyun return ret;
634*4882a593Smuzhiyun }
635*4882a593Smuzhiyun
636*4882a593Smuzhiyun /* read the dc8051 memory */
dc8051_memory_read(struct file * file,char __user * buf,size_t count,loff_t * ppos)637*4882a593Smuzhiyun static ssize_t dc8051_memory_read(struct file *file, char __user *buf,
638*4882a593Smuzhiyun size_t count, loff_t *ppos)
639*4882a593Smuzhiyun {
640*4882a593Smuzhiyun struct hfi1_pportdata *ppd = private2ppd(file);
641*4882a593Smuzhiyun ssize_t rval;
642*4882a593Smuzhiyun void *tmp;
643*4882a593Smuzhiyun loff_t start, end;
644*4882a593Smuzhiyun
645*4882a593Smuzhiyun /* the checks below expect the position to be positive */
646*4882a593Smuzhiyun if (*ppos < 0)
647*4882a593Smuzhiyun return -EINVAL;
648*4882a593Smuzhiyun
649*4882a593Smuzhiyun tmp = kzalloc(DC8051_DATA_MEM_SIZE, GFP_KERNEL);
650*4882a593Smuzhiyun if (!tmp)
651*4882a593Smuzhiyun return -ENOMEM;
652*4882a593Smuzhiyun
653*4882a593Smuzhiyun /*
654*4882a593Smuzhiyun * Fill in the requested portion of the temporary buffer from the
655*4882a593Smuzhiyun * 8051 memory. The 8051 memory read is done in terms of 8 bytes.
656*4882a593Smuzhiyun * Adjust start and end to fit. Skip reading anything if out of
657*4882a593Smuzhiyun * range.
658*4882a593Smuzhiyun */
659*4882a593Smuzhiyun start = *ppos & ~0x7; /* round down */
660*4882a593Smuzhiyun if (start < DC8051_DATA_MEM_SIZE) {
661*4882a593Smuzhiyun end = (*ppos + count + 7) & ~0x7; /* round up */
662*4882a593Smuzhiyun if (end > DC8051_DATA_MEM_SIZE)
663*4882a593Smuzhiyun end = DC8051_DATA_MEM_SIZE;
664*4882a593Smuzhiyun rval = read_8051_data(ppd->dd, start, end - start,
665*4882a593Smuzhiyun (u64 *)(tmp + start));
666*4882a593Smuzhiyun if (rval)
667*4882a593Smuzhiyun goto done;
668*4882a593Smuzhiyun }
669*4882a593Smuzhiyun
670*4882a593Smuzhiyun rval = simple_read_from_buffer(buf, count, ppos, tmp,
671*4882a593Smuzhiyun DC8051_DATA_MEM_SIZE);
672*4882a593Smuzhiyun done:
673*4882a593Smuzhiyun kfree(tmp);
674*4882a593Smuzhiyun return rval;
675*4882a593Smuzhiyun }
676*4882a593Smuzhiyun
debugfs_lcb_read(struct file * file,char __user * buf,size_t count,loff_t * ppos)677*4882a593Smuzhiyun static ssize_t debugfs_lcb_read(struct file *file, char __user *buf,
678*4882a593Smuzhiyun size_t count, loff_t *ppos)
679*4882a593Smuzhiyun {
680*4882a593Smuzhiyun struct hfi1_pportdata *ppd = private2ppd(file);
681*4882a593Smuzhiyun struct hfi1_devdata *dd = ppd->dd;
682*4882a593Smuzhiyun unsigned long total, csr_off;
683*4882a593Smuzhiyun u64 data;
684*4882a593Smuzhiyun
685*4882a593Smuzhiyun if (*ppos < 0)
686*4882a593Smuzhiyun return -EINVAL;
687*4882a593Smuzhiyun /* only read 8 byte quantities */
688*4882a593Smuzhiyun if ((count % 8) != 0)
689*4882a593Smuzhiyun return -EINVAL;
690*4882a593Smuzhiyun /* offset must be 8-byte aligned */
691*4882a593Smuzhiyun if ((*ppos % 8) != 0)
692*4882a593Smuzhiyun return -EINVAL;
693*4882a593Smuzhiyun /* do nothing if out of range or zero count */
694*4882a593Smuzhiyun if (*ppos >= (LCB_END - LCB_START) || !count)
695*4882a593Smuzhiyun return 0;
696*4882a593Smuzhiyun /* reduce count if needed */
697*4882a593Smuzhiyun if (*ppos + count > LCB_END - LCB_START)
698*4882a593Smuzhiyun count = (LCB_END - LCB_START) - *ppos;
699*4882a593Smuzhiyun
700*4882a593Smuzhiyun csr_off = LCB_START + *ppos;
701*4882a593Smuzhiyun for (total = 0; total < count; total += 8, csr_off += 8) {
702*4882a593Smuzhiyun if (read_lcb_csr(dd, csr_off, (u64 *)&data))
703*4882a593Smuzhiyun break; /* failed */
704*4882a593Smuzhiyun if (put_user(data, (unsigned long __user *)(buf + total)))
705*4882a593Smuzhiyun break;
706*4882a593Smuzhiyun }
707*4882a593Smuzhiyun *ppos += total;
708*4882a593Smuzhiyun return total;
709*4882a593Smuzhiyun }
710*4882a593Smuzhiyun
debugfs_lcb_write(struct file * file,const char __user * buf,size_t count,loff_t * ppos)711*4882a593Smuzhiyun static ssize_t debugfs_lcb_write(struct file *file, const char __user *buf,
712*4882a593Smuzhiyun size_t count, loff_t *ppos)
713*4882a593Smuzhiyun {
714*4882a593Smuzhiyun struct hfi1_pportdata *ppd = private2ppd(file);
715*4882a593Smuzhiyun struct hfi1_devdata *dd = ppd->dd;
716*4882a593Smuzhiyun unsigned long total, csr_off, data;
717*4882a593Smuzhiyun
718*4882a593Smuzhiyun if (*ppos < 0)
719*4882a593Smuzhiyun return -EINVAL;
720*4882a593Smuzhiyun /* only write 8 byte quantities */
721*4882a593Smuzhiyun if ((count % 8) != 0)
722*4882a593Smuzhiyun return -EINVAL;
723*4882a593Smuzhiyun /* offset must be 8-byte aligned */
724*4882a593Smuzhiyun if ((*ppos % 8) != 0)
725*4882a593Smuzhiyun return -EINVAL;
726*4882a593Smuzhiyun /* do nothing if out of range or zero count */
727*4882a593Smuzhiyun if (*ppos >= (LCB_END - LCB_START) || !count)
728*4882a593Smuzhiyun return 0;
729*4882a593Smuzhiyun /* reduce count if needed */
730*4882a593Smuzhiyun if (*ppos + count > LCB_END - LCB_START)
731*4882a593Smuzhiyun count = (LCB_END - LCB_START) - *ppos;
732*4882a593Smuzhiyun
733*4882a593Smuzhiyun csr_off = LCB_START + *ppos;
734*4882a593Smuzhiyun for (total = 0; total < count; total += 8, csr_off += 8) {
735*4882a593Smuzhiyun if (get_user(data, (unsigned long __user *)(buf + total)))
736*4882a593Smuzhiyun break;
737*4882a593Smuzhiyun if (write_lcb_csr(dd, csr_off, data))
738*4882a593Smuzhiyun break; /* failed */
739*4882a593Smuzhiyun }
740*4882a593Smuzhiyun *ppos += total;
741*4882a593Smuzhiyun return total;
742*4882a593Smuzhiyun }
743*4882a593Smuzhiyun
744*4882a593Smuzhiyun /*
745*4882a593Smuzhiyun * read the per-port QSFP data for ppd
746*4882a593Smuzhiyun */
qsfp_debugfs_dump(struct file * file,char __user * buf,size_t count,loff_t * ppos)747*4882a593Smuzhiyun static ssize_t qsfp_debugfs_dump(struct file *file, char __user *buf,
748*4882a593Smuzhiyun size_t count, loff_t *ppos)
749*4882a593Smuzhiyun {
750*4882a593Smuzhiyun struct hfi1_pportdata *ppd;
751*4882a593Smuzhiyun char *tmp;
752*4882a593Smuzhiyun int ret;
753*4882a593Smuzhiyun
754*4882a593Smuzhiyun ppd = private2ppd(file);
755*4882a593Smuzhiyun tmp = kmalloc(PAGE_SIZE, GFP_KERNEL);
756*4882a593Smuzhiyun if (!tmp)
757*4882a593Smuzhiyun return -ENOMEM;
758*4882a593Smuzhiyun
759*4882a593Smuzhiyun ret = qsfp_dump(ppd, tmp, PAGE_SIZE);
760*4882a593Smuzhiyun if (ret > 0)
761*4882a593Smuzhiyun ret = simple_read_from_buffer(buf, count, ppos, tmp, ret);
762*4882a593Smuzhiyun kfree(tmp);
763*4882a593Smuzhiyun return ret;
764*4882a593Smuzhiyun }
765*4882a593Smuzhiyun
766*4882a593Smuzhiyun /* Do an i2c write operation on the chain for the given HFI. */
__i2c_debugfs_write(struct file * file,const char __user * buf,size_t count,loff_t * ppos,u32 target)767*4882a593Smuzhiyun static ssize_t __i2c_debugfs_write(struct file *file, const char __user *buf,
768*4882a593Smuzhiyun size_t count, loff_t *ppos, u32 target)
769*4882a593Smuzhiyun {
770*4882a593Smuzhiyun struct hfi1_pportdata *ppd;
771*4882a593Smuzhiyun char *buff;
772*4882a593Smuzhiyun int ret;
773*4882a593Smuzhiyun int i2c_addr;
774*4882a593Smuzhiyun int offset;
775*4882a593Smuzhiyun int total_written;
776*4882a593Smuzhiyun
777*4882a593Smuzhiyun ppd = private2ppd(file);
778*4882a593Smuzhiyun
779*4882a593Smuzhiyun /* byte offset format: [offsetSize][i2cAddr][offsetHigh][offsetLow] */
780*4882a593Smuzhiyun i2c_addr = (*ppos >> 16) & 0xffff;
781*4882a593Smuzhiyun offset = *ppos & 0xffff;
782*4882a593Smuzhiyun
783*4882a593Smuzhiyun /* explicitly reject invalid address 0 to catch cp and cat */
784*4882a593Smuzhiyun if (i2c_addr == 0)
785*4882a593Smuzhiyun return -EINVAL;
786*4882a593Smuzhiyun
787*4882a593Smuzhiyun buff = memdup_user(buf, count);
788*4882a593Smuzhiyun if (IS_ERR(buff))
789*4882a593Smuzhiyun return PTR_ERR(buff);
790*4882a593Smuzhiyun
791*4882a593Smuzhiyun total_written = i2c_write(ppd, target, i2c_addr, offset, buff, count);
792*4882a593Smuzhiyun if (total_written < 0) {
793*4882a593Smuzhiyun ret = total_written;
794*4882a593Smuzhiyun goto _free;
795*4882a593Smuzhiyun }
796*4882a593Smuzhiyun
797*4882a593Smuzhiyun *ppos += total_written;
798*4882a593Smuzhiyun
799*4882a593Smuzhiyun ret = total_written;
800*4882a593Smuzhiyun
801*4882a593Smuzhiyun _free:
802*4882a593Smuzhiyun kfree(buff);
803*4882a593Smuzhiyun return ret;
804*4882a593Smuzhiyun }
805*4882a593Smuzhiyun
806*4882a593Smuzhiyun /* Do an i2c write operation on chain for HFI 0. */
i2c1_debugfs_write(struct file * file,const char __user * buf,size_t count,loff_t * ppos)807*4882a593Smuzhiyun static ssize_t i2c1_debugfs_write(struct file *file, const char __user *buf,
808*4882a593Smuzhiyun size_t count, loff_t *ppos)
809*4882a593Smuzhiyun {
810*4882a593Smuzhiyun return __i2c_debugfs_write(file, buf, count, ppos, 0);
811*4882a593Smuzhiyun }
812*4882a593Smuzhiyun
813*4882a593Smuzhiyun /* Do an i2c write operation on chain for HFI 1. */
i2c2_debugfs_write(struct file * file,const char __user * buf,size_t count,loff_t * ppos)814*4882a593Smuzhiyun static ssize_t i2c2_debugfs_write(struct file *file, const char __user *buf,
815*4882a593Smuzhiyun size_t count, loff_t *ppos)
816*4882a593Smuzhiyun {
817*4882a593Smuzhiyun return __i2c_debugfs_write(file, buf, count, ppos, 1);
818*4882a593Smuzhiyun }
819*4882a593Smuzhiyun
820*4882a593Smuzhiyun /* Do an i2c read operation on the chain for the given HFI. */
__i2c_debugfs_read(struct file * file,char __user * buf,size_t count,loff_t * ppos,u32 target)821*4882a593Smuzhiyun static ssize_t __i2c_debugfs_read(struct file *file, char __user *buf,
822*4882a593Smuzhiyun size_t count, loff_t *ppos, u32 target)
823*4882a593Smuzhiyun {
824*4882a593Smuzhiyun struct hfi1_pportdata *ppd;
825*4882a593Smuzhiyun char *buff;
826*4882a593Smuzhiyun int ret;
827*4882a593Smuzhiyun int i2c_addr;
828*4882a593Smuzhiyun int offset;
829*4882a593Smuzhiyun int total_read;
830*4882a593Smuzhiyun
831*4882a593Smuzhiyun ppd = private2ppd(file);
832*4882a593Smuzhiyun
833*4882a593Smuzhiyun /* byte offset format: [offsetSize][i2cAddr][offsetHigh][offsetLow] */
834*4882a593Smuzhiyun i2c_addr = (*ppos >> 16) & 0xffff;
835*4882a593Smuzhiyun offset = *ppos & 0xffff;
836*4882a593Smuzhiyun
837*4882a593Smuzhiyun /* explicitly reject invalid address 0 to catch cp and cat */
838*4882a593Smuzhiyun if (i2c_addr == 0)
839*4882a593Smuzhiyun return -EINVAL;
840*4882a593Smuzhiyun
841*4882a593Smuzhiyun buff = kmalloc(count, GFP_KERNEL);
842*4882a593Smuzhiyun if (!buff)
843*4882a593Smuzhiyun return -ENOMEM;
844*4882a593Smuzhiyun
845*4882a593Smuzhiyun total_read = i2c_read(ppd, target, i2c_addr, offset, buff, count);
846*4882a593Smuzhiyun if (total_read < 0) {
847*4882a593Smuzhiyun ret = total_read;
848*4882a593Smuzhiyun goto _free;
849*4882a593Smuzhiyun }
850*4882a593Smuzhiyun
851*4882a593Smuzhiyun *ppos += total_read;
852*4882a593Smuzhiyun
853*4882a593Smuzhiyun ret = copy_to_user(buf, buff, total_read);
854*4882a593Smuzhiyun if (ret > 0) {
855*4882a593Smuzhiyun ret = -EFAULT;
856*4882a593Smuzhiyun goto _free;
857*4882a593Smuzhiyun }
858*4882a593Smuzhiyun
859*4882a593Smuzhiyun ret = total_read;
860*4882a593Smuzhiyun
861*4882a593Smuzhiyun _free:
862*4882a593Smuzhiyun kfree(buff);
863*4882a593Smuzhiyun return ret;
864*4882a593Smuzhiyun }
865*4882a593Smuzhiyun
866*4882a593Smuzhiyun /* Do an i2c read operation on chain for HFI 0. */
i2c1_debugfs_read(struct file * file,char __user * buf,size_t count,loff_t * ppos)867*4882a593Smuzhiyun static ssize_t i2c1_debugfs_read(struct file *file, char __user *buf,
868*4882a593Smuzhiyun size_t count, loff_t *ppos)
869*4882a593Smuzhiyun {
870*4882a593Smuzhiyun return __i2c_debugfs_read(file, buf, count, ppos, 0);
871*4882a593Smuzhiyun }
872*4882a593Smuzhiyun
873*4882a593Smuzhiyun /* Do an i2c read operation on chain for HFI 1. */
i2c2_debugfs_read(struct file * file,char __user * buf,size_t count,loff_t * ppos)874*4882a593Smuzhiyun static ssize_t i2c2_debugfs_read(struct file *file, char __user *buf,
875*4882a593Smuzhiyun size_t count, loff_t *ppos)
876*4882a593Smuzhiyun {
877*4882a593Smuzhiyun return __i2c_debugfs_read(file, buf, count, ppos, 1);
878*4882a593Smuzhiyun }
879*4882a593Smuzhiyun
880*4882a593Smuzhiyun /* Do a QSFP write operation on the i2c chain for the given HFI. */
__qsfp_debugfs_write(struct file * file,const char __user * buf,size_t count,loff_t * ppos,u32 target)881*4882a593Smuzhiyun static ssize_t __qsfp_debugfs_write(struct file *file, const char __user *buf,
882*4882a593Smuzhiyun size_t count, loff_t *ppos, u32 target)
883*4882a593Smuzhiyun {
884*4882a593Smuzhiyun struct hfi1_pportdata *ppd;
885*4882a593Smuzhiyun char *buff;
886*4882a593Smuzhiyun int ret;
887*4882a593Smuzhiyun int total_written;
888*4882a593Smuzhiyun
889*4882a593Smuzhiyun if (*ppos + count > QSFP_PAGESIZE * 4) /* base page + page00-page03 */
890*4882a593Smuzhiyun return -EINVAL;
891*4882a593Smuzhiyun
892*4882a593Smuzhiyun ppd = private2ppd(file);
893*4882a593Smuzhiyun
894*4882a593Smuzhiyun buff = memdup_user(buf, count);
895*4882a593Smuzhiyun if (IS_ERR(buff))
896*4882a593Smuzhiyun return PTR_ERR(buff);
897*4882a593Smuzhiyun
898*4882a593Smuzhiyun total_written = qsfp_write(ppd, target, *ppos, buff, count);
899*4882a593Smuzhiyun if (total_written < 0) {
900*4882a593Smuzhiyun ret = total_written;
901*4882a593Smuzhiyun goto _free;
902*4882a593Smuzhiyun }
903*4882a593Smuzhiyun
904*4882a593Smuzhiyun *ppos += total_written;
905*4882a593Smuzhiyun
906*4882a593Smuzhiyun ret = total_written;
907*4882a593Smuzhiyun
908*4882a593Smuzhiyun _free:
909*4882a593Smuzhiyun kfree(buff);
910*4882a593Smuzhiyun return ret;
911*4882a593Smuzhiyun }
912*4882a593Smuzhiyun
913*4882a593Smuzhiyun /* Do a QSFP write operation on i2c chain for HFI 0. */
qsfp1_debugfs_write(struct file * file,const char __user * buf,size_t count,loff_t * ppos)914*4882a593Smuzhiyun static ssize_t qsfp1_debugfs_write(struct file *file, const char __user *buf,
915*4882a593Smuzhiyun size_t count, loff_t *ppos)
916*4882a593Smuzhiyun {
917*4882a593Smuzhiyun return __qsfp_debugfs_write(file, buf, count, ppos, 0);
918*4882a593Smuzhiyun }
919*4882a593Smuzhiyun
920*4882a593Smuzhiyun /* Do a QSFP write operation on i2c chain for HFI 1. */
qsfp2_debugfs_write(struct file * file,const char __user * buf,size_t count,loff_t * ppos)921*4882a593Smuzhiyun static ssize_t qsfp2_debugfs_write(struct file *file, const char __user *buf,
922*4882a593Smuzhiyun size_t count, loff_t *ppos)
923*4882a593Smuzhiyun {
924*4882a593Smuzhiyun return __qsfp_debugfs_write(file, buf, count, ppos, 1);
925*4882a593Smuzhiyun }
926*4882a593Smuzhiyun
927*4882a593Smuzhiyun /* Do a QSFP read operation on the i2c chain for the given HFI. */
__qsfp_debugfs_read(struct file * file,char __user * buf,size_t count,loff_t * ppos,u32 target)928*4882a593Smuzhiyun static ssize_t __qsfp_debugfs_read(struct file *file, char __user *buf,
929*4882a593Smuzhiyun size_t count, loff_t *ppos, u32 target)
930*4882a593Smuzhiyun {
931*4882a593Smuzhiyun struct hfi1_pportdata *ppd;
932*4882a593Smuzhiyun char *buff;
933*4882a593Smuzhiyun int ret;
934*4882a593Smuzhiyun int total_read;
935*4882a593Smuzhiyun
936*4882a593Smuzhiyun if (*ppos + count > QSFP_PAGESIZE * 4) { /* base page + page00-page03 */
937*4882a593Smuzhiyun ret = -EINVAL;
938*4882a593Smuzhiyun goto _return;
939*4882a593Smuzhiyun }
940*4882a593Smuzhiyun
941*4882a593Smuzhiyun ppd = private2ppd(file);
942*4882a593Smuzhiyun
943*4882a593Smuzhiyun buff = kmalloc(count, GFP_KERNEL);
944*4882a593Smuzhiyun if (!buff) {
945*4882a593Smuzhiyun ret = -ENOMEM;
946*4882a593Smuzhiyun goto _return;
947*4882a593Smuzhiyun }
948*4882a593Smuzhiyun
949*4882a593Smuzhiyun total_read = qsfp_read(ppd, target, *ppos, buff, count);
950*4882a593Smuzhiyun if (total_read < 0) {
951*4882a593Smuzhiyun ret = total_read;
952*4882a593Smuzhiyun goto _free;
953*4882a593Smuzhiyun }
954*4882a593Smuzhiyun
955*4882a593Smuzhiyun *ppos += total_read;
956*4882a593Smuzhiyun
957*4882a593Smuzhiyun ret = copy_to_user(buf, buff, total_read);
958*4882a593Smuzhiyun if (ret > 0) {
959*4882a593Smuzhiyun ret = -EFAULT;
960*4882a593Smuzhiyun goto _free;
961*4882a593Smuzhiyun }
962*4882a593Smuzhiyun
963*4882a593Smuzhiyun ret = total_read;
964*4882a593Smuzhiyun
965*4882a593Smuzhiyun _free:
966*4882a593Smuzhiyun kfree(buff);
967*4882a593Smuzhiyun _return:
968*4882a593Smuzhiyun return ret;
969*4882a593Smuzhiyun }
970*4882a593Smuzhiyun
971*4882a593Smuzhiyun /* Do a QSFP read operation on i2c chain for HFI 0. */
qsfp1_debugfs_read(struct file * file,char __user * buf,size_t count,loff_t * ppos)972*4882a593Smuzhiyun static ssize_t qsfp1_debugfs_read(struct file *file, char __user *buf,
973*4882a593Smuzhiyun size_t count, loff_t *ppos)
974*4882a593Smuzhiyun {
975*4882a593Smuzhiyun return __qsfp_debugfs_read(file, buf, count, ppos, 0);
976*4882a593Smuzhiyun }
977*4882a593Smuzhiyun
978*4882a593Smuzhiyun /* Do a QSFP read operation on i2c chain for HFI 1. */
qsfp2_debugfs_read(struct file * file,char __user * buf,size_t count,loff_t * ppos)979*4882a593Smuzhiyun static ssize_t qsfp2_debugfs_read(struct file *file, char __user *buf,
980*4882a593Smuzhiyun size_t count, loff_t *ppos)
981*4882a593Smuzhiyun {
982*4882a593Smuzhiyun return __qsfp_debugfs_read(file, buf, count, ppos, 1);
983*4882a593Smuzhiyun }
984*4882a593Smuzhiyun
__i2c_debugfs_open(struct inode * in,struct file * fp,u32 target)985*4882a593Smuzhiyun static int __i2c_debugfs_open(struct inode *in, struct file *fp, u32 target)
986*4882a593Smuzhiyun {
987*4882a593Smuzhiyun struct hfi1_pportdata *ppd;
988*4882a593Smuzhiyun
989*4882a593Smuzhiyun ppd = private2ppd(fp);
990*4882a593Smuzhiyun
991*4882a593Smuzhiyun return acquire_chip_resource(ppd->dd, i2c_target(target), 0);
992*4882a593Smuzhiyun }
993*4882a593Smuzhiyun
i2c1_debugfs_open(struct inode * in,struct file * fp)994*4882a593Smuzhiyun static int i2c1_debugfs_open(struct inode *in, struct file *fp)
995*4882a593Smuzhiyun {
996*4882a593Smuzhiyun return __i2c_debugfs_open(in, fp, 0);
997*4882a593Smuzhiyun }
998*4882a593Smuzhiyun
i2c2_debugfs_open(struct inode * in,struct file * fp)999*4882a593Smuzhiyun static int i2c2_debugfs_open(struct inode *in, struct file *fp)
1000*4882a593Smuzhiyun {
1001*4882a593Smuzhiyun return __i2c_debugfs_open(in, fp, 1);
1002*4882a593Smuzhiyun }
1003*4882a593Smuzhiyun
__i2c_debugfs_release(struct inode * in,struct file * fp,u32 target)1004*4882a593Smuzhiyun static int __i2c_debugfs_release(struct inode *in, struct file *fp, u32 target)
1005*4882a593Smuzhiyun {
1006*4882a593Smuzhiyun struct hfi1_pportdata *ppd;
1007*4882a593Smuzhiyun
1008*4882a593Smuzhiyun ppd = private2ppd(fp);
1009*4882a593Smuzhiyun
1010*4882a593Smuzhiyun release_chip_resource(ppd->dd, i2c_target(target));
1011*4882a593Smuzhiyun
1012*4882a593Smuzhiyun return 0;
1013*4882a593Smuzhiyun }
1014*4882a593Smuzhiyun
i2c1_debugfs_release(struct inode * in,struct file * fp)1015*4882a593Smuzhiyun static int i2c1_debugfs_release(struct inode *in, struct file *fp)
1016*4882a593Smuzhiyun {
1017*4882a593Smuzhiyun return __i2c_debugfs_release(in, fp, 0);
1018*4882a593Smuzhiyun }
1019*4882a593Smuzhiyun
i2c2_debugfs_release(struct inode * in,struct file * fp)1020*4882a593Smuzhiyun static int i2c2_debugfs_release(struct inode *in, struct file *fp)
1021*4882a593Smuzhiyun {
1022*4882a593Smuzhiyun return __i2c_debugfs_release(in, fp, 1);
1023*4882a593Smuzhiyun }
1024*4882a593Smuzhiyun
__qsfp_debugfs_open(struct inode * in,struct file * fp,u32 target)1025*4882a593Smuzhiyun static int __qsfp_debugfs_open(struct inode *in, struct file *fp, u32 target)
1026*4882a593Smuzhiyun {
1027*4882a593Smuzhiyun struct hfi1_pportdata *ppd;
1028*4882a593Smuzhiyun
1029*4882a593Smuzhiyun ppd = private2ppd(fp);
1030*4882a593Smuzhiyun
1031*4882a593Smuzhiyun return acquire_chip_resource(ppd->dd, i2c_target(target), 0);
1032*4882a593Smuzhiyun }
1033*4882a593Smuzhiyun
qsfp1_debugfs_open(struct inode * in,struct file * fp)1034*4882a593Smuzhiyun static int qsfp1_debugfs_open(struct inode *in, struct file *fp)
1035*4882a593Smuzhiyun {
1036*4882a593Smuzhiyun return __qsfp_debugfs_open(in, fp, 0);
1037*4882a593Smuzhiyun }
1038*4882a593Smuzhiyun
qsfp2_debugfs_open(struct inode * in,struct file * fp)1039*4882a593Smuzhiyun static int qsfp2_debugfs_open(struct inode *in, struct file *fp)
1040*4882a593Smuzhiyun {
1041*4882a593Smuzhiyun return __qsfp_debugfs_open(in, fp, 1);
1042*4882a593Smuzhiyun }
1043*4882a593Smuzhiyun
__qsfp_debugfs_release(struct inode * in,struct file * fp,u32 target)1044*4882a593Smuzhiyun static int __qsfp_debugfs_release(struct inode *in, struct file *fp, u32 target)
1045*4882a593Smuzhiyun {
1046*4882a593Smuzhiyun struct hfi1_pportdata *ppd;
1047*4882a593Smuzhiyun
1048*4882a593Smuzhiyun ppd = private2ppd(fp);
1049*4882a593Smuzhiyun
1050*4882a593Smuzhiyun release_chip_resource(ppd->dd, i2c_target(target));
1051*4882a593Smuzhiyun
1052*4882a593Smuzhiyun return 0;
1053*4882a593Smuzhiyun }
1054*4882a593Smuzhiyun
qsfp1_debugfs_release(struct inode * in,struct file * fp)1055*4882a593Smuzhiyun static int qsfp1_debugfs_release(struct inode *in, struct file *fp)
1056*4882a593Smuzhiyun {
1057*4882a593Smuzhiyun return __qsfp_debugfs_release(in, fp, 0);
1058*4882a593Smuzhiyun }
1059*4882a593Smuzhiyun
qsfp2_debugfs_release(struct inode * in,struct file * fp)1060*4882a593Smuzhiyun static int qsfp2_debugfs_release(struct inode *in, struct file *fp)
1061*4882a593Smuzhiyun {
1062*4882a593Smuzhiyun return __qsfp_debugfs_release(in, fp, 1);
1063*4882a593Smuzhiyun }
1064*4882a593Smuzhiyun
1065*4882a593Smuzhiyun #define EXPROM_WRITE_ENABLE BIT_ULL(14)
1066*4882a593Smuzhiyun
1067*4882a593Smuzhiyun static bool exprom_wp_disabled;
1068*4882a593Smuzhiyun
exprom_wp_set(struct hfi1_devdata * dd,bool disable)1069*4882a593Smuzhiyun static int exprom_wp_set(struct hfi1_devdata *dd, bool disable)
1070*4882a593Smuzhiyun {
1071*4882a593Smuzhiyun u64 gpio_val = 0;
1072*4882a593Smuzhiyun
1073*4882a593Smuzhiyun if (disable) {
1074*4882a593Smuzhiyun gpio_val = EXPROM_WRITE_ENABLE;
1075*4882a593Smuzhiyun exprom_wp_disabled = true;
1076*4882a593Smuzhiyun dd_dev_info(dd, "Disable Expansion ROM Write Protection\n");
1077*4882a593Smuzhiyun } else {
1078*4882a593Smuzhiyun exprom_wp_disabled = false;
1079*4882a593Smuzhiyun dd_dev_info(dd, "Enable Expansion ROM Write Protection\n");
1080*4882a593Smuzhiyun }
1081*4882a593Smuzhiyun
1082*4882a593Smuzhiyun write_csr(dd, ASIC_GPIO_OUT, gpio_val);
1083*4882a593Smuzhiyun write_csr(dd, ASIC_GPIO_OE, gpio_val);
1084*4882a593Smuzhiyun
1085*4882a593Smuzhiyun return 0;
1086*4882a593Smuzhiyun }
1087*4882a593Smuzhiyun
exprom_wp_debugfs_read(struct file * file,char __user * buf,size_t count,loff_t * ppos)1088*4882a593Smuzhiyun static ssize_t exprom_wp_debugfs_read(struct file *file, char __user *buf,
1089*4882a593Smuzhiyun size_t count, loff_t *ppos)
1090*4882a593Smuzhiyun {
1091*4882a593Smuzhiyun return 0;
1092*4882a593Smuzhiyun }
1093*4882a593Smuzhiyun
exprom_wp_debugfs_write(struct file * file,const char __user * buf,size_t count,loff_t * ppos)1094*4882a593Smuzhiyun static ssize_t exprom_wp_debugfs_write(struct file *file,
1095*4882a593Smuzhiyun const char __user *buf, size_t count,
1096*4882a593Smuzhiyun loff_t *ppos)
1097*4882a593Smuzhiyun {
1098*4882a593Smuzhiyun struct hfi1_pportdata *ppd = private2ppd(file);
1099*4882a593Smuzhiyun char cdata;
1100*4882a593Smuzhiyun
1101*4882a593Smuzhiyun if (count != 1)
1102*4882a593Smuzhiyun return -EINVAL;
1103*4882a593Smuzhiyun if (get_user(cdata, buf))
1104*4882a593Smuzhiyun return -EFAULT;
1105*4882a593Smuzhiyun if (cdata == '0')
1106*4882a593Smuzhiyun exprom_wp_set(ppd->dd, false);
1107*4882a593Smuzhiyun else if (cdata == '1')
1108*4882a593Smuzhiyun exprom_wp_set(ppd->dd, true);
1109*4882a593Smuzhiyun else
1110*4882a593Smuzhiyun return -EINVAL;
1111*4882a593Smuzhiyun
1112*4882a593Smuzhiyun return 1;
1113*4882a593Smuzhiyun }
1114*4882a593Smuzhiyun
1115*4882a593Smuzhiyun static unsigned long exprom_in_use;
1116*4882a593Smuzhiyun
exprom_wp_debugfs_open(struct inode * in,struct file * fp)1117*4882a593Smuzhiyun static int exprom_wp_debugfs_open(struct inode *in, struct file *fp)
1118*4882a593Smuzhiyun {
1119*4882a593Smuzhiyun if (test_and_set_bit(0, &exprom_in_use))
1120*4882a593Smuzhiyun return -EBUSY;
1121*4882a593Smuzhiyun
1122*4882a593Smuzhiyun return 0;
1123*4882a593Smuzhiyun }
1124*4882a593Smuzhiyun
exprom_wp_debugfs_release(struct inode * in,struct file * fp)1125*4882a593Smuzhiyun static int exprom_wp_debugfs_release(struct inode *in, struct file *fp)
1126*4882a593Smuzhiyun {
1127*4882a593Smuzhiyun struct hfi1_pportdata *ppd = private2ppd(fp);
1128*4882a593Smuzhiyun
1129*4882a593Smuzhiyun if (exprom_wp_disabled)
1130*4882a593Smuzhiyun exprom_wp_set(ppd->dd, false);
1131*4882a593Smuzhiyun clear_bit(0, &exprom_in_use);
1132*4882a593Smuzhiyun
1133*4882a593Smuzhiyun return 0;
1134*4882a593Smuzhiyun }
1135*4882a593Smuzhiyun
1136*4882a593Smuzhiyun #define DEBUGFS_OPS(nm, readroutine, writeroutine) \
1137*4882a593Smuzhiyun { \
1138*4882a593Smuzhiyun .name = nm, \
1139*4882a593Smuzhiyun .ops = { \
1140*4882a593Smuzhiyun .owner = THIS_MODULE, \
1141*4882a593Smuzhiyun .read = readroutine, \
1142*4882a593Smuzhiyun .write = writeroutine, \
1143*4882a593Smuzhiyun .llseek = generic_file_llseek, \
1144*4882a593Smuzhiyun }, \
1145*4882a593Smuzhiyun }
1146*4882a593Smuzhiyun
1147*4882a593Smuzhiyun #define DEBUGFS_XOPS(nm, readf, writef, openf, releasef) \
1148*4882a593Smuzhiyun { \
1149*4882a593Smuzhiyun .name = nm, \
1150*4882a593Smuzhiyun .ops = { \
1151*4882a593Smuzhiyun .owner = THIS_MODULE, \
1152*4882a593Smuzhiyun .read = readf, \
1153*4882a593Smuzhiyun .write = writef, \
1154*4882a593Smuzhiyun .llseek = generic_file_llseek, \
1155*4882a593Smuzhiyun .open = openf, \
1156*4882a593Smuzhiyun .release = releasef \
1157*4882a593Smuzhiyun }, \
1158*4882a593Smuzhiyun }
1159*4882a593Smuzhiyun
1160*4882a593Smuzhiyun static const struct counter_info cntr_ops[] = {
1161*4882a593Smuzhiyun DEBUGFS_OPS("counter_names", dev_names_read, NULL),
1162*4882a593Smuzhiyun DEBUGFS_OPS("counters", dev_counters_read, NULL),
1163*4882a593Smuzhiyun DEBUGFS_OPS("portcounter_names", portnames_read, NULL),
1164*4882a593Smuzhiyun };
1165*4882a593Smuzhiyun
1166*4882a593Smuzhiyun static const struct counter_info port_cntr_ops[] = {
1167*4882a593Smuzhiyun DEBUGFS_OPS("port%dcounters", portcntrs_debugfs_read, NULL),
1168*4882a593Smuzhiyun DEBUGFS_XOPS("i2c1", i2c1_debugfs_read, i2c1_debugfs_write,
1169*4882a593Smuzhiyun i2c1_debugfs_open, i2c1_debugfs_release),
1170*4882a593Smuzhiyun DEBUGFS_XOPS("i2c2", i2c2_debugfs_read, i2c2_debugfs_write,
1171*4882a593Smuzhiyun i2c2_debugfs_open, i2c2_debugfs_release),
1172*4882a593Smuzhiyun DEBUGFS_OPS("qsfp_dump%d", qsfp_debugfs_dump, NULL),
1173*4882a593Smuzhiyun DEBUGFS_XOPS("qsfp1", qsfp1_debugfs_read, qsfp1_debugfs_write,
1174*4882a593Smuzhiyun qsfp1_debugfs_open, qsfp1_debugfs_release),
1175*4882a593Smuzhiyun DEBUGFS_XOPS("qsfp2", qsfp2_debugfs_read, qsfp2_debugfs_write,
1176*4882a593Smuzhiyun qsfp2_debugfs_open, qsfp2_debugfs_release),
1177*4882a593Smuzhiyun DEBUGFS_XOPS("exprom_wp", exprom_wp_debugfs_read,
1178*4882a593Smuzhiyun exprom_wp_debugfs_write, exprom_wp_debugfs_open,
1179*4882a593Smuzhiyun exprom_wp_debugfs_release),
1180*4882a593Smuzhiyun DEBUGFS_OPS("asic_flags", asic_flags_read, asic_flags_write),
1181*4882a593Smuzhiyun DEBUGFS_OPS("dc8051_memory", dc8051_memory_read, NULL),
1182*4882a593Smuzhiyun DEBUGFS_OPS("lcb", debugfs_lcb_read, debugfs_lcb_write),
1183*4882a593Smuzhiyun };
1184*4882a593Smuzhiyun
_sdma_cpu_list_seq_start(struct seq_file * s,loff_t * pos)1185*4882a593Smuzhiyun static void *_sdma_cpu_list_seq_start(struct seq_file *s, loff_t *pos)
1186*4882a593Smuzhiyun {
1187*4882a593Smuzhiyun if (*pos >= num_online_cpus())
1188*4882a593Smuzhiyun return NULL;
1189*4882a593Smuzhiyun
1190*4882a593Smuzhiyun return pos;
1191*4882a593Smuzhiyun }
1192*4882a593Smuzhiyun
_sdma_cpu_list_seq_next(struct seq_file * s,void * v,loff_t * pos)1193*4882a593Smuzhiyun static void *_sdma_cpu_list_seq_next(struct seq_file *s, void *v, loff_t *pos)
1194*4882a593Smuzhiyun {
1195*4882a593Smuzhiyun ++*pos;
1196*4882a593Smuzhiyun if (*pos >= num_online_cpus())
1197*4882a593Smuzhiyun return NULL;
1198*4882a593Smuzhiyun
1199*4882a593Smuzhiyun return pos;
1200*4882a593Smuzhiyun }
1201*4882a593Smuzhiyun
_sdma_cpu_list_seq_stop(struct seq_file * s,void * v)1202*4882a593Smuzhiyun static void _sdma_cpu_list_seq_stop(struct seq_file *s, void *v)
1203*4882a593Smuzhiyun {
1204*4882a593Smuzhiyun /* nothing allocated */
1205*4882a593Smuzhiyun }
1206*4882a593Smuzhiyun
_sdma_cpu_list_seq_show(struct seq_file * s,void * v)1207*4882a593Smuzhiyun static int _sdma_cpu_list_seq_show(struct seq_file *s, void *v)
1208*4882a593Smuzhiyun {
1209*4882a593Smuzhiyun struct hfi1_ibdev *ibd = (struct hfi1_ibdev *)s->private;
1210*4882a593Smuzhiyun struct hfi1_devdata *dd = dd_from_dev(ibd);
1211*4882a593Smuzhiyun loff_t *spos = v;
1212*4882a593Smuzhiyun loff_t i = *spos;
1213*4882a593Smuzhiyun
1214*4882a593Smuzhiyun sdma_seqfile_dump_cpu_list(s, dd, (unsigned long)i);
1215*4882a593Smuzhiyun return 0;
1216*4882a593Smuzhiyun }
1217*4882a593Smuzhiyun
1218*4882a593Smuzhiyun DEBUGFS_SEQ_FILE_OPS(sdma_cpu_list);
1219*4882a593Smuzhiyun DEBUGFS_SEQ_FILE_OPEN(sdma_cpu_list)
1220*4882a593Smuzhiyun DEBUGFS_FILE_OPS(sdma_cpu_list);
1221*4882a593Smuzhiyun
hfi1_dbg_ibdev_init(struct hfi1_ibdev * ibd)1222*4882a593Smuzhiyun void hfi1_dbg_ibdev_init(struct hfi1_ibdev *ibd)
1223*4882a593Smuzhiyun {
1224*4882a593Smuzhiyun char name[sizeof("port0counters") + 1];
1225*4882a593Smuzhiyun char link[10];
1226*4882a593Smuzhiyun struct hfi1_devdata *dd = dd_from_dev(ibd);
1227*4882a593Smuzhiyun struct hfi1_pportdata *ppd;
1228*4882a593Smuzhiyun struct dentry *root;
1229*4882a593Smuzhiyun int unit = dd->unit;
1230*4882a593Smuzhiyun int i, j;
1231*4882a593Smuzhiyun
1232*4882a593Smuzhiyun if (!hfi1_dbg_root)
1233*4882a593Smuzhiyun return;
1234*4882a593Smuzhiyun snprintf(name, sizeof(name), "%s_%d", class_name(), unit);
1235*4882a593Smuzhiyun snprintf(link, sizeof(link), "%d", unit);
1236*4882a593Smuzhiyun root = debugfs_create_dir(name, hfi1_dbg_root);
1237*4882a593Smuzhiyun ibd->hfi1_ibdev_dbg = root;
1238*4882a593Smuzhiyun
1239*4882a593Smuzhiyun ibd->hfi1_ibdev_link =
1240*4882a593Smuzhiyun debugfs_create_symlink(link, hfi1_dbg_root, name);
1241*4882a593Smuzhiyun
1242*4882a593Smuzhiyun debugfs_create_file("opcode_stats", 0444, root, ibd,
1243*4882a593Smuzhiyun &_opcode_stats_file_ops);
1244*4882a593Smuzhiyun debugfs_create_file("tx_opcode_stats", 0444, root, ibd,
1245*4882a593Smuzhiyun &_tx_opcode_stats_file_ops);
1246*4882a593Smuzhiyun debugfs_create_file("ctx_stats", 0444, root, ibd, &_ctx_stats_file_ops);
1247*4882a593Smuzhiyun debugfs_create_file("qp_stats", 0444, root, ibd, &_qp_stats_file_ops);
1248*4882a593Smuzhiyun debugfs_create_file("sdes", 0444, root, ibd, &_sdes_file_ops);
1249*4882a593Smuzhiyun debugfs_create_file("rcds", 0444, root, ibd, &_rcds_file_ops);
1250*4882a593Smuzhiyun debugfs_create_file("pios", 0444, root, ibd, &_pios_file_ops);
1251*4882a593Smuzhiyun debugfs_create_file("sdma_cpu_list", 0444, root, ibd,
1252*4882a593Smuzhiyun &_sdma_cpu_list_file_ops);
1253*4882a593Smuzhiyun
1254*4882a593Smuzhiyun /* dev counter files */
1255*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(cntr_ops); i++)
1256*4882a593Smuzhiyun debugfs_create_file(cntr_ops[i].name, 0444, root, dd,
1257*4882a593Smuzhiyun &cntr_ops[i].ops);
1258*4882a593Smuzhiyun
1259*4882a593Smuzhiyun /* per port files */
1260*4882a593Smuzhiyun for (ppd = dd->pport, j = 0; j < dd->num_pports; j++, ppd++)
1261*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(port_cntr_ops); i++) {
1262*4882a593Smuzhiyun snprintf(name,
1263*4882a593Smuzhiyun sizeof(name),
1264*4882a593Smuzhiyun port_cntr_ops[i].name,
1265*4882a593Smuzhiyun j + 1);
1266*4882a593Smuzhiyun debugfs_create_file(name,
1267*4882a593Smuzhiyun !port_cntr_ops[i].ops.write ?
1268*4882a593Smuzhiyun S_IRUGO :
1269*4882a593Smuzhiyun S_IRUGO | S_IWUSR,
1270*4882a593Smuzhiyun root, ppd, &port_cntr_ops[i].ops);
1271*4882a593Smuzhiyun }
1272*4882a593Smuzhiyun
1273*4882a593Smuzhiyun hfi1_fault_init_debugfs(ibd);
1274*4882a593Smuzhiyun }
1275*4882a593Smuzhiyun
hfi1_dbg_ibdev_exit(struct hfi1_ibdev * ibd)1276*4882a593Smuzhiyun void hfi1_dbg_ibdev_exit(struct hfi1_ibdev *ibd)
1277*4882a593Smuzhiyun {
1278*4882a593Smuzhiyun if (!hfi1_dbg_root)
1279*4882a593Smuzhiyun goto out;
1280*4882a593Smuzhiyun hfi1_fault_exit_debugfs(ibd);
1281*4882a593Smuzhiyun debugfs_remove(ibd->hfi1_ibdev_link);
1282*4882a593Smuzhiyun debugfs_remove_recursive(ibd->hfi1_ibdev_dbg);
1283*4882a593Smuzhiyun out:
1284*4882a593Smuzhiyun ibd->hfi1_ibdev_dbg = NULL;
1285*4882a593Smuzhiyun }
1286*4882a593Smuzhiyun
1287*4882a593Smuzhiyun /*
1288*4882a593Smuzhiyun * driver stats field names, one line per stat, single string. Used by
1289*4882a593Smuzhiyun * programs like hfistats to print the stats in a way which works for
1290*4882a593Smuzhiyun * different versions of drivers, without changing program source.
1291*4882a593Smuzhiyun * if hfi1_ib_stats changes, this needs to change. Names need to be
1292*4882a593Smuzhiyun * 12 chars or less (w/o newline), for proper display by hfistats utility.
1293*4882a593Smuzhiyun */
1294*4882a593Smuzhiyun static const char * const hfi1_statnames[] = {
1295*4882a593Smuzhiyun /* must be element 0*/
1296*4882a593Smuzhiyun "KernIntr",
1297*4882a593Smuzhiyun "ErrorIntr",
1298*4882a593Smuzhiyun "Tx_Errs",
1299*4882a593Smuzhiyun "Rcv_Errs",
1300*4882a593Smuzhiyun "H/W_Errs",
1301*4882a593Smuzhiyun "NoPIOBufs",
1302*4882a593Smuzhiyun "CtxtsOpen",
1303*4882a593Smuzhiyun "RcvLen_Errs",
1304*4882a593Smuzhiyun "EgrBufFull",
1305*4882a593Smuzhiyun "EgrHdrFull"
1306*4882a593Smuzhiyun };
1307*4882a593Smuzhiyun
_driver_stats_names_seq_start(struct seq_file * s,loff_t * pos)1308*4882a593Smuzhiyun static void *_driver_stats_names_seq_start(struct seq_file *s, loff_t *pos)
1309*4882a593Smuzhiyun {
1310*4882a593Smuzhiyun if (*pos >= ARRAY_SIZE(hfi1_statnames))
1311*4882a593Smuzhiyun return NULL;
1312*4882a593Smuzhiyun return pos;
1313*4882a593Smuzhiyun }
1314*4882a593Smuzhiyun
_driver_stats_names_seq_next(struct seq_file * s,void * v,loff_t * pos)1315*4882a593Smuzhiyun static void *_driver_stats_names_seq_next(
1316*4882a593Smuzhiyun struct seq_file *s,
1317*4882a593Smuzhiyun void *v,
1318*4882a593Smuzhiyun loff_t *pos)
1319*4882a593Smuzhiyun {
1320*4882a593Smuzhiyun ++*pos;
1321*4882a593Smuzhiyun if (*pos >= ARRAY_SIZE(hfi1_statnames))
1322*4882a593Smuzhiyun return NULL;
1323*4882a593Smuzhiyun return pos;
1324*4882a593Smuzhiyun }
1325*4882a593Smuzhiyun
_driver_stats_names_seq_stop(struct seq_file * s,void * v)1326*4882a593Smuzhiyun static void _driver_stats_names_seq_stop(struct seq_file *s, void *v)
1327*4882a593Smuzhiyun {
1328*4882a593Smuzhiyun }
1329*4882a593Smuzhiyun
_driver_stats_names_seq_show(struct seq_file * s,void * v)1330*4882a593Smuzhiyun static int _driver_stats_names_seq_show(struct seq_file *s, void *v)
1331*4882a593Smuzhiyun {
1332*4882a593Smuzhiyun loff_t *spos = v;
1333*4882a593Smuzhiyun
1334*4882a593Smuzhiyun seq_printf(s, "%s\n", hfi1_statnames[*spos]);
1335*4882a593Smuzhiyun return 0;
1336*4882a593Smuzhiyun }
1337*4882a593Smuzhiyun
1338*4882a593Smuzhiyun DEBUGFS_SEQ_FILE_OPS(driver_stats_names);
1339*4882a593Smuzhiyun DEBUGFS_SEQ_FILE_OPEN(driver_stats_names)
1340*4882a593Smuzhiyun DEBUGFS_FILE_OPS(driver_stats_names);
1341*4882a593Smuzhiyun
_driver_stats_seq_start(struct seq_file * s,loff_t * pos)1342*4882a593Smuzhiyun static void *_driver_stats_seq_start(struct seq_file *s, loff_t *pos)
1343*4882a593Smuzhiyun {
1344*4882a593Smuzhiyun if (*pos >= ARRAY_SIZE(hfi1_statnames))
1345*4882a593Smuzhiyun return NULL;
1346*4882a593Smuzhiyun return pos;
1347*4882a593Smuzhiyun }
1348*4882a593Smuzhiyun
_driver_stats_seq_next(struct seq_file * s,void * v,loff_t * pos)1349*4882a593Smuzhiyun static void *_driver_stats_seq_next(struct seq_file *s, void *v, loff_t *pos)
1350*4882a593Smuzhiyun {
1351*4882a593Smuzhiyun ++*pos;
1352*4882a593Smuzhiyun if (*pos >= ARRAY_SIZE(hfi1_statnames))
1353*4882a593Smuzhiyun return NULL;
1354*4882a593Smuzhiyun return pos;
1355*4882a593Smuzhiyun }
1356*4882a593Smuzhiyun
_driver_stats_seq_stop(struct seq_file * s,void * v)1357*4882a593Smuzhiyun static void _driver_stats_seq_stop(struct seq_file *s, void *v)
1358*4882a593Smuzhiyun {
1359*4882a593Smuzhiyun }
1360*4882a593Smuzhiyun
hfi1_sps_ints(void)1361*4882a593Smuzhiyun static u64 hfi1_sps_ints(void)
1362*4882a593Smuzhiyun {
1363*4882a593Smuzhiyun unsigned long index, flags;
1364*4882a593Smuzhiyun struct hfi1_devdata *dd;
1365*4882a593Smuzhiyun u64 sps_ints = 0;
1366*4882a593Smuzhiyun
1367*4882a593Smuzhiyun xa_lock_irqsave(&hfi1_dev_table, flags);
1368*4882a593Smuzhiyun xa_for_each(&hfi1_dev_table, index, dd) {
1369*4882a593Smuzhiyun sps_ints += get_all_cpu_total(dd->int_counter);
1370*4882a593Smuzhiyun }
1371*4882a593Smuzhiyun xa_unlock_irqrestore(&hfi1_dev_table, flags);
1372*4882a593Smuzhiyun return sps_ints;
1373*4882a593Smuzhiyun }
1374*4882a593Smuzhiyun
_driver_stats_seq_show(struct seq_file * s,void * v)1375*4882a593Smuzhiyun static int _driver_stats_seq_show(struct seq_file *s, void *v)
1376*4882a593Smuzhiyun {
1377*4882a593Smuzhiyun loff_t *spos = v;
1378*4882a593Smuzhiyun char *buffer;
1379*4882a593Smuzhiyun u64 *stats = (u64 *)&hfi1_stats;
1380*4882a593Smuzhiyun size_t sz = seq_get_buf(s, &buffer);
1381*4882a593Smuzhiyun
1382*4882a593Smuzhiyun if (sz < sizeof(u64))
1383*4882a593Smuzhiyun return SEQ_SKIP;
1384*4882a593Smuzhiyun /* special case for interrupts */
1385*4882a593Smuzhiyun if (*spos == 0)
1386*4882a593Smuzhiyun *(u64 *)buffer = hfi1_sps_ints();
1387*4882a593Smuzhiyun else
1388*4882a593Smuzhiyun *(u64 *)buffer = stats[*spos];
1389*4882a593Smuzhiyun seq_commit(s, sizeof(u64));
1390*4882a593Smuzhiyun return 0;
1391*4882a593Smuzhiyun }
1392*4882a593Smuzhiyun
1393*4882a593Smuzhiyun DEBUGFS_SEQ_FILE_OPS(driver_stats);
1394*4882a593Smuzhiyun DEBUGFS_SEQ_FILE_OPEN(driver_stats)
1395*4882a593Smuzhiyun DEBUGFS_FILE_OPS(driver_stats);
1396*4882a593Smuzhiyun
hfi1_dbg_init(void)1397*4882a593Smuzhiyun void hfi1_dbg_init(void)
1398*4882a593Smuzhiyun {
1399*4882a593Smuzhiyun hfi1_dbg_root = debugfs_create_dir(DRIVER_NAME, NULL);
1400*4882a593Smuzhiyun debugfs_create_file("driver_stats_names", 0444, hfi1_dbg_root, NULL,
1401*4882a593Smuzhiyun &_driver_stats_names_file_ops);
1402*4882a593Smuzhiyun debugfs_create_file("driver_stats", 0444, hfi1_dbg_root, NULL,
1403*4882a593Smuzhiyun &_driver_stats_file_ops);
1404*4882a593Smuzhiyun }
1405*4882a593Smuzhiyun
hfi1_dbg_exit(void)1406*4882a593Smuzhiyun void hfi1_dbg_exit(void)
1407*4882a593Smuzhiyun {
1408*4882a593Smuzhiyun debugfs_remove_recursive(hfi1_dbg_root);
1409*4882a593Smuzhiyun hfi1_dbg_root = NULL;
1410*4882a593Smuzhiyun }
1411