1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB 2 /* Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */ 3 4 #include <linux/debugfs.h> 5 #include "bridge.h" 6 #include "bridge_priv.h" 7 8 static void *mlx5_esw_bridge_debugfs_start(struct seq_file *seq, loff_t *pos); 9 static void *mlx5_esw_bridge_debugfs_next(struct seq_file *seq, void *v, loff_t *pos); 10 static void mlx5_esw_bridge_debugfs_stop(struct seq_file *seq, void *v); 11 static int mlx5_esw_bridge_debugfs_show(struct seq_file *seq, void *v); 12 13 static const struct seq_operations mlx5_esw_bridge_debugfs_sops = { 14 .start = mlx5_esw_bridge_debugfs_start, 15 .next = mlx5_esw_bridge_debugfs_next, 16 .stop = mlx5_esw_bridge_debugfs_stop, 17 .show = mlx5_esw_bridge_debugfs_show, 18 }; 19 DEFINE_SEQ_ATTRIBUTE(mlx5_esw_bridge_debugfs); 20 21 static void *mlx5_esw_bridge_debugfs_start(struct seq_file *seq, loff_t *pos) 22 { 23 struct mlx5_esw_bridge *bridge = seq->private; 24 25 rtnl_lock(); 26 return *pos ? seq_list_start(&bridge->fdb_list, *pos - 1) : SEQ_START_TOKEN; 27 } 28 29 static void *mlx5_esw_bridge_debugfs_next(struct seq_file *seq, void *v, loff_t *pos) 30 { 31 struct mlx5_esw_bridge *bridge = seq->private; 32 33 return seq_list_next(v == SEQ_START_TOKEN ? &bridge->fdb_list : v, &bridge->fdb_list, pos); 34 } 35 36 static void mlx5_esw_bridge_debugfs_stop(struct seq_file *seq, void *v) 37 { 38 rtnl_unlock(); 39 } 40 41 static int mlx5_esw_bridge_debugfs_show(struct seq_file *seq, void *v) 42 { 43 struct mlx5_esw_bridge_fdb_entry *entry; 44 u64 packets, bytes, lastuse; 45 46 if (v == SEQ_START_TOKEN) { 47 seq_printf(seq, "%-16s %-17s %4s %20s %20s %20s %5s\n", 48 "DEV", "MAC", "VLAN", "PACKETS", "BYTES", "LASTUSE", "FLAGS"); 49 return 0; 50 } 51 52 entry = list_entry(v, struct mlx5_esw_bridge_fdb_entry, list); 53 mlx5_fc_query_cached_raw(entry->ingress_counter, &bytes, &packets, &lastuse); 54 seq_printf(seq, "%-16s %-17pM %4d %20llu %20llu %20llu %#5x\n", 55 entry->dev->name, entry->key.addr, entry->key.vid, packets, bytes, lastuse, 56 entry->flags); 57 return 0; 58 } 59 60 void mlx5_esw_bridge_debugfs_init(struct net_device *br_netdev, struct mlx5_esw_bridge *bridge) 61 { 62 if (!bridge->br_offloads->debugfs_root) 63 return; 64 65 bridge->debugfs_dir = debugfs_create_dir(br_netdev->name, 66 bridge->br_offloads->debugfs_root); 67 debugfs_create_file("fdb", 0444, bridge->debugfs_dir, bridge, 68 &mlx5_esw_bridge_debugfs_fops); 69 } 70 71 void mlx5_esw_bridge_debugfs_cleanup(struct mlx5_esw_bridge *bridge) 72 { 73 debugfs_remove_recursive(bridge->debugfs_dir); 74 bridge->debugfs_dir = NULL; 75 } 76 77 void mlx5_esw_bridge_debugfs_offloads_init(struct mlx5_esw_bridge_offloads *br_offloads) 78 { 79 if (!br_offloads->esw->debugfs_root) 80 return; 81 82 br_offloads->debugfs_root = debugfs_create_dir("bridge", br_offloads->esw->debugfs_root); 83 } 84 85 void mlx5_esw_bridge_debugfs_offloads_cleanup(struct mlx5_esw_bridge_offloads *br_offloads) 86 { 87 debugfs_remove_recursive(br_offloads->debugfs_root); 88 br_offloads->debugfs_root = NULL; 89 } 90