Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
0002 /* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */
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 }