162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* Copyright(c) 2017 - 2019 Pensando Systems, Inc */ 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci#include <linux/pci.h> 562306a36Sopenharmony_ci#include <linux/netdevice.h> 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#include "ionic.h" 862306a36Sopenharmony_ci#include "ionic_bus.h" 962306a36Sopenharmony_ci#include "ionic_lif.h" 1062306a36Sopenharmony_ci#include "ionic_debugfs.h" 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#ifdef CONFIG_DEBUG_FS 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_cistatic struct dentry *ionic_dir; 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_civoid ionic_debugfs_create(void) 1762306a36Sopenharmony_ci{ 1862306a36Sopenharmony_ci ionic_dir = debugfs_create_dir(IONIC_DRV_NAME, NULL); 1962306a36Sopenharmony_ci} 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_civoid ionic_debugfs_destroy(void) 2262306a36Sopenharmony_ci{ 2362306a36Sopenharmony_ci debugfs_remove_recursive(ionic_dir); 2462306a36Sopenharmony_ci} 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_civoid ionic_debugfs_add_dev(struct ionic *ionic) 2762306a36Sopenharmony_ci{ 2862306a36Sopenharmony_ci ionic->dentry = debugfs_create_dir(ionic_bus_info(ionic), ionic_dir); 2962306a36Sopenharmony_ci} 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_civoid ionic_debugfs_del_dev(struct ionic *ionic) 3262306a36Sopenharmony_ci{ 3362306a36Sopenharmony_ci debugfs_remove_recursive(ionic->dentry); 3462306a36Sopenharmony_ci ionic->dentry = NULL; 3562306a36Sopenharmony_ci} 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_cistatic int identity_show(struct seq_file *seq, void *v) 3862306a36Sopenharmony_ci{ 3962306a36Sopenharmony_ci struct ionic *ionic = seq->private; 4062306a36Sopenharmony_ci struct ionic_identity *ident; 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci ident = &ionic->ident; 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci seq_printf(seq, "nlifs: %d\n", ident->dev.nlifs); 4562306a36Sopenharmony_ci seq_printf(seq, "nintrs: %d\n", ident->dev.nintrs); 4662306a36Sopenharmony_ci seq_printf(seq, "ndbpgs_per_lif: %d\n", ident->dev.ndbpgs_per_lif); 4762306a36Sopenharmony_ci seq_printf(seq, "intr_coal_mult: %d\n", ident->dev.intr_coal_mult); 4862306a36Sopenharmony_ci seq_printf(seq, "intr_coal_div: %d\n", ident->dev.intr_coal_div); 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci seq_printf(seq, "max_ucast_filters: %d\n", ident->lif.eth.max_ucast_filters); 5162306a36Sopenharmony_ci seq_printf(seq, "max_mcast_filters: %d\n", ident->lif.eth.max_mcast_filters); 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci return 0; 5462306a36Sopenharmony_ci} 5562306a36Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(identity); 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_civoid ionic_debugfs_add_ident(struct ionic *ionic) 5862306a36Sopenharmony_ci{ 5962306a36Sopenharmony_ci debugfs_create_file("identity", 0400, ionic->dentry, 6062306a36Sopenharmony_ci ionic, &identity_fops); 6162306a36Sopenharmony_ci} 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_civoid ionic_debugfs_add_sizes(struct ionic *ionic) 6462306a36Sopenharmony_ci{ 6562306a36Sopenharmony_ci debugfs_create_u32("nlifs", 0400, ionic->dentry, 6662306a36Sopenharmony_ci (u32 *)&ionic->ident.dev.nlifs); 6762306a36Sopenharmony_ci debugfs_create_u32("nintrs", 0400, ionic->dentry, &ionic->nintrs); 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci debugfs_create_u32("ntxqs_per_lif", 0400, ionic->dentry, 7062306a36Sopenharmony_ci (u32 *)&ionic->ident.lif.eth.config.queue_count[IONIC_QTYPE_TXQ]); 7162306a36Sopenharmony_ci debugfs_create_u32("nrxqs_per_lif", 0400, ionic->dentry, 7262306a36Sopenharmony_ci (u32 *)&ionic->ident.lif.eth.config.queue_count[IONIC_QTYPE_RXQ]); 7362306a36Sopenharmony_ci} 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_cistatic int q_tail_show(struct seq_file *seq, void *v) 7662306a36Sopenharmony_ci{ 7762306a36Sopenharmony_ci struct ionic_queue *q = seq->private; 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci seq_printf(seq, "%d\n", q->tail_idx); 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci return 0; 8262306a36Sopenharmony_ci} 8362306a36Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(q_tail); 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_cistatic int q_head_show(struct seq_file *seq, void *v) 8662306a36Sopenharmony_ci{ 8762306a36Sopenharmony_ci struct ionic_queue *q = seq->private; 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci seq_printf(seq, "%d\n", q->head_idx); 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci return 0; 9262306a36Sopenharmony_ci} 9362306a36Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(q_head); 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_cistatic int cq_tail_show(struct seq_file *seq, void *v) 9662306a36Sopenharmony_ci{ 9762306a36Sopenharmony_ci struct ionic_cq *cq = seq->private; 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci seq_printf(seq, "%d\n", cq->tail_idx); 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci return 0; 10262306a36Sopenharmony_ci} 10362306a36Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(cq_tail); 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_cistatic const struct debugfs_reg32 intr_ctrl_regs[] = { 10662306a36Sopenharmony_ci { .name = "coal_init", .offset = 0, }, 10762306a36Sopenharmony_ci { .name = "mask", .offset = 4, }, 10862306a36Sopenharmony_ci { .name = "credits", .offset = 8, }, 10962306a36Sopenharmony_ci { .name = "mask_on_assert", .offset = 12, }, 11062306a36Sopenharmony_ci { .name = "coal_timer", .offset = 16, }, 11162306a36Sopenharmony_ci}; 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_civoid ionic_debugfs_add_qcq(struct ionic_lif *lif, struct ionic_qcq *qcq) 11462306a36Sopenharmony_ci{ 11562306a36Sopenharmony_ci struct dentry *qcq_dentry, *q_dentry, *cq_dentry; 11662306a36Sopenharmony_ci struct dentry *intr_dentry, *stats_dentry; 11762306a36Sopenharmony_ci struct ionic_dev *idev = &lif->ionic->idev; 11862306a36Sopenharmony_ci struct debugfs_regset32 *intr_ctrl_regset; 11962306a36Sopenharmony_ci struct ionic_intr_info *intr = &qcq->intr; 12062306a36Sopenharmony_ci struct debugfs_blob_wrapper *desc_blob; 12162306a36Sopenharmony_ci struct device *dev = lif->ionic->dev; 12262306a36Sopenharmony_ci struct ionic_queue *q = &qcq->q; 12362306a36Sopenharmony_ci struct ionic_cq *cq = &qcq->cq; 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci qcq_dentry = debugfs_create_dir(q->name, lif->dentry); 12662306a36Sopenharmony_ci if (IS_ERR_OR_NULL(qcq_dentry)) 12762306a36Sopenharmony_ci return; 12862306a36Sopenharmony_ci qcq->dentry = qcq_dentry; 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci debugfs_create_x64("q_base_pa", 0400, qcq_dentry, &qcq->q_base_pa); 13162306a36Sopenharmony_ci debugfs_create_x32("q_size", 0400, qcq_dentry, &qcq->q_size); 13262306a36Sopenharmony_ci debugfs_create_x64("cq_base_pa", 0400, qcq_dentry, &qcq->cq_base_pa); 13362306a36Sopenharmony_ci debugfs_create_x32("cq_size", 0400, qcq_dentry, &qcq->cq_size); 13462306a36Sopenharmony_ci debugfs_create_x64("sg_base_pa", 0400, qcq_dentry, &qcq->sg_base_pa); 13562306a36Sopenharmony_ci debugfs_create_x32("sg_size", 0400, qcq_dentry, &qcq->sg_size); 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci q_dentry = debugfs_create_dir("q", qcq->dentry); 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci debugfs_create_u32("index", 0400, q_dentry, &q->index); 14062306a36Sopenharmony_ci debugfs_create_u32("num_descs", 0400, q_dentry, &q->num_descs); 14162306a36Sopenharmony_ci debugfs_create_u32("desc_size", 0400, q_dentry, &q->desc_size); 14262306a36Sopenharmony_ci debugfs_create_u32("pid", 0400, q_dentry, &q->pid); 14362306a36Sopenharmony_ci debugfs_create_u32("qid", 0400, q_dentry, &q->hw_index); 14462306a36Sopenharmony_ci debugfs_create_u32("qtype", 0400, q_dentry, &q->hw_type); 14562306a36Sopenharmony_ci debugfs_create_u64("drop", 0400, q_dentry, &q->drop); 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci debugfs_create_file("tail", 0400, q_dentry, q, &q_tail_fops); 14862306a36Sopenharmony_ci debugfs_create_file("head", 0400, q_dentry, q, &q_head_fops); 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci desc_blob = devm_kzalloc(dev, sizeof(*desc_blob), GFP_KERNEL); 15162306a36Sopenharmony_ci if (!desc_blob) 15262306a36Sopenharmony_ci return; 15362306a36Sopenharmony_ci desc_blob->data = q->base; 15462306a36Sopenharmony_ci desc_blob->size = (unsigned long)q->num_descs * q->desc_size; 15562306a36Sopenharmony_ci debugfs_create_blob("desc_blob", 0400, q_dentry, desc_blob); 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci if (qcq->flags & IONIC_QCQ_F_SG) { 15862306a36Sopenharmony_ci desc_blob = devm_kzalloc(dev, sizeof(*desc_blob), GFP_KERNEL); 15962306a36Sopenharmony_ci if (!desc_blob) 16062306a36Sopenharmony_ci return; 16162306a36Sopenharmony_ci desc_blob->data = q->sg_base; 16262306a36Sopenharmony_ci desc_blob->size = (unsigned long)q->num_descs * q->sg_desc_size; 16362306a36Sopenharmony_ci debugfs_create_blob("sg_desc_blob", 0400, q_dentry, 16462306a36Sopenharmony_ci desc_blob); 16562306a36Sopenharmony_ci } 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci cq_dentry = debugfs_create_dir("cq", qcq->dentry); 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci debugfs_create_x64("base_pa", 0400, cq_dentry, &cq->base_pa); 17062306a36Sopenharmony_ci debugfs_create_u32("num_descs", 0400, cq_dentry, &cq->num_descs); 17162306a36Sopenharmony_ci debugfs_create_u32("desc_size", 0400, cq_dentry, &cq->desc_size); 17262306a36Sopenharmony_ci debugfs_create_bool("done_color", 0400, cq_dentry, &cq->done_color); 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci debugfs_create_file("tail", 0400, cq_dentry, cq, &cq_tail_fops); 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci desc_blob = devm_kzalloc(dev, sizeof(*desc_blob), GFP_KERNEL); 17762306a36Sopenharmony_ci if (!desc_blob) 17862306a36Sopenharmony_ci return; 17962306a36Sopenharmony_ci desc_blob->data = cq->base; 18062306a36Sopenharmony_ci desc_blob->size = (unsigned long)cq->num_descs * cq->desc_size; 18162306a36Sopenharmony_ci debugfs_create_blob("desc_blob", 0400, cq_dentry, desc_blob); 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci if (qcq->flags & IONIC_QCQ_F_INTR) { 18462306a36Sopenharmony_ci intr_dentry = debugfs_create_dir("intr", qcq->dentry); 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci debugfs_create_u32("index", 0400, intr_dentry, 18762306a36Sopenharmony_ci &intr->index); 18862306a36Sopenharmony_ci debugfs_create_u32("vector", 0400, intr_dentry, 18962306a36Sopenharmony_ci &intr->vector); 19062306a36Sopenharmony_ci debugfs_create_u32("dim_coal_hw", 0400, intr_dentry, 19162306a36Sopenharmony_ci &intr->dim_coal_hw); 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci intr_ctrl_regset = devm_kzalloc(dev, sizeof(*intr_ctrl_regset), 19462306a36Sopenharmony_ci GFP_KERNEL); 19562306a36Sopenharmony_ci if (!intr_ctrl_regset) 19662306a36Sopenharmony_ci return; 19762306a36Sopenharmony_ci intr_ctrl_regset->regs = intr_ctrl_regs; 19862306a36Sopenharmony_ci intr_ctrl_regset->nregs = ARRAY_SIZE(intr_ctrl_regs); 19962306a36Sopenharmony_ci intr_ctrl_regset->base = &idev->intr_ctrl[intr->index]; 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci debugfs_create_regset32("intr_ctrl", 0400, intr_dentry, 20262306a36Sopenharmony_ci intr_ctrl_regset); 20362306a36Sopenharmony_ci } 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci if (qcq->flags & IONIC_QCQ_F_NOTIFYQ) { 20662306a36Sopenharmony_ci stats_dentry = debugfs_create_dir("notifyblock", qcq->dentry); 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci debugfs_create_u64("eid", 0400, stats_dentry, 20962306a36Sopenharmony_ci (u64 *)&lif->info->status.eid); 21062306a36Sopenharmony_ci debugfs_create_u16("link_status", 0400, stats_dentry, 21162306a36Sopenharmony_ci (u16 *)&lif->info->status.link_status); 21262306a36Sopenharmony_ci debugfs_create_u32("link_speed", 0400, stats_dentry, 21362306a36Sopenharmony_ci (u32 *)&lif->info->status.link_speed); 21462306a36Sopenharmony_ci debugfs_create_u16("link_down_count", 0400, stats_dentry, 21562306a36Sopenharmony_ci (u16 *)&lif->info->status.link_down_count); 21662306a36Sopenharmony_ci } 21762306a36Sopenharmony_ci} 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_cistatic int netdev_show(struct seq_file *seq, void *v) 22062306a36Sopenharmony_ci{ 22162306a36Sopenharmony_ci struct net_device *netdev = seq->private; 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci seq_printf(seq, "%s\n", netdev->name); 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci return 0; 22662306a36Sopenharmony_ci} 22762306a36Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(netdev); 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_cistatic int lif_filters_show(struct seq_file *seq, void *v) 23062306a36Sopenharmony_ci{ 23162306a36Sopenharmony_ci struct ionic_lif *lif = seq->private; 23262306a36Sopenharmony_ci struct ionic_rx_filter *f; 23362306a36Sopenharmony_ci struct hlist_head *head; 23462306a36Sopenharmony_ci struct hlist_node *tmp; 23562306a36Sopenharmony_ci unsigned int i; 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci seq_puts(seq, "id flow state type filter\n"); 23862306a36Sopenharmony_ci spin_lock_bh(&lif->rx_filters.lock); 23962306a36Sopenharmony_ci for (i = 0; i < IONIC_RX_FILTER_HLISTS; i++) { 24062306a36Sopenharmony_ci head = &lif->rx_filters.by_id[i]; 24162306a36Sopenharmony_ci hlist_for_each_entry_safe(f, tmp, head, by_id) { 24262306a36Sopenharmony_ci switch (le16_to_cpu(f->cmd.match)) { 24362306a36Sopenharmony_ci case IONIC_RX_FILTER_MATCH_VLAN: 24462306a36Sopenharmony_ci seq_printf(seq, "0x%04x 0x%08x 0x%02x vlan 0x%04x\n", 24562306a36Sopenharmony_ci f->filter_id, f->flow_id, f->state, 24662306a36Sopenharmony_ci le16_to_cpu(f->cmd.vlan.vlan)); 24762306a36Sopenharmony_ci break; 24862306a36Sopenharmony_ci case IONIC_RX_FILTER_MATCH_MAC: 24962306a36Sopenharmony_ci seq_printf(seq, "0x%04x 0x%08x 0x%02x mac %pM\n", 25062306a36Sopenharmony_ci f->filter_id, f->flow_id, f->state, 25162306a36Sopenharmony_ci f->cmd.mac.addr); 25262306a36Sopenharmony_ci break; 25362306a36Sopenharmony_ci case IONIC_RX_FILTER_MATCH_MAC_VLAN: 25462306a36Sopenharmony_ci seq_printf(seq, "0x%04x 0x%08x 0x%02x macvl 0x%04x %pM\n", 25562306a36Sopenharmony_ci f->filter_id, f->flow_id, f->state, 25662306a36Sopenharmony_ci le16_to_cpu(f->cmd.vlan.vlan), 25762306a36Sopenharmony_ci f->cmd.mac.addr); 25862306a36Sopenharmony_ci break; 25962306a36Sopenharmony_ci case IONIC_RX_FILTER_STEER_PKTCLASS: 26062306a36Sopenharmony_ci seq_printf(seq, "0x%04x 0x%08x 0x%02x rxstr 0x%llx\n", 26162306a36Sopenharmony_ci f->filter_id, f->flow_id, f->state, 26262306a36Sopenharmony_ci le64_to_cpu(f->cmd.pkt_class)); 26362306a36Sopenharmony_ci break; 26462306a36Sopenharmony_ci } 26562306a36Sopenharmony_ci } 26662306a36Sopenharmony_ci } 26762306a36Sopenharmony_ci spin_unlock_bh(&lif->rx_filters.lock); 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci return 0; 27062306a36Sopenharmony_ci} 27162306a36Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(lif_filters); 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_civoid ionic_debugfs_add_lif(struct ionic_lif *lif) 27462306a36Sopenharmony_ci{ 27562306a36Sopenharmony_ci struct dentry *lif_dentry; 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci lif_dentry = debugfs_create_dir(lif->name, lif->ionic->dentry); 27862306a36Sopenharmony_ci if (IS_ERR_OR_NULL(lif_dentry)) 27962306a36Sopenharmony_ci return; 28062306a36Sopenharmony_ci lif->dentry = lif_dentry; 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ci debugfs_create_file("netdev", 0400, lif->dentry, 28362306a36Sopenharmony_ci lif->netdev, &netdev_fops); 28462306a36Sopenharmony_ci debugfs_create_file("filters", 0400, lif->dentry, 28562306a36Sopenharmony_ci lif, &lif_filters_fops); 28662306a36Sopenharmony_ci} 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_civoid ionic_debugfs_del_lif(struct ionic_lif *lif) 28962306a36Sopenharmony_ci{ 29062306a36Sopenharmony_ci debugfs_remove_recursive(lif->dentry); 29162306a36Sopenharmony_ci lif->dentry = NULL; 29262306a36Sopenharmony_ci} 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_civoid ionic_debugfs_del_qcq(struct ionic_qcq *qcq) 29562306a36Sopenharmony_ci{ 29662306a36Sopenharmony_ci debugfs_remove_recursive(qcq->dentry); 29762306a36Sopenharmony_ci qcq->dentry = NULL; 29862306a36Sopenharmony_ci} 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci#endif 301