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