1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB 2 /* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */ 3 4 #include "lag.h" 5 6 static char *get_str_mode_type(struct mlx5_lag *ldev) 7 { 8 if (ldev->flags & MLX5_LAG_FLAG_ROCE) 9 return "roce"; 10 if (ldev->flags & MLX5_LAG_FLAG_SRIOV) 11 return "switchdev"; 12 if (ldev->flags & MLX5_LAG_FLAG_MULTIPATH) 13 return "multipath"; 14 15 return NULL; 16 } 17 18 static int type_show(struct seq_file *file, void *priv) 19 { 20 struct mlx5_core_dev *dev = file->private; 21 struct mlx5_lag *ldev; 22 char *mode = NULL; 23 24 ldev = dev->priv.lag; 25 mutex_lock(&ldev->lock); 26 if (__mlx5_lag_is_active(ldev)) 27 mode = get_str_mode_type(ldev); 28 mutex_unlock(&ldev->lock); 29 if (!mode) 30 return -EINVAL; 31 seq_printf(file, "%s\n", mode); 32 33 return 0; 34 } 35 36 static int port_sel_mode_show(struct seq_file *file, void *priv) 37 { 38 struct mlx5_core_dev *dev = file->private; 39 struct mlx5_lag *ldev; 40 int ret = 0; 41 char *mode; 42 43 ldev = dev->priv.lag; 44 mutex_lock(&ldev->lock); 45 if (__mlx5_lag_is_active(ldev)) 46 mode = get_str_port_sel_mode(ldev->flags); 47 else 48 ret = -EINVAL; 49 mutex_unlock(&ldev->lock); 50 if (ret || !mode) 51 return ret; 52 53 seq_printf(file, "%s\n", mode); 54 return 0; 55 } 56 57 static int state_show(struct seq_file *file, void *priv) 58 { 59 struct mlx5_core_dev *dev = file->private; 60 struct mlx5_lag *ldev; 61 bool active; 62 63 ldev = dev->priv.lag; 64 mutex_lock(&ldev->lock); 65 active = __mlx5_lag_is_active(ldev); 66 mutex_unlock(&ldev->lock); 67 seq_printf(file, "%s\n", active ? "active" : "disabled"); 68 return 0; 69 } 70 71 static int flags_show(struct seq_file *file, void *priv) 72 { 73 struct mlx5_core_dev *dev = file->private; 74 struct mlx5_lag *ldev; 75 bool shared_fdb; 76 bool lag_active; 77 78 ldev = dev->priv.lag; 79 mutex_lock(&ldev->lock); 80 lag_active = __mlx5_lag_is_active(ldev); 81 if (lag_active) 82 shared_fdb = ldev->shared_fdb; 83 84 mutex_unlock(&ldev->lock); 85 if (!lag_active) 86 return -EINVAL; 87 88 seq_printf(file, "%s:%s\n", "shared_fdb", shared_fdb ? "on" : "off"); 89 return 0; 90 } 91 92 static int mapping_show(struct seq_file *file, void *priv) 93 { 94 struct mlx5_core_dev *dev = file->private; 95 u8 ports[MLX5_MAX_PORTS] = {}; 96 struct mlx5_lag *ldev; 97 bool hash = false; 98 bool lag_active; 99 int num_ports; 100 int i; 101 102 ldev = dev->priv.lag; 103 mutex_lock(&ldev->lock); 104 lag_active = __mlx5_lag_is_active(ldev); 105 if (lag_active) { 106 if (ldev->flags & MLX5_LAG_FLAG_HASH_BASED) { 107 mlx5_infer_tx_enabled(&ldev->tracker, ldev->ports, ports, 108 &num_ports); 109 hash = true; 110 } else { 111 for (i = 0; i < ldev->ports; i++) 112 ports[i] = ldev->v2p_map[i]; 113 num_ports = ldev->ports; 114 } 115 } 116 mutex_unlock(&ldev->lock); 117 if (!lag_active) 118 return -EINVAL; 119 120 for (i = 0; i < num_ports; i++) { 121 if (hash) 122 seq_printf(file, "%d\n", ports[i] + 1); 123 else 124 seq_printf(file, "%d:%d\n", i + 1, ports[i]); 125 } 126 127 return 0; 128 } 129 130 static int members_show(struct seq_file *file, void *priv) 131 { 132 struct mlx5_core_dev *dev = file->private; 133 struct mlx5_lag *ldev; 134 int i; 135 136 ldev = dev->priv.lag; 137 mutex_lock(&ldev->lock); 138 for (i = 0; i < ldev->ports; i++) { 139 if (!ldev->pf[i].dev) 140 continue; 141 seq_printf(file, "%s\n", dev_name(ldev->pf[i].dev->device)); 142 } 143 mutex_unlock(&ldev->lock); 144 145 return 0; 146 } 147 148 DEFINE_SHOW_ATTRIBUTE(type); 149 DEFINE_SHOW_ATTRIBUTE(port_sel_mode); 150 DEFINE_SHOW_ATTRIBUTE(state); 151 DEFINE_SHOW_ATTRIBUTE(flags); 152 DEFINE_SHOW_ATTRIBUTE(mapping); 153 DEFINE_SHOW_ATTRIBUTE(members); 154 155 void mlx5_ldev_add_debugfs(struct mlx5_core_dev *dev) 156 { 157 struct dentry *dbg; 158 159 dbg = debugfs_create_dir("lag", mlx5_debugfs_get_dev_root(dev)); 160 dev->priv.dbg.lag_debugfs = dbg; 161 162 debugfs_create_file("type", 0444, dbg, dev, &type_fops); 163 debugfs_create_file("port_sel_mode", 0444, dbg, dev, &port_sel_mode_fops); 164 debugfs_create_file("state", 0444, dbg, dev, &state_fops); 165 debugfs_create_file("flags", 0444, dbg, dev, &flags_fops); 166 debugfs_create_file("mapping", 0444, dbg, dev, &mapping_fops); 167 debugfs_create_file("members", 0444, dbg, dev, &members_fops); 168 } 169 170 void mlx5_ldev_remove_debugfs(struct dentry *dbg) 171 { 172 debugfs_remove_recursive(dbg); 173 } 174