18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* Copyright(c) 2017 - 2019 Pensando Systems, Inc */ 38c2ecf20Sopenharmony_ci 48c2ecf20Sopenharmony_ci#include <linux/pci.h> 58c2ecf20Sopenharmony_ci#include <linux/netdevice.h> 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#include "ionic.h" 88c2ecf20Sopenharmony_ci#include "ionic_bus.h" 98c2ecf20Sopenharmony_ci#include "ionic_lif.h" 108c2ecf20Sopenharmony_ci#include "ionic_debugfs.h" 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#ifdef CONFIG_DEBUG_FS 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_cistatic struct dentry *ionic_dir; 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_civoid ionic_debugfs_create(void) 178c2ecf20Sopenharmony_ci{ 188c2ecf20Sopenharmony_ci ionic_dir = debugfs_create_dir(IONIC_DRV_NAME, NULL); 198c2ecf20Sopenharmony_ci} 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_civoid ionic_debugfs_destroy(void) 228c2ecf20Sopenharmony_ci{ 238c2ecf20Sopenharmony_ci debugfs_remove_recursive(ionic_dir); 248c2ecf20Sopenharmony_ci} 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_civoid ionic_debugfs_add_dev(struct ionic *ionic) 278c2ecf20Sopenharmony_ci{ 288c2ecf20Sopenharmony_ci ionic->dentry = debugfs_create_dir(ionic_bus_info(ionic), ionic_dir); 298c2ecf20Sopenharmony_ci} 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_civoid ionic_debugfs_del_dev(struct ionic *ionic) 328c2ecf20Sopenharmony_ci{ 338c2ecf20Sopenharmony_ci debugfs_remove_recursive(ionic->dentry); 348c2ecf20Sopenharmony_ci ionic->dentry = NULL; 358c2ecf20Sopenharmony_ci} 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_cistatic int identity_show(struct seq_file *seq, void *v) 388c2ecf20Sopenharmony_ci{ 398c2ecf20Sopenharmony_ci struct ionic *ionic = seq->private; 408c2ecf20Sopenharmony_ci struct ionic_identity *ident; 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci ident = &ionic->ident; 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci seq_printf(seq, "nlifs: %d\n", ident->dev.nlifs); 458c2ecf20Sopenharmony_ci seq_printf(seq, "nintrs: %d\n", ident->dev.nintrs); 468c2ecf20Sopenharmony_ci seq_printf(seq, "ndbpgs_per_lif: %d\n", ident->dev.ndbpgs_per_lif); 478c2ecf20Sopenharmony_ci seq_printf(seq, "intr_coal_mult: %d\n", ident->dev.intr_coal_mult); 488c2ecf20Sopenharmony_ci seq_printf(seq, "intr_coal_div: %d\n", ident->dev.intr_coal_div); 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci seq_printf(seq, "max_ucast_filters: %d\n", ident->lif.eth.max_ucast_filters); 518c2ecf20Sopenharmony_ci seq_printf(seq, "max_mcast_filters: %d\n", ident->lif.eth.max_mcast_filters); 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci return 0; 548c2ecf20Sopenharmony_ci} 558c2ecf20Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(identity); 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_civoid ionic_debugfs_add_ident(struct ionic *ionic) 588c2ecf20Sopenharmony_ci{ 598c2ecf20Sopenharmony_ci debugfs_create_file("identity", 0400, ionic->dentry, 608c2ecf20Sopenharmony_ci ionic, &identity_fops); 618c2ecf20Sopenharmony_ci} 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_civoid ionic_debugfs_add_sizes(struct ionic *ionic) 648c2ecf20Sopenharmony_ci{ 658c2ecf20Sopenharmony_ci debugfs_create_u32("nlifs", 0400, ionic->dentry, 668c2ecf20Sopenharmony_ci (u32 *)&ionic->ident.dev.nlifs); 678c2ecf20Sopenharmony_ci debugfs_create_u32("nintrs", 0400, ionic->dentry, &ionic->nintrs); 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci debugfs_create_u32("ntxqs_per_lif", 0400, ionic->dentry, 708c2ecf20Sopenharmony_ci (u32 *)&ionic->ident.lif.eth.config.queue_count[IONIC_QTYPE_TXQ]); 718c2ecf20Sopenharmony_ci debugfs_create_u32("nrxqs_per_lif", 0400, ionic->dentry, 728c2ecf20Sopenharmony_ci (u32 *)&ionic->ident.lif.eth.config.queue_count[IONIC_QTYPE_RXQ]); 738c2ecf20Sopenharmony_ci} 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_cistatic int q_tail_show(struct seq_file *seq, void *v) 768c2ecf20Sopenharmony_ci{ 778c2ecf20Sopenharmony_ci struct ionic_queue *q = seq->private; 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci seq_printf(seq, "%d\n", q->tail_idx); 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci return 0; 828c2ecf20Sopenharmony_ci} 838c2ecf20Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(q_tail); 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_cistatic int q_head_show(struct seq_file *seq, void *v) 868c2ecf20Sopenharmony_ci{ 878c2ecf20Sopenharmony_ci struct ionic_queue *q = seq->private; 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci seq_printf(seq, "%d\n", q->head_idx); 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci return 0; 928c2ecf20Sopenharmony_ci} 938c2ecf20Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(q_head); 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_cistatic int cq_tail_show(struct seq_file *seq, void *v) 968c2ecf20Sopenharmony_ci{ 978c2ecf20Sopenharmony_ci struct ionic_cq *cq = seq->private; 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci seq_printf(seq, "%d\n", cq->tail_idx); 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci return 0; 1028c2ecf20Sopenharmony_ci} 1038c2ecf20Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(cq_tail); 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_cistatic const struct debugfs_reg32 intr_ctrl_regs[] = { 1068c2ecf20Sopenharmony_ci { .name = "coal_init", .offset = 0, }, 1078c2ecf20Sopenharmony_ci { .name = "mask", .offset = 4, }, 1088c2ecf20Sopenharmony_ci { .name = "credits", .offset = 8, }, 1098c2ecf20Sopenharmony_ci { .name = "mask_on_assert", .offset = 12, }, 1108c2ecf20Sopenharmony_ci { .name = "coal_timer", .offset = 16, }, 1118c2ecf20Sopenharmony_ci}; 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_civoid ionic_debugfs_add_qcq(struct ionic_lif *lif, struct ionic_qcq *qcq) 1148c2ecf20Sopenharmony_ci{ 1158c2ecf20Sopenharmony_ci struct dentry *qcq_dentry, *q_dentry, *cq_dentry; 1168c2ecf20Sopenharmony_ci struct dentry *intr_dentry, *stats_dentry; 1178c2ecf20Sopenharmony_ci struct ionic_dev *idev = &lif->ionic->idev; 1188c2ecf20Sopenharmony_ci struct debugfs_regset32 *intr_ctrl_regset; 1198c2ecf20Sopenharmony_ci struct ionic_intr_info *intr = &qcq->intr; 1208c2ecf20Sopenharmony_ci struct debugfs_blob_wrapper *desc_blob; 1218c2ecf20Sopenharmony_ci struct device *dev = lif->ionic->dev; 1228c2ecf20Sopenharmony_ci struct ionic_queue *q = &qcq->q; 1238c2ecf20Sopenharmony_ci struct ionic_cq *cq = &qcq->cq; 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci qcq_dentry = debugfs_create_dir(q->name, lif->dentry); 1268c2ecf20Sopenharmony_ci if (IS_ERR_OR_NULL(qcq_dentry)) 1278c2ecf20Sopenharmony_ci return; 1288c2ecf20Sopenharmony_ci qcq->dentry = qcq_dentry; 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci debugfs_create_x64("q_base_pa", 0400, qcq_dentry, &qcq->q_base_pa); 1318c2ecf20Sopenharmony_ci debugfs_create_x32("q_size", 0400, qcq_dentry, &qcq->q_size); 1328c2ecf20Sopenharmony_ci debugfs_create_x64("cq_base_pa", 0400, qcq_dentry, &qcq->cq_base_pa); 1338c2ecf20Sopenharmony_ci debugfs_create_x32("cq_size", 0400, qcq_dentry, &qcq->cq_size); 1348c2ecf20Sopenharmony_ci debugfs_create_x64("sg_base_pa", 0400, qcq_dentry, &qcq->sg_base_pa); 1358c2ecf20Sopenharmony_ci debugfs_create_x32("sg_size", 0400, qcq_dentry, &qcq->sg_size); 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci q_dentry = debugfs_create_dir("q", qcq->dentry); 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci debugfs_create_u32("index", 0400, q_dentry, &q->index); 1408c2ecf20Sopenharmony_ci debugfs_create_u32("num_descs", 0400, q_dentry, &q->num_descs); 1418c2ecf20Sopenharmony_ci debugfs_create_u32("desc_size", 0400, q_dentry, &q->desc_size); 1428c2ecf20Sopenharmony_ci debugfs_create_u32("pid", 0400, q_dentry, &q->pid); 1438c2ecf20Sopenharmony_ci debugfs_create_u32("qid", 0400, q_dentry, &q->hw_index); 1448c2ecf20Sopenharmony_ci debugfs_create_u32("qtype", 0400, q_dentry, &q->hw_type); 1458c2ecf20Sopenharmony_ci debugfs_create_u64("drop", 0400, q_dentry, &q->drop); 1468c2ecf20Sopenharmony_ci debugfs_create_u64("stop", 0400, q_dentry, &q->stop); 1478c2ecf20Sopenharmony_ci debugfs_create_u64("wake", 0400, q_dentry, &q->wake); 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci debugfs_create_file("tail", 0400, q_dentry, q, &q_tail_fops); 1508c2ecf20Sopenharmony_ci debugfs_create_file("head", 0400, q_dentry, q, &q_head_fops); 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci desc_blob = devm_kzalloc(dev, sizeof(*desc_blob), GFP_KERNEL); 1538c2ecf20Sopenharmony_ci if (!desc_blob) 1548c2ecf20Sopenharmony_ci return; 1558c2ecf20Sopenharmony_ci desc_blob->data = q->base; 1568c2ecf20Sopenharmony_ci desc_blob->size = (unsigned long)q->num_descs * q->desc_size; 1578c2ecf20Sopenharmony_ci debugfs_create_blob("desc_blob", 0400, q_dentry, desc_blob); 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci if (qcq->flags & IONIC_QCQ_F_SG) { 1608c2ecf20Sopenharmony_ci desc_blob = devm_kzalloc(dev, sizeof(*desc_blob), GFP_KERNEL); 1618c2ecf20Sopenharmony_ci if (!desc_blob) 1628c2ecf20Sopenharmony_ci return; 1638c2ecf20Sopenharmony_ci desc_blob->data = q->sg_base; 1648c2ecf20Sopenharmony_ci desc_blob->size = (unsigned long)q->num_descs * q->sg_desc_size; 1658c2ecf20Sopenharmony_ci debugfs_create_blob("sg_desc_blob", 0400, q_dentry, 1668c2ecf20Sopenharmony_ci desc_blob); 1678c2ecf20Sopenharmony_ci } 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci cq_dentry = debugfs_create_dir("cq", qcq->dentry); 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci debugfs_create_x64("base_pa", 0400, cq_dentry, &cq->base_pa); 1728c2ecf20Sopenharmony_ci debugfs_create_u32("num_descs", 0400, cq_dentry, &cq->num_descs); 1738c2ecf20Sopenharmony_ci debugfs_create_u32("desc_size", 0400, cq_dentry, &cq->desc_size); 1748c2ecf20Sopenharmony_ci debugfs_create_bool("done_color", 0400, cq_dentry, &cq->done_color); 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci debugfs_create_file("tail", 0400, cq_dentry, cq, &cq_tail_fops); 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci desc_blob = devm_kzalloc(dev, sizeof(*desc_blob), GFP_KERNEL); 1798c2ecf20Sopenharmony_ci if (!desc_blob) 1808c2ecf20Sopenharmony_ci return; 1818c2ecf20Sopenharmony_ci desc_blob->data = cq->base; 1828c2ecf20Sopenharmony_ci desc_blob->size = (unsigned long)cq->num_descs * cq->desc_size; 1838c2ecf20Sopenharmony_ci debugfs_create_blob("desc_blob", 0400, cq_dentry, desc_blob); 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci if (qcq->flags & IONIC_QCQ_F_INTR) { 1868c2ecf20Sopenharmony_ci intr_dentry = debugfs_create_dir("intr", qcq->dentry); 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci debugfs_create_u32("index", 0400, intr_dentry, 1898c2ecf20Sopenharmony_ci &intr->index); 1908c2ecf20Sopenharmony_ci debugfs_create_u32("vector", 0400, intr_dentry, 1918c2ecf20Sopenharmony_ci &intr->vector); 1928c2ecf20Sopenharmony_ci debugfs_create_u32("dim_coal_hw", 0400, intr_dentry, 1938c2ecf20Sopenharmony_ci &intr->dim_coal_hw); 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci intr_ctrl_regset = devm_kzalloc(dev, sizeof(*intr_ctrl_regset), 1968c2ecf20Sopenharmony_ci GFP_KERNEL); 1978c2ecf20Sopenharmony_ci if (!intr_ctrl_regset) 1988c2ecf20Sopenharmony_ci return; 1998c2ecf20Sopenharmony_ci intr_ctrl_regset->regs = intr_ctrl_regs; 2008c2ecf20Sopenharmony_ci intr_ctrl_regset->nregs = ARRAY_SIZE(intr_ctrl_regs); 2018c2ecf20Sopenharmony_ci intr_ctrl_regset->base = &idev->intr_ctrl[intr->index]; 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ci debugfs_create_regset32("intr_ctrl", 0400, intr_dentry, 2048c2ecf20Sopenharmony_ci intr_ctrl_regset); 2058c2ecf20Sopenharmony_ci } 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci if (qcq->flags & IONIC_QCQ_F_NOTIFYQ) { 2088c2ecf20Sopenharmony_ci stats_dentry = debugfs_create_dir("notifyblock", qcq->dentry); 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci debugfs_create_u64("eid", 0400, stats_dentry, 2118c2ecf20Sopenharmony_ci (u64 *)&lif->info->status.eid); 2128c2ecf20Sopenharmony_ci debugfs_create_u16("link_status", 0400, stats_dentry, 2138c2ecf20Sopenharmony_ci (u16 *)&lif->info->status.link_status); 2148c2ecf20Sopenharmony_ci debugfs_create_u32("link_speed", 0400, stats_dentry, 2158c2ecf20Sopenharmony_ci (u32 *)&lif->info->status.link_speed); 2168c2ecf20Sopenharmony_ci debugfs_create_u16("link_down_count", 0400, stats_dentry, 2178c2ecf20Sopenharmony_ci (u16 *)&lif->info->status.link_down_count); 2188c2ecf20Sopenharmony_ci } 2198c2ecf20Sopenharmony_ci} 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_cistatic int netdev_show(struct seq_file *seq, void *v) 2228c2ecf20Sopenharmony_ci{ 2238c2ecf20Sopenharmony_ci struct net_device *netdev = seq->private; 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci seq_printf(seq, "%s\n", netdev->name); 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci return 0; 2288c2ecf20Sopenharmony_ci} 2298c2ecf20Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(netdev); 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_civoid ionic_debugfs_add_lif(struct ionic_lif *lif) 2328c2ecf20Sopenharmony_ci{ 2338c2ecf20Sopenharmony_ci struct dentry *lif_dentry; 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci lif_dentry = debugfs_create_dir(lif->name, lif->ionic->dentry); 2368c2ecf20Sopenharmony_ci if (IS_ERR_OR_NULL(lif_dentry)) 2378c2ecf20Sopenharmony_ci return; 2388c2ecf20Sopenharmony_ci lif->dentry = lif_dentry; 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci debugfs_create_file("netdev", 0400, lif->dentry, 2418c2ecf20Sopenharmony_ci lif->netdev, &netdev_fops); 2428c2ecf20Sopenharmony_ci} 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_civoid ionic_debugfs_del_lif(struct ionic_lif *lif) 2458c2ecf20Sopenharmony_ci{ 2468c2ecf20Sopenharmony_ci debugfs_remove_recursive(lif->dentry); 2478c2ecf20Sopenharmony_ci lif->dentry = NULL; 2488c2ecf20Sopenharmony_ci} 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_civoid ionic_debugfs_del_qcq(struct ionic_qcq *qcq) 2518c2ecf20Sopenharmony_ci{ 2528c2ecf20Sopenharmony_ci debugfs_remove_recursive(qcq->dentry); 2538c2ecf20Sopenharmony_ci qcq->dentry = NULL; 2548c2ecf20Sopenharmony_ci} 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci#endif 257