0001
0002
0003
0004 #include "lag.h"
0005
0006 static char *get_str_mode_type(struct mlx5_lag *ldev)
0007 {
0008 switch (ldev->mode) {
0009 case MLX5_LAG_MODE_ROCE: return "roce";
0010 case MLX5_LAG_MODE_SRIOV: return "switchdev";
0011 case MLX5_LAG_MODE_MULTIPATH: return "multipath";
0012 case MLX5_LAG_MODE_MPESW: return "multiport_eswitch";
0013 default: return "invalid";
0014 }
0015
0016 return NULL;
0017 }
0018
0019 static int type_show(struct seq_file *file, void *priv)
0020 {
0021 struct mlx5_core_dev *dev = file->private;
0022 struct mlx5_lag *ldev;
0023 char *mode = NULL;
0024
0025 ldev = dev->priv.lag;
0026 mutex_lock(&ldev->lock);
0027 if (__mlx5_lag_is_active(ldev))
0028 mode = get_str_mode_type(ldev);
0029 mutex_unlock(&ldev->lock);
0030 if (!mode)
0031 return -EINVAL;
0032 seq_printf(file, "%s\n", mode);
0033
0034 return 0;
0035 }
0036
0037 static int port_sel_mode_show(struct seq_file *file, void *priv)
0038 {
0039 struct mlx5_core_dev *dev = file->private;
0040 struct mlx5_lag *ldev;
0041 int ret = 0;
0042 char *mode;
0043
0044 ldev = dev->priv.lag;
0045 mutex_lock(&ldev->lock);
0046 if (__mlx5_lag_is_active(ldev))
0047 mode = mlx5_get_str_port_sel_mode(ldev->mode, ldev->mode_flags);
0048 else
0049 ret = -EINVAL;
0050 mutex_unlock(&ldev->lock);
0051 if (ret)
0052 return ret;
0053
0054 seq_printf(file, "%s\n", mode);
0055 return 0;
0056 }
0057
0058 static int state_show(struct seq_file *file, void *priv)
0059 {
0060 struct mlx5_core_dev *dev = file->private;
0061 struct mlx5_lag *ldev;
0062 bool active;
0063
0064 ldev = dev->priv.lag;
0065 mutex_lock(&ldev->lock);
0066 active = __mlx5_lag_is_active(ldev);
0067 mutex_unlock(&ldev->lock);
0068 seq_printf(file, "%s\n", active ? "active" : "disabled");
0069 return 0;
0070 }
0071
0072 static int flags_show(struct seq_file *file, void *priv)
0073 {
0074 struct mlx5_core_dev *dev = file->private;
0075 bool fdb_sel_mode_native;
0076 struct mlx5_lag *ldev;
0077 bool shared_fdb;
0078 bool lag_active;
0079
0080 ldev = dev->priv.lag;
0081 mutex_lock(&ldev->lock);
0082 lag_active = __mlx5_lag_is_active(ldev);
0083 if (!lag_active)
0084 goto unlock;
0085
0086 shared_fdb = test_bit(MLX5_LAG_MODE_FLAG_SHARED_FDB, &ldev->mode_flags);
0087 fdb_sel_mode_native = test_bit(MLX5_LAG_MODE_FLAG_FDB_SEL_MODE_NATIVE,
0088 &ldev->mode_flags);
0089
0090 unlock:
0091 mutex_unlock(&ldev->lock);
0092 if (!lag_active)
0093 return -EINVAL;
0094
0095 seq_printf(file, "%s:%s\n", "shared_fdb", shared_fdb ? "on" : "off");
0096 seq_printf(file, "%s:%s\n", "fdb_selection_mode",
0097 fdb_sel_mode_native ? "native" : "affinity");
0098 return 0;
0099 }
0100
0101 static int mapping_show(struct seq_file *file, void *priv)
0102 {
0103 struct mlx5_core_dev *dev = file->private;
0104 u8 ports[MLX5_MAX_PORTS] = {};
0105 struct mlx5_lag *ldev;
0106 bool hash = false;
0107 bool lag_active;
0108 int num_ports;
0109 int i;
0110
0111 ldev = dev->priv.lag;
0112 mutex_lock(&ldev->lock);
0113 lag_active = __mlx5_lag_is_active(ldev);
0114 if (lag_active) {
0115 if (test_bit(MLX5_LAG_MODE_FLAG_HASH_BASED, &ldev->mode_flags)) {
0116 mlx5_infer_tx_enabled(&ldev->tracker, ldev->ports, ports,
0117 &num_ports);
0118 hash = true;
0119 } else {
0120 for (i = 0; i < ldev->ports; i++)
0121 ports[i] = ldev->v2p_map[i];
0122 num_ports = ldev->ports;
0123 }
0124 }
0125 mutex_unlock(&ldev->lock);
0126 if (!lag_active)
0127 return -EINVAL;
0128
0129 for (i = 0; i < num_ports; i++) {
0130 if (hash)
0131 seq_printf(file, "%d\n", ports[i] + 1);
0132 else
0133 seq_printf(file, "%d:%d\n", i + 1, ports[i]);
0134 }
0135
0136 return 0;
0137 }
0138
0139 static int members_show(struct seq_file *file, void *priv)
0140 {
0141 struct mlx5_core_dev *dev = file->private;
0142 struct mlx5_lag *ldev;
0143 int i;
0144
0145 ldev = dev->priv.lag;
0146 mutex_lock(&ldev->lock);
0147 for (i = 0; i < ldev->ports; i++) {
0148 if (!ldev->pf[i].dev)
0149 continue;
0150 seq_printf(file, "%s\n", dev_name(ldev->pf[i].dev->device));
0151 }
0152 mutex_unlock(&ldev->lock);
0153
0154 return 0;
0155 }
0156
0157 DEFINE_SHOW_ATTRIBUTE(type);
0158 DEFINE_SHOW_ATTRIBUTE(port_sel_mode);
0159 DEFINE_SHOW_ATTRIBUTE(state);
0160 DEFINE_SHOW_ATTRIBUTE(flags);
0161 DEFINE_SHOW_ATTRIBUTE(mapping);
0162 DEFINE_SHOW_ATTRIBUTE(members);
0163
0164 void mlx5_ldev_add_debugfs(struct mlx5_core_dev *dev)
0165 {
0166 struct dentry *dbg;
0167
0168 dbg = debugfs_create_dir("lag", mlx5_debugfs_get_dev_root(dev));
0169 dev->priv.dbg.lag_debugfs = dbg;
0170
0171 debugfs_create_file("type", 0444, dbg, dev, &type_fops);
0172 debugfs_create_file("port_sel_mode", 0444, dbg, dev, &port_sel_mode_fops);
0173 debugfs_create_file("state", 0444, dbg, dev, &state_fops);
0174 debugfs_create_file("flags", 0444, dbg, dev, &flags_fops);
0175 debugfs_create_file("mapping", 0444, dbg, dev, &mapping_fops);
0176 debugfs_create_file("members", 0444, dbg, dev, &members_fops);
0177 }
0178
0179 void mlx5_ldev_remove_debugfs(struct dentry *dbg)
0180 {
0181 debugfs_remove_recursive(dbg);
0182 }