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