18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * debugfs code for HSR & PRP 38c2ecf20Sopenharmony_ci * Copyright (C) 2019 Texas Instruments Incorporated 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Author(s): 68c2ecf20Sopenharmony_ci * Murali Karicheri <m-karicheri2@ti.com> 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * This program is free software; you can redistribute it and/or 98c2ecf20Sopenharmony_ci * modify it under the terms of the GNU General Public License as 108c2ecf20Sopenharmony_ci * published by the Free Software Foundation version 2. 118c2ecf20Sopenharmony_ci * 128c2ecf20Sopenharmony_ci * This program is distributed "as is" WITHOUT ANY WARRANTY of any 138c2ecf20Sopenharmony_ci * kind, whether express or implied; without even the implied warranty 148c2ecf20Sopenharmony_ci * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 158c2ecf20Sopenharmony_ci * GNU General Public License for more details. 168c2ecf20Sopenharmony_ci */ 178c2ecf20Sopenharmony_ci#include <linux/module.h> 188c2ecf20Sopenharmony_ci#include <linux/errno.h> 198c2ecf20Sopenharmony_ci#include <linux/debugfs.h> 208c2ecf20Sopenharmony_ci#include "hsr_main.h" 218c2ecf20Sopenharmony_ci#include "hsr_framereg.h" 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_cistatic struct dentry *hsr_debugfs_root_dir; 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci/* hsr_node_table_show - Formats and prints node_table entries */ 268c2ecf20Sopenharmony_cistatic int 278c2ecf20Sopenharmony_cihsr_node_table_show(struct seq_file *sfp, void *data) 288c2ecf20Sopenharmony_ci{ 298c2ecf20Sopenharmony_ci struct hsr_priv *priv = (struct hsr_priv *)sfp->private; 308c2ecf20Sopenharmony_ci struct hsr_node *node; 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci seq_printf(sfp, "Node Table entries for (%s) device\n", 338c2ecf20Sopenharmony_ci (priv->prot_version == PRP_V1 ? "PRP" : "HSR")); 348c2ecf20Sopenharmony_ci seq_puts(sfp, "MAC-Address-A, MAC-Address-B, time_in[A], "); 358c2ecf20Sopenharmony_ci seq_puts(sfp, "time_in[B], Address-B port, "); 368c2ecf20Sopenharmony_ci if (priv->prot_version == PRP_V1) 378c2ecf20Sopenharmony_ci seq_puts(sfp, "SAN-A, SAN-B, DAN-P\n"); 388c2ecf20Sopenharmony_ci else 398c2ecf20Sopenharmony_ci seq_puts(sfp, "DAN-H\n"); 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci rcu_read_lock(); 428c2ecf20Sopenharmony_ci list_for_each_entry_rcu(node, &priv->node_db, mac_list) { 438c2ecf20Sopenharmony_ci /* skip self node */ 448c2ecf20Sopenharmony_ci if (hsr_addr_is_self(priv, node->macaddress_A)) 458c2ecf20Sopenharmony_ci continue; 468c2ecf20Sopenharmony_ci seq_printf(sfp, "%pM ", &node->macaddress_A[0]); 478c2ecf20Sopenharmony_ci seq_printf(sfp, "%pM ", &node->macaddress_B[0]); 488c2ecf20Sopenharmony_ci seq_printf(sfp, "%10lx, ", node->time_in[HSR_PT_SLAVE_A]); 498c2ecf20Sopenharmony_ci seq_printf(sfp, "%10lx, ", node->time_in[HSR_PT_SLAVE_B]); 508c2ecf20Sopenharmony_ci seq_printf(sfp, "%14x, ", node->addr_B_port); 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci if (priv->prot_version == PRP_V1) 538c2ecf20Sopenharmony_ci seq_printf(sfp, "%5x, %5x, %5x\n", 548c2ecf20Sopenharmony_ci node->san_a, node->san_b, 558c2ecf20Sopenharmony_ci (node->san_a == 0 && node->san_b == 0)); 568c2ecf20Sopenharmony_ci else 578c2ecf20Sopenharmony_ci seq_printf(sfp, "%5x\n", 1); 588c2ecf20Sopenharmony_ci } 598c2ecf20Sopenharmony_ci rcu_read_unlock(); 608c2ecf20Sopenharmony_ci return 0; 618c2ecf20Sopenharmony_ci} 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(hsr_node_table); 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_civoid hsr_debugfs_rename(struct net_device *dev) 668c2ecf20Sopenharmony_ci{ 678c2ecf20Sopenharmony_ci struct hsr_priv *priv = netdev_priv(dev); 688c2ecf20Sopenharmony_ci struct dentry *d; 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci d = debugfs_rename(hsr_debugfs_root_dir, priv->node_tbl_root, 718c2ecf20Sopenharmony_ci hsr_debugfs_root_dir, dev->name); 728c2ecf20Sopenharmony_ci if (IS_ERR(d)) 738c2ecf20Sopenharmony_ci netdev_warn(dev, "failed to rename\n"); 748c2ecf20Sopenharmony_ci else 758c2ecf20Sopenharmony_ci priv->node_tbl_root = d; 768c2ecf20Sopenharmony_ci} 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci/* hsr_debugfs_init - create hsr node_table file for dumping 798c2ecf20Sopenharmony_ci * the node table 808c2ecf20Sopenharmony_ci * 818c2ecf20Sopenharmony_ci * Description: 828c2ecf20Sopenharmony_ci * When debugfs is configured this routine sets up the node_table file per 838c2ecf20Sopenharmony_ci * hsr device for dumping the node_table entries 848c2ecf20Sopenharmony_ci */ 858c2ecf20Sopenharmony_civoid hsr_debugfs_init(struct hsr_priv *priv, struct net_device *hsr_dev) 868c2ecf20Sopenharmony_ci{ 878c2ecf20Sopenharmony_ci struct dentry *de = NULL; 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci de = debugfs_create_dir(hsr_dev->name, hsr_debugfs_root_dir); 908c2ecf20Sopenharmony_ci if (IS_ERR(de)) { 918c2ecf20Sopenharmony_ci pr_err("Cannot create hsr debugfs directory\n"); 928c2ecf20Sopenharmony_ci return; 938c2ecf20Sopenharmony_ci } 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci priv->node_tbl_root = de; 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci de = debugfs_create_file("node_table", S_IFREG | 0444, 988c2ecf20Sopenharmony_ci priv->node_tbl_root, priv, 998c2ecf20Sopenharmony_ci &hsr_node_table_fops); 1008c2ecf20Sopenharmony_ci if (IS_ERR(de)) { 1018c2ecf20Sopenharmony_ci pr_err("Cannot create hsr node_table file\n"); 1028c2ecf20Sopenharmony_ci debugfs_remove(priv->node_tbl_root); 1038c2ecf20Sopenharmony_ci priv->node_tbl_root = NULL; 1048c2ecf20Sopenharmony_ci return; 1058c2ecf20Sopenharmony_ci } 1068c2ecf20Sopenharmony_ci} 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci/* hsr_debugfs_term - Tear down debugfs intrastructure 1098c2ecf20Sopenharmony_ci * 1108c2ecf20Sopenharmony_ci * Description: 1118c2ecf20Sopenharmony_ci * When Debufs is configured this routine removes debugfs file system 1128c2ecf20Sopenharmony_ci * elements that are specific to hsr 1138c2ecf20Sopenharmony_ci */ 1148c2ecf20Sopenharmony_civoid 1158c2ecf20Sopenharmony_cihsr_debugfs_term(struct hsr_priv *priv) 1168c2ecf20Sopenharmony_ci{ 1178c2ecf20Sopenharmony_ci debugfs_remove_recursive(priv->node_tbl_root); 1188c2ecf20Sopenharmony_ci priv->node_tbl_root = NULL; 1198c2ecf20Sopenharmony_ci} 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_civoid hsr_debugfs_create_root(void) 1228c2ecf20Sopenharmony_ci{ 1238c2ecf20Sopenharmony_ci hsr_debugfs_root_dir = debugfs_create_dir("hsr", NULL); 1248c2ecf20Sopenharmony_ci if (IS_ERR(hsr_debugfs_root_dir)) { 1258c2ecf20Sopenharmony_ci pr_err("Cannot create hsr debugfs root directory\n"); 1268c2ecf20Sopenharmony_ci hsr_debugfs_root_dir = NULL; 1278c2ecf20Sopenharmony_ci } 1288c2ecf20Sopenharmony_ci} 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_civoid hsr_debugfs_remove_root(void) 1318c2ecf20Sopenharmony_ci{ 1328c2ecf20Sopenharmony_ci /* debugfs_remove() internally checks NULL and ERROR */ 1338c2ecf20Sopenharmony_ci debugfs_remove(hsr_debugfs_root_dir); 1348c2ecf20Sopenharmony_ci} 135