1*145eba1aSCai Huoqing // SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause
2f48ad614SDennis Dalessandro /*
3b5de809eSMitko Haralanov  * Copyright(c) 2015-2018 Intel Corporation.
4f48ad614SDennis Dalessandro  */
5*145eba1aSCai Huoqing 
6f48ad614SDennis Dalessandro #include <linux/debugfs.h>
7f48ad614SDennis Dalessandro #include <linux/seq_file.h>
8f48ad614SDennis Dalessandro #include <linux/kernel.h>
9f48ad614SDennis Dalessandro #include <linux/export.h>
101bb0d7b7SMichael J. Ruhl #include <linux/string.h>
110181ce31SDon Hiatt #include <linux/types.h>
120181ce31SDon Hiatt #include <linux/ratelimit.h>
130181ce31SDon Hiatt #include <linux/fault-inject.h>
14f48ad614SDennis Dalessandro 
15f48ad614SDennis Dalessandro #include "hfi.h"
160181ce31SDon Hiatt #include "trace.h"
17f48ad614SDennis Dalessandro #include "debugfs.h"
18f48ad614SDennis Dalessandro #include "device.h"
19f48ad614SDennis Dalessandro #include "qp.h"
20f48ad614SDennis Dalessandro #include "sdma.h"
21a74d5307SMitko Haralanov #include "fault.h"
22f48ad614SDennis Dalessandro 
23f48ad614SDennis Dalessandro static struct dentry *hfi1_dbg_root;
24f48ad614SDennis Dalessandro 
2516170d9cSMike Marciniszyn /* wrappers to enforce srcu in seq file */
hfi1_seq_read(struct file * file,char __user * buf,size_t size,loff_t * ppos)26a74d5307SMitko Haralanov ssize_t hfi1_seq_read(struct file *file, char __user *buf, size_t size,
2716170d9cSMike Marciniszyn 		      loff_t *ppos)
2816170d9cSMike Marciniszyn {
2916170d9cSMike Marciniszyn 	struct dentry *d = file->f_path.dentry;
3016170d9cSMike Marciniszyn 	ssize_t r;
3116170d9cSMike Marciniszyn 
327cda7b8fSNicolai Stange 	r = debugfs_file_get(d);
337cda7b8fSNicolai Stange 	if (unlikely(r))
347cda7b8fSNicolai Stange 		return r;
3516170d9cSMike Marciniszyn 	r = seq_read(file, buf, size, ppos);
367cda7b8fSNicolai Stange 	debugfs_file_put(d);
3716170d9cSMike Marciniszyn 	return r;
3816170d9cSMike Marciniszyn }
3916170d9cSMike Marciniszyn 
hfi1_seq_lseek(struct file * file,loff_t offset,int whence)40a74d5307SMitko Haralanov loff_t hfi1_seq_lseek(struct file *file, loff_t offset, int whence)
4116170d9cSMike Marciniszyn {
4216170d9cSMike Marciniszyn 	struct dentry *d = file->f_path.dentry;
4316170d9cSMike Marciniszyn 	loff_t r;
4416170d9cSMike Marciniszyn 
457cda7b8fSNicolai Stange 	r = debugfs_file_get(d);
467cda7b8fSNicolai Stange 	if (unlikely(r))
477cda7b8fSNicolai Stange 		return r;
4816170d9cSMike Marciniszyn 	r = seq_lseek(file, offset, whence);
497cda7b8fSNicolai Stange 	debugfs_file_put(d);
5016170d9cSMike Marciniszyn 	return r;
5116170d9cSMike Marciniszyn }
5216170d9cSMike Marciniszyn 
53f48ad614SDennis Dalessandro #define private2dd(file) (file_inode(file)->i_private)
54f48ad614SDennis Dalessandro #define private2ppd(file) (file_inode(file)->i_private)
55f48ad614SDennis Dalessandro 
_opcode_stats_seq_start(struct seq_file * s,loff_t * pos)56f48ad614SDennis Dalessandro static void *_opcode_stats_seq_start(struct seq_file *s, loff_t *pos)
57f48ad614SDennis Dalessandro {
58f48ad614SDennis Dalessandro 	struct hfi1_opcode_stats_perctx *opstats;
59f48ad614SDennis Dalessandro 
60f48ad614SDennis Dalessandro 	if (*pos >= ARRAY_SIZE(opstats->stats))
61f48ad614SDennis Dalessandro 		return NULL;
62f48ad614SDennis Dalessandro 	return pos;
63f48ad614SDennis Dalessandro }
64f48ad614SDennis Dalessandro 
_opcode_stats_seq_next(struct seq_file * s,void * v,loff_t * pos)65f48ad614SDennis Dalessandro static void *_opcode_stats_seq_next(struct seq_file *s, void *v, loff_t *pos)
66f48ad614SDennis Dalessandro {
67f48ad614SDennis Dalessandro 	struct hfi1_opcode_stats_perctx *opstats;
68f48ad614SDennis Dalessandro 
69f48ad614SDennis Dalessandro 	++*pos;
70f48ad614SDennis Dalessandro 	if (*pos >= ARRAY_SIZE(opstats->stats))
71f48ad614SDennis Dalessandro 		return NULL;
72f48ad614SDennis Dalessandro 	return pos;
73f48ad614SDennis Dalessandro }
74f48ad614SDennis Dalessandro 
_opcode_stats_seq_stop(struct seq_file * s,void * v)75f48ad614SDennis Dalessandro static void _opcode_stats_seq_stop(struct seq_file *s, void *v)
76f48ad614SDennis Dalessandro {
77f48ad614SDennis Dalessandro }
78f48ad614SDennis Dalessandro 
opcode_stats_show(struct seq_file * s,u8 i,u64 packets,u64 bytes)791b311f89SMike Marciniszyn static int opcode_stats_show(struct seq_file *s, u8 i, u64 packets, u64 bytes)
801b311f89SMike Marciniszyn {
811b311f89SMike Marciniszyn 	if (!packets && !bytes)
821b311f89SMike Marciniszyn 		return SEQ_SKIP;
831b311f89SMike Marciniszyn 	seq_printf(s, "%02x %llu/%llu\n", i,
841b311f89SMike Marciniszyn 		   (unsigned long long)packets,
851b311f89SMike Marciniszyn 		   (unsigned long long)bytes);
861b311f89SMike Marciniszyn 
871b311f89SMike Marciniszyn 	return 0;
881b311f89SMike Marciniszyn }
891b311f89SMike Marciniszyn 
_opcode_stats_seq_show(struct seq_file * s,void * v)90f48ad614SDennis Dalessandro static int _opcode_stats_seq_show(struct seq_file *s, void *v)
91f48ad614SDennis Dalessandro {
92f48ad614SDennis Dalessandro 	loff_t *spos = v;
93f48ad614SDennis Dalessandro 	loff_t i = *spos, j;
94f48ad614SDennis Dalessandro 	u64 n_packets = 0, n_bytes = 0;
95f48ad614SDennis Dalessandro 	struct hfi1_ibdev *ibd = (struct hfi1_ibdev *)s->private;
96f48ad614SDennis Dalessandro 	struct hfi1_devdata *dd = dd_from_dev(ibd);
97d295dbebSMichael J. Ruhl 	struct hfi1_ctxtdata *rcd;
98f48ad614SDennis Dalessandro 
992280740fSVishwanathapura, Niranjana 	for (j = 0; j < dd->first_dyn_alloc_ctxt; j++) {
100d295dbebSMichael J. Ruhl 		rcd = hfi1_rcd_get_by_index(dd, j);
101d295dbebSMichael J. Ruhl 		if (rcd) {
102d295dbebSMichael J. Ruhl 			n_packets += rcd->opstats->stats[i].n_packets;
103d295dbebSMichael J. Ruhl 			n_bytes += rcd->opstats->stats[i].n_bytes;
104d295dbebSMichael J. Ruhl 		}
105d295dbebSMichael J. Ruhl 		hfi1_rcd_put(rcd);
106f48ad614SDennis Dalessandro 	}
1071b311f89SMike Marciniszyn 	return opcode_stats_show(s, i, n_packets, n_bytes);
108f48ad614SDennis Dalessandro }
109f48ad614SDennis Dalessandro 
110f48ad614SDennis Dalessandro DEBUGFS_SEQ_FILE_OPS(opcode_stats);
111f48ad614SDennis Dalessandro DEBUGFS_SEQ_FILE_OPEN(opcode_stats)
112f48ad614SDennis Dalessandro DEBUGFS_FILE_OPS(opcode_stats);
113f48ad614SDennis Dalessandro 
_tx_opcode_stats_seq_start(struct seq_file * s,loff_t * pos)1141b311f89SMike Marciniszyn static void *_tx_opcode_stats_seq_start(struct seq_file *s, loff_t *pos)
1151b311f89SMike Marciniszyn {
1161b311f89SMike Marciniszyn 	return _opcode_stats_seq_start(s, pos);
1171b311f89SMike Marciniszyn }
1181b311f89SMike Marciniszyn 
_tx_opcode_stats_seq_next(struct seq_file * s,void * v,loff_t * pos)1191b311f89SMike Marciniszyn static void *_tx_opcode_stats_seq_next(struct seq_file *s, void *v, loff_t *pos)
1201b311f89SMike Marciniszyn {
1211b311f89SMike Marciniszyn 	return _opcode_stats_seq_next(s, v, pos);
1221b311f89SMike Marciniszyn }
1231b311f89SMike Marciniszyn 
_tx_opcode_stats_seq_stop(struct seq_file * s,void * v)1241b311f89SMike Marciniszyn static void _tx_opcode_stats_seq_stop(struct seq_file *s, void *v)
1251b311f89SMike Marciniszyn {
1261b311f89SMike Marciniszyn }
1271b311f89SMike Marciniszyn 
_tx_opcode_stats_seq_show(struct seq_file * s,void * v)1281b311f89SMike Marciniszyn static int _tx_opcode_stats_seq_show(struct seq_file *s, void *v)
1291b311f89SMike Marciniszyn {
1301b311f89SMike Marciniszyn 	loff_t *spos = v;
1311b311f89SMike Marciniszyn 	loff_t i = *spos;
1321b311f89SMike Marciniszyn 	int j;
1331b311f89SMike Marciniszyn 	u64 n_packets = 0, n_bytes = 0;
1341b311f89SMike Marciniszyn 	struct hfi1_ibdev *ibd = (struct hfi1_ibdev *)s->private;
1351b311f89SMike Marciniszyn 	struct hfi1_devdata *dd = dd_from_dev(ibd);
1361b311f89SMike Marciniszyn 
1371b311f89SMike Marciniszyn 	for_each_possible_cpu(j) {
1381b311f89SMike Marciniszyn 		struct hfi1_opcode_stats_perctx *s =
1391b311f89SMike Marciniszyn 			per_cpu_ptr(dd->tx_opstats, j);
1401b311f89SMike Marciniszyn 		n_packets += s->stats[i].n_packets;
1411b311f89SMike Marciniszyn 		n_bytes += s->stats[i].n_bytes;
1421b311f89SMike Marciniszyn 	}
1431b311f89SMike Marciniszyn 	return opcode_stats_show(s, i, n_packets, n_bytes);
1441b311f89SMike Marciniszyn }
1451b311f89SMike Marciniszyn 
1461b311f89SMike Marciniszyn DEBUGFS_SEQ_FILE_OPS(tx_opcode_stats);
1471b311f89SMike Marciniszyn DEBUGFS_SEQ_FILE_OPEN(tx_opcode_stats)
1481b311f89SMike Marciniszyn DEBUGFS_FILE_OPS(tx_opcode_stats);
1491b311f89SMike Marciniszyn 
_ctx_stats_seq_start(struct seq_file * s,loff_t * pos)150f48ad614SDennis Dalessandro static void *_ctx_stats_seq_start(struct seq_file *s, loff_t *pos)
151f48ad614SDennis Dalessandro {
152f48ad614SDennis Dalessandro 	struct hfi1_ibdev *ibd = (struct hfi1_ibdev *)s->private;
153f48ad614SDennis Dalessandro 	struct hfi1_devdata *dd = dd_from_dev(ibd);
154f48ad614SDennis Dalessandro 
155f48ad614SDennis Dalessandro 	if (!*pos)
156f48ad614SDennis Dalessandro 		return SEQ_START_TOKEN;
1572280740fSVishwanathapura, Niranjana 	if (*pos >= dd->first_dyn_alloc_ctxt)
158f48ad614SDennis Dalessandro 		return NULL;
159f48ad614SDennis Dalessandro 	return pos;
160f48ad614SDennis Dalessandro }
161f48ad614SDennis Dalessandro 
_ctx_stats_seq_next(struct seq_file * s,void * v,loff_t * pos)162f48ad614SDennis Dalessandro static void *_ctx_stats_seq_next(struct seq_file *s, void *v, loff_t *pos)
163f48ad614SDennis Dalessandro {
164f48ad614SDennis Dalessandro 	struct hfi1_ibdev *ibd = (struct hfi1_ibdev *)s->private;
165f48ad614SDennis Dalessandro 	struct hfi1_devdata *dd = dd_from_dev(ibd);
166f48ad614SDennis Dalessandro 
167f48ad614SDennis Dalessandro 	if (v == SEQ_START_TOKEN)
168f48ad614SDennis Dalessandro 		return pos;
169f48ad614SDennis Dalessandro 
170f48ad614SDennis Dalessandro 	++*pos;
1712280740fSVishwanathapura, Niranjana 	if (*pos >= dd->first_dyn_alloc_ctxt)
172f48ad614SDennis Dalessandro 		return NULL;
173f48ad614SDennis Dalessandro 	return pos;
174f48ad614SDennis Dalessandro }
175f48ad614SDennis Dalessandro 
_ctx_stats_seq_stop(struct seq_file * s,void * v)176f48ad614SDennis Dalessandro static void _ctx_stats_seq_stop(struct seq_file *s, void *v)
177f48ad614SDennis Dalessandro {
178f48ad614SDennis Dalessandro 	/* nothing allocated */
179f48ad614SDennis Dalessandro }
180f48ad614SDennis Dalessandro 
_ctx_stats_seq_show(struct seq_file * s,void * v)181f48ad614SDennis Dalessandro static int _ctx_stats_seq_show(struct seq_file *s, void *v)
182f48ad614SDennis Dalessandro {
183f48ad614SDennis Dalessandro 	loff_t *spos;
184f48ad614SDennis Dalessandro 	loff_t i, j;
185f48ad614SDennis Dalessandro 	u64 n_packets = 0;
186f48ad614SDennis Dalessandro 	struct hfi1_ibdev *ibd = (struct hfi1_ibdev *)s->private;
187f48ad614SDennis Dalessandro 	struct hfi1_devdata *dd = dd_from_dev(ibd);
188d295dbebSMichael J. Ruhl 	struct hfi1_ctxtdata *rcd;
189f48ad614SDennis Dalessandro 
190f48ad614SDennis Dalessandro 	if (v == SEQ_START_TOKEN) {
191f48ad614SDennis Dalessandro 		seq_puts(s, "Ctx:npkts\n");
192f48ad614SDennis Dalessandro 		return 0;
193f48ad614SDennis Dalessandro 	}
194f48ad614SDennis Dalessandro 
195f48ad614SDennis Dalessandro 	spos = v;
196f48ad614SDennis Dalessandro 	i = *spos;
197f48ad614SDennis Dalessandro 
198d59075adSMichael J. Ruhl 	rcd = hfi1_rcd_get_by_index_safe(dd, i);
199d295dbebSMichael J. Ruhl 	if (!rcd)
200f48ad614SDennis Dalessandro 		return SEQ_SKIP;
201f48ad614SDennis Dalessandro 
202d295dbebSMichael J. Ruhl 	for (j = 0; j < ARRAY_SIZE(rcd->opstats->stats); j++)
203d295dbebSMichael J. Ruhl 		n_packets += rcd->opstats->stats[j].n_packets;
204d295dbebSMichael J. Ruhl 
205d295dbebSMichael J. Ruhl 	hfi1_rcd_put(rcd);
206f48ad614SDennis Dalessandro 
207f48ad614SDennis Dalessandro 	if (!n_packets)
208f48ad614SDennis Dalessandro 		return SEQ_SKIP;
209f48ad614SDennis Dalessandro 
210f48ad614SDennis Dalessandro 	seq_printf(s, "  %llu:%llu\n", i, n_packets);
211f48ad614SDennis Dalessandro 	return 0;
212f48ad614SDennis Dalessandro }
213f48ad614SDennis Dalessandro 
214f48ad614SDennis Dalessandro DEBUGFS_SEQ_FILE_OPS(ctx_stats);
215f48ad614SDennis Dalessandro DEBUGFS_SEQ_FILE_OPEN(ctx_stats)
216f48ad614SDennis Dalessandro DEBUGFS_FILE_OPS(ctx_stats);
217f48ad614SDennis Dalessandro 
_qp_stats_seq_start(struct seq_file * s,loff_t * pos)218f48ad614SDennis Dalessandro static void *_qp_stats_seq_start(struct seq_file *s, loff_t *pos)
219f48ad614SDennis Dalessandro 	__acquires(RCU)
220f48ad614SDennis Dalessandro {
221e5c197acSMike Marciniszyn 	struct rvt_qp_iter *iter;
222f48ad614SDennis Dalessandro 	loff_t n = *pos;
223f48ad614SDennis Dalessandro 
224e5c197acSMike Marciniszyn 	iter = rvt_qp_iter_init(s->private, 0, NULL);
225c62fb260SMike Marciniszyn 
226c62fb260SMike Marciniszyn 	/* stop calls rcu_read_unlock */
227c62fb260SMike Marciniszyn 	rcu_read_lock();
228c62fb260SMike Marciniszyn 
229f48ad614SDennis Dalessandro 	if (!iter)
230f48ad614SDennis Dalessandro 		return NULL;
231f48ad614SDennis Dalessandro 
232c62fb260SMike Marciniszyn 	do {
233e5c197acSMike Marciniszyn 		if (rvt_qp_iter_next(iter)) {
234f48ad614SDennis Dalessandro 			kfree(iter);
235f48ad614SDennis Dalessandro 			return NULL;
236f48ad614SDennis Dalessandro 		}
237c62fb260SMike Marciniszyn 	} while (n--);
238f48ad614SDennis Dalessandro 
239f48ad614SDennis Dalessandro 	return iter;
240f48ad614SDennis Dalessandro }
241f48ad614SDennis Dalessandro 
_qp_stats_seq_next(struct seq_file * s,void * iter_ptr,loff_t * pos)242f48ad614SDennis Dalessandro static void *_qp_stats_seq_next(struct seq_file *s, void *iter_ptr,
243f48ad614SDennis Dalessandro 				loff_t *pos)
244c62fb260SMike Marciniszyn 	__must_hold(RCU)
245f48ad614SDennis Dalessandro {
246e5c197acSMike Marciniszyn 	struct rvt_qp_iter *iter = iter_ptr;
247f48ad614SDennis Dalessandro 
248f48ad614SDennis Dalessandro 	(*pos)++;
249f48ad614SDennis Dalessandro 
250e5c197acSMike Marciniszyn 	if (rvt_qp_iter_next(iter)) {
251f48ad614SDennis Dalessandro 		kfree(iter);
252f48ad614SDennis Dalessandro 		return NULL;
253f48ad614SDennis Dalessandro 	}
254f48ad614SDennis Dalessandro 
255f48ad614SDennis Dalessandro 	return iter;
256f48ad614SDennis Dalessandro }
257f48ad614SDennis Dalessandro 
_qp_stats_seq_stop(struct seq_file * s,void * iter_ptr)258f48ad614SDennis Dalessandro static void _qp_stats_seq_stop(struct seq_file *s, void *iter_ptr)
259f48ad614SDennis Dalessandro 	__releases(RCU)
260f48ad614SDennis Dalessandro {
261f48ad614SDennis Dalessandro 	rcu_read_unlock();
262f48ad614SDennis Dalessandro }
263f48ad614SDennis Dalessandro 
_qp_stats_seq_show(struct seq_file * s,void * iter_ptr)264f48ad614SDennis Dalessandro static int _qp_stats_seq_show(struct seq_file *s, void *iter_ptr)
265f48ad614SDennis Dalessandro {
266e5c197acSMike Marciniszyn 	struct rvt_qp_iter *iter = iter_ptr;
267f48ad614SDennis Dalessandro 
268f48ad614SDennis Dalessandro 	if (!iter)
269f48ad614SDennis Dalessandro 		return 0;
270f48ad614SDennis Dalessandro 
271f48ad614SDennis Dalessandro 	qp_iter_print(s, iter);
272f48ad614SDennis Dalessandro 
273f48ad614SDennis Dalessandro 	return 0;
274f48ad614SDennis Dalessandro }
275f48ad614SDennis Dalessandro 
276f48ad614SDennis Dalessandro DEBUGFS_SEQ_FILE_OPS(qp_stats);
277f48ad614SDennis Dalessandro DEBUGFS_SEQ_FILE_OPEN(qp_stats)
278f48ad614SDennis Dalessandro DEBUGFS_FILE_OPS(qp_stats);
279f48ad614SDennis Dalessandro 
_sdes_seq_start(struct seq_file * s,loff_t * pos)280f48ad614SDennis Dalessandro static void *_sdes_seq_start(struct seq_file *s, loff_t *pos)
281f48ad614SDennis Dalessandro {
282f48ad614SDennis Dalessandro 	struct hfi1_ibdev *ibd;
283f48ad614SDennis Dalessandro 	struct hfi1_devdata *dd;
284f48ad614SDennis Dalessandro 
285f48ad614SDennis Dalessandro 	ibd = (struct hfi1_ibdev *)s->private;
286f48ad614SDennis Dalessandro 	dd = dd_from_dev(ibd);
287f48ad614SDennis Dalessandro 	if (!dd->per_sdma || *pos >= dd->num_sdma)
288f48ad614SDennis Dalessandro 		return NULL;
289f48ad614SDennis Dalessandro 	return pos;
290f48ad614SDennis Dalessandro }
291f48ad614SDennis Dalessandro 
_sdes_seq_next(struct seq_file * s,void * v,loff_t * pos)292f48ad614SDennis Dalessandro static void *_sdes_seq_next(struct seq_file *s, void *v, loff_t *pos)
293f48ad614SDennis Dalessandro {
294f48ad614SDennis Dalessandro 	struct hfi1_ibdev *ibd = (struct hfi1_ibdev *)s->private;
295f48ad614SDennis Dalessandro 	struct hfi1_devdata *dd = dd_from_dev(ibd);
296f48ad614SDennis Dalessandro 
297f48ad614SDennis Dalessandro 	++*pos;
298f48ad614SDennis Dalessandro 	if (!dd->per_sdma || *pos >= dd->num_sdma)
299f48ad614SDennis Dalessandro 		return NULL;
300f48ad614SDennis Dalessandro 	return pos;
301f48ad614SDennis Dalessandro }
302f48ad614SDennis Dalessandro 
_sdes_seq_stop(struct seq_file * s,void * v)303f48ad614SDennis Dalessandro static void _sdes_seq_stop(struct seq_file *s, void *v)
304f48ad614SDennis Dalessandro {
305f48ad614SDennis Dalessandro }
306f48ad614SDennis Dalessandro 
_sdes_seq_show(struct seq_file * s,void * v)307f48ad614SDennis Dalessandro static int _sdes_seq_show(struct seq_file *s, void *v)
308f48ad614SDennis Dalessandro {
309f48ad614SDennis Dalessandro 	struct hfi1_ibdev *ibd = (struct hfi1_ibdev *)s->private;
310f48ad614SDennis Dalessandro 	struct hfi1_devdata *dd = dd_from_dev(ibd);
311f48ad614SDennis Dalessandro 	loff_t *spos = v;
312f48ad614SDennis Dalessandro 	loff_t i = *spos;
313f48ad614SDennis Dalessandro 
314f48ad614SDennis Dalessandro 	sdma_seqfile_dump_sde(s, &dd->per_sdma[i]);
315f48ad614SDennis Dalessandro 	return 0;
316f48ad614SDennis Dalessandro }
317f48ad614SDennis Dalessandro 
318f48ad614SDennis Dalessandro DEBUGFS_SEQ_FILE_OPS(sdes);
319f48ad614SDennis Dalessandro DEBUGFS_SEQ_FILE_OPEN(sdes)
320f48ad614SDennis Dalessandro DEBUGFS_FILE_OPS(sdes);
321f48ad614SDennis Dalessandro 
_rcds_seq_start(struct seq_file * s,loff_t * pos)322bf808b50SKaike Wan static void *_rcds_seq_start(struct seq_file *s, loff_t *pos)
323bf808b50SKaike Wan {
324bf808b50SKaike Wan 	struct hfi1_ibdev *ibd;
325bf808b50SKaike Wan 	struct hfi1_devdata *dd;
326bf808b50SKaike Wan 
327bf808b50SKaike Wan 	ibd = (struct hfi1_ibdev *)s->private;
328bf808b50SKaike Wan 	dd = dd_from_dev(ibd);
329bf808b50SKaike Wan 	if (!dd->rcd || *pos >= dd->n_krcv_queues)
330bf808b50SKaike Wan 		return NULL;
331bf808b50SKaike Wan 	return pos;
332bf808b50SKaike Wan }
333bf808b50SKaike Wan 
_rcds_seq_next(struct seq_file * s,void * v,loff_t * pos)334bf808b50SKaike Wan static void *_rcds_seq_next(struct seq_file *s, void *v, loff_t *pos)
335bf808b50SKaike Wan {
336bf808b50SKaike Wan 	struct hfi1_ibdev *ibd = (struct hfi1_ibdev *)s->private;
337bf808b50SKaike Wan 	struct hfi1_devdata *dd = dd_from_dev(ibd);
338bf808b50SKaike Wan 
339bf808b50SKaike Wan 	++*pos;
34044ec5aa3SMichael J. Ruhl 	if (!dd->rcd || *pos >= dd->num_rcv_contexts)
341bf808b50SKaike Wan 		return NULL;
342bf808b50SKaike Wan 	return pos;
343bf808b50SKaike Wan }
344bf808b50SKaike Wan 
_rcds_seq_stop(struct seq_file * s,void * v)345bf808b50SKaike Wan static void _rcds_seq_stop(struct seq_file *s, void *v)
346bf808b50SKaike Wan {
347bf808b50SKaike Wan }
348bf808b50SKaike Wan 
_rcds_seq_show(struct seq_file * s,void * v)349bf808b50SKaike Wan static int _rcds_seq_show(struct seq_file *s, void *v)
350bf808b50SKaike Wan {
351bf808b50SKaike Wan 	struct hfi1_ibdev *ibd = (struct hfi1_ibdev *)s->private;
352bf808b50SKaike Wan 	struct hfi1_devdata *dd = dd_from_dev(ibd);
353bf808b50SKaike Wan 	struct hfi1_ctxtdata *rcd;
354bf808b50SKaike Wan 	loff_t *spos = v;
355bf808b50SKaike Wan 	loff_t i = *spos;
356bf808b50SKaike Wan 
357d59075adSMichael J. Ruhl 	rcd = hfi1_rcd_get_by_index_safe(dd, i);
358bf808b50SKaike Wan 	if (rcd)
359bf808b50SKaike Wan 		seqfile_dump_rcd(s, rcd);
360bf808b50SKaike Wan 	hfi1_rcd_put(rcd);
361bf808b50SKaike Wan 	return 0;
362bf808b50SKaike Wan }
363bf808b50SKaike Wan 
364bf808b50SKaike Wan DEBUGFS_SEQ_FILE_OPS(rcds);
365bf808b50SKaike Wan DEBUGFS_SEQ_FILE_OPEN(rcds)
366bf808b50SKaike Wan DEBUGFS_FILE_OPS(rcds);
367bf808b50SKaike Wan 
_pios_seq_start(struct seq_file * s,loff_t * pos)368937488a8SKaike Wan static void *_pios_seq_start(struct seq_file *s, loff_t *pos)
369937488a8SKaike Wan {
370937488a8SKaike Wan 	struct hfi1_ibdev *ibd;
371937488a8SKaike Wan 	struct hfi1_devdata *dd;
372937488a8SKaike Wan 
373937488a8SKaike Wan 	ibd = (struct hfi1_ibdev *)s->private;
374937488a8SKaike Wan 	dd = dd_from_dev(ibd);
375937488a8SKaike Wan 	if (!dd->send_contexts || *pos >= dd->num_send_contexts)
376937488a8SKaike Wan 		return NULL;
377937488a8SKaike Wan 	return pos;
378937488a8SKaike Wan }
379937488a8SKaike Wan 
_pios_seq_next(struct seq_file * s,void * v,loff_t * pos)380937488a8SKaike Wan static void *_pios_seq_next(struct seq_file *s, void *v, loff_t *pos)
381937488a8SKaike Wan {
382937488a8SKaike Wan 	struct hfi1_ibdev *ibd = (struct hfi1_ibdev *)s->private;
383937488a8SKaike Wan 	struct hfi1_devdata *dd = dd_from_dev(ibd);
384937488a8SKaike Wan 
385937488a8SKaike Wan 	++*pos;
386937488a8SKaike Wan 	if (!dd->send_contexts || *pos >= dd->num_send_contexts)
387937488a8SKaike Wan 		return NULL;
388937488a8SKaike Wan 	return pos;
389937488a8SKaike Wan }
390937488a8SKaike Wan 
_pios_seq_stop(struct seq_file * s,void * v)391937488a8SKaike Wan static void _pios_seq_stop(struct seq_file *s, void *v)
392937488a8SKaike Wan {
393937488a8SKaike Wan }
394937488a8SKaike Wan 
_pios_seq_show(struct seq_file * s,void * v)395937488a8SKaike Wan static int _pios_seq_show(struct seq_file *s, void *v)
396937488a8SKaike Wan {
397937488a8SKaike Wan 	struct hfi1_ibdev *ibd = (struct hfi1_ibdev *)s->private;
398937488a8SKaike Wan 	struct hfi1_devdata *dd = dd_from_dev(ibd);
399937488a8SKaike Wan 	struct send_context_info *sci;
400937488a8SKaike Wan 	loff_t *spos = v;
401937488a8SKaike Wan 	loff_t i = *spos;
402937488a8SKaike Wan 	unsigned long flags;
403937488a8SKaike Wan 
404937488a8SKaike Wan 	spin_lock_irqsave(&dd->sc_lock, flags);
405937488a8SKaike Wan 	sci = &dd->send_contexts[i];
406937488a8SKaike Wan 	if (sci && sci->type != SC_USER && sci->allocated && sci->sc)
407937488a8SKaike Wan 		seqfile_dump_sci(s, i, sci);
408937488a8SKaike Wan 	spin_unlock_irqrestore(&dd->sc_lock, flags);
409937488a8SKaike Wan 	return 0;
410937488a8SKaike Wan }
411937488a8SKaike Wan 
412937488a8SKaike Wan DEBUGFS_SEQ_FILE_OPS(pios);
413937488a8SKaike Wan DEBUGFS_SEQ_FILE_OPEN(pios)
414937488a8SKaike Wan DEBUGFS_FILE_OPS(pios);
415937488a8SKaike Wan 
416f48ad614SDennis Dalessandro /* read the per-device counters */
dev_counters_read(struct file * file,char __user * buf,size_t count,loff_t * ppos)417f48ad614SDennis Dalessandro static ssize_t dev_counters_read(struct file *file, char __user *buf,
418f48ad614SDennis Dalessandro 				 size_t count, loff_t *ppos)
419f48ad614SDennis Dalessandro {
420f48ad614SDennis Dalessandro 	u64 *counters;
421f48ad614SDennis Dalessandro 	size_t avail;
422f48ad614SDennis Dalessandro 	struct hfi1_devdata *dd;
423f48ad614SDennis Dalessandro 	ssize_t rval;
424f48ad614SDennis Dalessandro 
425f48ad614SDennis Dalessandro 	dd = private2dd(file);
426f48ad614SDennis Dalessandro 	avail = hfi1_read_cntrs(dd, NULL, &counters);
427f48ad614SDennis Dalessandro 	rval =  simple_read_from_buffer(buf, count, ppos, counters, avail);
428f48ad614SDennis Dalessandro 	return rval;
429f48ad614SDennis Dalessandro }
430f48ad614SDennis Dalessandro 
431f48ad614SDennis Dalessandro /* read the per-device counters */
dev_names_read(struct file * file,char __user * buf,size_t count,loff_t * ppos)432f48ad614SDennis Dalessandro static ssize_t dev_names_read(struct file *file, char __user *buf,
433f48ad614SDennis Dalessandro 			      size_t count, loff_t *ppos)
434f48ad614SDennis Dalessandro {
435f48ad614SDennis Dalessandro 	char *names;
436f48ad614SDennis Dalessandro 	size_t avail;
437f48ad614SDennis Dalessandro 	struct hfi1_devdata *dd;
438f48ad614SDennis Dalessandro 	ssize_t rval;
439f48ad614SDennis Dalessandro 
440f48ad614SDennis Dalessandro 	dd = private2dd(file);
441f48ad614SDennis Dalessandro 	avail = hfi1_read_cntrs(dd, &names, NULL);
442f48ad614SDennis Dalessandro 	rval =  simple_read_from_buffer(buf, count, ppos, names, avail);
443f48ad614SDennis Dalessandro 	return rval;
444f48ad614SDennis Dalessandro }
445f48ad614SDennis Dalessandro 
446f48ad614SDennis Dalessandro struct counter_info {
447f48ad614SDennis Dalessandro 	char *name;
448f48ad614SDennis Dalessandro 	const struct file_operations ops;
449f48ad614SDennis Dalessandro };
450f48ad614SDennis Dalessandro 
451f48ad614SDennis Dalessandro /*
452f48ad614SDennis Dalessandro  * Could use file_inode(file)->i_ino to figure out which file,
453f48ad614SDennis Dalessandro  * instead of separate routine for each, but for now, this works...
454f48ad614SDennis Dalessandro  */
455f48ad614SDennis Dalessandro 
456f48ad614SDennis Dalessandro /* read the per-port names (same for each port) */
portnames_read(struct file * file,char __user * buf,size_t count,loff_t * ppos)457f48ad614SDennis Dalessandro static ssize_t portnames_read(struct file *file, char __user *buf,
458f48ad614SDennis Dalessandro 			      size_t count, loff_t *ppos)
459f48ad614SDennis Dalessandro {
460f48ad614SDennis Dalessandro 	char *names;
461f48ad614SDennis Dalessandro 	size_t avail;
462f48ad614SDennis Dalessandro 	struct hfi1_devdata *dd;
463f48ad614SDennis Dalessandro 	ssize_t rval;
464f48ad614SDennis Dalessandro 
465f48ad614SDennis Dalessandro 	dd = private2dd(file);
466f48ad614SDennis Dalessandro 	avail = hfi1_read_portcntrs(dd->pport, &names, NULL);
467f48ad614SDennis Dalessandro 	rval = simple_read_from_buffer(buf, count, ppos, names, avail);
468f48ad614SDennis Dalessandro 	return rval;
469f48ad614SDennis Dalessandro }
470f48ad614SDennis Dalessandro 
471f48ad614SDennis Dalessandro /* read the per-port counters */
portcntrs_debugfs_read(struct file * file,char __user * buf,size_t count,loff_t * ppos)472f48ad614SDennis Dalessandro static ssize_t portcntrs_debugfs_read(struct file *file, char __user *buf,
473f48ad614SDennis Dalessandro 				      size_t count, loff_t *ppos)
474f48ad614SDennis Dalessandro {
475f48ad614SDennis Dalessandro 	u64 *counters;
476f48ad614SDennis Dalessandro 	size_t avail;
477f48ad614SDennis Dalessandro 	struct hfi1_pportdata *ppd;
478f48ad614SDennis Dalessandro 	ssize_t rval;
479f48ad614SDennis Dalessandro 
480f48ad614SDennis Dalessandro 	ppd = private2ppd(file);
481f48ad614SDennis Dalessandro 	avail = hfi1_read_portcntrs(ppd, NULL, &counters);
482f48ad614SDennis Dalessandro 	rval = simple_read_from_buffer(buf, count, ppos, counters, avail);
483f48ad614SDennis Dalessandro 	return rval;
484f48ad614SDennis Dalessandro }
485f48ad614SDennis Dalessandro 
check_dyn_flag(u64 scratch0,char * p,int size,int * used,int this_hfi,int hfi,u32 flag,const char * what)486f48ad614SDennis Dalessandro static void check_dyn_flag(u64 scratch0, char *p, int size, int *used,
487f48ad614SDennis Dalessandro 			   int this_hfi, int hfi, u32 flag, const char *what)
488f48ad614SDennis Dalessandro {
489f48ad614SDennis Dalessandro 	u32 mask;
490f48ad614SDennis Dalessandro 
491f48ad614SDennis Dalessandro 	mask = flag << (hfi ? CR_DYN_SHIFT : 0);
492f48ad614SDennis Dalessandro 	if (scratch0 & mask) {
493f48ad614SDennis Dalessandro 		*used += scnprintf(p + *used, size - *used,
494f48ad614SDennis Dalessandro 				   "  0x%08x - HFI%d %s in use, %s device\n",
495f48ad614SDennis Dalessandro 				   mask, hfi, what,
496f48ad614SDennis Dalessandro 				   this_hfi == hfi ? "this" : "other");
497f48ad614SDennis Dalessandro 	}
498f48ad614SDennis Dalessandro }
499f48ad614SDennis Dalessandro 
asic_flags_read(struct file * file,char __user * buf,size_t count,loff_t * ppos)500f48ad614SDennis Dalessandro static ssize_t asic_flags_read(struct file *file, char __user *buf,
501f48ad614SDennis Dalessandro 			       size_t count, loff_t *ppos)
502f48ad614SDennis Dalessandro {
503f48ad614SDennis Dalessandro 	struct hfi1_pportdata *ppd;
504f48ad614SDennis Dalessandro 	struct hfi1_devdata *dd;
505f48ad614SDennis Dalessandro 	u64 scratch0;
506f48ad614SDennis Dalessandro 	char *tmp;
507f48ad614SDennis Dalessandro 	int ret = 0;
508f48ad614SDennis Dalessandro 	int size;
509f48ad614SDennis Dalessandro 	int used;
510f48ad614SDennis Dalessandro 	int i;
511f48ad614SDennis Dalessandro 
512f48ad614SDennis Dalessandro 	ppd = private2ppd(file);
513f48ad614SDennis Dalessandro 	dd = ppd->dd;
514f48ad614SDennis Dalessandro 	size = PAGE_SIZE;
515f48ad614SDennis Dalessandro 	used = 0;
516f48ad614SDennis Dalessandro 	tmp = kmalloc(size, GFP_KERNEL);
51716170d9cSMike Marciniszyn 	if (!tmp)
518f48ad614SDennis Dalessandro 		return -ENOMEM;
519f48ad614SDennis Dalessandro 
520f48ad614SDennis Dalessandro 	scratch0 = read_csr(dd, ASIC_CFG_SCRATCH);
521f48ad614SDennis Dalessandro 	used += scnprintf(tmp + used, size - used,
522f48ad614SDennis Dalessandro 			  "Resource flags: 0x%016llx\n", scratch0);
523f48ad614SDennis Dalessandro 
524f48ad614SDennis Dalessandro 	/* check permanent flag */
525f48ad614SDennis Dalessandro 	if (scratch0 & CR_THERM_INIT) {
526f48ad614SDennis Dalessandro 		used += scnprintf(tmp + used, size - used,
527f48ad614SDennis Dalessandro 				  "  0x%08x - thermal monitoring initialized\n",
528f48ad614SDennis Dalessandro 				  (u32)CR_THERM_INIT);
529f48ad614SDennis Dalessandro 	}
530f48ad614SDennis Dalessandro 
531f48ad614SDennis Dalessandro 	/* check each dynamic flag on each HFI */
532f48ad614SDennis Dalessandro 	for (i = 0; i < 2; i++) {
533f48ad614SDennis Dalessandro 		check_dyn_flag(scratch0, tmp, size, &used, dd->hfi1_id, i,
534f48ad614SDennis Dalessandro 			       CR_SBUS, "SBus");
535f48ad614SDennis Dalessandro 		check_dyn_flag(scratch0, tmp, size, &used, dd->hfi1_id, i,
536f48ad614SDennis Dalessandro 			       CR_EPROM, "EPROM");
537f48ad614SDennis Dalessandro 		check_dyn_flag(scratch0, tmp, size, &used, dd->hfi1_id, i,
538f48ad614SDennis Dalessandro 			       CR_I2C1, "i2c chain 1");
539f48ad614SDennis Dalessandro 		check_dyn_flag(scratch0, tmp, size, &used, dd->hfi1_id, i,
540f48ad614SDennis Dalessandro 			       CR_I2C2, "i2c chain 2");
541f48ad614SDennis Dalessandro 	}
542f48ad614SDennis Dalessandro 	used += scnprintf(tmp + used, size - used, "Write bits to clear\n");
543f48ad614SDennis Dalessandro 
544f48ad614SDennis Dalessandro 	ret = simple_read_from_buffer(buf, count, ppos, tmp, used);
545f48ad614SDennis Dalessandro 	kfree(tmp);
546f48ad614SDennis Dalessandro 	return ret;
547f48ad614SDennis Dalessandro }
548f48ad614SDennis Dalessandro 
asic_flags_write(struct file * file,const char __user * buf,size_t count,loff_t * ppos)549f48ad614SDennis Dalessandro static ssize_t asic_flags_write(struct file *file, const char __user *buf,
550f48ad614SDennis Dalessandro 				size_t count, loff_t *ppos)
551f48ad614SDennis Dalessandro {
552f48ad614SDennis Dalessandro 	struct hfi1_pportdata *ppd;
553f48ad614SDennis Dalessandro 	struct hfi1_devdata *dd;
554f48ad614SDennis Dalessandro 	char *buff;
555f48ad614SDennis Dalessandro 	int ret;
556f48ad614SDennis Dalessandro 	unsigned long long value;
557f48ad614SDennis Dalessandro 	u64 scratch0;
558f48ad614SDennis Dalessandro 	u64 clear;
559f48ad614SDennis Dalessandro 
560f48ad614SDennis Dalessandro 	ppd = private2ppd(file);
561f48ad614SDennis Dalessandro 	dd = ppd->dd;
562f48ad614SDennis Dalessandro 
563f48ad614SDennis Dalessandro 	/* zero terminate and read the expected integer */
5641bb0d7b7SMichael J. Ruhl 	buff = memdup_user_nul(buf, count);
5651bb0d7b7SMichael J. Ruhl 	if (IS_ERR(buff))
5661bb0d7b7SMichael J. Ruhl 		return PTR_ERR(buff);
5671bb0d7b7SMichael J. Ruhl 
568f48ad614SDennis Dalessandro 	ret = kstrtoull(buff, 0, &value);
569f48ad614SDennis Dalessandro 	if (ret)
570f48ad614SDennis Dalessandro 		goto do_free;
571f48ad614SDennis Dalessandro 	clear = value;
572f48ad614SDennis Dalessandro 
573f48ad614SDennis Dalessandro 	/* obtain exclusive access */
574f48ad614SDennis Dalessandro 	mutex_lock(&dd->asic_data->asic_resource_mutex);
575f48ad614SDennis Dalessandro 	acquire_hw_mutex(dd);
576f48ad614SDennis Dalessandro 
577f48ad614SDennis Dalessandro 	scratch0 = read_csr(dd, ASIC_CFG_SCRATCH);
578f48ad614SDennis Dalessandro 	scratch0 &= ~clear;
579f48ad614SDennis Dalessandro 	write_csr(dd, ASIC_CFG_SCRATCH, scratch0);
580f48ad614SDennis Dalessandro 	/* force write to be visible to other HFI on another OS */
581f48ad614SDennis Dalessandro 	(void)read_csr(dd, ASIC_CFG_SCRATCH);
582f48ad614SDennis Dalessandro 
583f48ad614SDennis Dalessandro 	release_hw_mutex(dd);
584f48ad614SDennis Dalessandro 	mutex_unlock(&dd->asic_data->asic_resource_mutex);
585f48ad614SDennis Dalessandro 
586f48ad614SDennis Dalessandro 	/* return the number of bytes written */
587f48ad614SDennis Dalessandro 	ret = count;
588f48ad614SDennis Dalessandro 
589f48ad614SDennis Dalessandro  do_free:
590f48ad614SDennis Dalessandro 	kfree(buff);
591f48ad614SDennis Dalessandro 	return ret;
592f48ad614SDennis Dalessandro }
593f48ad614SDennis Dalessandro 
5941b9e7749SDean Luick /* read the dc8051 memory */
dc8051_memory_read(struct file * file,char __user * buf,size_t count,loff_t * ppos)5951b9e7749SDean Luick static ssize_t dc8051_memory_read(struct file *file, char __user *buf,
5961b9e7749SDean Luick 				  size_t count, loff_t *ppos)
5971b9e7749SDean Luick {
5981b9e7749SDean Luick 	struct hfi1_pportdata *ppd = private2ppd(file);
5991b9e7749SDean Luick 	ssize_t rval;
6001b9e7749SDean Luick 	void *tmp;
6011b9e7749SDean Luick 	loff_t start, end;
6021b9e7749SDean Luick 
6031b9e7749SDean Luick 	/* the checks below expect the position to be positive */
6041b9e7749SDean Luick 	if (*ppos < 0)
6051b9e7749SDean Luick 		return -EINVAL;
6061b9e7749SDean Luick 
6071b9e7749SDean Luick 	tmp = kzalloc(DC8051_DATA_MEM_SIZE, GFP_KERNEL);
6081b9e7749SDean Luick 	if (!tmp)
6091b9e7749SDean Luick 		return -ENOMEM;
6101b9e7749SDean Luick 
6111b9e7749SDean Luick 	/*
6121b9e7749SDean Luick 	 * Fill in the requested portion of the temporary buffer from the
6131b9e7749SDean Luick 	 * 8051 memory.  The 8051 memory read is done in terms of 8 bytes.
6141b9e7749SDean Luick 	 * Adjust start and end to fit.  Skip reading anything if out of
6151b9e7749SDean Luick 	 * range.
6161b9e7749SDean Luick 	 */
6171b9e7749SDean Luick 	start = *ppos & ~0x7;	/* round down */
6181b9e7749SDean Luick 	if (start < DC8051_DATA_MEM_SIZE) {
6191b9e7749SDean Luick 		end = (*ppos + count + 7) & ~0x7; /* round up */
6201b9e7749SDean Luick 		if (end > DC8051_DATA_MEM_SIZE)
6211b9e7749SDean Luick 			end = DC8051_DATA_MEM_SIZE;
6221b9e7749SDean Luick 		rval = read_8051_data(ppd->dd, start, end - start,
6231b9e7749SDean Luick 				      (u64 *)(tmp + start));
6241b9e7749SDean Luick 		if (rval)
6251b9e7749SDean Luick 			goto done;
6261b9e7749SDean Luick 	}
6271b9e7749SDean Luick 
6281b9e7749SDean Luick 	rval = simple_read_from_buffer(buf, count, ppos, tmp,
6291b9e7749SDean Luick 				       DC8051_DATA_MEM_SIZE);
6301b9e7749SDean Luick done:
6311b9e7749SDean Luick 	kfree(tmp);
6321b9e7749SDean Luick 	return rval;
6331b9e7749SDean Luick }
6341b9e7749SDean Luick 
debugfs_lcb_read(struct file * file,char __user * buf,size_t count,loff_t * ppos)6351b9e7749SDean Luick static ssize_t debugfs_lcb_read(struct file *file, char __user *buf,
6361b9e7749SDean Luick 				size_t count, loff_t *ppos)
6371b9e7749SDean Luick {
6381b9e7749SDean Luick 	struct hfi1_pportdata *ppd = private2ppd(file);
6391b9e7749SDean Luick 	struct hfi1_devdata *dd = ppd->dd;
6401b9e7749SDean Luick 	unsigned long total, csr_off;
6411b9e7749SDean Luick 	u64 data;
6421b9e7749SDean Luick 
6431b9e7749SDean Luick 	if (*ppos < 0)
6441b9e7749SDean Luick 		return -EINVAL;
6451b9e7749SDean Luick 	/* only read 8 byte quantities */
6461b9e7749SDean Luick 	if ((count % 8) != 0)
6471b9e7749SDean Luick 		return -EINVAL;
6481b9e7749SDean Luick 	/* offset must be 8-byte aligned */
6491b9e7749SDean Luick 	if ((*ppos % 8) != 0)
6501b9e7749SDean Luick 		return -EINVAL;
6511b9e7749SDean Luick 	/* do nothing if out of range or zero count */
6521b9e7749SDean Luick 	if (*ppos >= (LCB_END - LCB_START) || !count)
6531b9e7749SDean Luick 		return 0;
6541b9e7749SDean Luick 	/* reduce count if needed */
6551b9e7749SDean Luick 	if (*ppos + count > LCB_END - LCB_START)
6561b9e7749SDean Luick 		count = (LCB_END - LCB_START) - *ppos;
6571b9e7749SDean Luick 
6581b9e7749SDean Luick 	csr_off = LCB_START + *ppos;
6591b9e7749SDean Luick 	for (total = 0; total < count; total += 8, csr_off += 8) {
6601b9e7749SDean Luick 		if (read_lcb_csr(dd, csr_off, (u64 *)&data))
6611b9e7749SDean Luick 			break; /* failed */
6621b9e7749SDean Luick 		if (put_user(data, (unsigned long __user *)(buf + total)))
6631b9e7749SDean Luick 			break;
6641b9e7749SDean Luick 	}
6651b9e7749SDean Luick 	*ppos += total;
6661b9e7749SDean Luick 	return total;
6671b9e7749SDean Luick }
6681b9e7749SDean Luick 
debugfs_lcb_write(struct file * file,const char __user * buf,size_t count,loff_t * ppos)6691b9e7749SDean Luick static ssize_t debugfs_lcb_write(struct file *file, const char __user *buf,
6701b9e7749SDean Luick 				 size_t count, loff_t *ppos)
6711b9e7749SDean Luick {
6721b9e7749SDean Luick 	struct hfi1_pportdata *ppd = private2ppd(file);
6731b9e7749SDean Luick 	struct hfi1_devdata *dd = ppd->dd;
6741b9e7749SDean Luick 	unsigned long total, csr_off, data;
6751b9e7749SDean Luick 
6761b9e7749SDean Luick 	if (*ppos < 0)
6771b9e7749SDean Luick 		return -EINVAL;
6781b9e7749SDean Luick 	/* only write 8 byte quantities */
6791b9e7749SDean Luick 	if ((count % 8) != 0)
6801b9e7749SDean Luick 		return -EINVAL;
6811b9e7749SDean Luick 	/* offset must be 8-byte aligned */
6821b9e7749SDean Luick 	if ((*ppos % 8) != 0)
6831b9e7749SDean Luick 		return -EINVAL;
6841b9e7749SDean Luick 	/* do nothing if out of range or zero count */
6851b9e7749SDean Luick 	if (*ppos >= (LCB_END - LCB_START) || !count)
6861b9e7749SDean Luick 		return 0;
6871b9e7749SDean Luick 	/* reduce count if needed */
6881b9e7749SDean Luick 	if (*ppos + count > LCB_END - LCB_START)
6891b9e7749SDean Luick 		count = (LCB_END - LCB_START) - *ppos;
6901b9e7749SDean Luick 
6911b9e7749SDean Luick 	csr_off = LCB_START + *ppos;
6921b9e7749SDean Luick 	for (total = 0; total < count; total += 8, csr_off += 8) {
6931b9e7749SDean Luick 		if (get_user(data, (unsigned long __user *)(buf + total)))
6941b9e7749SDean Luick 			break;
6951b9e7749SDean Luick 		if (write_lcb_csr(dd, csr_off, data))
6961b9e7749SDean Luick 			break; /* failed */
6971b9e7749SDean Luick 	}
6981b9e7749SDean Luick 	*ppos += total;
6991b9e7749SDean Luick 	return total;
7001b9e7749SDean Luick }
7011b9e7749SDean Luick 
702f48ad614SDennis Dalessandro /*
703f48ad614SDennis Dalessandro  * read the per-port QSFP data for ppd
704f48ad614SDennis Dalessandro  */
qsfp_debugfs_dump(struct file * file,char __user * buf,size_t count,loff_t * ppos)705f48ad614SDennis Dalessandro static ssize_t qsfp_debugfs_dump(struct file *file, char __user *buf,
706f48ad614SDennis Dalessandro 				 size_t count, loff_t *ppos)
707f48ad614SDennis Dalessandro {
708f48ad614SDennis Dalessandro 	struct hfi1_pportdata *ppd;
709f48ad614SDennis Dalessandro 	char *tmp;
710f48ad614SDennis Dalessandro 	int ret;
711f48ad614SDennis Dalessandro 
712f48ad614SDennis Dalessandro 	ppd = private2ppd(file);
713f48ad614SDennis Dalessandro 	tmp = kmalloc(PAGE_SIZE, GFP_KERNEL);
71416170d9cSMike Marciniszyn 	if (!tmp)
715f48ad614SDennis Dalessandro 		return -ENOMEM;
716f48ad614SDennis Dalessandro 
717f48ad614SDennis Dalessandro 	ret = qsfp_dump(ppd, tmp, PAGE_SIZE);
718f48ad614SDennis Dalessandro 	if (ret > 0)
719f48ad614SDennis Dalessandro 		ret = simple_read_from_buffer(buf, count, ppos, tmp, ret);
720f48ad614SDennis Dalessandro 	kfree(tmp);
721f48ad614SDennis Dalessandro 	return ret;
722f48ad614SDennis Dalessandro }
723f48ad614SDennis Dalessandro 
724f48ad614SDennis Dalessandro /* 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)725f48ad614SDennis Dalessandro static ssize_t __i2c_debugfs_write(struct file *file, const char __user *buf,
726f48ad614SDennis Dalessandro 				   size_t count, loff_t *ppos, u32 target)
727f48ad614SDennis Dalessandro {
728f48ad614SDennis Dalessandro 	struct hfi1_pportdata *ppd;
729f48ad614SDennis Dalessandro 	char *buff;
730f48ad614SDennis Dalessandro 	int ret;
731f48ad614SDennis Dalessandro 	int i2c_addr;
732f48ad614SDennis Dalessandro 	int offset;
733f48ad614SDennis Dalessandro 	int total_written;
734f48ad614SDennis Dalessandro 
735f48ad614SDennis Dalessandro 	ppd = private2ppd(file);
736f48ad614SDennis Dalessandro 
737f48ad614SDennis Dalessandro 	/* byte offset format: [offsetSize][i2cAddr][offsetHigh][offsetLow] */
738f48ad614SDennis Dalessandro 	i2c_addr = (*ppos >> 16) & 0xffff;
739f48ad614SDennis Dalessandro 	offset = *ppos & 0xffff;
740f48ad614SDennis Dalessandro 
741f48ad614SDennis Dalessandro 	/* explicitly reject invalid address 0 to catch cp and cat */
74216170d9cSMike Marciniszyn 	if (i2c_addr == 0)
74316170d9cSMike Marciniszyn 		return -EINVAL;
744f48ad614SDennis Dalessandro 
7451bb0d7b7SMichael J. Ruhl 	buff = memdup_user(buf, count);
7461bb0d7b7SMichael J. Ruhl 	if (IS_ERR(buff))
7471bb0d7b7SMichael J. Ruhl 		return PTR_ERR(buff);
748f48ad614SDennis Dalessandro 
749f48ad614SDennis Dalessandro 	total_written = i2c_write(ppd, target, i2c_addr, offset, buff, count);
750f48ad614SDennis Dalessandro 	if (total_written < 0) {
751f48ad614SDennis Dalessandro 		ret = total_written;
752f48ad614SDennis Dalessandro 		goto _free;
753f48ad614SDennis Dalessandro 	}
754f48ad614SDennis Dalessandro 
755f48ad614SDennis Dalessandro 	*ppos += total_written;
756f48ad614SDennis Dalessandro 
757f48ad614SDennis Dalessandro 	ret = total_written;
758f48ad614SDennis Dalessandro 
759f48ad614SDennis Dalessandro  _free:
760f48ad614SDennis Dalessandro 	kfree(buff);
761f48ad614SDennis Dalessandro 	return ret;
762f48ad614SDennis Dalessandro }
763f48ad614SDennis Dalessandro 
764f48ad614SDennis Dalessandro /* 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)765f48ad614SDennis Dalessandro static ssize_t i2c1_debugfs_write(struct file *file, const char __user *buf,
766f48ad614SDennis Dalessandro 				  size_t count, loff_t *ppos)
767f48ad614SDennis Dalessandro {
768f48ad614SDennis Dalessandro 	return __i2c_debugfs_write(file, buf, count, ppos, 0);
769f48ad614SDennis Dalessandro }
770f48ad614SDennis Dalessandro 
771f48ad614SDennis Dalessandro /* 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)772f48ad614SDennis Dalessandro static ssize_t i2c2_debugfs_write(struct file *file, const char __user *buf,
773f48ad614SDennis Dalessandro 				  size_t count, loff_t *ppos)
774f48ad614SDennis Dalessandro {
775f48ad614SDennis Dalessandro 	return __i2c_debugfs_write(file, buf, count, ppos, 1);
776f48ad614SDennis Dalessandro }
777f48ad614SDennis Dalessandro 
778f48ad614SDennis Dalessandro /* 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)779f48ad614SDennis Dalessandro static ssize_t __i2c_debugfs_read(struct file *file, char __user *buf,
780f48ad614SDennis Dalessandro 				  size_t count, loff_t *ppos, u32 target)
781f48ad614SDennis Dalessandro {
782f48ad614SDennis Dalessandro 	struct hfi1_pportdata *ppd;
783f48ad614SDennis Dalessandro 	char *buff;
784f48ad614SDennis Dalessandro 	int ret;
785f48ad614SDennis Dalessandro 	int i2c_addr;
786f48ad614SDennis Dalessandro 	int offset;
787f48ad614SDennis Dalessandro 	int total_read;
788f48ad614SDennis Dalessandro 
789f48ad614SDennis Dalessandro 	ppd = private2ppd(file);
790f48ad614SDennis Dalessandro 
791f48ad614SDennis Dalessandro 	/* byte offset format: [offsetSize][i2cAddr][offsetHigh][offsetLow] */
792f48ad614SDennis Dalessandro 	i2c_addr = (*ppos >> 16) & 0xffff;
793f48ad614SDennis Dalessandro 	offset = *ppos & 0xffff;
794f48ad614SDennis Dalessandro 
795f48ad614SDennis Dalessandro 	/* explicitly reject invalid address 0 to catch cp and cat */
79616170d9cSMike Marciniszyn 	if (i2c_addr == 0)
79716170d9cSMike Marciniszyn 		return -EINVAL;
798f48ad614SDennis Dalessandro 
799f48ad614SDennis Dalessandro 	buff = kmalloc(count, GFP_KERNEL);
80016170d9cSMike Marciniszyn 	if (!buff)
80116170d9cSMike Marciniszyn 		return -ENOMEM;
802f48ad614SDennis Dalessandro 
803f48ad614SDennis Dalessandro 	total_read = i2c_read(ppd, target, i2c_addr, offset, buff, count);
804f48ad614SDennis Dalessandro 	if (total_read < 0) {
805f48ad614SDennis Dalessandro 		ret = total_read;
806f48ad614SDennis Dalessandro 		goto _free;
807f48ad614SDennis Dalessandro 	}
808f48ad614SDennis Dalessandro 
809f48ad614SDennis Dalessandro 	*ppos += total_read;
810f48ad614SDennis Dalessandro 
811f48ad614SDennis Dalessandro 	ret = copy_to_user(buf, buff, total_read);
812f48ad614SDennis Dalessandro 	if (ret > 0) {
813f48ad614SDennis Dalessandro 		ret = -EFAULT;
814f48ad614SDennis Dalessandro 		goto _free;
815f48ad614SDennis Dalessandro 	}
816f48ad614SDennis Dalessandro 
817f48ad614SDennis Dalessandro 	ret = total_read;
818f48ad614SDennis Dalessandro 
819f48ad614SDennis Dalessandro  _free:
820f48ad614SDennis Dalessandro 	kfree(buff);
821f48ad614SDennis Dalessandro 	return ret;
822f48ad614SDennis Dalessandro }
823f48ad614SDennis Dalessandro 
824f48ad614SDennis Dalessandro /* 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)825f48ad614SDennis Dalessandro static ssize_t i2c1_debugfs_read(struct file *file, char __user *buf,
826f48ad614SDennis Dalessandro 				 size_t count, loff_t *ppos)
827f48ad614SDennis Dalessandro {
828f48ad614SDennis Dalessandro 	return __i2c_debugfs_read(file, buf, count, ppos, 0);
829f48ad614SDennis Dalessandro }
830f48ad614SDennis Dalessandro 
831f48ad614SDennis Dalessandro /* 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)832f48ad614SDennis Dalessandro static ssize_t i2c2_debugfs_read(struct file *file, char __user *buf,
833f48ad614SDennis Dalessandro 				 size_t count, loff_t *ppos)
834f48ad614SDennis Dalessandro {
835f48ad614SDennis Dalessandro 	return __i2c_debugfs_read(file, buf, count, ppos, 1);
836f48ad614SDennis Dalessandro }
837f48ad614SDennis Dalessandro 
838f48ad614SDennis Dalessandro /* 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)839f48ad614SDennis Dalessandro static ssize_t __qsfp_debugfs_write(struct file *file, const char __user *buf,
840f48ad614SDennis Dalessandro 				    size_t count, loff_t *ppos, u32 target)
841f48ad614SDennis Dalessandro {
842f48ad614SDennis Dalessandro 	struct hfi1_pportdata *ppd;
843f48ad614SDennis Dalessandro 	char *buff;
844f48ad614SDennis Dalessandro 	int ret;
845f48ad614SDennis Dalessandro 	int total_written;
846f48ad614SDennis Dalessandro 
84716170d9cSMike Marciniszyn 	if (*ppos + count > QSFP_PAGESIZE * 4) /* base page + page00-page03 */
84816170d9cSMike Marciniszyn 		return -EINVAL;
849f48ad614SDennis Dalessandro 
850f48ad614SDennis Dalessandro 	ppd = private2ppd(file);
851f48ad614SDennis Dalessandro 
8521bb0d7b7SMichael J. Ruhl 	buff = memdup_user(buf, count);
8531bb0d7b7SMichael J. Ruhl 	if (IS_ERR(buff))
8541bb0d7b7SMichael J. Ruhl 		return PTR_ERR(buff);
855f48ad614SDennis Dalessandro 
856f48ad614SDennis Dalessandro 	total_written = qsfp_write(ppd, target, *ppos, buff, count);
857f48ad614SDennis Dalessandro 	if (total_written < 0) {
858f48ad614SDennis Dalessandro 		ret = total_written;
859f48ad614SDennis Dalessandro 		goto _free;
860f48ad614SDennis Dalessandro 	}
861f48ad614SDennis Dalessandro 
862f48ad614SDennis Dalessandro 	*ppos += total_written;
863f48ad614SDennis Dalessandro 
864f48ad614SDennis Dalessandro 	ret = total_written;
865f48ad614SDennis Dalessandro 
866f48ad614SDennis Dalessandro  _free:
867f48ad614SDennis Dalessandro 	kfree(buff);
868f48ad614SDennis Dalessandro 	return ret;
869f48ad614SDennis Dalessandro }
870f48ad614SDennis Dalessandro 
871f48ad614SDennis Dalessandro /* 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)872f48ad614SDennis Dalessandro static ssize_t qsfp1_debugfs_write(struct file *file, const char __user *buf,
873f48ad614SDennis Dalessandro 				   size_t count, loff_t *ppos)
874f48ad614SDennis Dalessandro {
875f48ad614SDennis Dalessandro 	return __qsfp_debugfs_write(file, buf, count, ppos, 0);
876f48ad614SDennis Dalessandro }
877f48ad614SDennis Dalessandro 
878f48ad614SDennis Dalessandro /* 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)879f48ad614SDennis Dalessandro static ssize_t qsfp2_debugfs_write(struct file *file, const char __user *buf,
880f48ad614SDennis Dalessandro 				   size_t count, loff_t *ppos)
881f48ad614SDennis Dalessandro {
882f48ad614SDennis Dalessandro 	return __qsfp_debugfs_write(file, buf, count, ppos, 1);
883f48ad614SDennis Dalessandro }
884f48ad614SDennis Dalessandro 
885f48ad614SDennis Dalessandro /* 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)886f48ad614SDennis Dalessandro static ssize_t __qsfp_debugfs_read(struct file *file, char __user *buf,
887f48ad614SDennis Dalessandro 				   size_t count, loff_t *ppos, u32 target)
888f48ad614SDennis Dalessandro {
889f48ad614SDennis Dalessandro 	struct hfi1_pportdata *ppd;
890f48ad614SDennis Dalessandro 	char *buff;
891f48ad614SDennis Dalessandro 	int ret;
892f48ad614SDennis Dalessandro 	int total_read;
893f48ad614SDennis Dalessandro 
894f48ad614SDennis Dalessandro 	if (*ppos + count > QSFP_PAGESIZE * 4) { /* base page + page00-page03 */
895f48ad614SDennis Dalessandro 		ret = -EINVAL;
896f48ad614SDennis Dalessandro 		goto _return;
897f48ad614SDennis Dalessandro 	}
898f48ad614SDennis Dalessandro 
899f48ad614SDennis Dalessandro 	ppd = private2ppd(file);
900f48ad614SDennis Dalessandro 
901f48ad614SDennis Dalessandro 	buff = kmalloc(count, GFP_KERNEL);
902f48ad614SDennis Dalessandro 	if (!buff) {
903f48ad614SDennis Dalessandro 		ret = -ENOMEM;
904f48ad614SDennis Dalessandro 		goto _return;
905f48ad614SDennis Dalessandro 	}
906f48ad614SDennis Dalessandro 
907f48ad614SDennis Dalessandro 	total_read = qsfp_read(ppd, target, *ppos, buff, count);
908f48ad614SDennis Dalessandro 	if (total_read < 0) {
909f48ad614SDennis Dalessandro 		ret = total_read;
910f48ad614SDennis Dalessandro 		goto _free;
911f48ad614SDennis Dalessandro 	}
912f48ad614SDennis Dalessandro 
913f48ad614SDennis Dalessandro 	*ppos += total_read;
914f48ad614SDennis Dalessandro 
915f48ad614SDennis Dalessandro 	ret = copy_to_user(buf, buff, total_read);
916f48ad614SDennis Dalessandro 	if (ret > 0) {
917f48ad614SDennis Dalessandro 		ret = -EFAULT;
918f48ad614SDennis Dalessandro 		goto _free;
919f48ad614SDennis Dalessandro 	}
920f48ad614SDennis Dalessandro 
921f48ad614SDennis Dalessandro 	ret = total_read;
922f48ad614SDennis Dalessandro 
923f48ad614SDennis Dalessandro  _free:
924f48ad614SDennis Dalessandro 	kfree(buff);
925f48ad614SDennis Dalessandro  _return:
926f48ad614SDennis Dalessandro 	return ret;
927f48ad614SDennis Dalessandro }
928f48ad614SDennis Dalessandro 
929f48ad614SDennis Dalessandro /* 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)930f48ad614SDennis Dalessandro static ssize_t qsfp1_debugfs_read(struct file *file, char __user *buf,
931f48ad614SDennis Dalessandro 				  size_t count, loff_t *ppos)
932f48ad614SDennis Dalessandro {
933f48ad614SDennis Dalessandro 	return __qsfp_debugfs_read(file, buf, count, ppos, 0);
934f48ad614SDennis Dalessandro }
935f48ad614SDennis Dalessandro 
936f48ad614SDennis Dalessandro /* 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)937f48ad614SDennis Dalessandro static ssize_t qsfp2_debugfs_read(struct file *file, char __user *buf,
938f48ad614SDennis Dalessandro 				  size_t count, loff_t *ppos)
939f48ad614SDennis Dalessandro {
940f48ad614SDennis Dalessandro 	return __qsfp_debugfs_read(file, buf, count, ppos, 1);
941f48ad614SDennis Dalessandro }
942f48ad614SDennis Dalessandro 
__i2c_debugfs_open(struct inode * in,struct file * fp,u32 target)943f48ad614SDennis Dalessandro static int __i2c_debugfs_open(struct inode *in, struct file *fp, u32 target)
944f48ad614SDennis Dalessandro {
945f48ad614SDennis Dalessandro 	struct hfi1_pportdata *ppd;
946f48ad614SDennis Dalessandro 
947f48ad614SDennis Dalessandro 	ppd = private2ppd(fp);
948f48ad614SDennis Dalessandro 
949822fbd37SDennis Dalessandro 	return acquire_chip_resource(ppd->dd, i2c_target(target), 0);
950f48ad614SDennis Dalessandro }
951f48ad614SDennis Dalessandro 
i2c1_debugfs_open(struct inode * in,struct file * fp)952f48ad614SDennis Dalessandro static int i2c1_debugfs_open(struct inode *in, struct file *fp)
953f48ad614SDennis Dalessandro {
954f48ad614SDennis Dalessandro 	return __i2c_debugfs_open(in, fp, 0);
955f48ad614SDennis Dalessandro }
956f48ad614SDennis Dalessandro 
i2c2_debugfs_open(struct inode * in,struct file * fp)957f48ad614SDennis Dalessandro static int i2c2_debugfs_open(struct inode *in, struct file *fp)
958f48ad614SDennis Dalessandro {
959f48ad614SDennis Dalessandro 	return __i2c_debugfs_open(in, fp, 1);
960f48ad614SDennis Dalessandro }
961f48ad614SDennis Dalessandro 
__i2c_debugfs_release(struct inode * in,struct file * fp,u32 target)962f48ad614SDennis Dalessandro static int __i2c_debugfs_release(struct inode *in, struct file *fp, u32 target)
963f48ad614SDennis Dalessandro {
964f48ad614SDennis Dalessandro 	struct hfi1_pportdata *ppd;
965f48ad614SDennis Dalessandro 
966f48ad614SDennis Dalessandro 	ppd = private2ppd(fp);
967f48ad614SDennis Dalessandro 
968f48ad614SDennis Dalessandro 	release_chip_resource(ppd->dd, i2c_target(target));
969f48ad614SDennis Dalessandro 
970f48ad614SDennis Dalessandro 	return 0;
971f48ad614SDennis Dalessandro }
972f48ad614SDennis Dalessandro 
i2c1_debugfs_release(struct inode * in,struct file * fp)973f48ad614SDennis Dalessandro static int i2c1_debugfs_release(struct inode *in, struct file *fp)
974f48ad614SDennis Dalessandro {
975f48ad614SDennis Dalessandro 	return __i2c_debugfs_release(in, fp, 0);
976f48ad614SDennis Dalessandro }
977f48ad614SDennis Dalessandro 
i2c2_debugfs_release(struct inode * in,struct file * fp)978f48ad614SDennis Dalessandro static int i2c2_debugfs_release(struct inode *in, struct file *fp)
979f48ad614SDennis Dalessandro {
980f48ad614SDennis Dalessandro 	return __i2c_debugfs_release(in, fp, 1);
981f48ad614SDennis Dalessandro }
982f48ad614SDennis Dalessandro 
__qsfp_debugfs_open(struct inode * in,struct file * fp,u32 target)983f48ad614SDennis Dalessandro static int __qsfp_debugfs_open(struct inode *in, struct file *fp, u32 target)
984f48ad614SDennis Dalessandro {
985f48ad614SDennis Dalessandro 	struct hfi1_pportdata *ppd;
986f48ad614SDennis Dalessandro 
987f48ad614SDennis Dalessandro 	ppd = private2ppd(fp);
988f48ad614SDennis Dalessandro 
989822fbd37SDennis Dalessandro 	return acquire_chip_resource(ppd->dd, i2c_target(target), 0);
990f48ad614SDennis Dalessandro }
991f48ad614SDennis Dalessandro 
qsfp1_debugfs_open(struct inode * in,struct file * fp)992f48ad614SDennis Dalessandro static int qsfp1_debugfs_open(struct inode *in, struct file *fp)
993f48ad614SDennis Dalessandro {
994f48ad614SDennis Dalessandro 	return __qsfp_debugfs_open(in, fp, 0);
995f48ad614SDennis Dalessandro }
996f48ad614SDennis Dalessandro 
qsfp2_debugfs_open(struct inode * in,struct file * fp)997f48ad614SDennis Dalessandro static int qsfp2_debugfs_open(struct inode *in, struct file *fp)
998f48ad614SDennis Dalessandro {
999f48ad614SDennis Dalessandro 	return __qsfp_debugfs_open(in, fp, 1);
1000f48ad614SDennis Dalessandro }
1001f48ad614SDennis Dalessandro 
__qsfp_debugfs_release(struct inode * in,struct file * fp,u32 target)1002f48ad614SDennis Dalessandro static int __qsfp_debugfs_release(struct inode *in, struct file *fp, u32 target)
1003f48ad614SDennis Dalessandro {
1004f48ad614SDennis Dalessandro 	struct hfi1_pportdata *ppd;
1005f48ad614SDennis Dalessandro 
1006f48ad614SDennis Dalessandro 	ppd = private2ppd(fp);
1007f48ad614SDennis Dalessandro 
1008f48ad614SDennis Dalessandro 	release_chip_resource(ppd->dd, i2c_target(target));
1009f48ad614SDennis Dalessandro 
1010f48ad614SDennis Dalessandro 	return 0;
1011f48ad614SDennis Dalessandro }
1012f48ad614SDennis Dalessandro 
qsfp1_debugfs_release(struct inode * in,struct file * fp)1013f48ad614SDennis Dalessandro static int qsfp1_debugfs_release(struct inode *in, struct file *fp)
1014f48ad614SDennis Dalessandro {
1015f48ad614SDennis Dalessandro 	return __qsfp_debugfs_release(in, fp, 0);
1016f48ad614SDennis Dalessandro }
1017f48ad614SDennis Dalessandro 
qsfp2_debugfs_release(struct inode * in,struct file * fp)1018f48ad614SDennis Dalessandro static int qsfp2_debugfs_release(struct inode *in, struct file *fp)
1019f48ad614SDennis Dalessandro {
1020f48ad614SDennis Dalessandro 	return __qsfp_debugfs_release(in, fp, 1);
1021f48ad614SDennis Dalessandro }
1022f48ad614SDennis Dalessandro 
102307c5ba91SJosh Collier #define EXPROM_WRITE_ENABLE BIT_ULL(14)
102407c5ba91SJosh Collier 
102507c5ba91SJosh Collier static bool exprom_wp_disabled;
102607c5ba91SJosh Collier 
exprom_wp_set(struct hfi1_devdata * dd,bool disable)102707c5ba91SJosh Collier static int exprom_wp_set(struct hfi1_devdata *dd, bool disable)
102807c5ba91SJosh Collier {
102907c5ba91SJosh Collier 	u64 gpio_val = 0;
103007c5ba91SJosh Collier 
103107c5ba91SJosh Collier 	if (disable) {
103207c5ba91SJosh Collier 		gpio_val = EXPROM_WRITE_ENABLE;
103307c5ba91SJosh Collier 		exprom_wp_disabled = true;
103407c5ba91SJosh Collier 		dd_dev_info(dd, "Disable Expansion ROM Write Protection\n");
103507c5ba91SJosh Collier 	} else {
103607c5ba91SJosh Collier 		exprom_wp_disabled = false;
103707c5ba91SJosh Collier 		dd_dev_info(dd, "Enable Expansion ROM Write Protection\n");
103807c5ba91SJosh Collier 	}
103907c5ba91SJosh Collier 
104007c5ba91SJosh Collier 	write_csr(dd, ASIC_GPIO_OUT, gpio_val);
104107c5ba91SJosh Collier 	write_csr(dd, ASIC_GPIO_OE, gpio_val);
104207c5ba91SJosh Collier 
104307c5ba91SJosh Collier 	return 0;
104407c5ba91SJosh Collier }
104507c5ba91SJosh Collier 
exprom_wp_debugfs_read(struct file * file,char __user * buf,size_t count,loff_t * ppos)104607c5ba91SJosh Collier static ssize_t exprom_wp_debugfs_read(struct file *file, char __user *buf,
104707c5ba91SJosh Collier 				      size_t count, loff_t *ppos)
104807c5ba91SJosh Collier {
104907c5ba91SJosh Collier 	return 0;
105007c5ba91SJosh Collier }
105107c5ba91SJosh Collier 
exprom_wp_debugfs_write(struct file * file,const char __user * buf,size_t count,loff_t * ppos)105207c5ba91SJosh Collier static ssize_t exprom_wp_debugfs_write(struct file *file,
105307c5ba91SJosh Collier 				       const char __user *buf, size_t count,
105407c5ba91SJosh Collier 				       loff_t *ppos)
105507c5ba91SJosh Collier {
105607c5ba91SJosh Collier 	struct hfi1_pportdata *ppd = private2ppd(file);
105707c5ba91SJosh Collier 	char cdata;
105807c5ba91SJosh Collier 
105907c5ba91SJosh Collier 	if (count != 1)
106007c5ba91SJosh Collier 		return -EINVAL;
106107c5ba91SJosh Collier 	if (get_user(cdata, buf))
106207c5ba91SJosh Collier 		return -EFAULT;
106307c5ba91SJosh Collier 	if (cdata == '0')
106407c5ba91SJosh Collier 		exprom_wp_set(ppd->dd, false);
106507c5ba91SJosh Collier 	else if (cdata == '1')
106607c5ba91SJosh Collier 		exprom_wp_set(ppd->dd, true);
106707c5ba91SJosh Collier 	else
106807c5ba91SJosh Collier 		return -EINVAL;
106907c5ba91SJosh Collier 
107007c5ba91SJosh Collier 	return 1;
107107c5ba91SJosh Collier }
107207c5ba91SJosh Collier 
107307c5ba91SJosh Collier static unsigned long exprom_in_use;
107407c5ba91SJosh Collier 
exprom_wp_debugfs_open(struct inode * in,struct file * fp)107507c5ba91SJosh Collier static int exprom_wp_debugfs_open(struct inode *in, struct file *fp)
107607c5ba91SJosh Collier {
107707c5ba91SJosh Collier 	if (test_and_set_bit(0, &exprom_in_use))
107807c5ba91SJosh Collier 		return -EBUSY;
107907c5ba91SJosh Collier 
108007c5ba91SJosh Collier 	return 0;
108107c5ba91SJosh Collier }
108207c5ba91SJosh Collier 
exprom_wp_debugfs_release(struct inode * in,struct file * fp)108307c5ba91SJosh Collier static int exprom_wp_debugfs_release(struct inode *in, struct file *fp)
108407c5ba91SJosh Collier {
108507c5ba91SJosh Collier 	struct hfi1_pportdata *ppd = private2ppd(fp);
108607c5ba91SJosh Collier 
108707c5ba91SJosh Collier 	if (exprom_wp_disabled)
108807c5ba91SJosh Collier 		exprom_wp_set(ppd->dd, false);
108907c5ba91SJosh Collier 	clear_bit(0, &exprom_in_use);
109007c5ba91SJosh Collier 
109107c5ba91SJosh Collier 	return 0;
109207c5ba91SJosh Collier }
109307c5ba91SJosh Collier 
1094f48ad614SDennis Dalessandro #define DEBUGFS_OPS(nm, readroutine, writeroutine)	\
1095f48ad614SDennis Dalessandro { \
1096f48ad614SDennis Dalessandro 	.name = nm, \
1097f48ad614SDennis Dalessandro 	.ops = { \
109809fbca8eSDennis Dalessandro 		.owner = THIS_MODULE, \
1099f48ad614SDennis Dalessandro 		.read = readroutine, \
1100f48ad614SDennis Dalessandro 		.write = writeroutine, \
1101f48ad614SDennis Dalessandro 		.llseek = generic_file_llseek, \
1102f48ad614SDennis Dalessandro 	}, \
1103f48ad614SDennis Dalessandro }
1104f48ad614SDennis Dalessandro 
1105f48ad614SDennis Dalessandro #define DEBUGFS_XOPS(nm, readf, writef, openf, releasef) \
1106f48ad614SDennis Dalessandro { \
1107f48ad614SDennis Dalessandro 	.name = nm, \
1108f48ad614SDennis Dalessandro 	.ops = { \
110909fbca8eSDennis Dalessandro 		.owner = THIS_MODULE, \
1110f48ad614SDennis Dalessandro 		.read = readf, \
1111f48ad614SDennis Dalessandro 		.write = writef, \
1112f48ad614SDennis Dalessandro 		.llseek = generic_file_llseek, \
1113f48ad614SDennis Dalessandro 		.open = openf, \
1114f48ad614SDennis Dalessandro 		.release = releasef \
1115f48ad614SDennis Dalessandro 	}, \
1116f48ad614SDennis Dalessandro }
1117f48ad614SDennis Dalessandro 
1118f48ad614SDennis Dalessandro static const struct counter_info cntr_ops[] = {
1119f48ad614SDennis Dalessandro 	DEBUGFS_OPS("counter_names", dev_names_read, NULL),
1120f48ad614SDennis Dalessandro 	DEBUGFS_OPS("counters", dev_counters_read, NULL),
1121f48ad614SDennis Dalessandro 	DEBUGFS_OPS("portcounter_names", portnames_read, NULL),
1122f48ad614SDennis Dalessandro };
1123f48ad614SDennis Dalessandro 
1124f48ad614SDennis Dalessandro static const struct counter_info port_cntr_ops[] = {
1125f48ad614SDennis Dalessandro 	DEBUGFS_OPS("port%dcounters", portcntrs_debugfs_read, NULL),
1126f48ad614SDennis Dalessandro 	DEBUGFS_XOPS("i2c1", i2c1_debugfs_read, i2c1_debugfs_write,
1127f48ad614SDennis Dalessandro 		     i2c1_debugfs_open, i2c1_debugfs_release),
1128f48ad614SDennis Dalessandro 	DEBUGFS_XOPS("i2c2", i2c2_debugfs_read, i2c2_debugfs_write,
1129f48ad614SDennis Dalessandro 		     i2c2_debugfs_open, i2c2_debugfs_release),
1130f48ad614SDennis Dalessandro 	DEBUGFS_OPS("qsfp_dump%d", qsfp_debugfs_dump, NULL),
1131f48ad614SDennis Dalessandro 	DEBUGFS_XOPS("qsfp1", qsfp1_debugfs_read, qsfp1_debugfs_write,
1132f48ad614SDennis Dalessandro 		     qsfp1_debugfs_open, qsfp1_debugfs_release),
1133f48ad614SDennis Dalessandro 	DEBUGFS_XOPS("qsfp2", qsfp2_debugfs_read, qsfp2_debugfs_write,
1134f48ad614SDennis Dalessandro 		     qsfp2_debugfs_open, qsfp2_debugfs_release),
113507c5ba91SJosh Collier 	DEBUGFS_XOPS("exprom_wp", exprom_wp_debugfs_read,
113607c5ba91SJosh Collier 		     exprom_wp_debugfs_write, exprom_wp_debugfs_open,
113707c5ba91SJosh Collier 		     exprom_wp_debugfs_release),
1138f48ad614SDennis Dalessandro 	DEBUGFS_OPS("asic_flags", asic_flags_read, asic_flags_write),
11391b9e7749SDean Luick 	DEBUGFS_OPS("dc8051_memory", dc8051_memory_read, NULL),
11401b9e7749SDean Luick 	DEBUGFS_OPS("lcb", debugfs_lcb_read, debugfs_lcb_write),
1141f48ad614SDennis Dalessandro };
1142f48ad614SDennis Dalessandro 
_sdma_cpu_list_seq_start(struct seq_file * s,loff_t * pos)1143af3674d6STadeusz Struk static void *_sdma_cpu_list_seq_start(struct seq_file *s, loff_t *pos)
1144af3674d6STadeusz Struk {
1145af3674d6STadeusz Struk 	if (*pos >= num_online_cpus())
1146af3674d6STadeusz Struk 		return NULL;
1147af3674d6STadeusz Struk 
1148af3674d6STadeusz Struk 	return pos;
1149af3674d6STadeusz Struk }
1150af3674d6STadeusz Struk 
_sdma_cpu_list_seq_next(struct seq_file * s,void * v,loff_t * pos)1151af3674d6STadeusz Struk static void *_sdma_cpu_list_seq_next(struct seq_file *s, void *v, loff_t *pos)
1152af3674d6STadeusz Struk {
1153af3674d6STadeusz Struk 	++*pos;
1154af3674d6STadeusz Struk 	if (*pos >= num_online_cpus())
1155af3674d6STadeusz Struk 		return NULL;
1156af3674d6STadeusz Struk 
1157af3674d6STadeusz Struk 	return pos;
1158af3674d6STadeusz Struk }
1159af3674d6STadeusz Struk 
_sdma_cpu_list_seq_stop(struct seq_file * s,void * v)1160af3674d6STadeusz Struk static void _sdma_cpu_list_seq_stop(struct seq_file *s, void *v)
1161af3674d6STadeusz Struk {
1162af3674d6STadeusz Struk 	/* nothing allocated */
1163af3674d6STadeusz Struk }
1164af3674d6STadeusz Struk 
_sdma_cpu_list_seq_show(struct seq_file * s,void * v)1165af3674d6STadeusz Struk static int _sdma_cpu_list_seq_show(struct seq_file *s, void *v)
1166af3674d6STadeusz Struk {
1167af3674d6STadeusz Struk 	struct hfi1_ibdev *ibd = (struct hfi1_ibdev *)s->private;
1168af3674d6STadeusz Struk 	struct hfi1_devdata *dd = dd_from_dev(ibd);
1169af3674d6STadeusz Struk 	loff_t *spos = v;
1170af3674d6STadeusz Struk 	loff_t i = *spos;
1171af3674d6STadeusz Struk 
1172af3674d6STadeusz Struk 	sdma_seqfile_dump_cpu_list(s, dd, (unsigned long)i);
1173af3674d6STadeusz Struk 	return 0;
1174af3674d6STadeusz Struk }
1175af3674d6STadeusz Struk 
1176af3674d6STadeusz Struk DEBUGFS_SEQ_FILE_OPS(sdma_cpu_list);
1177af3674d6STadeusz Struk DEBUGFS_SEQ_FILE_OPEN(sdma_cpu_list)
1178af3674d6STadeusz Struk DEBUGFS_FILE_OPS(sdma_cpu_list);
1179af3674d6STadeusz Struk 
hfi1_dbg_ibdev_init(struct hfi1_ibdev * ibd)1180f48ad614SDennis Dalessandro void hfi1_dbg_ibdev_init(struct hfi1_ibdev *ibd)
1181f48ad614SDennis Dalessandro {
1182f48ad614SDennis Dalessandro 	char name[sizeof("port0counters") + 1];
1183f48ad614SDennis Dalessandro 	char link[10];
1184f48ad614SDennis Dalessandro 	struct hfi1_devdata *dd = dd_from_dev(ibd);
1185f48ad614SDennis Dalessandro 	struct hfi1_pportdata *ppd;
11865c432764SGreg Kroah-Hartman 	struct dentry *root;
1187f48ad614SDennis Dalessandro 	int unit = dd->unit;
1188f48ad614SDennis Dalessandro 	int i, j;
1189f48ad614SDennis Dalessandro 
1190f48ad614SDennis Dalessandro 	if (!hfi1_dbg_root)
1191f48ad614SDennis Dalessandro 		return;
1192f48ad614SDennis Dalessandro 	snprintf(name, sizeof(name), "%s_%d", class_name(), unit);
1193f48ad614SDennis Dalessandro 	snprintf(link, sizeof(link), "%d", unit);
11945c432764SGreg Kroah-Hartman 	root = debugfs_create_dir(name, hfi1_dbg_root);
11955c432764SGreg Kroah-Hartman 	ibd->hfi1_ibdev_dbg = root;
11965c432764SGreg Kroah-Hartman 
1197f48ad614SDennis Dalessandro 	ibd->hfi1_ibdev_link =
1198f48ad614SDennis Dalessandro 		debugfs_create_symlink(link, hfi1_dbg_root, name);
11995c432764SGreg Kroah-Hartman 
12005c432764SGreg Kroah-Hartman 	debugfs_create_file("opcode_stats", 0444, root, ibd,
12015c432764SGreg Kroah-Hartman 			    &_opcode_stats_file_ops);
12025c432764SGreg Kroah-Hartman 	debugfs_create_file("tx_opcode_stats", 0444, root, ibd,
12035c432764SGreg Kroah-Hartman 			    &_tx_opcode_stats_file_ops);
12045c432764SGreg Kroah-Hartman 	debugfs_create_file("ctx_stats", 0444, root, ibd, &_ctx_stats_file_ops);
12055c432764SGreg Kroah-Hartman 	debugfs_create_file("qp_stats", 0444, root, ibd, &_qp_stats_file_ops);
12065c432764SGreg Kroah-Hartman 	debugfs_create_file("sdes", 0444, root, ibd, &_sdes_file_ops);
12075c432764SGreg Kroah-Hartman 	debugfs_create_file("rcds", 0444, root, ibd, &_rcds_file_ops);
12085c432764SGreg Kroah-Hartman 	debugfs_create_file("pios", 0444, root, ibd, &_pios_file_ops);
12095c432764SGreg Kroah-Hartman 	debugfs_create_file("sdma_cpu_list", 0444, root, ibd,
12105c432764SGreg Kroah-Hartman 			    &_sdma_cpu_list_file_ops);
12115c432764SGreg Kroah-Hartman 
1212f48ad614SDennis Dalessandro 	/* dev counter files */
1213f48ad614SDennis Dalessandro 	for (i = 0; i < ARRAY_SIZE(cntr_ops); i++)
12145c432764SGreg Kroah-Hartman 		debugfs_create_file(cntr_ops[i].name, 0444, root, dd,
12155c432764SGreg Kroah-Hartman 				    &cntr_ops[i].ops);
12165c432764SGreg Kroah-Hartman 
1217f48ad614SDennis Dalessandro 	/* per port files */
1218f48ad614SDennis Dalessandro 	for (ppd = dd->pport, j = 0; j < dd->num_pports; j++, ppd++)
1219f48ad614SDennis Dalessandro 		for (i = 0; i < ARRAY_SIZE(port_cntr_ops); i++) {
1220f48ad614SDennis Dalessandro 			snprintf(name,
1221f48ad614SDennis Dalessandro 				 sizeof(name),
1222f48ad614SDennis Dalessandro 				 port_cntr_ops[i].name,
1223f48ad614SDennis Dalessandro 				 j + 1);
12245c432764SGreg Kroah-Hartman 			debugfs_create_file(name,
1225f48ad614SDennis Dalessandro 					    !port_cntr_ops[i].ops.write ?
12265c432764SGreg Kroah-Hartman 						    S_IRUGO :
12275c432764SGreg Kroah-Hartman 						    S_IRUGO | S_IWUSR,
12285c432764SGreg Kroah-Hartman 					    root, ppd, &port_cntr_ops[i].ops);
1229f48ad614SDennis Dalessandro 		}
12300181ce31SDon Hiatt 
1231a74d5307SMitko Haralanov 	hfi1_fault_init_debugfs(ibd);
1232f48ad614SDennis Dalessandro }
1233f48ad614SDennis Dalessandro 
hfi1_dbg_ibdev_exit(struct hfi1_ibdev * ibd)1234f48ad614SDennis Dalessandro void hfi1_dbg_ibdev_exit(struct hfi1_ibdev *ibd)
1235f48ad614SDennis Dalessandro {
1236f48ad614SDennis Dalessandro 	if (!hfi1_dbg_root)
1237f48ad614SDennis Dalessandro 		goto out;
1238a74d5307SMitko Haralanov 	hfi1_fault_exit_debugfs(ibd);
1239f48ad614SDennis Dalessandro 	debugfs_remove(ibd->hfi1_ibdev_link);
1240f48ad614SDennis Dalessandro 	debugfs_remove_recursive(ibd->hfi1_ibdev_dbg);
1241f48ad614SDennis Dalessandro out:
1242f48ad614SDennis Dalessandro 	ibd->hfi1_ibdev_dbg = NULL;
1243f48ad614SDennis Dalessandro }
1244f48ad614SDennis Dalessandro 
1245f48ad614SDennis Dalessandro /*
1246f48ad614SDennis Dalessandro  * driver stats field names, one line per stat, single string.  Used by
1247f48ad614SDennis Dalessandro  * programs like hfistats to print the stats in a way which works for
1248f48ad614SDennis Dalessandro  * different versions of drivers, without changing program source.
1249f48ad614SDennis Dalessandro  * if hfi1_ib_stats changes, this needs to change.  Names need to be
1250f48ad614SDennis Dalessandro  * 12 chars or less (w/o newline), for proper display by hfistats utility.
1251f48ad614SDennis Dalessandro  */
1252f48ad614SDennis Dalessandro static const char * const hfi1_statnames[] = {
1253f48ad614SDennis Dalessandro 	/* must be element 0*/
1254f48ad614SDennis Dalessandro 	"KernIntr",
1255f48ad614SDennis Dalessandro 	"ErrorIntr",
1256f48ad614SDennis Dalessandro 	"Tx_Errs",
1257f48ad614SDennis Dalessandro 	"Rcv_Errs",
1258f48ad614SDennis Dalessandro 	"H/W_Errs",
1259f48ad614SDennis Dalessandro 	"NoPIOBufs",
1260f48ad614SDennis Dalessandro 	"CtxtsOpen",
1261f48ad614SDennis Dalessandro 	"RcvLen_Errs",
1262f48ad614SDennis Dalessandro 	"EgrBufFull",
1263f48ad614SDennis Dalessandro 	"EgrHdrFull"
1264f48ad614SDennis Dalessandro };
1265f48ad614SDennis Dalessandro 
_driver_stats_names_seq_start(struct seq_file * s,loff_t * pos)1266f48ad614SDennis Dalessandro static void *_driver_stats_names_seq_start(struct seq_file *s, loff_t *pos)
1267f48ad614SDennis Dalessandro {
1268f48ad614SDennis Dalessandro 	if (*pos >= ARRAY_SIZE(hfi1_statnames))
1269f48ad614SDennis Dalessandro 		return NULL;
1270f48ad614SDennis Dalessandro 	return pos;
1271f48ad614SDennis Dalessandro }
1272f48ad614SDennis Dalessandro 
_driver_stats_names_seq_next(struct seq_file * s,void * v,loff_t * pos)1273f48ad614SDennis Dalessandro static void *_driver_stats_names_seq_next(
1274f48ad614SDennis Dalessandro 	struct seq_file *s,
1275f48ad614SDennis Dalessandro 	void *v,
1276f48ad614SDennis Dalessandro 	loff_t *pos)
1277f48ad614SDennis Dalessandro {
1278f48ad614SDennis Dalessandro 	++*pos;
1279f48ad614SDennis Dalessandro 	if (*pos >= ARRAY_SIZE(hfi1_statnames))
1280f48ad614SDennis Dalessandro 		return NULL;
1281f48ad614SDennis Dalessandro 	return pos;
1282f48ad614SDennis Dalessandro }
1283f48ad614SDennis Dalessandro 
_driver_stats_names_seq_stop(struct seq_file * s,void * v)1284f48ad614SDennis Dalessandro static void _driver_stats_names_seq_stop(struct seq_file *s, void *v)
1285f48ad614SDennis Dalessandro {
1286f48ad614SDennis Dalessandro }
1287f48ad614SDennis Dalessandro 
_driver_stats_names_seq_show(struct seq_file * s,void * v)1288f48ad614SDennis Dalessandro static int _driver_stats_names_seq_show(struct seq_file *s, void *v)
1289f48ad614SDennis Dalessandro {
1290f48ad614SDennis Dalessandro 	loff_t *spos = v;
1291f48ad614SDennis Dalessandro 
1292f48ad614SDennis Dalessandro 	seq_printf(s, "%s\n", hfi1_statnames[*spos]);
1293f48ad614SDennis Dalessandro 	return 0;
1294f48ad614SDennis Dalessandro }
1295f48ad614SDennis Dalessandro 
1296f48ad614SDennis Dalessandro DEBUGFS_SEQ_FILE_OPS(driver_stats_names);
1297f48ad614SDennis Dalessandro DEBUGFS_SEQ_FILE_OPEN(driver_stats_names)
1298f48ad614SDennis Dalessandro DEBUGFS_FILE_OPS(driver_stats_names);
1299f48ad614SDennis Dalessandro 
_driver_stats_seq_start(struct seq_file * s,loff_t * pos)1300f48ad614SDennis Dalessandro static void *_driver_stats_seq_start(struct seq_file *s, loff_t *pos)
1301f48ad614SDennis Dalessandro {
1302f48ad614SDennis Dalessandro 	if (*pos >= ARRAY_SIZE(hfi1_statnames))
1303f48ad614SDennis Dalessandro 		return NULL;
1304f48ad614SDennis Dalessandro 	return pos;
1305f48ad614SDennis Dalessandro }
1306f48ad614SDennis Dalessandro 
_driver_stats_seq_next(struct seq_file * s,void * v,loff_t * pos)1307f48ad614SDennis Dalessandro static void *_driver_stats_seq_next(struct seq_file *s, void *v, loff_t *pos)
1308f48ad614SDennis Dalessandro {
1309f48ad614SDennis Dalessandro 	++*pos;
1310f48ad614SDennis Dalessandro 	if (*pos >= ARRAY_SIZE(hfi1_statnames))
1311f48ad614SDennis Dalessandro 		return NULL;
1312f48ad614SDennis Dalessandro 	return pos;
1313f48ad614SDennis Dalessandro }
1314f48ad614SDennis Dalessandro 
_driver_stats_seq_stop(struct seq_file * s,void * v)1315f48ad614SDennis Dalessandro static void _driver_stats_seq_stop(struct seq_file *s, void *v)
1316f48ad614SDennis Dalessandro {
1317f48ad614SDennis Dalessandro }
1318f48ad614SDennis Dalessandro 
hfi1_sps_show_ints(struct seq_file * s)13194b89451dSChristoph Hellwig static void hfi1_sps_show_ints(struct seq_file *s)
1320f48ad614SDennis Dalessandro {
132103b92789SMatthew Wilcox 	unsigned long index, flags;
1322f48ad614SDennis Dalessandro 	struct hfi1_devdata *dd;
1323f48ad614SDennis Dalessandro 	u64 sps_ints = 0;
1324f48ad614SDennis Dalessandro 
132503b92789SMatthew Wilcox 	xa_lock_irqsave(&hfi1_dev_table, flags);
132603b92789SMatthew Wilcox 	xa_for_each(&hfi1_dev_table, index, dd) {
1327f48ad614SDennis Dalessandro 		sps_ints += get_all_cpu_total(dd->int_counter);
1328f48ad614SDennis Dalessandro 	}
132903b92789SMatthew Wilcox 	xa_unlock_irqrestore(&hfi1_dev_table, flags);
13304b89451dSChristoph Hellwig 	seq_write(s, &sps_ints, sizeof(u64));
1331f48ad614SDennis Dalessandro }
1332f48ad614SDennis Dalessandro 
_driver_stats_seq_show(struct seq_file * s,void * v)1333f48ad614SDennis Dalessandro static int _driver_stats_seq_show(struct seq_file *s, void *v)
1334f48ad614SDennis Dalessandro {
1335f48ad614SDennis Dalessandro 	loff_t *spos = v;
1336f48ad614SDennis Dalessandro 	u64 *stats = (u64 *)&hfi1_stats;
1337f48ad614SDennis Dalessandro 
1338f48ad614SDennis Dalessandro 	/* special case for interrupts */
1339f48ad614SDennis Dalessandro 	if (*spos == 0)
13404b89451dSChristoph Hellwig 		hfi1_sps_show_ints(s);
1341f48ad614SDennis Dalessandro 	else
13424b89451dSChristoph Hellwig 		seq_write(s, stats + *spos, sizeof(u64));
1343f48ad614SDennis Dalessandro 	return 0;
1344f48ad614SDennis Dalessandro }
1345f48ad614SDennis Dalessandro 
1346f48ad614SDennis Dalessandro DEBUGFS_SEQ_FILE_OPS(driver_stats);
1347f48ad614SDennis Dalessandro DEBUGFS_SEQ_FILE_OPEN(driver_stats)
1348f48ad614SDennis Dalessandro DEBUGFS_FILE_OPS(driver_stats);
1349f48ad614SDennis Dalessandro 
hfi1_dbg_init(void)1350f48ad614SDennis Dalessandro void hfi1_dbg_init(void)
1351f48ad614SDennis Dalessandro {
1352f48ad614SDennis Dalessandro 	hfi1_dbg_root  = debugfs_create_dir(DRIVER_NAME, NULL);
13535c432764SGreg Kroah-Hartman 	debugfs_create_file("driver_stats_names", 0444, hfi1_dbg_root, NULL,
13545c432764SGreg Kroah-Hartman 			    &_driver_stats_names_file_ops);
13555c432764SGreg Kroah-Hartman 	debugfs_create_file("driver_stats", 0444, hfi1_dbg_root, NULL,
13565c432764SGreg Kroah-Hartman 			    &_driver_stats_file_ops);
1357f48ad614SDennis Dalessandro }
1358f48ad614SDennis Dalessandro 
hfi1_dbg_exit(void)1359f48ad614SDennis Dalessandro void hfi1_dbg_exit(void)
1360f48ad614SDennis Dalessandro {
1361f48ad614SDennis Dalessandro 	debugfs_remove_recursive(hfi1_dbg_root);
1362f48ad614SDennis Dalessandro 	hfi1_dbg_root = NULL;
1363f48ad614SDennis Dalessandro }
1364