Commit | Line | Data |
---|---|---|
56ade8fe JP |
1 | /* |
2 | * drivers/net/ethernet/mellanox/mlxsw/spectrum.h | |
3 | * Copyright (c) 2015 Mellanox Technologies. All rights reserved. | |
4 | * Copyright (c) 2015 Jiri Pirko <jiri@mellanox.com> | |
5 | * Copyright (c) 2015 Ido Schimmel <idosch@mellanox.com> | |
6 | * Copyright (c) 2015 Elad Raz <eladr@mellanox.com> | |
7 | * | |
8 | * Redistribution and use in source and binary forms, with or without | |
9 | * modification, are permitted provided that the following conditions are met: | |
10 | * | |
11 | * 1. Redistributions of source code must retain the above copyright | |
12 | * notice, this list of conditions and the following disclaimer. | |
13 | * 2. Redistributions in binary form must reproduce the above copyright | |
14 | * notice, this list of conditions and the following disclaimer in the | |
15 | * documentation and/or other materials provided with the distribution. | |
16 | * 3. Neither the names of the copyright holders nor the names of its | |
17 | * contributors may be used to endorse or promote products derived from | |
18 | * this software without specific prior written permission. | |
19 | * | |
20 | * Alternatively, this software may be distributed under the terms of the | |
21 | * GNU General Public License ("GPL") version 2 as published by the Free | |
22 | * Software Foundation. | |
23 | * | |
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | |
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
34 | * POSSIBILITY OF SUCH DAMAGE. | |
35 | */ | |
36 | ||
37 | #ifndef _MLXSW_SPECTRUM_H | |
38 | #define _MLXSW_SPECTRUM_H | |
39 | ||
40 | #include <linux/types.h> | |
41 | #include <linux/netdevice.h> | |
42 | #include <linux/bitops.h> | |
43 | #include <linux/if_vlan.h> | |
7f71eb46 | 44 | #include <linux/list.h> |
8e8dfe9f | 45 | #include <linux/dcbnl.h> |
56ade8fe | 46 | #include <net/switchdev.h> |
c4745500 | 47 | #include <net/devlink.h> |
56ade8fe | 48 | |
3a49b4fd | 49 | #include "port.h" |
56ade8fe JP |
50 | #include "core.h" |
51 | ||
52 | #define MLXSW_SP_VFID_BASE VLAN_N_VID | |
7f71eb46 | 53 | #define MLXSW_SP_VFID_PORT_MAX 512 /* Non-bridged VLAN interfaces */ |
b555cf4a | 54 | #define MLXSW_SP_VFID_BR_MAX 6144 /* Bridged VLAN interfaces */ |
7f71eb46 IS |
55 | #define MLXSW_SP_VFID_MAX (MLXSW_SP_VFID_PORT_MAX + MLXSW_SP_VFID_BR_MAX) |
56 | ||
0d65fc13 JP |
57 | #define MLXSW_SP_LAG_MAX 64 |
58 | #define MLXSW_SP_PORT_PER_LAG_MAX 16 | |
56ade8fe | 59 | |
53ae6283 ER |
60 | #define MLXSW_SP_MID_MAX 7000 |
61 | ||
18f1e70c IS |
62 | #define MLXSW_SP_PORTS_PER_CLUSTER_MAX 4 |
63 | ||
64 | #define MLXSW_SP_PORT_BASE_SPEED 25000 /* Mb/s */ | |
65 | ||
1a198449 IS |
66 | #define MLXSW_SP_BYTES_PER_CELL 96 |
67 | ||
68 | #define MLXSW_SP_BYTES_TO_CELLS(b) DIV_ROUND_UP(b, MLXSW_SP_BYTES_PER_CELL) | |
69 | ||
56ade8fe JP |
70 | struct mlxsw_sp_port; |
71 | ||
0d65fc13 JP |
72 | struct mlxsw_sp_upper { |
73 | struct net_device *dev; | |
74 | unsigned int ref_count; | |
75 | }; | |
76 | ||
7f71eb46 IS |
77 | struct mlxsw_sp_vfid { |
78 | struct list_head list; | |
79 | u16 nr_vports; | |
80 | u16 vfid; /* Starting at 0 */ | |
26f0e7fb | 81 | struct net_device *br_dev; |
7f71eb46 IS |
82 | u16 vid; |
83 | }; | |
84 | ||
3a49b4fd ER |
85 | struct mlxsw_sp_mid { |
86 | struct list_head list; | |
87 | unsigned char addr[ETH_ALEN]; | |
88 | u16 vid; | |
89 | u16 mid; | |
90 | unsigned int ref_count; | |
91 | }; | |
92 | ||
7f71eb46 IS |
93 | static inline u16 mlxsw_sp_vfid_to_fid(u16 vfid) |
94 | { | |
95 | return MLXSW_SP_VFID_BASE + vfid; | |
96 | } | |
97 | ||
aac78a44 IS |
98 | static inline u16 mlxsw_sp_fid_to_vfid(u16 fid) |
99 | { | |
100 | return fid - MLXSW_SP_VFID_BASE; | |
101 | } | |
102 | ||
103 | static inline bool mlxsw_sp_fid_is_vfid(u16 fid) | |
104 | { | |
105 | return fid >= MLXSW_SP_VFID_BASE; | |
106 | } | |
107 | ||
56ade8fe | 108 | struct mlxsw_sp { |
7f71eb46 IS |
109 | struct { |
110 | struct list_head list; | |
111 | unsigned long mapped[BITS_TO_LONGS(MLXSW_SP_VFID_PORT_MAX)]; | |
112 | } port_vfids; | |
26f0e7fb IS |
113 | struct { |
114 | struct list_head list; | |
115 | unsigned long mapped[BITS_TO_LONGS(MLXSW_SP_VFID_BR_MAX)]; | |
116 | } br_vfids; | |
3a49b4fd ER |
117 | struct { |
118 | struct list_head list; | |
119 | unsigned long mapped[BITS_TO_LONGS(MLXSW_SP_MID_MAX)]; | |
120 | } br_mids; | |
56ade8fe JP |
121 | unsigned long active_fids[BITS_TO_LONGS(VLAN_N_VID)]; |
122 | struct mlxsw_sp_port **ports; | |
123 | struct mlxsw_core *core; | |
124 | const struct mlxsw_bus_info *bus_info; | |
125 | unsigned char base_mac[ETH_ALEN]; | |
126 | struct { | |
127 | struct delayed_work dw; | |
128 | #define MLXSW_SP_DEFAULT_LEARNING_INTERVAL 100 | |
129 | unsigned int interval; /* ms */ | |
130 | } fdb_notify; | |
869f63a4 IS |
131 | #define MLXSW_SP_MIN_AGEING_TIME 10 |
132 | #define MLXSW_SP_MAX_AGEING_TIME 1000000 | |
56ade8fe JP |
133 | #define MLXSW_SP_DEFAULT_AGEING_TIME 300 |
134 | u32 ageing_time; | |
0d65fc13 JP |
135 | struct mlxsw_sp_upper master_bridge; |
136 | struct mlxsw_sp_upper lags[MLXSW_SP_LAG_MAX]; | |
558c2d5e | 137 | u8 port_to_module[MLXSW_PORT_MAX_PORTS]; |
56ade8fe JP |
138 | }; |
139 | ||
0d65fc13 JP |
140 | static inline struct mlxsw_sp_upper * |
141 | mlxsw_sp_lag_get(struct mlxsw_sp *mlxsw_sp, u16 lag_id) | |
142 | { | |
143 | return &mlxsw_sp->lags[lag_id]; | |
144 | } | |
145 | ||
56ade8fe JP |
146 | struct mlxsw_sp_port_pcpu_stats { |
147 | u64 rx_packets; | |
148 | u64 rx_bytes; | |
149 | u64 tx_packets; | |
150 | u64 tx_bytes; | |
151 | struct u64_stats_sync syncp; | |
152 | u32 tx_dropped; | |
153 | }; | |
154 | ||
155 | struct mlxsw_sp_port { | |
156 | struct net_device *dev; | |
157 | struct mlxsw_sp_port_pcpu_stats __percpu *pcpu_stats; | |
158 | struct mlxsw_sp *mlxsw_sp; | |
159 | u8 local_port; | |
160 | u8 stp_state; | |
0d9b970c JP |
161 | u8 learning:1, |
162 | learning_sync:1, | |
0293038e | 163 | uc_flood:1, |
0d65fc13 | 164 | bridged:1, |
18f1e70c IS |
165 | lagged:1, |
166 | split:1; | |
56ade8fe | 167 | u16 pvid; |
0d65fc13 | 168 | u16 lag_id; |
7f71eb46 IS |
169 | struct { |
170 | struct list_head list; | |
171 | struct mlxsw_sp_vfid *vfid; | |
172 | u16 vid; | |
173 | } vport; | |
8e8dfe9f IS |
174 | struct { |
175 | struct ieee_ets *ets; | |
176 | } dcb; | |
56ade8fe | 177 | /* 802.1Q bridge VLANs */ |
bd40e9d6 | 178 | unsigned long *active_vlans; |
fc1273af | 179 | unsigned long *untagged_vlans; |
56ade8fe | 180 | /* VLAN interfaces */ |
7f71eb46 | 181 | struct list_head vports_list; |
c4745500 | 182 | struct devlink_port devlink_port; |
56ade8fe JP |
183 | }; |
184 | ||
0d65fc13 JP |
185 | static inline struct mlxsw_sp_port * |
186 | mlxsw_sp_port_lagged_get(struct mlxsw_sp *mlxsw_sp, u16 lag_id, u8 port_index) | |
187 | { | |
188 | struct mlxsw_sp_port *mlxsw_sp_port; | |
189 | u8 local_port; | |
190 | ||
191 | local_port = mlxsw_core_lag_mapping_get(mlxsw_sp->core, | |
192 | lag_id, port_index); | |
193 | mlxsw_sp_port = mlxsw_sp->ports[local_port]; | |
194 | return mlxsw_sp_port && mlxsw_sp_port->lagged ? mlxsw_sp_port : NULL; | |
195 | } | |
196 | ||
7f71eb46 IS |
197 | static inline bool |
198 | mlxsw_sp_port_is_vport(const struct mlxsw_sp_port *mlxsw_sp_port) | |
199 | { | |
200 | return mlxsw_sp_port->vport.vfid; | |
201 | } | |
202 | ||
26f0e7fb IS |
203 | static inline struct net_device * |
204 | mlxsw_sp_vport_br_get(const struct mlxsw_sp_port *mlxsw_sp_vport) | |
205 | { | |
206 | return mlxsw_sp_vport->vport.vfid->br_dev; | |
207 | } | |
208 | ||
7f71eb46 IS |
209 | static inline u16 |
210 | mlxsw_sp_vport_vid_get(const struct mlxsw_sp_port *mlxsw_sp_vport) | |
211 | { | |
212 | return mlxsw_sp_vport->vport.vid; | |
213 | } | |
214 | ||
215 | static inline u16 | |
216 | mlxsw_sp_vport_vfid_get(const struct mlxsw_sp_port *mlxsw_sp_vport) | |
217 | { | |
218 | return mlxsw_sp_vport->vport.vfid->vfid; | |
219 | } | |
220 | ||
221 | static inline struct mlxsw_sp_port * | |
222 | mlxsw_sp_port_vport_find(const struct mlxsw_sp_port *mlxsw_sp_port, u16 vid) | |
223 | { | |
224 | struct mlxsw_sp_port *mlxsw_sp_vport; | |
225 | ||
226 | list_for_each_entry(mlxsw_sp_vport, &mlxsw_sp_port->vports_list, | |
227 | vport.list) { | |
228 | if (mlxsw_sp_vport_vid_get(mlxsw_sp_vport) == vid) | |
229 | return mlxsw_sp_vport; | |
230 | } | |
231 | ||
232 | return NULL; | |
233 | } | |
234 | ||
aac78a44 IS |
235 | static inline struct mlxsw_sp_port * |
236 | mlxsw_sp_port_vport_find_by_vfid(const struct mlxsw_sp_port *mlxsw_sp_port, | |
237 | u16 vfid) | |
238 | { | |
239 | struct mlxsw_sp_port *mlxsw_sp_vport; | |
240 | ||
241 | list_for_each_entry(mlxsw_sp_vport, &mlxsw_sp_port->vports_list, | |
242 | vport.list) { | |
243 | if (mlxsw_sp_vport_vfid_get(mlxsw_sp_vport) == vfid) | |
244 | return mlxsw_sp_vport; | |
245 | } | |
246 | ||
247 | return NULL; | |
248 | } | |
249 | ||
56ade8fe JP |
250 | enum mlxsw_sp_flood_table { |
251 | MLXSW_SP_FLOOD_TABLE_UC, | |
252 | MLXSW_SP_FLOOD_TABLE_BM, | |
253 | }; | |
254 | ||
255 | int mlxsw_sp_buffers_init(struct mlxsw_sp *mlxsw_sp); | |
256 | int mlxsw_sp_port_buffers_init(struct mlxsw_sp_port *mlxsw_sp_port); | |
257 | ||
258 | int mlxsw_sp_switchdev_init(struct mlxsw_sp *mlxsw_sp); | |
259 | void mlxsw_sp_switchdev_fini(struct mlxsw_sp *mlxsw_sp); | |
260 | int mlxsw_sp_port_vlan_init(struct mlxsw_sp_port *mlxsw_sp_port); | |
261 | void mlxsw_sp_port_switchdev_init(struct mlxsw_sp_port *mlxsw_sp_port); | |
262 | void mlxsw_sp_port_switchdev_fini(struct mlxsw_sp_port *mlxsw_sp_port); | |
263 | int mlxsw_sp_port_vid_to_fid_set(struct mlxsw_sp_port *mlxsw_sp_port, | |
264 | enum mlxsw_reg_svfa_mt mt, bool valid, u16 fid, | |
265 | u16 vid); | |
266 | int mlxsw_sp_port_vlan_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid_begin, | |
267 | u16 vid_end, bool is_member, bool untagged); | |
268 | int mlxsw_sp_port_add_vid(struct net_device *dev, __be16 __always_unused proto, | |
269 | u16 vid); | |
270 | int mlxsw_sp_port_kill_vid(struct net_device *dev, | |
271 | __be16 __always_unused proto, u16 vid); | |
7f71eb46 | 272 | int mlxsw_sp_vport_flood_set(struct mlxsw_sp_port *mlxsw_sp_vport, u16 vfid, |
19ae6124 | 273 | bool set, bool only_uc); |
4dc236c3 | 274 | void mlxsw_sp_port_active_vlans_del(struct mlxsw_sp_port *mlxsw_sp_port); |
28a01d2d | 275 | int mlxsw_sp_port_pvid_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid); |
8e8dfe9f IS |
276 | int mlxsw_sp_port_ets_set(struct mlxsw_sp_port *mlxsw_sp_port, |
277 | enum mlxsw_reg_qeec_hr hr, u8 index, u8 next_index, | |
278 | bool dwrr, u8 dwrr_weight); | |
279 | int mlxsw_sp_port_prio_tc_set(struct mlxsw_sp_port *mlxsw_sp_port, | |
280 | u8 switch_prio, u8 tclass); | |
281 | int __mlxsw_sp_port_headroom_set(struct mlxsw_sp_port *mlxsw_sp_port, int mtu, | |
282 | u8 *prio_tc); | |
56ade8fe | 283 | |
f00817df IS |
284 | #ifdef CONFIG_MLXSW_SPECTRUM_DCB |
285 | ||
286 | int mlxsw_sp_port_dcb_init(struct mlxsw_sp_port *mlxsw_sp_port); | |
287 | void mlxsw_sp_port_dcb_fini(struct mlxsw_sp_port *mlxsw_sp_port); | |
288 | ||
289 | #else | |
290 | ||
291 | static inline int mlxsw_sp_port_dcb_init(struct mlxsw_sp_port *mlxsw_sp_port) | |
292 | { | |
293 | return 0; | |
294 | } | |
295 | ||
296 | static inline void mlxsw_sp_port_dcb_fini(struct mlxsw_sp_port *mlxsw_sp_port) | |
297 | {} | |
298 | ||
299 | #endif | |
300 | ||
56ade8fe | 301 | #endif |