brintos

brintos / linux-shallow public Read only

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