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