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 8static void *mlx5_esw_bridge_debugfs_start(struct seq_file *seq, loff_t *pos); 9static void *mlx5_esw_bridge_debugfs_next(struct seq_file *seq, void *v, loff_t *pos); 10static void mlx5_esw_bridge_debugfs_stop(struct seq_file *seq, void *v); 11static int mlx5_esw_bridge_debugfs_show(struct seq_file *seq, void *v); 12 13static 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}; 19DEFINE_SEQ_ATTRIBUTE(mlx5_esw_bridge_debugfs); 20 21static 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 29static 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 36static void mlx5_esw_bridge_debugfs_stop(struct seq_file *seq, void *v) 37{ 38 rtnl_unlock(); 39} 40 41static 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 60void 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", 0400, bridge->debugfs_dir, bridge, 68 &mlx5_esw_bridge_debugfs_fops); 69} 70 71void 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 77void 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 85void 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