mlxsw: spectrum: Add mlxsw_sp_span_ops.buffsize_get for Spectrum-3
[linux-2.6-microblaze.git] / drivers / net / ethernet / mellanox / mlxsw / spectrum.c
1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /* Copyright (c) 2015-2018 Mellanox Technologies. All rights reserved */
3
4 #include <linux/kernel.h>
5 #include <linux/module.h>
6 #include <linux/types.h>
7 #include <linux/pci.h>
8 #include <linux/netdevice.h>
9 #include <linux/etherdevice.h>
10 #include <linux/ethtool.h>
11 #include <linux/slab.h>
12 #include <linux/device.h>
13 #include <linux/skbuff.h>
14 #include <linux/if_vlan.h>
15 #include <linux/if_bridge.h>
16 #include <linux/workqueue.h>
17 #include <linux/jiffies.h>
18 #include <linux/bitops.h>
19 #include <linux/list.h>
20 #include <linux/notifier.h>
21 #include <linux/dcbnl.h>
22 #include <linux/inetdevice.h>
23 #include <linux/netlink.h>
24 #include <linux/jhash.h>
25 #include <linux/log2.h>
26 #include <net/switchdev.h>
27 #include <net/pkt_cls.h>
28 #include <net/tc_act/tc_mirred.h>
29 #include <net/netevent.h>
30 #include <net/tc_act/tc_sample.h>
31 #include <net/addrconf.h>
32
33 #include "spectrum.h"
34 #include "pci.h"
35 #include "core.h"
36 #include "core_env.h"
37 #include "reg.h"
38 #include "port.h"
39 #include "trap.h"
40 #include "txheader.h"
41 #include "spectrum_cnt.h"
42 #include "spectrum_dpipe.h"
43 #include "spectrum_acl_flex_actions.h"
44 #include "spectrum_span.h"
45 #include "spectrum_ptp.h"
46 #include "../mlxfw/mlxfw.h"
47
48 #define MLXSW_SP1_FWREV_MAJOR 13
49 #define MLXSW_SP1_FWREV_MINOR 2000
50 #define MLXSW_SP1_FWREV_SUBMINOR 2714
51 #define MLXSW_SP1_FWREV_CAN_RESET_MINOR 1702
52
53 static const struct mlxsw_fw_rev mlxsw_sp1_fw_rev = {
54         .major = MLXSW_SP1_FWREV_MAJOR,
55         .minor = MLXSW_SP1_FWREV_MINOR,
56         .subminor = MLXSW_SP1_FWREV_SUBMINOR,
57         .can_reset_minor = MLXSW_SP1_FWREV_CAN_RESET_MINOR,
58 };
59
60 #define MLXSW_SP1_FW_FILENAME \
61         "mellanox/mlxsw_spectrum-" __stringify(MLXSW_SP1_FWREV_MAJOR) \
62         "." __stringify(MLXSW_SP1_FWREV_MINOR) \
63         "." __stringify(MLXSW_SP1_FWREV_SUBMINOR) ".mfa2"
64
65 #define MLXSW_SP2_FWREV_MAJOR 29
66 #define MLXSW_SP2_FWREV_MINOR 2000
67 #define MLXSW_SP2_FWREV_SUBMINOR 2714
68
69 static const struct mlxsw_fw_rev mlxsw_sp2_fw_rev = {
70         .major = MLXSW_SP2_FWREV_MAJOR,
71         .minor = MLXSW_SP2_FWREV_MINOR,
72         .subminor = MLXSW_SP2_FWREV_SUBMINOR,
73 };
74
75 #define MLXSW_SP2_FW_FILENAME \
76         "mellanox/mlxsw_spectrum2-" __stringify(MLXSW_SP2_FWREV_MAJOR) \
77         "." __stringify(MLXSW_SP2_FWREV_MINOR) \
78         "." __stringify(MLXSW_SP2_FWREV_SUBMINOR) ".mfa2"
79
80 static const char mlxsw_sp1_driver_name[] = "mlxsw_spectrum";
81 static const char mlxsw_sp2_driver_name[] = "mlxsw_spectrum2";
82 static const char mlxsw_sp3_driver_name[] = "mlxsw_spectrum3";
83 static const char mlxsw_sp_driver_version[] = "1.0";
84
85 static const unsigned char mlxsw_sp1_mac_mask[ETH_ALEN] = {
86         0xff, 0xff, 0xff, 0xff, 0xfc, 0x00
87 };
88 static const unsigned char mlxsw_sp2_mac_mask[ETH_ALEN] = {
89         0xff, 0xff, 0xff, 0xff, 0xf0, 0x00
90 };
91
92 /* tx_hdr_version
93  * Tx header version.
94  * Must be set to 1.
95  */
96 MLXSW_ITEM32(tx, hdr, version, 0x00, 28, 4);
97
98 /* tx_hdr_ctl
99  * Packet control type.
100  * 0 - Ethernet control (e.g. EMADs, LACP)
101  * 1 - Ethernet data
102  */
103 MLXSW_ITEM32(tx, hdr, ctl, 0x00, 26, 2);
104
105 /* tx_hdr_proto
106  * Packet protocol type. Must be set to 1 (Ethernet).
107  */
108 MLXSW_ITEM32(tx, hdr, proto, 0x00, 21, 3);
109
110 /* tx_hdr_rx_is_router
111  * Packet is sent from the router. Valid for data packets only.
112  */
113 MLXSW_ITEM32(tx, hdr, rx_is_router, 0x00, 19, 1);
114
115 /* tx_hdr_fid_valid
116  * Indicates if the 'fid' field is valid and should be used for
117  * forwarding lookup. Valid for data packets only.
118  */
119 MLXSW_ITEM32(tx, hdr, fid_valid, 0x00, 16, 1);
120
121 /* tx_hdr_swid
122  * Switch partition ID. Must be set to 0.
123  */
124 MLXSW_ITEM32(tx, hdr, swid, 0x00, 12, 3);
125
126 /* tx_hdr_control_tclass
127  * Indicates if the packet should use the control TClass and not one
128  * of the data TClasses.
129  */
130 MLXSW_ITEM32(tx, hdr, control_tclass, 0x00, 6, 1);
131
132 /* tx_hdr_etclass
133  * Egress TClass to be used on the egress device on the egress port.
134  */
135 MLXSW_ITEM32(tx, hdr, etclass, 0x00, 0, 4);
136
137 /* tx_hdr_port_mid
138  * Destination local port for unicast packets.
139  * Destination multicast ID for multicast packets.
140  *
141  * Control packets are directed to a specific egress port, while data
142  * packets are transmitted through the CPU port (0) into the switch partition,
143  * where forwarding rules are applied.
144  */
145 MLXSW_ITEM32(tx, hdr, port_mid, 0x04, 16, 16);
146
147 /* tx_hdr_fid
148  * Forwarding ID used for L2 forwarding lookup. Valid only if 'fid_valid' is
149  * set, otherwise calculated based on the packet's VID using VID to FID mapping.
150  * Valid for data packets only.
151  */
152 MLXSW_ITEM32(tx, hdr, fid, 0x08, 0, 16);
153
154 /* tx_hdr_type
155  * 0 - Data packets
156  * 6 - Control packets
157  */
158 MLXSW_ITEM32(tx, hdr, type, 0x0C, 0, 4);
159
160 struct mlxsw_sp_mlxfw_dev {
161         struct mlxfw_dev mlxfw_dev;
162         struct mlxsw_sp *mlxsw_sp;
163 };
164
165 struct mlxsw_sp_ptp_ops {
166         struct mlxsw_sp_ptp_clock *
167                 (*clock_init)(struct mlxsw_sp *mlxsw_sp, struct device *dev);
168         void (*clock_fini)(struct mlxsw_sp_ptp_clock *clock);
169
170         struct mlxsw_sp_ptp_state *(*init)(struct mlxsw_sp *mlxsw_sp);
171         void (*fini)(struct mlxsw_sp_ptp_state *ptp_state);
172
173         /* Notify a driver that a packet that might be PTP was received. Driver
174          * is responsible for freeing the passed-in SKB.
175          */
176         void (*receive)(struct mlxsw_sp *mlxsw_sp, struct sk_buff *skb,
177                         u8 local_port);
178
179         /* Notify a driver that a timestamped packet was transmitted. Driver
180          * is responsible for freeing the passed-in SKB.
181          */
182         void (*transmitted)(struct mlxsw_sp *mlxsw_sp, struct sk_buff *skb,
183                             u8 local_port);
184
185         int (*hwtstamp_get)(struct mlxsw_sp_port *mlxsw_sp_port,
186                             struct hwtstamp_config *config);
187         int (*hwtstamp_set)(struct mlxsw_sp_port *mlxsw_sp_port,
188                             struct hwtstamp_config *config);
189         void (*shaper_work)(struct work_struct *work);
190         int (*get_ts_info)(struct mlxsw_sp *mlxsw_sp,
191                            struct ethtool_ts_info *info);
192         int (*get_stats_count)(void);
193         void (*get_stats_strings)(u8 **p);
194         void (*get_stats)(struct mlxsw_sp_port *mlxsw_sp_port,
195                           u64 *data, int data_index);
196 };
197
198 struct mlxsw_sp_span_ops {
199         u32 (*buffsize_get)(int mtu, u32 speed);
200 };
201
202 static int mlxsw_sp_component_query(struct mlxfw_dev *mlxfw_dev,
203                                     u16 component_index, u32 *p_max_size,
204                                     u8 *p_align_bits, u16 *p_max_write_size)
205 {
206         struct mlxsw_sp_mlxfw_dev *mlxsw_sp_mlxfw_dev =
207                 container_of(mlxfw_dev, struct mlxsw_sp_mlxfw_dev, mlxfw_dev);
208         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_mlxfw_dev->mlxsw_sp;
209         char mcqi_pl[MLXSW_REG_MCQI_LEN];
210         int err;
211
212         mlxsw_reg_mcqi_pack(mcqi_pl, component_index);
213         err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(mcqi), mcqi_pl);
214         if (err)
215                 return err;
216         mlxsw_reg_mcqi_unpack(mcqi_pl, p_max_size, p_align_bits,
217                               p_max_write_size);
218
219         *p_align_bits = max_t(u8, *p_align_bits, 2);
220         *p_max_write_size = min_t(u16, *p_max_write_size,
221                                   MLXSW_REG_MCDA_MAX_DATA_LEN);
222         return 0;
223 }
224
225 static int mlxsw_sp_fsm_lock(struct mlxfw_dev *mlxfw_dev, u32 *fwhandle)
226 {
227         struct mlxsw_sp_mlxfw_dev *mlxsw_sp_mlxfw_dev =
228                 container_of(mlxfw_dev, struct mlxsw_sp_mlxfw_dev, mlxfw_dev);
229         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_mlxfw_dev->mlxsw_sp;
230         char mcc_pl[MLXSW_REG_MCC_LEN];
231         u8 control_state;
232         int err;
233
234         mlxsw_reg_mcc_pack(mcc_pl, 0, 0, 0, 0);
235         err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(mcc), mcc_pl);
236         if (err)
237                 return err;
238
239         mlxsw_reg_mcc_unpack(mcc_pl, fwhandle, NULL, &control_state);
240         if (control_state != MLXFW_FSM_STATE_IDLE)
241                 return -EBUSY;
242
243         mlxsw_reg_mcc_pack(mcc_pl,
244                            MLXSW_REG_MCC_INSTRUCTION_LOCK_UPDATE_HANDLE,
245                            0, *fwhandle, 0);
246         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mcc), mcc_pl);
247 }
248
249 static int mlxsw_sp_fsm_component_update(struct mlxfw_dev *mlxfw_dev,
250                                          u32 fwhandle, u16 component_index,
251                                          u32 component_size)
252 {
253         struct mlxsw_sp_mlxfw_dev *mlxsw_sp_mlxfw_dev =
254                 container_of(mlxfw_dev, struct mlxsw_sp_mlxfw_dev, mlxfw_dev);
255         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_mlxfw_dev->mlxsw_sp;
256         char mcc_pl[MLXSW_REG_MCC_LEN];
257
258         mlxsw_reg_mcc_pack(mcc_pl, MLXSW_REG_MCC_INSTRUCTION_UPDATE_COMPONENT,
259                            component_index, fwhandle, component_size);
260         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mcc), mcc_pl);
261 }
262
263 static int mlxsw_sp_fsm_block_download(struct mlxfw_dev *mlxfw_dev,
264                                        u32 fwhandle, u8 *data, u16 size,
265                                        u32 offset)
266 {
267         struct mlxsw_sp_mlxfw_dev *mlxsw_sp_mlxfw_dev =
268                 container_of(mlxfw_dev, struct mlxsw_sp_mlxfw_dev, mlxfw_dev);
269         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_mlxfw_dev->mlxsw_sp;
270         char mcda_pl[MLXSW_REG_MCDA_LEN];
271
272         mlxsw_reg_mcda_pack(mcda_pl, fwhandle, offset, size, data);
273         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mcda), mcda_pl);
274 }
275
276 static int mlxsw_sp_fsm_component_verify(struct mlxfw_dev *mlxfw_dev,
277                                          u32 fwhandle, u16 component_index)
278 {
279         struct mlxsw_sp_mlxfw_dev *mlxsw_sp_mlxfw_dev =
280                 container_of(mlxfw_dev, struct mlxsw_sp_mlxfw_dev, mlxfw_dev);
281         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_mlxfw_dev->mlxsw_sp;
282         char mcc_pl[MLXSW_REG_MCC_LEN];
283
284         mlxsw_reg_mcc_pack(mcc_pl, MLXSW_REG_MCC_INSTRUCTION_VERIFY_COMPONENT,
285                            component_index, fwhandle, 0);
286         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mcc), mcc_pl);
287 }
288
289 static int mlxsw_sp_fsm_activate(struct mlxfw_dev *mlxfw_dev, u32 fwhandle)
290 {
291         struct mlxsw_sp_mlxfw_dev *mlxsw_sp_mlxfw_dev =
292                 container_of(mlxfw_dev, struct mlxsw_sp_mlxfw_dev, mlxfw_dev);
293         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_mlxfw_dev->mlxsw_sp;
294         char mcc_pl[MLXSW_REG_MCC_LEN];
295
296         mlxsw_reg_mcc_pack(mcc_pl, MLXSW_REG_MCC_INSTRUCTION_ACTIVATE, 0,
297                            fwhandle, 0);
298         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mcc), mcc_pl);
299 }
300
301 static int mlxsw_sp_fsm_query_state(struct mlxfw_dev *mlxfw_dev, u32 fwhandle,
302                                     enum mlxfw_fsm_state *fsm_state,
303                                     enum mlxfw_fsm_state_err *fsm_state_err)
304 {
305         struct mlxsw_sp_mlxfw_dev *mlxsw_sp_mlxfw_dev =
306                 container_of(mlxfw_dev, struct mlxsw_sp_mlxfw_dev, mlxfw_dev);
307         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_mlxfw_dev->mlxsw_sp;
308         char mcc_pl[MLXSW_REG_MCC_LEN];
309         u8 control_state;
310         u8 error_code;
311         int err;
312
313         mlxsw_reg_mcc_pack(mcc_pl, 0, 0, fwhandle, 0);
314         err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(mcc), mcc_pl);
315         if (err)
316                 return err;
317
318         mlxsw_reg_mcc_unpack(mcc_pl, NULL, &error_code, &control_state);
319         *fsm_state = control_state;
320         *fsm_state_err = min_t(enum mlxfw_fsm_state_err, error_code,
321                                MLXFW_FSM_STATE_ERR_MAX);
322         return 0;
323 }
324
325 static void mlxsw_sp_fsm_cancel(struct mlxfw_dev *mlxfw_dev, u32 fwhandle)
326 {
327         struct mlxsw_sp_mlxfw_dev *mlxsw_sp_mlxfw_dev =
328                 container_of(mlxfw_dev, struct mlxsw_sp_mlxfw_dev, mlxfw_dev);
329         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_mlxfw_dev->mlxsw_sp;
330         char mcc_pl[MLXSW_REG_MCC_LEN];
331
332         mlxsw_reg_mcc_pack(mcc_pl, MLXSW_REG_MCC_INSTRUCTION_CANCEL, 0,
333                            fwhandle, 0);
334         mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mcc), mcc_pl);
335 }
336
337 static void mlxsw_sp_fsm_release(struct mlxfw_dev *mlxfw_dev, u32 fwhandle)
338 {
339         struct mlxsw_sp_mlxfw_dev *mlxsw_sp_mlxfw_dev =
340                 container_of(mlxfw_dev, struct mlxsw_sp_mlxfw_dev, mlxfw_dev);
341         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_mlxfw_dev->mlxsw_sp;
342         char mcc_pl[MLXSW_REG_MCC_LEN];
343
344         mlxsw_reg_mcc_pack(mcc_pl,
345                            MLXSW_REG_MCC_INSTRUCTION_RELEASE_UPDATE_HANDLE, 0,
346                            fwhandle, 0);
347         mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mcc), mcc_pl);
348 }
349
350 static const struct mlxfw_dev_ops mlxsw_sp_mlxfw_dev_ops = {
351         .component_query        = mlxsw_sp_component_query,
352         .fsm_lock               = mlxsw_sp_fsm_lock,
353         .fsm_component_update   = mlxsw_sp_fsm_component_update,
354         .fsm_block_download     = mlxsw_sp_fsm_block_download,
355         .fsm_component_verify   = mlxsw_sp_fsm_component_verify,
356         .fsm_activate           = mlxsw_sp_fsm_activate,
357         .fsm_query_state        = mlxsw_sp_fsm_query_state,
358         .fsm_cancel             = mlxsw_sp_fsm_cancel,
359         .fsm_release            = mlxsw_sp_fsm_release,
360 };
361
362 static int mlxsw_sp_firmware_flash(struct mlxsw_sp *mlxsw_sp,
363                                    const struct firmware *firmware,
364                                    struct netlink_ext_ack *extack)
365 {
366         struct mlxsw_sp_mlxfw_dev mlxsw_sp_mlxfw_dev = {
367                 .mlxfw_dev = {
368                         .ops = &mlxsw_sp_mlxfw_dev_ops,
369                         .psid = mlxsw_sp->bus_info->psid,
370                         .psid_size = strlen(mlxsw_sp->bus_info->psid),
371                         .devlink = priv_to_devlink(mlxsw_sp->core),
372                 },
373                 .mlxsw_sp = mlxsw_sp
374         };
375         int err;
376
377         mlxsw_core_fw_flash_start(mlxsw_sp->core);
378         err = mlxfw_firmware_flash(&mlxsw_sp_mlxfw_dev.mlxfw_dev,
379                                    firmware, extack);
380         mlxsw_core_fw_flash_end(mlxsw_sp->core);
381
382         return err;
383 }
384
385 static int mlxsw_sp_fw_rev_validate(struct mlxsw_sp *mlxsw_sp)
386 {
387         const struct mlxsw_fw_rev *rev = &mlxsw_sp->bus_info->fw_rev;
388         const struct mlxsw_fw_rev *req_rev = mlxsw_sp->req_rev;
389         const char *fw_filename = mlxsw_sp->fw_filename;
390         union devlink_param_value value;
391         const struct firmware *firmware;
392         int err;
393
394         /* Don't check if driver does not require it */
395         if (!req_rev || !fw_filename)
396                 return 0;
397
398         /* Don't check if devlink 'fw_load_policy' param is 'flash' */
399         err = devlink_param_driverinit_value_get(priv_to_devlink(mlxsw_sp->core),
400                                                  DEVLINK_PARAM_GENERIC_ID_FW_LOAD_POLICY,
401                                                  &value);
402         if (err)
403                 return err;
404         if (value.vu8 == DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_FLASH)
405                 return 0;
406
407         /* Validate driver & FW are compatible */
408         if (rev->major != req_rev->major) {
409                 WARN(1, "Mismatch in major FW version [%d:%d] is never expected; Please contact support\n",
410                      rev->major, req_rev->major);
411                 return -EINVAL;
412         }
413         if (mlxsw_core_fw_rev_minor_subminor_validate(rev, req_rev))
414                 return 0;
415
416         dev_err(mlxsw_sp->bus_info->dev, "The firmware version %d.%d.%d is incompatible with the driver (required >= %d.%d.%d)\n",
417                 rev->major, rev->minor, rev->subminor, req_rev->major,
418                 req_rev->minor, req_rev->subminor);
419         dev_info(mlxsw_sp->bus_info->dev, "Flashing firmware using file %s\n",
420                  fw_filename);
421
422         err = request_firmware_direct(&firmware, fw_filename,
423                                       mlxsw_sp->bus_info->dev);
424         if (err) {
425                 dev_err(mlxsw_sp->bus_info->dev, "Could not request firmware file %s\n",
426                         fw_filename);
427                 return err;
428         }
429
430         err = mlxsw_sp_firmware_flash(mlxsw_sp, firmware, NULL);
431         release_firmware(firmware);
432         if (err)
433                 dev_err(mlxsw_sp->bus_info->dev, "Could not upgrade firmware\n");
434
435         /* On FW flash success, tell the caller FW reset is needed
436          * if current FW supports it.
437          */
438         if (rev->minor >= req_rev->can_reset_minor)
439                 return err ? err : -EAGAIN;
440         else
441                 return 0;
442 }
443
444 static int mlxsw_sp_flash_update(struct mlxsw_core *mlxsw_core,
445                                  const char *file_name, const char *component,
446                                  struct netlink_ext_ack *extack)
447 {
448         struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
449         const struct firmware *firmware;
450         int err;
451
452         if (component)
453                 return -EOPNOTSUPP;
454
455         err = request_firmware_direct(&firmware, file_name,
456                                       mlxsw_sp->bus_info->dev);
457         if (err)
458                 return err;
459         err = mlxsw_sp_firmware_flash(mlxsw_sp, firmware, extack);
460         release_firmware(firmware);
461
462         return err;
463 }
464
465 int mlxsw_sp_flow_counter_get(struct mlxsw_sp *mlxsw_sp,
466                               unsigned int counter_index, u64 *packets,
467                               u64 *bytes)
468 {
469         char mgpc_pl[MLXSW_REG_MGPC_LEN];
470         int err;
471
472         mlxsw_reg_mgpc_pack(mgpc_pl, counter_index, MLXSW_REG_MGPC_OPCODE_NOP,
473                             MLXSW_REG_FLOW_COUNTER_SET_TYPE_PACKETS_BYTES);
474         err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(mgpc), mgpc_pl);
475         if (err)
476                 return err;
477         if (packets)
478                 *packets = mlxsw_reg_mgpc_packet_counter_get(mgpc_pl);
479         if (bytes)
480                 *bytes = mlxsw_reg_mgpc_byte_counter_get(mgpc_pl);
481         return 0;
482 }
483
484 static int mlxsw_sp_flow_counter_clear(struct mlxsw_sp *mlxsw_sp,
485                                        unsigned int counter_index)
486 {
487         char mgpc_pl[MLXSW_REG_MGPC_LEN];
488
489         mlxsw_reg_mgpc_pack(mgpc_pl, counter_index, MLXSW_REG_MGPC_OPCODE_CLEAR,
490                             MLXSW_REG_FLOW_COUNTER_SET_TYPE_PACKETS_BYTES);
491         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mgpc), mgpc_pl);
492 }
493
494 int mlxsw_sp_flow_counter_alloc(struct mlxsw_sp *mlxsw_sp,
495                                 unsigned int *p_counter_index)
496 {
497         int err;
498
499         err = mlxsw_sp_counter_alloc(mlxsw_sp, MLXSW_SP_COUNTER_SUB_POOL_FLOW,
500                                      p_counter_index);
501         if (err)
502                 return err;
503         err = mlxsw_sp_flow_counter_clear(mlxsw_sp, *p_counter_index);
504         if (err)
505                 goto err_counter_clear;
506         return 0;
507
508 err_counter_clear:
509         mlxsw_sp_counter_free(mlxsw_sp, MLXSW_SP_COUNTER_SUB_POOL_FLOW,
510                               *p_counter_index);
511         return err;
512 }
513
514 void mlxsw_sp_flow_counter_free(struct mlxsw_sp *mlxsw_sp,
515                                 unsigned int counter_index)
516 {
517          mlxsw_sp_counter_free(mlxsw_sp, MLXSW_SP_COUNTER_SUB_POOL_FLOW,
518                                counter_index);
519 }
520
521 static void mlxsw_sp_txhdr_construct(struct sk_buff *skb,
522                                      const struct mlxsw_tx_info *tx_info)
523 {
524         char *txhdr = skb_push(skb, MLXSW_TXHDR_LEN);
525
526         memset(txhdr, 0, MLXSW_TXHDR_LEN);
527
528         mlxsw_tx_hdr_version_set(txhdr, MLXSW_TXHDR_VERSION_1);
529         mlxsw_tx_hdr_ctl_set(txhdr, MLXSW_TXHDR_ETH_CTL);
530         mlxsw_tx_hdr_proto_set(txhdr, MLXSW_TXHDR_PROTO_ETH);
531         mlxsw_tx_hdr_swid_set(txhdr, 0);
532         mlxsw_tx_hdr_control_tclass_set(txhdr, 1);
533         mlxsw_tx_hdr_port_mid_set(txhdr, tx_info->local_port);
534         mlxsw_tx_hdr_type_set(txhdr, MLXSW_TXHDR_TYPE_CONTROL);
535 }
536
537 enum mlxsw_reg_spms_state mlxsw_sp_stp_spms_state(u8 state)
538 {
539         switch (state) {
540         case BR_STATE_FORWARDING:
541                 return MLXSW_REG_SPMS_STATE_FORWARDING;
542         case BR_STATE_LEARNING:
543                 return MLXSW_REG_SPMS_STATE_LEARNING;
544         case BR_STATE_LISTENING: /* fall-through */
545         case BR_STATE_DISABLED: /* fall-through */
546         case BR_STATE_BLOCKING:
547                 return MLXSW_REG_SPMS_STATE_DISCARDING;
548         default:
549                 BUG();
550         }
551 }
552
553 int mlxsw_sp_port_vid_stp_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid,
554                               u8 state)
555 {
556         enum mlxsw_reg_spms_state spms_state = mlxsw_sp_stp_spms_state(state);
557         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
558         char *spms_pl;
559         int err;
560
561         spms_pl = kmalloc(MLXSW_REG_SPMS_LEN, GFP_KERNEL);
562         if (!spms_pl)
563                 return -ENOMEM;
564         mlxsw_reg_spms_pack(spms_pl, mlxsw_sp_port->local_port);
565         mlxsw_reg_spms_vid_pack(spms_pl, vid, spms_state);
566
567         err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(spms), spms_pl);
568         kfree(spms_pl);
569         return err;
570 }
571
572 static int mlxsw_sp_base_mac_get(struct mlxsw_sp *mlxsw_sp)
573 {
574         char spad_pl[MLXSW_REG_SPAD_LEN] = {0};
575         int err;
576
577         err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(spad), spad_pl);
578         if (err)
579                 return err;
580         mlxsw_reg_spad_base_mac_memcpy_from(spad_pl, mlxsw_sp->base_mac);
581         return 0;
582 }
583
584 static int mlxsw_sp_port_sample_set(struct mlxsw_sp_port *mlxsw_sp_port,
585                                     bool enable, u32 rate)
586 {
587         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
588         char mpsc_pl[MLXSW_REG_MPSC_LEN];
589
590         mlxsw_reg_mpsc_pack(mpsc_pl, mlxsw_sp_port->local_port, enable, rate);
591         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mpsc), mpsc_pl);
592 }
593
594 static int mlxsw_sp_port_admin_status_set(struct mlxsw_sp_port *mlxsw_sp_port,
595                                           bool is_up)
596 {
597         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
598         char paos_pl[MLXSW_REG_PAOS_LEN];
599
600         mlxsw_reg_paos_pack(paos_pl, mlxsw_sp_port->local_port,
601                             is_up ? MLXSW_PORT_ADMIN_STATUS_UP :
602                             MLXSW_PORT_ADMIN_STATUS_DOWN);
603         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(paos), paos_pl);
604 }
605
606 static int mlxsw_sp_port_dev_addr_set(struct mlxsw_sp_port *mlxsw_sp_port,
607                                       unsigned char *addr)
608 {
609         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
610         char ppad_pl[MLXSW_REG_PPAD_LEN];
611
612         mlxsw_reg_ppad_pack(ppad_pl, true, mlxsw_sp_port->local_port);
613         mlxsw_reg_ppad_mac_memcpy_to(ppad_pl, addr);
614         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ppad), ppad_pl);
615 }
616
617 static int mlxsw_sp_port_dev_addr_init(struct mlxsw_sp_port *mlxsw_sp_port)
618 {
619         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
620         unsigned char *addr = mlxsw_sp_port->dev->dev_addr;
621
622         ether_addr_copy(addr, mlxsw_sp->base_mac);
623         addr[ETH_ALEN - 1] += mlxsw_sp_port->local_port;
624         return mlxsw_sp_port_dev_addr_set(mlxsw_sp_port, addr);
625 }
626
627 static int mlxsw_sp_port_mtu_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 mtu)
628 {
629         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
630         char pmtu_pl[MLXSW_REG_PMTU_LEN];
631         int max_mtu;
632         int err;
633
634         mtu += MLXSW_TXHDR_LEN + ETH_HLEN;
635         mlxsw_reg_pmtu_pack(pmtu_pl, mlxsw_sp_port->local_port, 0);
636         err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(pmtu), pmtu_pl);
637         if (err)
638                 return err;
639         max_mtu = mlxsw_reg_pmtu_max_mtu_get(pmtu_pl);
640
641         if (mtu > max_mtu)
642                 return -EINVAL;
643
644         mlxsw_reg_pmtu_pack(pmtu_pl, mlxsw_sp_port->local_port, mtu);
645         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pmtu), pmtu_pl);
646 }
647
648 static int mlxsw_sp_port_swid_set(struct mlxsw_sp_port *mlxsw_sp_port, u8 swid)
649 {
650         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
651         char pspa_pl[MLXSW_REG_PSPA_LEN];
652
653         mlxsw_reg_pspa_pack(pspa_pl, swid, mlxsw_sp_port->local_port);
654         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pspa), pspa_pl);
655 }
656
657 int mlxsw_sp_port_vp_mode_set(struct mlxsw_sp_port *mlxsw_sp_port, bool enable)
658 {
659         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
660         char svpe_pl[MLXSW_REG_SVPE_LEN];
661
662         mlxsw_reg_svpe_pack(svpe_pl, mlxsw_sp_port->local_port, enable);
663         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(svpe), svpe_pl);
664 }
665
666 int mlxsw_sp_port_vid_learning_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid,
667                                    bool learn_enable)
668 {
669         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
670         char *spvmlr_pl;
671         int err;
672
673         spvmlr_pl = kmalloc(MLXSW_REG_SPVMLR_LEN, GFP_KERNEL);
674         if (!spvmlr_pl)
675                 return -ENOMEM;
676         mlxsw_reg_spvmlr_pack(spvmlr_pl, mlxsw_sp_port->local_port, vid, vid,
677                               learn_enable);
678         err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(spvmlr), spvmlr_pl);
679         kfree(spvmlr_pl);
680         return err;
681 }
682
683 static int __mlxsw_sp_port_pvid_set(struct mlxsw_sp_port *mlxsw_sp_port,
684                                     u16 vid)
685 {
686         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
687         char spvid_pl[MLXSW_REG_SPVID_LEN];
688
689         mlxsw_reg_spvid_pack(spvid_pl, mlxsw_sp_port->local_port, vid);
690         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(spvid), spvid_pl);
691 }
692
693 static int mlxsw_sp_port_allow_untagged_set(struct mlxsw_sp_port *mlxsw_sp_port,
694                                             bool allow)
695 {
696         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
697         char spaft_pl[MLXSW_REG_SPAFT_LEN];
698
699         mlxsw_reg_spaft_pack(spaft_pl, mlxsw_sp_port->local_port, allow);
700         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(spaft), spaft_pl);
701 }
702
703 int mlxsw_sp_port_pvid_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
704 {
705         int err;
706
707         if (!vid) {
708                 err = mlxsw_sp_port_allow_untagged_set(mlxsw_sp_port, false);
709                 if (err)
710                         return err;
711         } else {
712                 err = __mlxsw_sp_port_pvid_set(mlxsw_sp_port, vid);
713                 if (err)
714                         return err;
715                 err = mlxsw_sp_port_allow_untagged_set(mlxsw_sp_port, true);
716                 if (err)
717                         goto err_port_allow_untagged_set;
718         }
719
720         mlxsw_sp_port->pvid = vid;
721         return 0;
722
723 err_port_allow_untagged_set:
724         __mlxsw_sp_port_pvid_set(mlxsw_sp_port, mlxsw_sp_port->pvid);
725         return err;
726 }
727
728 static int
729 mlxsw_sp_port_system_port_mapping_set(struct mlxsw_sp_port *mlxsw_sp_port)
730 {
731         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
732         char sspr_pl[MLXSW_REG_SSPR_LEN];
733
734         mlxsw_reg_sspr_pack(sspr_pl, mlxsw_sp_port->local_port);
735         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sspr), sspr_pl);
736 }
737
738 static int
739 mlxsw_sp_port_module_info_get(struct mlxsw_sp *mlxsw_sp, u8 local_port,
740                               struct mlxsw_sp_port_mapping *port_mapping)
741 {
742         char pmlp_pl[MLXSW_REG_PMLP_LEN];
743         bool separate_rxtx;
744         u8 module;
745         u8 width;
746         int err;
747         int i;
748
749         mlxsw_reg_pmlp_pack(pmlp_pl, local_port);
750         err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(pmlp), pmlp_pl);
751         if (err)
752                 return err;
753         module = mlxsw_reg_pmlp_module_get(pmlp_pl, 0);
754         width = mlxsw_reg_pmlp_width_get(pmlp_pl);
755         separate_rxtx = mlxsw_reg_pmlp_rxtx_get(pmlp_pl);
756
757         if (width && !is_power_of_2(width)) {
758                 dev_err(mlxsw_sp->bus_info->dev, "Port %d: Unsupported module config: width value is not power of 2\n",
759                         local_port);
760                 return -EINVAL;
761         }
762
763         for (i = 0; i < width; i++) {
764                 if (mlxsw_reg_pmlp_module_get(pmlp_pl, i) != module) {
765                         dev_err(mlxsw_sp->bus_info->dev, "Port %d: Unsupported module config: contains multiple modules\n",
766                                 local_port);
767                         return -EINVAL;
768                 }
769                 if (separate_rxtx &&
770                     mlxsw_reg_pmlp_tx_lane_get(pmlp_pl, i) !=
771                     mlxsw_reg_pmlp_rx_lane_get(pmlp_pl, i)) {
772                         dev_err(mlxsw_sp->bus_info->dev, "Port %d: Unsupported module config: TX and RX lane numbers are different\n",
773                                 local_port);
774                         return -EINVAL;
775                 }
776                 if (mlxsw_reg_pmlp_tx_lane_get(pmlp_pl, i) != i) {
777                         dev_err(mlxsw_sp->bus_info->dev, "Port %d: Unsupported module config: TX and RX lane numbers are not sequential\n",
778                                 local_port);
779                         return -EINVAL;
780                 }
781         }
782
783         port_mapping->module = module;
784         port_mapping->width = width;
785         port_mapping->lane = mlxsw_reg_pmlp_tx_lane_get(pmlp_pl, 0);
786         return 0;
787 }
788
789 static int mlxsw_sp_port_module_map(struct mlxsw_sp_port *mlxsw_sp_port)
790 {
791         struct mlxsw_sp_port_mapping *port_mapping = &mlxsw_sp_port->mapping;
792         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
793         char pmlp_pl[MLXSW_REG_PMLP_LEN];
794         int i;
795
796         mlxsw_reg_pmlp_pack(pmlp_pl, mlxsw_sp_port->local_port);
797         mlxsw_reg_pmlp_width_set(pmlp_pl, port_mapping->width);
798         for (i = 0; i < port_mapping->width; i++) {
799                 mlxsw_reg_pmlp_module_set(pmlp_pl, i, port_mapping->module);
800                 mlxsw_reg_pmlp_tx_lane_set(pmlp_pl, i, port_mapping->lane + i); /* Rx & Tx */
801         }
802
803         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pmlp), pmlp_pl);
804 }
805
806 static int mlxsw_sp_port_module_unmap(struct mlxsw_sp_port *mlxsw_sp_port)
807 {
808         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
809         char pmlp_pl[MLXSW_REG_PMLP_LEN];
810
811         mlxsw_reg_pmlp_pack(pmlp_pl, mlxsw_sp_port->local_port);
812         mlxsw_reg_pmlp_width_set(pmlp_pl, 0);
813         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pmlp), pmlp_pl);
814 }
815
816 static int mlxsw_sp_port_open(struct net_device *dev)
817 {
818         struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
819         int err;
820
821         err = mlxsw_sp_port_admin_status_set(mlxsw_sp_port, true);
822         if (err)
823                 return err;
824         netif_start_queue(dev);
825         return 0;
826 }
827
828 static int mlxsw_sp_port_stop(struct net_device *dev)
829 {
830         struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
831
832         netif_stop_queue(dev);
833         return mlxsw_sp_port_admin_status_set(mlxsw_sp_port, false);
834 }
835
836 static netdev_tx_t mlxsw_sp_port_xmit(struct sk_buff *skb,
837                                       struct net_device *dev)
838 {
839         struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
840         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
841         struct mlxsw_sp_port_pcpu_stats *pcpu_stats;
842         const struct mlxsw_tx_info tx_info = {
843                 .local_port = mlxsw_sp_port->local_port,
844                 .is_emad = false,
845         };
846         u64 len;
847         int err;
848
849         if (skb_cow_head(skb, MLXSW_TXHDR_LEN)) {
850                 this_cpu_inc(mlxsw_sp_port->pcpu_stats->tx_dropped);
851                 dev_kfree_skb_any(skb);
852                 return NETDEV_TX_OK;
853         }
854
855         memset(skb->cb, 0, sizeof(struct mlxsw_skb_cb));
856
857         if (mlxsw_core_skb_transmit_busy(mlxsw_sp->core, &tx_info))
858                 return NETDEV_TX_BUSY;
859
860         if (eth_skb_pad(skb)) {
861                 this_cpu_inc(mlxsw_sp_port->pcpu_stats->tx_dropped);
862                 return NETDEV_TX_OK;
863         }
864
865         mlxsw_sp_txhdr_construct(skb, &tx_info);
866         /* TX header is consumed by HW on the way so we shouldn't count its
867          * bytes as being sent.
868          */
869         len = skb->len - MLXSW_TXHDR_LEN;
870
871         /* Due to a race we might fail here because of a full queue. In that
872          * unlikely case we simply drop the packet.
873          */
874         err = mlxsw_core_skb_transmit(mlxsw_sp->core, skb, &tx_info);
875
876         if (!err) {
877                 pcpu_stats = this_cpu_ptr(mlxsw_sp_port->pcpu_stats);
878                 u64_stats_update_begin(&pcpu_stats->syncp);
879                 pcpu_stats->tx_packets++;
880                 pcpu_stats->tx_bytes += len;
881                 u64_stats_update_end(&pcpu_stats->syncp);
882         } else {
883                 this_cpu_inc(mlxsw_sp_port->pcpu_stats->tx_dropped);
884                 dev_kfree_skb_any(skb);
885         }
886         return NETDEV_TX_OK;
887 }
888
889 static void mlxsw_sp_set_rx_mode(struct net_device *dev)
890 {
891 }
892
893 static int mlxsw_sp_port_set_mac_address(struct net_device *dev, void *p)
894 {
895         struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
896         struct sockaddr *addr = p;
897         int err;
898
899         if (!is_valid_ether_addr(addr->sa_data))
900                 return -EADDRNOTAVAIL;
901
902         err = mlxsw_sp_port_dev_addr_set(mlxsw_sp_port, addr->sa_data);
903         if (err)
904                 return err;
905         memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
906         return 0;
907 }
908
909 static u16 mlxsw_sp_pg_buf_threshold_get(const struct mlxsw_sp *mlxsw_sp,
910                                          int mtu)
911 {
912         return 2 * mlxsw_sp_bytes_cells(mlxsw_sp, mtu);
913 }
914
915 #define MLXSW_SP_CELL_FACTOR 2  /* 2 * cell_size / (IPG + cell_size + 1) */
916
917 static u16 mlxsw_sp_pfc_delay_get(const struct mlxsw_sp *mlxsw_sp, int mtu,
918                                   u16 delay)
919 {
920         delay = mlxsw_sp_bytes_cells(mlxsw_sp, DIV_ROUND_UP(delay,
921                                                             BITS_PER_BYTE));
922         return MLXSW_SP_CELL_FACTOR * delay + mlxsw_sp_bytes_cells(mlxsw_sp,
923                                                                    mtu);
924 }
925
926 /* Maximum delay buffer needed in case of PAUSE frames, in bytes.
927  * Assumes 100m cable and maximum MTU.
928  */
929 #define MLXSW_SP_PAUSE_DELAY 58752
930
931 static u16 mlxsw_sp_pg_buf_delay_get(const struct mlxsw_sp *mlxsw_sp, int mtu,
932                                      u16 delay, bool pfc, bool pause)
933 {
934         if (pfc)
935                 return mlxsw_sp_pfc_delay_get(mlxsw_sp, mtu, delay);
936         else if (pause)
937                 return mlxsw_sp_bytes_cells(mlxsw_sp, MLXSW_SP_PAUSE_DELAY);
938         else
939                 return 0;
940 }
941
942 static void mlxsw_sp_pg_buf_pack(char *pbmc_pl, int index, u16 size, u16 thres,
943                                  bool lossy)
944 {
945         if (lossy)
946                 mlxsw_reg_pbmc_lossy_buffer_pack(pbmc_pl, index, size);
947         else
948                 mlxsw_reg_pbmc_lossless_buffer_pack(pbmc_pl, index, size,
949                                                     thres);
950 }
951
952 int __mlxsw_sp_port_headroom_set(struct mlxsw_sp_port *mlxsw_sp_port, int mtu,
953                                  u8 *prio_tc, bool pause_en,
954                                  struct ieee_pfc *my_pfc)
955 {
956         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
957         u8 pfc_en = !!my_pfc ? my_pfc->pfc_en : 0;
958         u16 delay = !!my_pfc ? my_pfc->delay : 0;
959         char pbmc_pl[MLXSW_REG_PBMC_LEN];
960         u32 taken_headroom_cells = 0;
961         u32 max_headroom_cells;
962         int i, j, err;
963
964         max_headroom_cells = mlxsw_sp_sb_max_headroom_cells(mlxsw_sp);
965
966         mlxsw_reg_pbmc_pack(pbmc_pl, mlxsw_sp_port->local_port, 0, 0);
967         err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(pbmc), pbmc_pl);
968         if (err)
969                 return err;
970
971         for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
972                 bool configure = false;
973                 bool pfc = false;
974                 u16 thres_cells;
975                 u16 delay_cells;
976                 u16 total_cells;
977                 bool lossy;
978
979                 for (j = 0; j < IEEE_8021QAZ_MAX_TCS; j++) {
980                         if (prio_tc[j] == i) {
981                                 pfc = pfc_en & BIT(j);
982                                 configure = true;
983                                 break;
984                         }
985                 }
986
987                 if (!configure)
988                         continue;
989
990                 lossy = !(pfc || pause_en);
991                 thres_cells = mlxsw_sp_pg_buf_threshold_get(mlxsw_sp, mtu);
992                 delay_cells = mlxsw_sp_pg_buf_delay_get(mlxsw_sp, mtu, delay,
993                                                         pfc, pause_en);
994                 total_cells = thres_cells + delay_cells;
995
996                 taken_headroom_cells += total_cells;
997                 if (taken_headroom_cells > max_headroom_cells)
998                         return -ENOBUFS;
999
1000                 mlxsw_sp_pg_buf_pack(pbmc_pl, i, total_cells,
1001                                      thres_cells, lossy);
1002         }
1003
1004         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pbmc), pbmc_pl);
1005 }
1006
1007 static int mlxsw_sp_port_headroom_set(struct mlxsw_sp_port *mlxsw_sp_port,
1008                                       int mtu, bool pause_en)
1009 {
1010         u8 def_prio_tc[IEEE_8021QAZ_MAX_TCS] = {0};
1011         bool dcb_en = !!mlxsw_sp_port->dcb.ets;
1012         struct ieee_pfc *my_pfc;
1013         u8 *prio_tc;
1014
1015         prio_tc = dcb_en ? mlxsw_sp_port->dcb.ets->prio_tc : def_prio_tc;
1016         my_pfc = dcb_en ? mlxsw_sp_port->dcb.pfc : NULL;
1017
1018         return __mlxsw_sp_port_headroom_set(mlxsw_sp_port, mtu, prio_tc,
1019                                             pause_en, my_pfc);
1020 }
1021
1022 static int mlxsw_sp_port_change_mtu(struct net_device *dev, int mtu)
1023 {
1024         struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
1025         bool pause_en = mlxsw_sp_port_is_pause_en(mlxsw_sp_port);
1026         int err;
1027
1028         err = mlxsw_sp_port_headroom_set(mlxsw_sp_port, mtu, pause_en);
1029         if (err)
1030                 return err;
1031         err = mlxsw_sp_span_port_mtu_update(mlxsw_sp_port, mtu);
1032         if (err)
1033                 goto err_span_port_mtu_update;
1034         err = mlxsw_sp_port_mtu_set(mlxsw_sp_port, mtu);
1035         if (err)
1036                 goto err_port_mtu_set;
1037         dev->mtu = mtu;
1038         return 0;
1039
1040 err_port_mtu_set:
1041         mlxsw_sp_span_port_mtu_update(mlxsw_sp_port, dev->mtu);
1042 err_span_port_mtu_update:
1043         mlxsw_sp_port_headroom_set(mlxsw_sp_port, dev->mtu, pause_en);
1044         return err;
1045 }
1046
1047 static int
1048 mlxsw_sp_port_get_sw_stats64(const struct net_device *dev,
1049                              struct rtnl_link_stats64 *stats)
1050 {
1051         struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
1052         struct mlxsw_sp_port_pcpu_stats *p;
1053         u64 rx_packets, rx_bytes, tx_packets, tx_bytes;
1054         u32 tx_dropped = 0;
1055         unsigned int start;
1056         int i;
1057
1058         for_each_possible_cpu(i) {
1059                 p = per_cpu_ptr(mlxsw_sp_port->pcpu_stats, i);
1060                 do {
1061                         start = u64_stats_fetch_begin_irq(&p->syncp);
1062                         rx_packets      = p->rx_packets;
1063                         rx_bytes        = p->rx_bytes;
1064                         tx_packets      = p->tx_packets;
1065                         tx_bytes        = p->tx_bytes;
1066                 } while (u64_stats_fetch_retry_irq(&p->syncp, start));
1067
1068                 stats->rx_packets       += rx_packets;
1069                 stats->rx_bytes         += rx_bytes;
1070                 stats->tx_packets       += tx_packets;
1071                 stats->tx_bytes         += tx_bytes;
1072                 /* tx_dropped is u32, updated without syncp protection. */
1073                 tx_dropped      += p->tx_dropped;
1074         }
1075         stats->tx_dropped       = tx_dropped;
1076         return 0;
1077 }
1078
1079 static bool mlxsw_sp_port_has_offload_stats(const struct net_device *dev, int attr_id)
1080 {
1081         switch (attr_id) {
1082         case IFLA_OFFLOAD_XSTATS_CPU_HIT:
1083                 return true;
1084         }
1085
1086         return false;
1087 }
1088
1089 static int mlxsw_sp_port_get_offload_stats(int attr_id, const struct net_device *dev,
1090                                            void *sp)
1091 {
1092         switch (attr_id) {
1093         case IFLA_OFFLOAD_XSTATS_CPU_HIT:
1094                 return mlxsw_sp_port_get_sw_stats64(dev, sp);
1095         }
1096
1097         return -EINVAL;
1098 }
1099
1100 static int mlxsw_sp_port_get_stats_raw(struct net_device *dev, int grp,
1101                                        int prio, char *ppcnt_pl)
1102 {
1103         struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
1104         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1105
1106         mlxsw_reg_ppcnt_pack(ppcnt_pl, mlxsw_sp_port->local_port, grp, prio);
1107         return mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ppcnt), ppcnt_pl);
1108 }
1109
1110 static int mlxsw_sp_port_get_hw_stats(struct net_device *dev,
1111                                       struct rtnl_link_stats64 *stats)
1112 {
1113         char ppcnt_pl[MLXSW_REG_PPCNT_LEN];
1114         int err;
1115
1116         err = mlxsw_sp_port_get_stats_raw(dev, MLXSW_REG_PPCNT_IEEE_8023_CNT,
1117                                           0, ppcnt_pl);
1118         if (err)
1119                 goto out;
1120
1121         stats->tx_packets =
1122                 mlxsw_reg_ppcnt_a_frames_transmitted_ok_get(ppcnt_pl);
1123         stats->rx_packets =
1124                 mlxsw_reg_ppcnt_a_frames_received_ok_get(ppcnt_pl);
1125         stats->tx_bytes =
1126                 mlxsw_reg_ppcnt_a_octets_transmitted_ok_get(ppcnt_pl);
1127         stats->rx_bytes =
1128                 mlxsw_reg_ppcnt_a_octets_received_ok_get(ppcnt_pl);
1129         stats->multicast =
1130                 mlxsw_reg_ppcnt_a_multicast_frames_received_ok_get(ppcnt_pl);
1131
1132         stats->rx_crc_errors =
1133                 mlxsw_reg_ppcnt_a_frame_check_sequence_errors_get(ppcnt_pl);
1134         stats->rx_frame_errors =
1135                 mlxsw_reg_ppcnt_a_alignment_errors_get(ppcnt_pl);
1136
1137         stats->rx_length_errors = (
1138                 mlxsw_reg_ppcnt_a_in_range_length_errors_get(ppcnt_pl) +
1139                 mlxsw_reg_ppcnt_a_out_of_range_length_field_get(ppcnt_pl) +
1140                 mlxsw_reg_ppcnt_a_frame_too_long_errors_get(ppcnt_pl));
1141
1142         stats->rx_errors = (stats->rx_crc_errors +
1143                 stats->rx_frame_errors + stats->rx_length_errors);
1144
1145 out:
1146         return err;
1147 }
1148
1149 static void
1150 mlxsw_sp_port_get_hw_xstats(struct net_device *dev,
1151                             struct mlxsw_sp_port_xstats *xstats)
1152 {
1153         char ppcnt_pl[MLXSW_REG_PPCNT_LEN];
1154         int err, i;
1155
1156         err = mlxsw_sp_port_get_stats_raw(dev, MLXSW_REG_PPCNT_EXT_CNT, 0,
1157                                           ppcnt_pl);
1158         if (!err)
1159                 xstats->ecn = mlxsw_reg_ppcnt_ecn_marked_get(ppcnt_pl);
1160
1161         for (i = 0; i < TC_MAX_QUEUE; i++) {
1162                 err = mlxsw_sp_port_get_stats_raw(dev,
1163                                                   MLXSW_REG_PPCNT_TC_CONG_TC,
1164                                                   i, ppcnt_pl);
1165                 if (!err)
1166                         xstats->wred_drop[i] =
1167                                 mlxsw_reg_ppcnt_wred_discard_get(ppcnt_pl);
1168
1169                 err = mlxsw_sp_port_get_stats_raw(dev, MLXSW_REG_PPCNT_TC_CNT,
1170                                                   i, ppcnt_pl);
1171                 if (err)
1172                         continue;
1173
1174                 xstats->backlog[i] =
1175                         mlxsw_reg_ppcnt_tc_transmit_queue_get(ppcnt_pl);
1176                 xstats->tail_drop[i] =
1177                         mlxsw_reg_ppcnt_tc_no_buffer_discard_uc_get(ppcnt_pl);
1178         }
1179
1180         for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
1181                 err = mlxsw_sp_port_get_stats_raw(dev, MLXSW_REG_PPCNT_PRIO_CNT,
1182                                                   i, ppcnt_pl);
1183                 if (err)
1184                         continue;
1185
1186                 xstats->tx_packets[i] = mlxsw_reg_ppcnt_tx_frames_get(ppcnt_pl);
1187                 xstats->tx_bytes[i] = mlxsw_reg_ppcnt_tx_octets_get(ppcnt_pl);
1188         }
1189 }
1190
1191 static void update_stats_cache(struct work_struct *work)
1192 {
1193         struct mlxsw_sp_port *mlxsw_sp_port =
1194                 container_of(work, struct mlxsw_sp_port,
1195                              periodic_hw_stats.update_dw.work);
1196
1197         if (!netif_carrier_ok(mlxsw_sp_port->dev))
1198                 /* Note: mlxsw_sp_port_down_wipe_counters() clears the cache as
1199                  * necessary when port goes down.
1200                  */
1201                 goto out;
1202
1203         mlxsw_sp_port_get_hw_stats(mlxsw_sp_port->dev,
1204                                    &mlxsw_sp_port->periodic_hw_stats.stats);
1205         mlxsw_sp_port_get_hw_xstats(mlxsw_sp_port->dev,
1206                                     &mlxsw_sp_port->periodic_hw_stats.xstats);
1207
1208 out:
1209         mlxsw_core_schedule_dw(&mlxsw_sp_port->periodic_hw_stats.update_dw,
1210                                MLXSW_HW_STATS_UPDATE_TIME);
1211 }
1212
1213 /* Return the stats from a cache that is updated periodically,
1214  * as this function might get called in an atomic context.
1215  */
1216 static void
1217 mlxsw_sp_port_get_stats64(struct net_device *dev,
1218                           struct rtnl_link_stats64 *stats)
1219 {
1220         struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
1221
1222         memcpy(stats, &mlxsw_sp_port->periodic_hw_stats.stats, sizeof(*stats));
1223 }
1224
1225 static int __mlxsw_sp_port_vlan_set(struct mlxsw_sp_port *mlxsw_sp_port,
1226                                     u16 vid_begin, u16 vid_end,
1227                                     bool is_member, bool untagged)
1228 {
1229         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1230         char *spvm_pl;
1231         int err;
1232
1233         spvm_pl = kmalloc(MLXSW_REG_SPVM_LEN, GFP_KERNEL);
1234         if (!spvm_pl)
1235                 return -ENOMEM;
1236
1237         mlxsw_reg_spvm_pack(spvm_pl, mlxsw_sp_port->local_port, vid_begin,
1238                             vid_end, is_member, untagged);
1239         err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(spvm), spvm_pl);
1240         kfree(spvm_pl);
1241         return err;
1242 }
1243
1244 int mlxsw_sp_port_vlan_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid_begin,
1245                            u16 vid_end, bool is_member, bool untagged)
1246 {
1247         u16 vid, vid_e;
1248         int err;
1249
1250         for (vid = vid_begin; vid <= vid_end;
1251              vid += MLXSW_REG_SPVM_REC_MAX_COUNT) {
1252                 vid_e = min((u16) (vid + MLXSW_REG_SPVM_REC_MAX_COUNT - 1),
1253                             vid_end);
1254
1255                 err = __mlxsw_sp_port_vlan_set(mlxsw_sp_port, vid, vid_e,
1256                                                is_member, untagged);
1257                 if (err)
1258                         return err;
1259         }
1260
1261         return 0;
1262 }
1263
1264 static void mlxsw_sp_port_vlan_flush(struct mlxsw_sp_port *mlxsw_sp_port,
1265                                      bool flush_default)
1266 {
1267         struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan, *tmp;
1268
1269         list_for_each_entry_safe(mlxsw_sp_port_vlan, tmp,
1270                                  &mlxsw_sp_port->vlans_list, list) {
1271                 if (!flush_default &&
1272                     mlxsw_sp_port_vlan->vid == MLXSW_SP_DEFAULT_VID)
1273                         continue;
1274                 mlxsw_sp_port_vlan_destroy(mlxsw_sp_port_vlan);
1275         }
1276 }
1277
1278 static void
1279 mlxsw_sp_port_vlan_cleanup(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan)
1280 {
1281         if (mlxsw_sp_port_vlan->bridge_port)
1282                 mlxsw_sp_port_vlan_bridge_leave(mlxsw_sp_port_vlan);
1283         else if (mlxsw_sp_port_vlan->fid)
1284                 mlxsw_sp_port_vlan_router_leave(mlxsw_sp_port_vlan);
1285 }
1286
1287 struct mlxsw_sp_port_vlan *
1288 mlxsw_sp_port_vlan_create(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
1289 {
1290         struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
1291         bool untagged = vid == MLXSW_SP_DEFAULT_VID;
1292         int err;
1293
1294         mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_find_by_vid(mlxsw_sp_port, vid);
1295         if (mlxsw_sp_port_vlan)
1296                 return ERR_PTR(-EEXIST);
1297
1298         err = mlxsw_sp_port_vlan_set(mlxsw_sp_port, vid, vid, true, untagged);
1299         if (err)
1300                 return ERR_PTR(err);
1301
1302         mlxsw_sp_port_vlan = kzalloc(sizeof(*mlxsw_sp_port_vlan), GFP_KERNEL);
1303         if (!mlxsw_sp_port_vlan) {
1304                 err = -ENOMEM;
1305                 goto err_port_vlan_alloc;
1306         }
1307
1308         mlxsw_sp_port_vlan->mlxsw_sp_port = mlxsw_sp_port;
1309         mlxsw_sp_port_vlan->vid = vid;
1310         list_add(&mlxsw_sp_port_vlan->list, &mlxsw_sp_port->vlans_list);
1311
1312         return mlxsw_sp_port_vlan;
1313
1314 err_port_vlan_alloc:
1315         mlxsw_sp_port_vlan_set(mlxsw_sp_port, vid, vid, false, false);
1316         return ERR_PTR(err);
1317 }
1318
1319 void mlxsw_sp_port_vlan_destroy(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan)
1320 {
1321         struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp_port_vlan->mlxsw_sp_port;
1322         u16 vid = mlxsw_sp_port_vlan->vid;
1323
1324         mlxsw_sp_port_vlan_cleanup(mlxsw_sp_port_vlan);
1325         list_del(&mlxsw_sp_port_vlan->list);
1326         kfree(mlxsw_sp_port_vlan);
1327         mlxsw_sp_port_vlan_set(mlxsw_sp_port, vid, vid, false, false);
1328 }
1329
1330 static int mlxsw_sp_port_add_vid(struct net_device *dev,
1331                                  __be16 __always_unused proto, u16 vid)
1332 {
1333         struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
1334
1335         /* VLAN 0 is added to HW filter when device goes up, but it is
1336          * reserved in our case, so simply return.
1337          */
1338         if (!vid)
1339                 return 0;
1340
1341         return PTR_ERR_OR_ZERO(mlxsw_sp_port_vlan_create(mlxsw_sp_port, vid));
1342 }
1343
1344 static int mlxsw_sp_port_kill_vid(struct net_device *dev,
1345                                   __be16 __always_unused proto, u16 vid)
1346 {
1347         struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
1348         struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
1349
1350         /* VLAN 0 is removed from HW filter when device goes down, but
1351          * it is reserved in our case, so simply return.
1352          */
1353         if (!vid)
1354                 return 0;
1355
1356         mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_find_by_vid(mlxsw_sp_port, vid);
1357         if (!mlxsw_sp_port_vlan)
1358                 return 0;
1359         mlxsw_sp_port_vlan_destroy(mlxsw_sp_port_vlan);
1360
1361         return 0;
1362 }
1363
1364 static struct mlxsw_sp_port_mall_tc_entry *
1365 mlxsw_sp_port_mall_tc_entry_find(struct mlxsw_sp_port *port,
1366                                  unsigned long cookie) {
1367         struct mlxsw_sp_port_mall_tc_entry *mall_tc_entry;
1368
1369         list_for_each_entry(mall_tc_entry, &port->mall_tc_list, list)
1370                 if (mall_tc_entry->cookie == cookie)
1371                         return mall_tc_entry;
1372
1373         return NULL;
1374 }
1375
1376 static int
1377 mlxsw_sp_port_add_cls_matchall_mirror(struct mlxsw_sp_port *mlxsw_sp_port,
1378                                       struct mlxsw_sp_port_mall_mirror_tc_entry *mirror,
1379                                       const struct flow_action_entry *act,
1380                                       bool ingress)
1381 {
1382         enum mlxsw_sp_span_type span_type;
1383
1384         if (!act->dev) {
1385                 netdev_err(mlxsw_sp_port->dev, "Could not find requested device\n");
1386                 return -EINVAL;
1387         }
1388
1389         mirror->ingress = ingress;
1390         span_type = ingress ? MLXSW_SP_SPAN_INGRESS : MLXSW_SP_SPAN_EGRESS;
1391         return mlxsw_sp_span_mirror_add(mlxsw_sp_port, act->dev, span_type,
1392                                         true, &mirror->span_id);
1393 }
1394
1395 static void
1396 mlxsw_sp_port_del_cls_matchall_mirror(struct mlxsw_sp_port *mlxsw_sp_port,
1397                                       struct mlxsw_sp_port_mall_mirror_tc_entry *mirror)
1398 {
1399         enum mlxsw_sp_span_type span_type;
1400
1401         span_type = mirror->ingress ?
1402                         MLXSW_SP_SPAN_INGRESS : MLXSW_SP_SPAN_EGRESS;
1403         mlxsw_sp_span_mirror_del(mlxsw_sp_port, mirror->span_id,
1404                                  span_type, true);
1405 }
1406
1407 static int
1408 mlxsw_sp_port_add_cls_matchall_sample(struct mlxsw_sp_port *mlxsw_sp_port,
1409                                       struct tc_cls_matchall_offload *cls,
1410                                       const struct flow_action_entry *act,
1411                                       bool ingress)
1412 {
1413         int err;
1414
1415         if (!mlxsw_sp_port->sample)
1416                 return -EOPNOTSUPP;
1417         if (rtnl_dereference(mlxsw_sp_port->sample->psample_group)) {
1418                 netdev_err(mlxsw_sp_port->dev, "sample already active\n");
1419                 return -EEXIST;
1420         }
1421         if (act->sample.rate > MLXSW_REG_MPSC_RATE_MAX) {
1422                 netdev_err(mlxsw_sp_port->dev, "sample rate not supported\n");
1423                 return -EOPNOTSUPP;
1424         }
1425
1426         rcu_assign_pointer(mlxsw_sp_port->sample->psample_group,
1427                            act->sample.psample_group);
1428         mlxsw_sp_port->sample->truncate = act->sample.truncate;
1429         mlxsw_sp_port->sample->trunc_size = act->sample.trunc_size;
1430         mlxsw_sp_port->sample->rate = act->sample.rate;
1431
1432         err = mlxsw_sp_port_sample_set(mlxsw_sp_port, true, act->sample.rate);
1433         if (err)
1434                 goto err_port_sample_set;
1435         return 0;
1436
1437 err_port_sample_set:
1438         RCU_INIT_POINTER(mlxsw_sp_port->sample->psample_group, NULL);
1439         return err;
1440 }
1441
1442 static void
1443 mlxsw_sp_port_del_cls_matchall_sample(struct mlxsw_sp_port *mlxsw_sp_port)
1444 {
1445         if (!mlxsw_sp_port->sample)
1446                 return;
1447
1448         mlxsw_sp_port_sample_set(mlxsw_sp_port, false, 1);
1449         RCU_INIT_POINTER(mlxsw_sp_port->sample->psample_group, NULL);
1450 }
1451
1452 static int mlxsw_sp_port_add_cls_matchall(struct mlxsw_sp_port *mlxsw_sp_port,
1453                                           struct tc_cls_matchall_offload *f,
1454                                           bool ingress)
1455 {
1456         struct mlxsw_sp_port_mall_tc_entry *mall_tc_entry;
1457         __be16 protocol = f->common.protocol;
1458         struct flow_action_entry *act;
1459         int err;
1460
1461         if (!flow_offload_has_one_action(&f->rule->action)) {
1462                 netdev_err(mlxsw_sp_port->dev, "only singular actions are supported\n");
1463                 return -EOPNOTSUPP;
1464         }
1465
1466         mall_tc_entry = kzalloc(sizeof(*mall_tc_entry), GFP_KERNEL);
1467         if (!mall_tc_entry)
1468                 return -ENOMEM;
1469         mall_tc_entry->cookie = f->cookie;
1470
1471         act = &f->rule->action.entries[0];
1472
1473         if (act->id == FLOW_ACTION_MIRRED && protocol == htons(ETH_P_ALL)) {
1474                 struct mlxsw_sp_port_mall_mirror_tc_entry *mirror;
1475
1476                 mall_tc_entry->type = MLXSW_SP_PORT_MALL_MIRROR;
1477                 mirror = &mall_tc_entry->mirror;
1478                 err = mlxsw_sp_port_add_cls_matchall_mirror(mlxsw_sp_port,
1479                                                             mirror, act,
1480                                                             ingress);
1481         } else if (act->id == FLOW_ACTION_SAMPLE &&
1482                    protocol == htons(ETH_P_ALL)) {
1483                 mall_tc_entry->type = MLXSW_SP_PORT_MALL_SAMPLE;
1484                 err = mlxsw_sp_port_add_cls_matchall_sample(mlxsw_sp_port, f,
1485                                                             act, ingress);
1486         } else {
1487                 err = -EOPNOTSUPP;
1488         }
1489
1490         if (err)
1491                 goto err_add_action;
1492
1493         list_add_tail(&mall_tc_entry->list, &mlxsw_sp_port->mall_tc_list);
1494         return 0;
1495
1496 err_add_action:
1497         kfree(mall_tc_entry);
1498         return err;
1499 }
1500
1501 static void mlxsw_sp_port_del_cls_matchall(struct mlxsw_sp_port *mlxsw_sp_port,
1502                                            struct tc_cls_matchall_offload *f)
1503 {
1504         struct mlxsw_sp_port_mall_tc_entry *mall_tc_entry;
1505
1506         mall_tc_entry = mlxsw_sp_port_mall_tc_entry_find(mlxsw_sp_port,
1507                                                          f->cookie);
1508         if (!mall_tc_entry) {
1509                 netdev_dbg(mlxsw_sp_port->dev, "tc entry not found on port\n");
1510                 return;
1511         }
1512         list_del(&mall_tc_entry->list);
1513
1514         switch (mall_tc_entry->type) {
1515         case MLXSW_SP_PORT_MALL_MIRROR:
1516                 mlxsw_sp_port_del_cls_matchall_mirror(mlxsw_sp_port,
1517                                                       &mall_tc_entry->mirror);
1518                 break;
1519         case MLXSW_SP_PORT_MALL_SAMPLE:
1520                 mlxsw_sp_port_del_cls_matchall_sample(mlxsw_sp_port);
1521                 break;
1522         default:
1523                 WARN_ON(1);
1524         }
1525
1526         kfree(mall_tc_entry);
1527 }
1528
1529 static int mlxsw_sp_setup_tc_cls_matchall(struct mlxsw_sp_port *mlxsw_sp_port,
1530                                           struct tc_cls_matchall_offload *f,
1531                                           bool ingress)
1532 {
1533         switch (f->command) {
1534         case TC_CLSMATCHALL_REPLACE:
1535                 return mlxsw_sp_port_add_cls_matchall(mlxsw_sp_port, f,
1536                                                       ingress);
1537         case TC_CLSMATCHALL_DESTROY:
1538                 mlxsw_sp_port_del_cls_matchall(mlxsw_sp_port, f);
1539                 return 0;
1540         default:
1541                 return -EOPNOTSUPP;
1542         }
1543 }
1544
1545 static int
1546 mlxsw_sp_setup_tc_cls_flower(struct mlxsw_sp_acl_block *acl_block,
1547                              struct flow_cls_offload *f)
1548 {
1549         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_acl_block_mlxsw_sp(acl_block);
1550
1551         switch (f->command) {
1552         case FLOW_CLS_REPLACE:
1553                 return mlxsw_sp_flower_replace(mlxsw_sp, acl_block, f);
1554         case FLOW_CLS_DESTROY:
1555                 mlxsw_sp_flower_destroy(mlxsw_sp, acl_block, f);
1556                 return 0;
1557         case FLOW_CLS_STATS:
1558                 return mlxsw_sp_flower_stats(mlxsw_sp, acl_block, f);
1559         case FLOW_CLS_TMPLT_CREATE:
1560                 return mlxsw_sp_flower_tmplt_create(mlxsw_sp, acl_block, f);
1561         case FLOW_CLS_TMPLT_DESTROY:
1562                 mlxsw_sp_flower_tmplt_destroy(mlxsw_sp, acl_block, f);
1563                 return 0;
1564         default:
1565                 return -EOPNOTSUPP;
1566         }
1567 }
1568
1569 static int mlxsw_sp_setup_tc_block_cb_matchall(enum tc_setup_type type,
1570                                                void *type_data,
1571                                                void *cb_priv, bool ingress)
1572 {
1573         struct mlxsw_sp_port *mlxsw_sp_port = cb_priv;
1574
1575         switch (type) {
1576         case TC_SETUP_CLSMATCHALL:
1577                 if (!tc_cls_can_offload_and_chain0(mlxsw_sp_port->dev,
1578                                                    type_data))
1579                         return -EOPNOTSUPP;
1580
1581                 return mlxsw_sp_setup_tc_cls_matchall(mlxsw_sp_port, type_data,
1582                                                       ingress);
1583         case TC_SETUP_CLSFLOWER:
1584                 return 0;
1585         default:
1586                 return -EOPNOTSUPP;
1587         }
1588 }
1589
1590 static int mlxsw_sp_setup_tc_block_cb_matchall_ig(enum tc_setup_type type,
1591                                                   void *type_data,
1592                                                   void *cb_priv)
1593 {
1594         return mlxsw_sp_setup_tc_block_cb_matchall(type, type_data,
1595                                                    cb_priv, true);
1596 }
1597
1598 static int mlxsw_sp_setup_tc_block_cb_matchall_eg(enum tc_setup_type type,
1599                                                   void *type_data,
1600                                                   void *cb_priv)
1601 {
1602         return mlxsw_sp_setup_tc_block_cb_matchall(type, type_data,
1603                                                    cb_priv, false);
1604 }
1605
1606 static int mlxsw_sp_setup_tc_block_cb_flower(enum tc_setup_type type,
1607                                              void *type_data, void *cb_priv)
1608 {
1609         struct mlxsw_sp_acl_block *acl_block = cb_priv;
1610
1611         switch (type) {
1612         case TC_SETUP_CLSMATCHALL:
1613                 return 0;
1614         case TC_SETUP_CLSFLOWER:
1615                 if (mlxsw_sp_acl_block_disabled(acl_block))
1616                         return -EOPNOTSUPP;
1617
1618                 return mlxsw_sp_setup_tc_cls_flower(acl_block, type_data);
1619         default:
1620                 return -EOPNOTSUPP;
1621         }
1622 }
1623
1624 static void mlxsw_sp_tc_block_flower_release(void *cb_priv)
1625 {
1626         struct mlxsw_sp_acl_block *acl_block = cb_priv;
1627
1628         mlxsw_sp_acl_block_destroy(acl_block);
1629 }
1630
1631 static LIST_HEAD(mlxsw_sp_block_cb_list);
1632
1633 static int
1634 mlxsw_sp_setup_tc_block_flower_bind(struct mlxsw_sp_port *mlxsw_sp_port,
1635                                     struct flow_block_offload *f, bool ingress)
1636 {
1637         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1638         struct mlxsw_sp_acl_block *acl_block;
1639         struct flow_block_cb *block_cb;
1640         bool register_block = false;
1641         int err;
1642
1643         block_cb = flow_block_cb_lookup(f->block,
1644                                         mlxsw_sp_setup_tc_block_cb_flower,
1645                                         mlxsw_sp);
1646         if (!block_cb) {
1647                 acl_block = mlxsw_sp_acl_block_create(mlxsw_sp, f->net);
1648                 if (!acl_block)
1649                         return -ENOMEM;
1650                 block_cb = flow_block_cb_alloc(mlxsw_sp_setup_tc_block_cb_flower,
1651                                                mlxsw_sp, acl_block,
1652                                                mlxsw_sp_tc_block_flower_release);
1653                 if (IS_ERR(block_cb)) {
1654                         mlxsw_sp_acl_block_destroy(acl_block);
1655                         err = PTR_ERR(block_cb);
1656                         goto err_cb_register;
1657                 }
1658                 register_block = true;
1659         } else {
1660                 acl_block = flow_block_cb_priv(block_cb);
1661         }
1662         flow_block_cb_incref(block_cb);
1663         err = mlxsw_sp_acl_block_bind(mlxsw_sp, acl_block,
1664                                       mlxsw_sp_port, ingress, f->extack);
1665         if (err)
1666                 goto err_block_bind;
1667
1668         if (ingress)
1669                 mlxsw_sp_port->ing_acl_block = acl_block;
1670         else
1671                 mlxsw_sp_port->eg_acl_block = acl_block;
1672
1673         if (register_block) {
1674                 flow_block_cb_add(block_cb, f);
1675                 list_add_tail(&block_cb->driver_list, &mlxsw_sp_block_cb_list);
1676         }
1677
1678         return 0;
1679
1680 err_block_bind:
1681         if (!flow_block_cb_decref(block_cb))
1682                 flow_block_cb_free(block_cb);
1683 err_cb_register:
1684         return err;
1685 }
1686
1687 static void
1688 mlxsw_sp_setup_tc_block_flower_unbind(struct mlxsw_sp_port *mlxsw_sp_port,
1689                                       struct flow_block_offload *f, bool ingress)
1690 {
1691         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1692         struct mlxsw_sp_acl_block *acl_block;
1693         struct flow_block_cb *block_cb;
1694         int err;
1695
1696         block_cb = flow_block_cb_lookup(f->block,
1697                                         mlxsw_sp_setup_tc_block_cb_flower,
1698                                         mlxsw_sp);
1699         if (!block_cb)
1700                 return;
1701
1702         if (ingress)
1703                 mlxsw_sp_port->ing_acl_block = NULL;
1704         else
1705                 mlxsw_sp_port->eg_acl_block = NULL;
1706
1707         acl_block = flow_block_cb_priv(block_cb);
1708         err = mlxsw_sp_acl_block_unbind(mlxsw_sp, acl_block,
1709                                         mlxsw_sp_port, ingress);
1710         if (!err && !flow_block_cb_decref(block_cb)) {
1711                 flow_block_cb_remove(block_cb, f);
1712                 list_del(&block_cb->driver_list);
1713         }
1714 }
1715
1716 static int mlxsw_sp_setup_tc_block(struct mlxsw_sp_port *mlxsw_sp_port,
1717                                    struct flow_block_offload *f)
1718 {
1719         struct flow_block_cb *block_cb;
1720         flow_setup_cb_t *cb;
1721         bool ingress;
1722         int err;
1723
1724         if (f->binder_type == FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS) {
1725                 cb = mlxsw_sp_setup_tc_block_cb_matchall_ig;
1726                 ingress = true;
1727         } else if (f->binder_type == FLOW_BLOCK_BINDER_TYPE_CLSACT_EGRESS) {
1728                 cb = mlxsw_sp_setup_tc_block_cb_matchall_eg;
1729                 ingress = false;
1730         } else {
1731                 return -EOPNOTSUPP;
1732         }
1733
1734         f->driver_block_list = &mlxsw_sp_block_cb_list;
1735
1736         switch (f->command) {
1737         case FLOW_BLOCK_BIND:
1738                 if (flow_block_cb_is_busy(cb, mlxsw_sp_port,
1739                                           &mlxsw_sp_block_cb_list))
1740                         return -EBUSY;
1741
1742                 block_cb = flow_block_cb_alloc(cb, mlxsw_sp_port,
1743                                                mlxsw_sp_port, NULL);
1744                 if (IS_ERR(block_cb))
1745                         return PTR_ERR(block_cb);
1746                 err = mlxsw_sp_setup_tc_block_flower_bind(mlxsw_sp_port, f,
1747                                                           ingress);
1748                 if (err) {
1749                         flow_block_cb_free(block_cb);
1750                         return err;
1751                 }
1752                 flow_block_cb_add(block_cb, f);
1753                 list_add_tail(&block_cb->driver_list, &mlxsw_sp_block_cb_list);
1754                 return 0;
1755         case FLOW_BLOCK_UNBIND:
1756                 mlxsw_sp_setup_tc_block_flower_unbind(mlxsw_sp_port,
1757                                                       f, ingress);
1758                 block_cb = flow_block_cb_lookup(f->block, cb, mlxsw_sp_port);
1759                 if (!block_cb)
1760                         return -ENOENT;
1761
1762                 flow_block_cb_remove(block_cb, f);
1763                 list_del(&block_cb->driver_list);
1764                 return 0;
1765         default:
1766                 return -EOPNOTSUPP;
1767         }
1768 }
1769
1770 static int mlxsw_sp_setup_tc(struct net_device *dev, enum tc_setup_type type,
1771                              void *type_data)
1772 {
1773         struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
1774
1775         switch (type) {
1776         case TC_SETUP_BLOCK:
1777                 return mlxsw_sp_setup_tc_block(mlxsw_sp_port, type_data);
1778         case TC_SETUP_QDISC_RED:
1779                 return mlxsw_sp_setup_tc_red(mlxsw_sp_port, type_data);
1780         case TC_SETUP_QDISC_PRIO:
1781                 return mlxsw_sp_setup_tc_prio(mlxsw_sp_port, type_data);
1782         case TC_SETUP_QDISC_ETS:
1783                 return mlxsw_sp_setup_tc_ets(mlxsw_sp_port, type_data);
1784         case TC_SETUP_QDISC_TBF:
1785                 return mlxsw_sp_setup_tc_tbf(mlxsw_sp_port, type_data);
1786         default:
1787                 return -EOPNOTSUPP;
1788         }
1789 }
1790
1791
1792 static int mlxsw_sp_feature_hw_tc(struct net_device *dev, bool enable)
1793 {
1794         struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
1795
1796         if (!enable) {
1797                 if (mlxsw_sp_acl_block_rule_count(mlxsw_sp_port->ing_acl_block) ||
1798                     mlxsw_sp_acl_block_rule_count(mlxsw_sp_port->eg_acl_block) ||
1799                     !list_empty(&mlxsw_sp_port->mall_tc_list)) {
1800                         netdev_err(dev, "Active offloaded tc filters, can't turn hw_tc_offload off\n");
1801                         return -EINVAL;
1802                 }
1803                 mlxsw_sp_acl_block_disable_inc(mlxsw_sp_port->ing_acl_block);
1804                 mlxsw_sp_acl_block_disable_inc(mlxsw_sp_port->eg_acl_block);
1805         } else {
1806                 mlxsw_sp_acl_block_disable_dec(mlxsw_sp_port->ing_acl_block);
1807                 mlxsw_sp_acl_block_disable_dec(mlxsw_sp_port->eg_acl_block);
1808         }
1809         return 0;
1810 }
1811
1812 static int mlxsw_sp_feature_loopback(struct net_device *dev, bool enable)
1813 {
1814         struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
1815         char pplr_pl[MLXSW_REG_PPLR_LEN];
1816         int err;
1817
1818         if (netif_running(dev))
1819                 mlxsw_sp_port_admin_status_set(mlxsw_sp_port, false);
1820
1821         mlxsw_reg_pplr_pack(pplr_pl, mlxsw_sp_port->local_port, enable);
1822         err = mlxsw_reg_write(mlxsw_sp_port->mlxsw_sp->core, MLXSW_REG(pplr),
1823                               pplr_pl);
1824
1825         if (netif_running(dev))
1826                 mlxsw_sp_port_admin_status_set(mlxsw_sp_port, true);
1827
1828         return err;
1829 }
1830
1831 typedef int (*mlxsw_sp_feature_handler)(struct net_device *dev, bool enable);
1832
1833 static int mlxsw_sp_handle_feature(struct net_device *dev,
1834                                    netdev_features_t wanted_features,
1835                                    netdev_features_t feature,
1836                                    mlxsw_sp_feature_handler feature_handler)
1837 {
1838         netdev_features_t changes = wanted_features ^ dev->features;
1839         bool enable = !!(wanted_features & feature);
1840         int err;
1841
1842         if (!(changes & feature))
1843                 return 0;
1844
1845         err = feature_handler(dev, enable);
1846         if (err) {
1847                 netdev_err(dev, "%s feature %pNF failed, err %d\n",
1848                            enable ? "Enable" : "Disable", &feature, err);
1849                 return err;
1850         }
1851
1852         if (enable)
1853                 dev->features |= feature;
1854         else
1855                 dev->features &= ~feature;
1856
1857         return 0;
1858 }
1859 static int mlxsw_sp_set_features(struct net_device *dev,
1860                                  netdev_features_t features)
1861 {
1862         netdev_features_t oper_features = dev->features;
1863         int err = 0;
1864
1865         err |= mlxsw_sp_handle_feature(dev, features, NETIF_F_HW_TC,
1866                                        mlxsw_sp_feature_hw_tc);
1867         err |= mlxsw_sp_handle_feature(dev, features, NETIF_F_LOOPBACK,
1868                                        mlxsw_sp_feature_loopback);
1869
1870         if (err) {
1871                 dev->features = oper_features;
1872                 return -EINVAL;
1873         }
1874
1875         return 0;
1876 }
1877
1878 static struct devlink_port *
1879 mlxsw_sp_port_get_devlink_port(struct net_device *dev)
1880 {
1881         struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
1882         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1883
1884         return mlxsw_core_port_devlink_port_get(mlxsw_sp->core,
1885                                                 mlxsw_sp_port->local_port);
1886 }
1887
1888 static int mlxsw_sp_port_hwtstamp_set(struct mlxsw_sp_port *mlxsw_sp_port,
1889                                       struct ifreq *ifr)
1890 {
1891         struct hwtstamp_config config;
1892         int err;
1893
1894         if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
1895                 return -EFAULT;
1896
1897         err = mlxsw_sp_port->mlxsw_sp->ptp_ops->hwtstamp_set(mlxsw_sp_port,
1898                                                              &config);
1899         if (err)
1900                 return err;
1901
1902         if (copy_to_user(ifr->ifr_data, &config, sizeof(config)))
1903                 return -EFAULT;
1904
1905         return 0;
1906 }
1907
1908 static int mlxsw_sp_port_hwtstamp_get(struct mlxsw_sp_port *mlxsw_sp_port,
1909                                       struct ifreq *ifr)
1910 {
1911         struct hwtstamp_config config;
1912         int err;
1913
1914         err = mlxsw_sp_port->mlxsw_sp->ptp_ops->hwtstamp_get(mlxsw_sp_port,
1915                                                              &config);
1916         if (err)
1917                 return err;
1918
1919         if (copy_to_user(ifr->ifr_data, &config, sizeof(config)))
1920                 return -EFAULT;
1921
1922         return 0;
1923 }
1924
1925 static inline void mlxsw_sp_port_ptp_clear(struct mlxsw_sp_port *mlxsw_sp_port)
1926 {
1927         struct hwtstamp_config config = {0};
1928
1929         mlxsw_sp_port->mlxsw_sp->ptp_ops->hwtstamp_set(mlxsw_sp_port, &config);
1930 }
1931
1932 static int
1933 mlxsw_sp_port_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
1934 {
1935         struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
1936
1937         switch (cmd) {
1938         case SIOCSHWTSTAMP:
1939                 return mlxsw_sp_port_hwtstamp_set(mlxsw_sp_port, ifr);
1940         case SIOCGHWTSTAMP:
1941                 return mlxsw_sp_port_hwtstamp_get(mlxsw_sp_port, ifr);
1942         default:
1943                 return -EOPNOTSUPP;
1944         }
1945 }
1946
1947 static const struct net_device_ops mlxsw_sp_port_netdev_ops = {
1948         .ndo_open               = mlxsw_sp_port_open,
1949         .ndo_stop               = mlxsw_sp_port_stop,
1950         .ndo_start_xmit         = mlxsw_sp_port_xmit,
1951         .ndo_setup_tc           = mlxsw_sp_setup_tc,
1952         .ndo_set_rx_mode        = mlxsw_sp_set_rx_mode,
1953         .ndo_set_mac_address    = mlxsw_sp_port_set_mac_address,
1954         .ndo_change_mtu         = mlxsw_sp_port_change_mtu,
1955         .ndo_get_stats64        = mlxsw_sp_port_get_stats64,
1956         .ndo_has_offload_stats  = mlxsw_sp_port_has_offload_stats,
1957         .ndo_get_offload_stats  = mlxsw_sp_port_get_offload_stats,
1958         .ndo_vlan_rx_add_vid    = mlxsw_sp_port_add_vid,
1959         .ndo_vlan_rx_kill_vid   = mlxsw_sp_port_kill_vid,
1960         .ndo_set_features       = mlxsw_sp_set_features,
1961         .ndo_get_devlink_port   = mlxsw_sp_port_get_devlink_port,
1962         .ndo_do_ioctl           = mlxsw_sp_port_ioctl,
1963 };
1964
1965 static void mlxsw_sp_port_get_drvinfo(struct net_device *dev,
1966                                       struct ethtool_drvinfo *drvinfo)
1967 {
1968         struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
1969         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1970
1971         strlcpy(drvinfo->driver, mlxsw_sp->bus_info->device_kind,
1972                 sizeof(drvinfo->driver));
1973         strlcpy(drvinfo->version, mlxsw_sp_driver_version,
1974                 sizeof(drvinfo->version));
1975         snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
1976                  "%d.%d.%d",
1977                  mlxsw_sp->bus_info->fw_rev.major,
1978                  mlxsw_sp->bus_info->fw_rev.minor,
1979                  mlxsw_sp->bus_info->fw_rev.subminor);
1980         strlcpy(drvinfo->bus_info, mlxsw_sp->bus_info->device_name,
1981                 sizeof(drvinfo->bus_info));
1982 }
1983
1984 static void mlxsw_sp_port_get_pauseparam(struct net_device *dev,
1985                                          struct ethtool_pauseparam *pause)
1986 {
1987         struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
1988
1989         pause->rx_pause = mlxsw_sp_port->link.rx_pause;
1990         pause->tx_pause = mlxsw_sp_port->link.tx_pause;
1991 }
1992
1993 static int mlxsw_sp_port_pause_set(struct mlxsw_sp_port *mlxsw_sp_port,
1994                                    struct ethtool_pauseparam *pause)
1995 {
1996         char pfcc_pl[MLXSW_REG_PFCC_LEN];
1997
1998         mlxsw_reg_pfcc_pack(pfcc_pl, mlxsw_sp_port->local_port);
1999         mlxsw_reg_pfcc_pprx_set(pfcc_pl, pause->rx_pause);
2000         mlxsw_reg_pfcc_pptx_set(pfcc_pl, pause->tx_pause);
2001
2002         return mlxsw_reg_write(mlxsw_sp_port->mlxsw_sp->core, MLXSW_REG(pfcc),
2003                                pfcc_pl);
2004 }
2005
2006 static int mlxsw_sp_port_set_pauseparam(struct net_device *dev,
2007                                         struct ethtool_pauseparam *pause)
2008 {
2009         struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
2010         bool pause_en = pause->tx_pause || pause->rx_pause;
2011         int err;
2012
2013         if (mlxsw_sp_port->dcb.pfc && mlxsw_sp_port->dcb.pfc->pfc_en) {
2014                 netdev_err(dev, "PFC already enabled on port\n");
2015                 return -EINVAL;
2016         }
2017
2018         if (pause->autoneg) {
2019                 netdev_err(dev, "PAUSE frames autonegotiation isn't supported\n");
2020                 return -EINVAL;
2021         }
2022
2023         err = mlxsw_sp_port_headroom_set(mlxsw_sp_port, dev->mtu, pause_en);
2024         if (err) {
2025                 netdev_err(dev, "Failed to configure port's headroom\n");
2026                 return err;
2027         }
2028
2029         err = mlxsw_sp_port_pause_set(mlxsw_sp_port, pause);
2030         if (err) {
2031                 netdev_err(dev, "Failed to set PAUSE parameters\n");
2032                 goto err_port_pause_configure;
2033         }
2034
2035         mlxsw_sp_port->link.rx_pause = pause->rx_pause;
2036         mlxsw_sp_port->link.tx_pause = pause->tx_pause;
2037
2038         return 0;
2039
2040 err_port_pause_configure:
2041         pause_en = mlxsw_sp_port_is_pause_en(mlxsw_sp_port);
2042         mlxsw_sp_port_headroom_set(mlxsw_sp_port, dev->mtu, pause_en);
2043         return err;
2044 }
2045
2046 struct mlxsw_sp_port_hw_stats {
2047         char str[ETH_GSTRING_LEN];
2048         u64 (*getter)(const char *payload);
2049         bool cells_bytes;
2050 };
2051
2052 static struct mlxsw_sp_port_hw_stats mlxsw_sp_port_hw_stats[] = {
2053         {
2054                 .str = "a_frames_transmitted_ok",
2055                 .getter = mlxsw_reg_ppcnt_a_frames_transmitted_ok_get,
2056         },
2057         {
2058                 .str = "a_frames_received_ok",
2059                 .getter = mlxsw_reg_ppcnt_a_frames_received_ok_get,
2060         },
2061         {
2062                 .str = "a_frame_check_sequence_errors",
2063                 .getter = mlxsw_reg_ppcnt_a_frame_check_sequence_errors_get,
2064         },
2065         {
2066                 .str = "a_alignment_errors",
2067                 .getter = mlxsw_reg_ppcnt_a_alignment_errors_get,
2068         },
2069         {
2070                 .str = "a_octets_transmitted_ok",
2071                 .getter = mlxsw_reg_ppcnt_a_octets_transmitted_ok_get,
2072         },
2073         {
2074                 .str = "a_octets_received_ok",
2075                 .getter = mlxsw_reg_ppcnt_a_octets_received_ok_get,
2076         },
2077         {
2078                 .str = "a_multicast_frames_xmitted_ok",
2079                 .getter = mlxsw_reg_ppcnt_a_multicast_frames_xmitted_ok_get,
2080         },
2081         {
2082                 .str = "a_broadcast_frames_xmitted_ok",
2083                 .getter = mlxsw_reg_ppcnt_a_broadcast_frames_xmitted_ok_get,
2084         },
2085         {
2086                 .str = "a_multicast_frames_received_ok",
2087                 .getter = mlxsw_reg_ppcnt_a_multicast_frames_received_ok_get,
2088         },
2089         {
2090                 .str = "a_broadcast_frames_received_ok",
2091                 .getter = mlxsw_reg_ppcnt_a_broadcast_frames_received_ok_get,
2092         },
2093         {
2094                 .str = "a_in_range_length_errors",
2095                 .getter = mlxsw_reg_ppcnt_a_in_range_length_errors_get,
2096         },
2097         {
2098                 .str = "a_out_of_range_length_field",
2099                 .getter = mlxsw_reg_ppcnt_a_out_of_range_length_field_get,
2100         },
2101         {
2102                 .str = "a_frame_too_long_errors",
2103                 .getter = mlxsw_reg_ppcnt_a_frame_too_long_errors_get,
2104         },
2105         {
2106                 .str = "a_symbol_error_during_carrier",
2107                 .getter = mlxsw_reg_ppcnt_a_symbol_error_during_carrier_get,
2108         },
2109         {
2110                 .str = "a_mac_control_frames_transmitted",
2111                 .getter = mlxsw_reg_ppcnt_a_mac_control_frames_transmitted_get,
2112         },
2113         {
2114                 .str = "a_mac_control_frames_received",
2115                 .getter = mlxsw_reg_ppcnt_a_mac_control_frames_received_get,
2116         },
2117         {
2118                 .str = "a_unsupported_opcodes_received",
2119                 .getter = mlxsw_reg_ppcnt_a_unsupported_opcodes_received_get,
2120         },
2121         {
2122                 .str = "a_pause_mac_ctrl_frames_received",
2123                 .getter = mlxsw_reg_ppcnt_a_pause_mac_ctrl_frames_received_get,
2124         },
2125         {
2126                 .str = "a_pause_mac_ctrl_frames_xmitted",
2127                 .getter = mlxsw_reg_ppcnt_a_pause_mac_ctrl_frames_transmitted_get,
2128         },
2129 };
2130
2131 #define MLXSW_SP_PORT_HW_STATS_LEN ARRAY_SIZE(mlxsw_sp_port_hw_stats)
2132
2133 static struct mlxsw_sp_port_hw_stats mlxsw_sp_port_hw_rfc_2863_stats[] = {
2134         {
2135                 .str = "if_in_discards",
2136                 .getter = mlxsw_reg_ppcnt_if_in_discards_get,
2137         },
2138         {
2139                 .str = "if_out_discards",
2140                 .getter = mlxsw_reg_ppcnt_if_out_discards_get,
2141         },
2142         {
2143                 .str = "if_out_errors",
2144                 .getter = mlxsw_reg_ppcnt_if_out_errors_get,
2145         },
2146 };
2147
2148 #define MLXSW_SP_PORT_HW_RFC_2863_STATS_LEN \
2149         ARRAY_SIZE(mlxsw_sp_port_hw_rfc_2863_stats)
2150
2151 static struct mlxsw_sp_port_hw_stats mlxsw_sp_port_hw_rfc_2819_stats[] = {
2152         {
2153                 .str = "ether_stats_undersize_pkts",
2154                 .getter = mlxsw_reg_ppcnt_ether_stats_undersize_pkts_get,
2155         },
2156         {
2157                 .str = "ether_stats_oversize_pkts",
2158                 .getter = mlxsw_reg_ppcnt_ether_stats_oversize_pkts_get,
2159         },
2160         {
2161                 .str = "ether_stats_fragments",
2162                 .getter = mlxsw_reg_ppcnt_ether_stats_fragments_get,
2163         },
2164         {
2165                 .str = "ether_pkts64octets",
2166                 .getter = mlxsw_reg_ppcnt_ether_stats_pkts64octets_get,
2167         },
2168         {
2169                 .str = "ether_pkts65to127octets",
2170                 .getter = mlxsw_reg_ppcnt_ether_stats_pkts65to127octets_get,
2171         },
2172         {
2173                 .str = "ether_pkts128to255octets",
2174                 .getter = mlxsw_reg_ppcnt_ether_stats_pkts128to255octets_get,
2175         },
2176         {
2177                 .str = "ether_pkts256to511octets",
2178                 .getter = mlxsw_reg_ppcnt_ether_stats_pkts256to511octets_get,
2179         },
2180         {
2181                 .str = "ether_pkts512to1023octets",
2182                 .getter = mlxsw_reg_ppcnt_ether_stats_pkts512to1023octets_get,
2183         },
2184         {
2185                 .str = "ether_pkts1024to1518octets",
2186                 .getter = mlxsw_reg_ppcnt_ether_stats_pkts1024to1518octets_get,
2187         },
2188         {
2189                 .str = "ether_pkts1519to2047octets",
2190                 .getter = mlxsw_reg_ppcnt_ether_stats_pkts1519to2047octets_get,
2191         },
2192         {
2193                 .str = "ether_pkts2048to4095octets",
2194                 .getter = mlxsw_reg_ppcnt_ether_stats_pkts2048to4095octets_get,
2195         },
2196         {
2197                 .str = "ether_pkts4096to8191octets",
2198                 .getter = mlxsw_reg_ppcnt_ether_stats_pkts4096to8191octets_get,
2199         },
2200         {
2201                 .str = "ether_pkts8192to10239octets",
2202                 .getter = mlxsw_reg_ppcnt_ether_stats_pkts8192to10239octets_get,
2203         },
2204 };
2205
2206 #define MLXSW_SP_PORT_HW_RFC_2819_STATS_LEN \
2207         ARRAY_SIZE(mlxsw_sp_port_hw_rfc_2819_stats)
2208
2209 static struct mlxsw_sp_port_hw_stats mlxsw_sp_port_hw_rfc_3635_stats[] = {
2210         {
2211                 .str = "dot3stats_fcs_errors",
2212                 .getter = mlxsw_reg_ppcnt_dot3stats_fcs_errors_get,
2213         },
2214         {
2215                 .str = "dot3stats_symbol_errors",
2216                 .getter = mlxsw_reg_ppcnt_dot3stats_symbol_errors_get,
2217         },
2218         {
2219                 .str = "dot3control_in_unknown_opcodes",
2220                 .getter = mlxsw_reg_ppcnt_dot3control_in_unknown_opcodes_get,
2221         },
2222         {
2223                 .str = "dot3in_pause_frames",
2224                 .getter = mlxsw_reg_ppcnt_dot3in_pause_frames_get,
2225         },
2226 };
2227
2228 #define MLXSW_SP_PORT_HW_RFC_3635_STATS_LEN \
2229         ARRAY_SIZE(mlxsw_sp_port_hw_rfc_3635_stats)
2230
2231 static struct mlxsw_sp_port_hw_stats mlxsw_sp_port_hw_ext_stats[] = {
2232         {
2233                 .str = "ecn_marked",
2234                 .getter = mlxsw_reg_ppcnt_ecn_marked_get,
2235         },
2236 };
2237
2238 #define MLXSW_SP_PORT_HW_EXT_STATS_LEN ARRAY_SIZE(mlxsw_sp_port_hw_ext_stats)
2239
2240 static struct mlxsw_sp_port_hw_stats mlxsw_sp_port_hw_discard_stats[] = {
2241         {
2242                 .str = "discard_ingress_general",
2243                 .getter = mlxsw_reg_ppcnt_ingress_general_get,
2244         },
2245         {
2246                 .str = "discard_ingress_policy_engine",
2247                 .getter = mlxsw_reg_ppcnt_ingress_policy_engine_get,
2248         },
2249         {
2250                 .str = "discard_ingress_vlan_membership",
2251                 .getter = mlxsw_reg_ppcnt_ingress_vlan_membership_get,
2252         },
2253         {
2254                 .str = "discard_ingress_tag_frame_type",
2255                 .getter = mlxsw_reg_ppcnt_ingress_tag_frame_type_get,
2256         },
2257         {
2258                 .str = "discard_egress_vlan_membership",
2259                 .getter = mlxsw_reg_ppcnt_egress_vlan_membership_get,
2260         },
2261         {
2262                 .str = "discard_loopback_filter",
2263                 .getter = mlxsw_reg_ppcnt_loopback_filter_get,
2264         },
2265         {
2266                 .str = "discard_egress_general",
2267                 .getter = mlxsw_reg_ppcnt_egress_general_get,
2268         },
2269         {
2270                 .str = "discard_egress_hoq",
2271                 .getter = mlxsw_reg_ppcnt_egress_hoq_get,
2272         },
2273         {
2274                 .str = "discard_egress_policy_engine",
2275                 .getter = mlxsw_reg_ppcnt_egress_policy_engine_get,
2276         },
2277         {
2278                 .str = "discard_ingress_tx_link_down",
2279                 .getter = mlxsw_reg_ppcnt_ingress_tx_link_down_get,
2280         },
2281         {
2282                 .str = "discard_egress_stp_filter",
2283                 .getter = mlxsw_reg_ppcnt_egress_stp_filter_get,
2284         },
2285         {
2286                 .str = "discard_egress_sll",
2287                 .getter = mlxsw_reg_ppcnt_egress_sll_get,
2288         },
2289 };
2290
2291 #define MLXSW_SP_PORT_HW_DISCARD_STATS_LEN \
2292         ARRAY_SIZE(mlxsw_sp_port_hw_discard_stats)
2293
2294 static struct mlxsw_sp_port_hw_stats mlxsw_sp_port_hw_prio_stats[] = {
2295         {
2296                 .str = "rx_octets_prio",
2297                 .getter = mlxsw_reg_ppcnt_rx_octets_get,
2298         },
2299         {
2300                 .str = "rx_frames_prio",
2301                 .getter = mlxsw_reg_ppcnt_rx_frames_get,
2302         },
2303         {
2304                 .str = "tx_octets_prio",
2305                 .getter = mlxsw_reg_ppcnt_tx_octets_get,
2306         },
2307         {
2308                 .str = "tx_frames_prio",
2309                 .getter = mlxsw_reg_ppcnt_tx_frames_get,
2310         },
2311         {
2312                 .str = "rx_pause_prio",
2313                 .getter = mlxsw_reg_ppcnt_rx_pause_get,
2314         },
2315         {
2316                 .str = "rx_pause_duration_prio",
2317                 .getter = mlxsw_reg_ppcnt_rx_pause_duration_get,
2318         },
2319         {
2320                 .str = "tx_pause_prio",
2321                 .getter = mlxsw_reg_ppcnt_tx_pause_get,
2322         },
2323         {
2324                 .str = "tx_pause_duration_prio",
2325                 .getter = mlxsw_reg_ppcnt_tx_pause_duration_get,
2326         },
2327 };
2328
2329 #define MLXSW_SP_PORT_HW_PRIO_STATS_LEN ARRAY_SIZE(mlxsw_sp_port_hw_prio_stats)
2330
2331 static struct mlxsw_sp_port_hw_stats mlxsw_sp_port_hw_tc_stats[] = {
2332         {
2333                 .str = "tc_transmit_queue_tc",
2334                 .getter = mlxsw_reg_ppcnt_tc_transmit_queue_get,
2335                 .cells_bytes = true,
2336         },
2337         {
2338                 .str = "tc_no_buffer_discard_uc_tc",
2339                 .getter = mlxsw_reg_ppcnt_tc_no_buffer_discard_uc_get,
2340         },
2341 };
2342
2343 #define MLXSW_SP_PORT_HW_TC_STATS_LEN ARRAY_SIZE(mlxsw_sp_port_hw_tc_stats)
2344
2345 #define MLXSW_SP_PORT_ETHTOOL_STATS_LEN (MLXSW_SP_PORT_HW_STATS_LEN + \
2346                                          MLXSW_SP_PORT_HW_RFC_2863_STATS_LEN + \
2347                                          MLXSW_SP_PORT_HW_RFC_2819_STATS_LEN + \
2348                                          MLXSW_SP_PORT_HW_RFC_3635_STATS_LEN + \
2349                                          MLXSW_SP_PORT_HW_EXT_STATS_LEN + \
2350                                          MLXSW_SP_PORT_HW_DISCARD_STATS_LEN + \
2351                                          (MLXSW_SP_PORT_HW_PRIO_STATS_LEN * \
2352                                           IEEE_8021QAZ_MAX_TCS) + \
2353                                          (MLXSW_SP_PORT_HW_TC_STATS_LEN * \
2354                                           TC_MAX_QUEUE))
2355
2356 static void mlxsw_sp_port_get_prio_strings(u8 **p, int prio)
2357 {
2358         int i;
2359
2360         for (i = 0; i < MLXSW_SP_PORT_HW_PRIO_STATS_LEN; i++) {
2361                 snprintf(*p, ETH_GSTRING_LEN, "%.29s_%.1d",
2362                          mlxsw_sp_port_hw_prio_stats[i].str, prio);
2363                 *p += ETH_GSTRING_LEN;
2364         }
2365 }
2366
2367 static void mlxsw_sp_port_get_tc_strings(u8 **p, int tc)
2368 {
2369         int i;
2370
2371         for (i = 0; i < MLXSW_SP_PORT_HW_TC_STATS_LEN; i++) {
2372                 snprintf(*p, ETH_GSTRING_LEN, "%.29s_%.1d",
2373                          mlxsw_sp_port_hw_tc_stats[i].str, tc);
2374                 *p += ETH_GSTRING_LEN;
2375         }
2376 }
2377
2378 static void mlxsw_sp_port_get_strings(struct net_device *dev,
2379                                       u32 stringset, u8 *data)
2380 {
2381         struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
2382         u8 *p = data;
2383         int i;
2384
2385         switch (stringset) {
2386         case ETH_SS_STATS:
2387                 for (i = 0; i < MLXSW_SP_PORT_HW_STATS_LEN; i++) {
2388                         memcpy(p, mlxsw_sp_port_hw_stats[i].str,
2389                                ETH_GSTRING_LEN);
2390                         p += ETH_GSTRING_LEN;
2391                 }
2392
2393                 for (i = 0; i < MLXSW_SP_PORT_HW_RFC_2863_STATS_LEN; i++) {
2394                         memcpy(p, mlxsw_sp_port_hw_rfc_2863_stats[i].str,
2395                                ETH_GSTRING_LEN);
2396                         p += ETH_GSTRING_LEN;
2397                 }
2398
2399                 for (i = 0; i < MLXSW_SP_PORT_HW_RFC_2819_STATS_LEN; i++) {
2400                         memcpy(p, mlxsw_sp_port_hw_rfc_2819_stats[i].str,
2401                                ETH_GSTRING_LEN);
2402                         p += ETH_GSTRING_LEN;
2403                 }
2404
2405                 for (i = 0; i < MLXSW_SP_PORT_HW_RFC_3635_STATS_LEN; i++) {
2406                         memcpy(p, mlxsw_sp_port_hw_rfc_3635_stats[i].str,
2407                                ETH_GSTRING_LEN);
2408                         p += ETH_GSTRING_LEN;
2409                 }
2410
2411                 for (i = 0; i < MLXSW_SP_PORT_HW_EXT_STATS_LEN; i++) {
2412                         memcpy(p, mlxsw_sp_port_hw_ext_stats[i].str,
2413                                ETH_GSTRING_LEN);
2414                         p += ETH_GSTRING_LEN;
2415                 }
2416
2417                 for (i = 0; i < MLXSW_SP_PORT_HW_DISCARD_STATS_LEN; i++) {
2418                         memcpy(p, mlxsw_sp_port_hw_discard_stats[i].str,
2419                                ETH_GSTRING_LEN);
2420                         p += ETH_GSTRING_LEN;
2421                 }
2422
2423                 for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++)
2424                         mlxsw_sp_port_get_prio_strings(&p, i);
2425
2426                 for (i = 0; i < TC_MAX_QUEUE; i++)
2427                         mlxsw_sp_port_get_tc_strings(&p, i);
2428
2429                 mlxsw_sp_port->mlxsw_sp->ptp_ops->get_stats_strings(&p);
2430                 break;
2431         }
2432 }
2433
2434 static int mlxsw_sp_port_set_phys_id(struct net_device *dev,
2435                                      enum ethtool_phys_id_state state)
2436 {
2437         struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
2438         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
2439         char mlcr_pl[MLXSW_REG_MLCR_LEN];
2440         bool active;
2441
2442         switch (state) {
2443         case ETHTOOL_ID_ACTIVE:
2444                 active = true;
2445                 break;
2446         case ETHTOOL_ID_INACTIVE:
2447                 active = false;
2448                 break;
2449         default:
2450                 return -EOPNOTSUPP;
2451         }
2452
2453         mlxsw_reg_mlcr_pack(mlcr_pl, mlxsw_sp_port->local_port, active);
2454         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mlcr), mlcr_pl);
2455 }
2456
2457 static int
2458 mlxsw_sp_get_hw_stats_by_group(struct mlxsw_sp_port_hw_stats **p_hw_stats,
2459                                int *p_len, enum mlxsw_reg_ppcnt_grp grp)
2460 {
2461         switch (grp) {
2462         case MLXSW_REG_PPCNT_IEEE_8023_CNT:
2463                 *p_hw_stats = mlxsw_sp_port_hw_stats;
2464                 *p_len = MLXSW_SP_PORT_HW_STATS_LEN;
2465                 break;
2466         case MLXSW_REG_PPCNT_RFC_2863_CNT:
2467                 *p_hw_stats = mlxsw_sp_port_hw_rfc_2863_stats;
2468                 *p_len = MLXSW_SP_PORT_HW_RFC_2863_STATS_LEN;
2469                 break;
2470         case MLXSW_REG_PPCNT_RFC_2819_CNT:
2471                 *p_hw_stats = mlxsw_sp_port_hw_rfc_2819_stats;
2472                 *p_len = MLXSW_SP_PORT_HW_RFC_2819_STATS_LEN;
2473                 break;
2474         case MLXSW_REG_PPCNT_RFC_3635_CNT:
2475                 *p_hw_stats = mlxsw_sp_port_hw_rfc_3635_stats;
2476                 *p_len = MLXSW_SP_PORT_HW_RFC_3635_STATS_LEN;
2477                 break;
2478         case MLXSW_REG_PPCNT_EXT_CNT:
2479                 *p_hw_stats = mlxsw_sp_port_hw_ext_stats;
2480                 *p_len = MLXSW_SP_PORT_HW_EXT_STATS_LEN;
2481                 break;
2482         case MLXSW_REG_PPCNT_DISCARD_CNT:
2483                 *p_hw_stats = mlxsw_sp_port_hw_discard_stats;
2484                 *p_len = MLXSW_SP_PORT_HW_DISCARD_STATS_LEN;
2485                 break;
2486         case MLXSW_REG_PPCNT_PRIO_CNT:
2487                 *p_hw_stats = mlxsw_sp_port_hw_prio_stats;
2488                 *p_len = MLXSW_SP_PORT_HW_PRIO_STATS_LEN;
2489                 break;
2490         case MLXSW_REG_PPCNT_TC_CNT:
2491                 *p_hw_stats = mlxsw_sp_port_hw_tc_stats;
2492                 *p_len = MLXSW_SP_PORT_HW_TC_STATS_LEN;
2493                 break;
2494         default:
2495                 WARN_ON(1);
2496                 return -EOPNOTSUPP;
2497         }
2498         return 0;
2499 }
2500
2501 static void __mlxsw_sp_port_get_stats(struct net_device *dev,
2502                                       enum mlxsw_reg_ppcnt_grp grp, int prio,
2503                                       u64 *data, int data_index)
2504 {
2505         struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
2506         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
2507         struct mlxsw_sp_port_hw_stats *hw_stats;
2508         char ppcnt_pl[MLXSW_REG_PPCNT_LEN];
2509         int i, len;
2510         int err;
2511
2512         err = mlxsw_sp_get_hw_stats_by_group(&hw_stats, &len, grp);
2513         if (err)
2514                 return;
2515         mlxsw_sp_port_get_stats_raw(dev, grp, prio, ppcnt_pl);
2516         for (i = 0; i < len; i++) {
2517                 data[data_index + i] = hw_stats[i].getter(ppcnt_pl);
2518                 if (!hw_stats[i].cells_bytes)
2519                         continue;
2520                 data[data_index + i] = mlxsw_sp_cells_bytes(mlxsw_sp,
2521                                                             data[data_index + i]);
2522         }
2523 }
2524
2525 static void mlxsw_sp_port_get_stats(struct net_device *dev,
2526                                     struct ethtool_stats *stats, u64 *data)
2527 {
2528         struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
2529         int i, data_index = 0;
2530
2531         /* IEEE 802.3 Counters */
2532         __mlxsw_sp_port_get_stats(dev, MLXSW_REG_PPCNT_IEEE_8023_CNT, 0,
2533                                   data, data_index);
2534         data_index = MLXSW_SP_PORT_HW_STATS_LEN;
2535
2536         /* RFC 2863 Counters */
2537         __mlxsw_sp_port_get_stats(dev, MLXSW_REG_PPCNT_RFC_2863_CNT, 0,
2538                                   data, data_index);
2539         data_index += MLXSW_SP_PORT_HW_RFC_2863_STATS_LEN;
2540
2541         /* RFC 2819 Counters */
2542         __mlxsw_sp_port_get_stats(dev, MLXSW_REG_PPCNT_RFC_2819_CNT, 0,
2543                                   data, data_index);
2544         data_index += MLXSW_SP_PORT_HW_RFC_2819_STATS_LEN;
2545
2546         /* RFC 3635 Counters */
2547         __mlxsw_sp_port_get_stats(dev, MLXSW_REG_PPCNT_RFC_3635_CNT, 0,
2548                                   data, data_index);
2549         data_index += MLXSW_SP_PORT_HW_RFC_3635_STATS_LEN;
2550
2551         /* Extended Counters */
2552         __mlxsw_sp_port_get_stats(dev, MLXSW_REG_PPCNT_EXT_CNT, 0,
2553                                   data, data_index);
2554         data_index += MLXSW_SP_PORT_HW_EXT_STATS_LEN;
2555
2556         /* Discard Counters */
2557         __mlxsw_sp_port_get_stats(dev, MLXSW_REG_PPCNT_DISCARD_CNT, 0,
2558                                   data, data_index);
2559         data_index += MLXSW_SP_PORT_HW_DISCARD_STATS_LEN;
2560
2561         /* Per-Priority Counters */
2562         for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
2563                 __mlxsw_sp_port_get_stats(dev, MLXSW_REG_PPCNT_PRIO_CNT, i,
2564                                           data, data_index);
2565                 data_index += MLXSW_SP_PORT_HW_PRIO_STATS_LEN;
2566         }
2567
2568         /* Per-TC Counters */
2569         for (i = 0; i < TC_MAX_QUEUE; i++) {
2570                 __mlxsw_sp_port_get_stats(dev, MLXSW_REG_PPCNT_TC_CNT, i,
2571                                           data, data_index);
2572                 data_index += MLXSW_SP_PORT_HW_TC_STATS_LEN;
2573         }
2574
2575         /* PTP counters */
2576         mlxsw_sp_port->mlxsw_sp->ptp_ops->get_stats(mlxsw_sp_port,
2577                                                     data, data_index);
2578         data_index += mlxsw_sp_port->mlxsw_sp->ptp_ops->get_stats_count();
2579 }
2580
2581 static int mlxsw_sp_port_get_sset_count(struct net_device *dev, int sset)
2582 {
2583         struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
2584
2585         switch (sset) {
2586         case ETH_SS_STATS:
2587                 return MLXSW_SP_PORT_ETHTOOL_STATS_LEN +
2588                        mlxsw_sp_port->mlxsw_sp->ptp_ops->get_stats_count();
2589         default:
2590                 return -EOPNOTSUPP;
2591         }
2592 }
2593
2594 struct mlxsw_sp1_port_link_mode {
2595         enum ethtool_link_mode_bit_indices mask_ethtool;
2596         u32 mask;
2597         u32 speed;
2598 };
2599
2600 static const struct mlxsw_sp1_port_link_mode mlxsw_sp1_port_link_mode[] = {
2601         {
2602                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_100BASE_T,
2603                 .mask_ethtool   = ETHTOOL_LINK_MODE_100baseT_Full_BIT,
2604                 .speed          = SPEED_100,
2605         },
2606         {
2607                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_SGMII |
2608                                   MLXSW_REG_PTYS_ETH_SPEED_1000BASE_KX,
2609                 .mask_ethtool   = ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
2610                 .speed          = SPEED_1000,
2611         },
2612         {
2613                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_10GBASE_T,
2614                 .mask_ethtool   = ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
2615                 .speed          = SPEED_10000,
2616         },
2617         {
2618                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_10GBASE_CX4 |
2619                                   MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KX4,
2620                 .mask_ethtool   = ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT,
2621                 .speed          = SPEED_10000,
2622         },
2623         {
2624                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KR |
2625                                   MLXSW_REG_PTYS_ETH_SPEED_10GBASE_CR |
2626                                   MLXSW_REG_PTYS_ETH_SPEED_10GBASE_SR |
2627                                   MLXSW_REG_PTYS_ETH_SPEED_10GBASE_ER_LR,
2628                 .mask_ethtool   = ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
2629                 .speed          = SPEED_10000,
2630         },
2631         {
2632                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_20GBASE_KR2,
2633                 .mask_ethtool   = ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT,
2634                 .speed          = SPEED_20000,
2635         },
2636         {
2637                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_40GBASE_CR4,
2638                 .mask_ethtool   = ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT,
2639                 .speed          = SPEED_40000,
2640         },
2641         {
2642                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_40GBASE_KR4,
2643                 .mask_ethtool   = ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT,
2644                 .speed          = SPEED_40000,
2645         },
2646         {
2647                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_40GBASE_SR4,
2648                 .mask_ethtool   = ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT,
2649                 .speed          = SPEED_40000,
2650         },
2651         {
2652                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_40GBASE_LR4_ER4,
2653                 .mask_ethtool   = ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT,
2654                 .speed          = SPEED_40000,
2655         },
2656         {
2657                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_25GBASE_CR,
2658                 .mask_ethtool   = ETHTOOL_LINK_MODE_25000baseCR_Full_BIT,
2659                 .speed          = SPEED_25000,
2660         },
2661         {
2662                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_25GBASE_KR,
2663                 .mask_ethtool   = ETHTOOL_LINK_MODE_25000baseKR_Full_BIT,
2664                 .speed          = SPEED_25000,
2665         },
2666         {
2667                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_25GBASE_SR,
2668                 .mask_ethtool   = ETHTOOL_LINK_MODE_25000baseSR_Full_BIT,
2669                 .speed          = SPEED_25000,
2670         },
2671         {
2672                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_50GBASE_CR2,
2673                 .mask_ethtool   = ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT,
2674                 .speed          = SPEED_50000,
2675         },
2676         {
2677                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_50GBASE_KR2,
2678                 .mask_ethtool   = ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT,
2679                 .speed          = SPEED_50000,
2680         },
2681         {
2682                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_50GBASE_SR2,
2683                 .mask_ethtool   = ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT,
2684                 .speed          = SPEED_50000,
2685         },
2686         {
2687                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_100GBASE_CR4,
2688                 .mask_ethtool   = ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT,
2689                 .speed          = SPEED_100000,
2690         },
2691         {
2692                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_100GBASE_SR4,
2693                 .mask_ethtool   = ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT,
2694                 .speed          = SPEED_100000,
2695         },
2696         {
2697                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_100GBASE_KR4,
2698                 .mask_ethtool   = ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT,
2699                 .speed          = SPEED_100000,
2700         },
2701         {
2702                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_100GBASE_LR4_ER4,
2703                 .mask_ethtool   = ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT,
2704                 .speed          = SPEED_100000,
2705         },
2706 };
2707
2708 #define MLXSW_SP1_PORT_LINK_MODE_LEN ARRAY_SIZE(mlxsw_sp1_port_link_mode)
2709
2710 static void
2711 mlxsw_sp1_from_ptys_supported_port(struct mlxsw_sp *mlxsw_sp,
2712                                    u32 ptys_eth_proto,
2713                                    struct ethtool_link_ksettings *cmd)
2714 {
2715         if (ptys_eth_proto & (MLXSW_REG_PTYS_ETH_SPEED_10GBASE_CR |
2716                               MLXSW_REG_PTYS_ETH_SPEED_10GBASE_SR |
2717                               MLXSW_REG_PTYS_ETH_SPEED_40GBASE_CR4 |
2718                               MLXSW_REG_PTYS_ETH_SPEED_40GBASE_SR4 |
2719                               MLXSW_REG_PTYS_ETH_SPEED_100GBASE_SR4 |
2720                               MLXSW_REG_PTYS_ETH_SPEED_SGMII))
2721                 ethtool_link_ksettings_add_link_mode(cmd, supported, FIBRE);
2722
2723         if (ptys_eth_proto & (MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KR |
2724                               MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KX4 |
2725                               MLXSW_REG_PTYS_ETH_SPEED_40GBASE_KR4 |
2726                               MLXSW_REG_PTYS_ETH_SPEED_100GBASE_KR4 |
2727                               MLXSW_REG_PTYS_ETH_SPEED_1000BASE_KX))
2728                 ethtool_link_ksettings_add_link_mode(cmd, supported, Backplane);
2729 }
2730
2731 static void
2732 mlxsw_sp1_from_ptys_link(struct mlxsw_sp *mlxsw_sp, u32 ptys_eth_proto,
2733                          u8 width, unsigned long *mode)
2734 {
2735         int i;
2736
2737         for (i = 0; i < MLXSW_SP1_PORT_LINK_MODE_LEN; i++) {
2738                 if (ptys_eth_proto & mlxsw_sp1_port_link_mode[i].mask)
2739                         __set_bit(mlxsw_sp1_port_link_mode[i].mask_ethtool,
2740                                   mode);
2741         }
2742 }
2743
2744 static u32
2745 mlxsw_sp1_from_ptys_speed(struct mlxsw_sp *mlxsw_sp, u32 ptys_eth_proto)
2746 {
2747         int i;
2748
2749         for (i = 0; i < MLXSW_SP1_PORT_LINK_MODE_LEN; i++) {
2750                 if (ptys_eth_proto & mlxsw_sp1_port_link_mode[i].mask)
2751                         return mlxsw_sp1_port_link_mode[i].speed;
2752         }
2753
2754         return SPEED_UNKNOWN;
2755 }
2756
2757 static void
2758 mlxsw_sp1_from_ptys_speed_duplex(struct mlxsw_sp *mlxsw_sp, bool carrier_ok,
2759                                  u32 ptys_eth_proto,
2760                                  struct ethtool_link_ksettings *cmd)
2761 {
2762         cmd->base.speed = SPEED_UNKNOWN;
2763         cmd->base.duplex = DUPLEX_UNKNOWN;
2764
2765         if (!carrier_ok)
2766                 return;
2767
2768         cmd->base.speed = mlxsw_sp1_from_ptys_speed(mlxsw_sp, ptys_eth_proto);
2769         if (cmd->base.speed != SPEED_UNKNOWN)
2770                 cmd->base.duplex = DUPLEX_FULL;
2771 }
2772
2773 static u32
2774 mlxsw_sp1_to_ptys_advert_link(struct mlxsw_sp *mlxsw_sp, u8 width,
2775                               const struct ethtool_link_ksettings *cmd)
2776 {
2777         u32 ptys_proto = 0;
2778         int i;
2779
2780         for (i = 0; i < MLXSW_SP1_PORT_LINK_MODE_LEN; i++) {
2781                 if (test_bit(mlxsw_sp1_port_link_mode[i].mask_ethtool,
2782                              cmd->link_modes.advertising))
2783                         ptys_proto |= mlxsw_sp1_port_link_mode[i].mask;
2784         }
2785         return ptys_proto;
2786 }
2787
2788 static u32 mlxsw_sp1_to_ptys_speed(struct mlxsw_sp *mlxsw_sp, u8 width,
2789                                    u32 speed)
2790 {
2791         u32 ptys_proto = 0;
2792         int i;
2793
2794         for (i = 0; i < MLXSW_SP1_PORT_LINK_MODE_LEN; i++) {
2795                 if (speed == mlxsw_sp1_port_link_mode[i].speed)
2796                         ptys_proto |= mlxsw_sp1_port_link_mode[i].mask;
2797         }
2798         return ptys_proto;
2799 }
2800
2801 static void
2802 mlxsw_sp1_reg_ptys_eth_pack(struct mlxsw_sp *mlxsw_sp, char *payload,
2803                             u8 local_port, u32 proto_admin, bool autoneg)
2804 {
2805         mlxsw_reg_ptys_eth_pack(payload, local_port, proto_admin, autoneg);
2806 }
2807
2808 static void
2809 mlxsw_sp1_reg_ptys_eth_unpack(struct mlxsw_sp *mlxsw_sp, char *payload,
2810                               u32 *p_eth_proto_cap, u32 *p_eth_proto_admin,
2811                               u32 *p_eth_proto_oper)
2812 {
2813         mlxsw_reg_ptys_eth_unpack(payload, p_eth_proto_cap, p_eth_proto_admin,
2814                                   p_eth_proto_oper);
2815 }
2816
2817 static const struct mlxsw_sp_port_type_speed_ops
2818 mlxsw_sp1_port_type_speed_ops = {
2819         .from_ptys_supported_port       = mlxsw_sp1_from_ptys_supported_port,
2820         .from_ptys_link                 = mlxsw_sp1_from_ptys_link,
2821         .from_ptys_speed                = mlxsw_sp1_from_ptys_speed,
2822         .from_ptys_speed_duplex         = mlxsw_sp1_from_ptys_speed_duplex,
2823         .to_ptys_advert_link            = mlxsw_sp1_to_ptys_advert_link,
2824         .to_ptys_speed                  = mlxsw_sp1_to_ptys_speed,
2825         .reg_ptys_eth_pack              = mlxsw_sp1_reg_ptys_eth_pack,
2826         .reg_ptys_eth_unpack            = mlxsw_sp1_reg_ptys_eth_unpack,
2827 };
2828
2829 static const enum ethtool_link_mode_bit_indices
2830 mlxsw_sp2_mask_ethtool_sgmii_100m[] = {
2831         ETHTOOL_LINK_MODE_100baseT_Full_BIT,
2832 };
2833
2834 #define MLXSW_SP2_MASK_ETHTOOL_SGMII_100M_LEN \
2835         ARRAY_SIZE(mlxsw_sp2_mask_ethtool_sgmii_100m)
2836
2837 static const enum ethtool_link_mode_bit_indices
2838 mlxsw_sp2_mask_ethtool_1000base_x_sgmii[] = {
2839         ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
2840         ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
2841 };
2842
2843 #define MLXSW_SP2_MASK_ETHTOOL_1000BASE_X_SGMII_LEN \
2844         ARRAY_SIZE(mlxsw_sp2_mask_ethtool_1000base_x_sgmii)
2845
2846 static const enum ethtool_link_mode_bit_indices
2847 mlxsw_sp2_mask_ethtool_2_5gbase_x_2_5gmii[] = {
2848         ETHTOOL_LINK_MODE_2500baseX_Full_BIT,
2849 };
2850
2851 #define MLXSW_SP2_MASK_ETHTOOL_2_5GBASE_X_2_5GMII_LEN \
2852         ARRAY_SIZE(mlxsw_sp2_mask_ethtool_2_5gbase_x_2_5gmii)
2853
2854 static const enum ethtool_link_mode_bit_indices
2855 mlxsw_sp2_mask_ethtool_5gbase_r[] = {
2856         ETHTOOL_LINK_MODE_5000baseT_Full_BIT,
2857 };
2858
2859 #define MLXSW_SP2_MASK_ETHTOOL_5GBASE_R_LEN \
2860         ARRAY_SIZE(mlxsw_sp2_mask_ethtool_5gbase_r)
2861
2862 static const enum ethtool_link_mode_bit_indices
2863 mlxsw_sp2_mask_ethtool_xfi_xaui_1_10g[] = {
2864         ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
2865         ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
2866         ETHTOOL_LINK_MODE_10000baseR_FEC_BIT,
2867         ETHTOOL_LINK_MODE_10000baseCR_Full_BIT,
2868         ETHTOOL_LINK_MODE_10000baseSR_Full_BIT,
2869         ETHTOOL_LINK_MODE_10000baseLR_Full_BIT,
2870         ETHTOOL_LINK_MODE_10000baseER_Full_BIT,
2871 };
2872
2873 #define MLXSW_SP2_MASK_ETHTOOL_XFI_XAUI_1_10G_LEN \
2874         ARRAY_SIZE(mlxsw_sp2_mask_ethtool_xfi_xaui_1_10g)
2875
2876 static const enum ethtool_link_mode_bit_indices
2877 mlxsw_sp2_mask_ethtool_xlaui_4_xlppi_4_40g[] = {
2878         ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT,
2879         ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT,
2880         ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT,
2881         ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT,
2882 };
2883
2884 #define MLXSW_SP2_MASK_ETHTOOL_XLAUI_4_XLPPI_4_40G_LEN \
2885         ARRAY_SIZE(mlxsw_sp2_mask_ethtool_xlaui_4_xlppi_4_40g)
2886
2887 static const enum ethtool_link_mode_bit_indices
2888 mlxsw_sp2_mask_ethtool_25gaui_1_25gbase_cr_kr[] = {
2889         ETHTOOL_LINK_MODE_25000baseCR_Full_BIT,
2890         ETHTOOL_LINK_MODE_25000baseKR_Full_BIT,
2891         ETHTOOL_LINK_MODE_25000baseSR_Full_BIT,
2892 };
2893
2894 #define MLXSW_SP2_MASK_ETHTOOL_25GAUI_1_25GBASE_CR_KR_LEN \
2895         ARRAY_SIZE(mlxsw_sp2_mask_ethtool_25gaui_1_25gbase_cr_kr)
2896
2897 static const enum ethtool_link_mode_bit_indices
2898 mlxsw_sp2_mask_ethtool_50gaui_2_laui_2_50gbase_cr2_kr2[] = {
2899         ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT,
2900         ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT,
2901         ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT,
2902 };
2903
2904 #define MLXSW_SP2_MASK_ETHTOOL_50GAUI_2_LAUI_2_50GBASE_CR2_KR2_LEN \
2905         ARRAY_SIZE(mlxsw_sp2_mask_ethtool_50gaui_2_laui_2_50gbase_cr2_kr2)
2906
2907 static const enum ethtool_link_mode_bit_indices
2908 mlxsw_sp2_mask_ethtool_50gaui_1_laui_1_50gbase_cr_kr[] = {
2909         ETHTOOL_LINK_MODE_50000baseKR_Full_BIT,
2910         ETHTOOL_LINK_MODE_50000baseSR_Full_BIT,
2911         ETHTOOL_LINK_MODE_50000baseCR_Full_BIT,
2912         ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT,
2913         ETHTOOL_LINK_MODE_50000baseDR_Full_BIT,
2914 };
2915
2916 #define MLXSW_SP2_MASK_ETHTOOL_50GAUI_1_LAUI_1_50GBASE_CR_KR_LEN \
2917         ARRAY_SIZE(mlxsw_sp2_mask_ethtool_50gaui_1_laui_1_50gbase_cr_kr)
2918
2919 static const enum ethtool_link_mode_bit_indices
2920 mlxsw_sp2_mask_ethtool_caui_4_100gbase_cr4_kr4[] = {
2921         ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT,
2922         ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT,
2923         ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT,
2924         ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT,
2925 };
2926
2927 #define MLXSW_SP2_MASK_ETHTOOL_CAUI_4_100GBASE_CR4_KR4_LEN \
2928         ARRAY_SIZE(mlxsw_sp2_mask_ethtool_caui_4_100gbase_cr4_kr4)
2929
2930 static const enum ethtool_link_mode_bit_indices
2931 mlxsw_sp2_mask_ethtool_100gaui_2_100gbase_cr2_kr2[] = {
2932         ETHTOOL_LINK_MODE_100000baseKR2_Full_BIT,
2933         ETHTOOL_LINK_MODE_100000baseSR2_Full_BIT,
2934         ETHTOOL_LINK_MODE_100000baseCR2_Full_BIT,
2935         ETHTOOL_LINK_MODE_100000baseLR2_ER2_FR2_Full_BIT,
2936         ETHTOOL_LINK_MODE_100000baseDR2_Full_BIT,
2937 };
2938
2939 #define MLXSW_SP2_MASK_ETHTOOL_100GAUI_2_100GBASE_CR2_KR2_LEN \
2940         ARRAY_SIZE(mlxsw_sp2_mask_ethtool_100gaui_2_100gbase_cr2_kr2)
2941
2942 static const enum ethtool_link_mode_bit_indices
2943 mlxsw_sp2_mask_ethtool_200gaui_4_200gbase_cr4_kr4[] = {
2944         ETHTOOL_LINK_MODE_200000baseKR4_Full_BIT,
2945         ETHTOOL_LINK_MODE_200000baseSR4_Full_BIT,
2946         ETHTOOL_LINK_MODE_200000baseLR4_ER4_FR4_Full_BIT,
2947         ETHTOOL_LINK_MODE_200000baseDR4_Full_BIT,
2948         ETHTOOL_LINK_MODE_200000baseCR4_Full_BIT,
2949 };
2950
2951 #define MLXSW_SP2_MASK_ETHTOOL_200GAUI_4_200GBASE_CR4_KR4_LEN \
2952         ARRAY_SIZE(mlxsw_sp2_mask_ethtool_200gaui_4_200gbase_cr4_kr4)
2953
2954 static const enum ethtool_link_mode_bit_indices
2955 mlxsw_sp2_mask_ethtool_400gaui_8[] = {
2956         ETHTOOL_LINK_MODE_400000baseKR8_Full_BIT,
2957         ETHTOOL_LINK_MODE_400000baseSR8_Full_BIT,
2958         ETHTOOL_LINK_MODE_400000baseLR8_ER8_FR8_Full_BIT,
2959         ETHTOOL_LINK_MODE_400000baseDR8_Full_BIT,
2960         ETHTOOL_LINK_MODE_400000baseCR8_Full_BIT,
2961 };
2962
2963 #define MLXSW_SP2_MASK_ETHTOOL_400GAUI_8_LEN \
2964         ARRAY_SIZE(mlxsw_sp2_mask_ethtool_400gaui_8)
2965
2966 #define MLXSW_SP_PORT_MASK_WIDTH_1X     BIT(0)
2967 #define MLXSW_SP_PORT_MASK_WIDTH_2X     BIT(1)
2968 #define MLXSW_SP_PORT_MASK_WIDTH_4X     BIT(2)
2969 #define MLXSW_SP_PORT_MASK_WIDTH_8X     BIT(3)
2970
2971 static u8 mlxsw_sp_port_mask_width_get(u8 width)
2972 {
2973         switch (width) {
2974         case 1:
2975                 return MLXSW_SP_PORT_MASK_WIDTH_1X;
2976         case 2:
2977                 return MLXSW_SP_PORT_MASK_WIDTH_2X;
2978         case 4:
2979                 return MLXSW_SP_PORT_MASK_WIDTH_4X;
2980         case 8:
2981                 return MLXSW_SP_PORT_MASK_WIDTH_8X;
2982         default:
2983                 WARN_ON_ONCE(1);
2984                 return 0;
2985         }
2986 }
2987
2988 struct mlxsw_sp2_port_link_mode {
2989         const enum ethtool_link_mode_bit_indices *mask_ethtool;
2990         int m_ethtool_len;
2991         u32 mask;
2992         u32 speed;
2993         u8 mask_width;
2994 };
2995
2996 static const struct mlxsw_sp2_port_link_mode mlxsw_sp2_port_link_mode[] = {
2997         {
2998                 .mask           = MLXSW_REG_PTYS_EXT_ETH_SPEED_SGMII_100M,
2999                 .mask_ethtool   = mlxsw_sp2_mask_ethtool_sgmii_100m,
3000                 .m_ethtool_len  = MLXSW_SP2_MASK_ETHTOOL_SGMII_100M_LEN,
3001                 .mask_width     = MLXSW_SP_PORT_MASK_WIDTH_1X |
3002                                   MLXSW_SP_PORT_MASK_WIDTH_2X |
3003                                   MLXSW_SP_PORT_MASK_WIDTH_4X |
3004                                   MLXSW_SP_PORT_MASK_WIDTH_8X,
3005                 .speed          = SPEED_100,
3006         },
3007         {
3008                 .mask           = MLXSW_REG_PTYS_EXT_ETH_SPEED_1000BASE_X_SGMII,
3009                 .mask_ethtool   = mlxsw_sp2_mask_ethtool_1000base_x_sgmii,
3010                 .m_ethtool_len  = MLXSW_SP2_MASK_ETHTOOL_1000BASE_X_SGMII_LEN,
3011                 .mask_width     = MLXSW_SP_PORT_MASK_WIDTH_1X |
3012                                   MLXSW_SP_PORT_MASK_WIDTH_2X |
3013                                   MLXSW_SP_PORT_MASK_WIDTH_4X |
3014                                   MLXSW_SP_PORT_MASK_WIDTH_8X,
3015                 .speed          = SPEED_1000,
3016         },
3017         {
3018                 .mask           = MLXSW_REG_PTYS_EXT_ETH_SPEED_2_5GBASE_X_2_5GMII,
3019                 .mask_ethtool   = mlxsw_sp2_mask_ethtool_2_5gbase_x_2_5gmii,
3020                 .m_ethtool_len  = MLXSW_SP2_MASK_ETHTOOL_2_5GBASE_X_2_5GMII_LEN,
3021                 .mask_width     = MLXSW_SP_PORT_MASK_WIDTH_1X |
3022                                   MLXSW_SP_PORT_MASK_WIDTH_2X |
3023                                   MLXSW_SP_PORT_MASK_WIDTH_4X |
3024                                   MLXSW_SP_PORT_MASK_WIDTH_8X,
3025                 .speed          = SPEED_2500,
3026         },
3027         {
3028                 .mask           = MLXSW_REG_PTYS_EXT_ETH_SPEED_5GBASE_R,
3029                 .mask_ethtool   = mlxsw_sp2_mask_ethtool_5gbase_r,
3030                 .m_ethtool_len  = MLXSW_SP2_MASK_ETHTOOL_5GBASE_R_LEN,
3031                 .mask_width     = MLXSW_SP_PORT_MASK_WIDTH_1X |
3032                                   MLXSW_SP_PORT_MASK_WIDTH_2X |
3033                                   MLXSW_SP_PORT_MASK_WIDTH_4X |
3034                                   MLXSW_SP_PORT_MASK_WIDTH_8X,
3035                 .speed          = SPEED_5000,
3036         },
3037         {
3038                 .mask           = MLXSW_REG_PTYS_EXT_ETH_SPEED_XFI_XAUI_1_10G,
3039                 .mask_ethtool   = mlxsw_sp2_mask_ethtool_xfi_xaui_1_10g,
3040                 .m_ethtool_len  = MLXSW_SP2_MASK_ETHTOOL_XFI_XAUI_1_10G_LEN,
3041                 .mask_width     = MLXSW_SP_PORT_MASK_WIDTH_1X |
3042                                   MLXSW_SP_PORT_MASK_WIDTH_2X |
3043                                   MLXSW_SP_PORT_MASK_WIDTH_4X |
3044                                   MLXSW_SP_PORT_MASK_WIDTH_8X,
3045                 .speed          = SPEED_10000,
3046         },
3047         {
3048                 .mask           = MLXSW_REG_PTYS_EXT_ETH_SPEED_XLAUI_4_XLPPI_4_40G,
3049                 .mask_ethtool   = mlxsw_sp2_mask_ethtool_xlaui_4_xlppi_4_40g,
3050                 .m_ethtool_len  = MLXSW_SP2_MASK_ETHTOOL_XLAUI_4_XLPPI_4_40G_LEN,
3051                 .mask_width     = MLXSW_SP_PORT_MASK_WIDTH_4X |
3052                                   MLXSW_SP_PORT_MASK_WIDTH_8X,
3053                 .speed          = SPEED_40000,
3054         },
3055         {
3056                 .mask           = MLXSW_REG_PTYS_EXT_ETH_SPEED_25GAUI_1_25GBASE_CR_KR,
3057                 .mask_ethtool   = mlxsw_sp2_mask_ethtool_25gaui_1_25gbase_cr_kr,
3058                 .m_ethtool_len  = MLXSW_SP2_MASK_ETHTOOL_25GAUI_1_25GBASE_CR_KR_LEN,
3059                 .mask_width     = MLXSW_SP_PORT_MASK_WIDTH_1X |
3060                                   MLXSW_SP_PORT_MASK_WIDTH_2X |
3061                                   MLXSW_SP_PORT_MASK_WIDTH_4X |
3062                                   MLXSW_SP_PORT_MASK_WIDTH_8X,
3063                 .speed          = SPEED_25000,
3064         },
3065         {
3066                 .mask           = MLXSW_REG_PTYS_EXT_ETH_SPEED_50GAUI_2_LAUI_2_50GBASE_CR2_KR2,
3067                 .mask_ethtool   = mlxsw_sp2_mask_ethtool_50gaui_2_laui_2_50gbase_cr2_kr2,
3068                 .m_ethtool_len  = MLXSW_SP2_MASK_ETHTOOL_50GAUI_2_LAUI_2_50GBASE_CR2_KR2_LEN,
3069                 .mask_width     = MLXSW_SP_PORT_MASK_WIDTH_2X |
3070                                   MLXSW_SP_PORT_MASK_WIDTH_4X |
3071                                   MLXSW_SP_PORT_MASK_WIDTH_8X,
3072                 .speed          = SPEED_50000,
3073         },
3074         {
3075                 .mask           = MLXSW_REG_PTYS_EXT_ETH_SPEED_50GAUI_1_LAUI_1_50GBASE_CR_KR,
3076                 .mask_ethtool   = mlxsw_sp2_mask_ethtool_50gaui_1_laui_1_50gbase_cr_kr,
3077                 .m_ethtool_len  = MLXSW_SP2_MASK_ETHTOOL_50GAUI_1_LAUI_1_50GBASE_CR_KR_LEN,
3078                 .mask_width     = MLXSW_SP_PORT_MASK_WIDTH_1X,
3079                 .speed          = SPEED_50000,
3080         },
3081         {
3082                 .mask           = MLXSW_REG_PTYS_EXT_ETH_SPEED_CAUI_4_100GBASE_CR4_KR4,
3083                 .mask_ethtool   = mlxsw_sp2_mask_ethtool_caui_4_100gbase_cr4_kr4,
3084                 .m_ethtool_len  = MLXSW_SP2_MASK_ETHTOOL_CAUI_4_100GBASE_CR4_KR4_LEN,
3085                 .mask_width     = MLXSW_SP_PORT_MASK_WIDTH_4X |
3086                                   MLXSW_SP_PORT_MASK_WIDTH_8X,
3087                 .speed          = SPEED_100000,
3088         },
3089         {
3090                 .mask           = MLXSW_REG_PTYS_EXT_ETH_SPEED_100GAUI_2_100GBASE_CR2_KR2,
3091                 .mask_ethtool   = mlxsw_sp2_mask_ethtool_100gaui_2_100gbase_cr2_kr2,
3092                 .m_ethtool_len  = MLXSW_SP2_MASK_ETHTOOL_100GAUI_2_100GBASE_CR2_KR2_LEN,
3093                 .mask_width     = MLXSW_SP_PORT_MASK_WIDTH_2X,
3094                 .speed          = SPEED_100000,
3095         },
3096         {
3097                 .mask           = MLXSW_REG_PTYS_EXT_ETH_SPEED_200GAUI_4_200GBASE_CR4_KR4,
3098                 .mask_ethtool   = mlxsw_sp2_mask_ethtool_200gaui_4_200gbase_cr4_kr4,
3099                 .m_ethtool_len  = MLXSW_SP2_MASK_ETHTOOL_200GAUI_4_200GBASE_CR4_KR4_LEN,
3100                 .mask_width     = MLXSW_SP_PORT_MASK_WIDTH_4X |
3101                                   MLXSW_SP_PORT_MASK_WIDTH_8X,
3102                 .speed          = SPEED_200000,
3103         },
3104         {
3105                 .mask           = MLXSW_REG_PTYS_EXT_ETH_SPEED_400GAUI_8,
3106                 .mask_ethtool   = mlxsw_sp2_mask_ethtool_400gaui_8,
3107                 .m_ethtool_len  = MLXSW_SP2_MASK_ETHTOOL_400GAUI_8_LEN,
3108                 .mask_width     = MLXSW_SP_PORT_MASK_WIDTH_8X,
3109                 .speed          = SPEED_400000,
3110         },
3111 };
3112
3113 #define MLXSW_SP2_PORT_LINK_MODE_LEN ARRAY_SIZE(mlxsw_sp2_port_link_mode)
3114
3115 static void
3116 mlxsw_sp2_from_ptys_supported_port(struct mlxsw_sp *mlxsw_sp,
3117                                    u32 ptys_eth_proto,
3118                                    struct ethtool_link_ksettings *cmd)
3119 {
3120         ethtool_link_ksettings_add_link_mode(cmd, supported, FIBRE);
3121         ethtool_link_ksettings_add_link_mode(cmd, supported, Backplane);
3122 }
3123
3124 static void
3125 mlxsw_sp2_set_bit_ethtool(const struct mlxsw_sp2_port_link_mode *link_mode,
3126                           unsigned long *mode)
3127 {
3128         int i;
3129
3130         for (i = 0; i < link_mode->m_ethtool_len; i++)
3131                 __set_bit(link_mode->mask_ethtool[i], mode);
3132 }
3133
3134 static void
3135 mlxsw_sp2_from_ptys_link(struct mlxsw_sp *mlxsw_sp, u32 ptys_eth_proto,
3136                          u8 width, unsigned long *mode)
3137 {
3138         u8 mask_width = mlxsw_sp_port_mask_width_get(width);
3139         int i;
3140
3141         for (i = 0; i < MLXSW_SP2_PORT_LINK_MODE_LEN; i++) {
3142                 if ((ptys_eth_proto & mlxsw_sp2_port_link_mode[i].mask) &&
3143                     (mask_width & mlxsw_sp2_port_link_mode[i].mask_width))
3144                         mlxsw_sp2_set_bit_ethtool(&mlxsw_sp2_port_link_mode[i],
3145                                                   mode);
3146         }
3147 }
3148
3149 static u32
3150 mlxsw_sp2_from_ptys_speed(struct mlxsw_sp *mlxsw_sp, u32 ptys_eth_proto)
3151 {
3152         int i;
3153
3154         for (i = 0; i < MLXSW_SP2_PORT_LINK_MODE_LEN; i++) {
3155                 if (ptys_eth_proto & mlxsw_sp2_port_link_mode[i].mask)
3156                         return mlxsw_sp2_port_link_mode[i].speed;
3157         }
3158
3159         return SPEED_UNKNOWN;
3160 }
3161
3162 static void
3163 mlxsw_sp2_from_ptys_speed_duplex(struct mlxsw_sp *mlxsw_sp, bool carrier_ok,
3164                                  u32 ptys_eth_proto,
3165                                  struct ethtool_link_ksettings *cmd)
3166 {
3167         cmd->base.speed = SPEED_UNKNOWN;
3168         cmd->base.duplex = DUPLEX_UNKNOWN;
3169
3170         if (!carrier_ok)
3171                 return;
3172
3173         cmd->base.speed = mlxsw_sp2_from_ptys_speed(mlxsw_sp, ptys_eth_proto);
3174         if (cmd->base.speed != SPEED_UNKNOWN)
3175                 cmd->base.duplex = DUPLEX_FULL;
3176 }
3177
3178 static bool
3179 mlxsw_sp2_test_bit_ethtool(const struct mlxsw_sp2_port_link_mode *link_mode,
3180                            const unsigned long *mode)
3181 {
3182         int cnt = 0;
3183         int i;
3184
3185         for (i = 0; i < link_mode->m_ethtool_len; i++) {
3186                 if (test_bit(link_mode->mask_ethtool[i], mode))
3187                         cnt++;
3188         }
3189
3190         return cnt == link_mode->m_ethtool_len;
3191 }
3192
3193 static u32
3194 mlxsw_sp2_to_ptys_advert_link(struct mlxsw_sp *mlxsw_sp, u8 width,
3195                               const struct ethtool_link_ksettings *cmd)
3196 {
3197         u8 mask_width = mlxsw_sp_port_mask_width_get(width);
3198         u32 ptys_proto = 0;
3199         int i;
3200
3201         for (i = 0; i < MLXSW_SP2_PORT_LINK_MODE_LEN; i++) {
3202                 if ((mask_width & mlxsw_sp2_port_link_mode[i].mask_width) &&
3203                     mlxsw_sp2_test_bit_ethtool(&mlxsw_sp2_port_link_mode[i],
3204                                                cmd->link_modes.advertising))
3205                         ptys_proto |= mlxsw_sp2_port_link_mode[i].mask;
3206         }
3207         return ptys_proto;
3208 }
3209
3210 static u32 mlxsw_sp2_to_ptys_speed(struct mlxsw_sp *mlxsw_sp,
3211                                    u8 width, u32 speed)
3212 {
3213         u8 mask_width = mlxsw_sp_port_mask_width_get(width);
3214         u32 ptys_proto = 0;
3215         int i;
3216
3217         for (i = 0; i < MLXSW_SP2_PORT_LINK_MODE_LEN; i++) {
3218                 if ((speed == mlxsw_sp2_port_link_mode[i].speed) &&
3219                     (mask_width & mlxsw_sp2_port_link_mode[i].mask_width))
3220                         ptys_proto |= mlxsw_sp2_port_link_mode[i].mask;
3221         }
3222         return ptys_proto;
3223 }
3224
3225 static void
3226 mlxsw_sp2_reg_ptys_eth_pack(struct mlxsw_sp *mlxsw_sp, char *payload,
3227                             u8 local_port, u32 proto_admin,
3228                             bool autoneg)
3229 {
3230         mlxsw_reg_ptys_ext_eth_pack(payload, local_port, proto_admin, autoneg);
3231 }
3232
3233 static void
3234 mlxsw_sp2_reg_ptys_eth_unpack(struct mlxsw_sp *mlxsw_sp, char *payload,
3235                               u32 *p_eth_proto_cap, u32 *p_eth_proto_admin,
3236                               u32 *p_eth_proto_oper)
3237 {
3238         mlxsw_reg_ptys_ext_eth_unpack(payload, p_eth_proto_cap,
3239                                       p_eth_proto_admin, p_eth_proto_oper);
3240 }
3241
3242 static const struct mlxsw_sp_port_type_speed_ops
3243 mlxsw_sp2_port_type_speed_ops = {
3244         .from_ptys_supported_port       = mlxsw_sp2_from_ptys_supported_port,
3245         .from_ptys_link                 = mlxsw_sp2_from_ptys_link,
3246         .from_ptys_speed                = mlxsw_sp2_from_ptys_speed,
3247         .from_ptys_speed_duplex         = mlxsw_sp2_from_ptys_speed_duplex,
3248         .to_ptys_advert_link            = mlxsw_sp2_to_ptys_advert_link,
3249         .to_ptys_speed                  = mlxsw_sp2_to_ptys_speed,
3250         .reg_ptys_eth_pack              = mlxsw_sp2_reg_ptys_eth_pack,
3251         .reg_ptys_eth_unpack            = mlxsw_sp2_reg_ptys_eth_unpack,
3252 };
3253
3254 static void
3255 mlxsw_sp_port_get_link_supported(struct mlxsw_sp *mlxsw_sp, u32 eth_proto_cap,
3256                                  u8 width, struct ethtool_link_ksettings *cmd)
3257 {
3258         const struct mlxsw_sp_port_type_speed_ops *ops;
3259
3260         ops = mlxsw_sp->port_type_speed_ops;
3261
3262         ethtool_link_ksettings_add_link_mode(cmd, supported, Asym_Pause);
3263         ethtool_link_ksettings_add_link_mode(cmd, supported, Autoneg);
3264         ethtool_link_ksettings_add_link_mode(cmd, supported, Pause);
3265
3266         ops->from_ptys_supported_port(mlxsw_sp, eth_proto_cap, cmd);
3267         ops->from_ptys_link(mlxsw_sp, eth_proto_cap, width,
3268                             cmd->link_modes.supported);
3269 }
3270
3271 static void
3272 mlxsw_sp_port_get_link_advertise(struct mlxsw_sp *mlxsw_sp,
3273                                  u32 eth_proto_admin, bool autoneg, u8 width,
3274                                  struct ethtool_link_ksettings *cmd)
3275 {
3276         const struct mlxsw_sp_port_type_speed_ops *ops;
3277
3278         ops = mlxsw_sp->port_type_speed_ops;
3279
3280         if (!autoneg)
3281                 return;
3282
3283         ethtool_link_ksettings_add_link_mode(cmd, advertising, Autoneg);
3284         ops->from_ptys_link(mlxsw_sp, eth_proto_admin, width,
3285                             cmd->link_modes.advertising);
3286 }
3287
3288 static u8
3289 mlxsw_sp_port_connector_port(enum mlxsw_reg_ptys_connector_type connector_type)
3290 {
3291         switch (connector_type) {
3292         case MLXSW_REG_PTYS_CONNECTOR_TYPE_UNKNOWN_OR_NO_CONNECTOR:
3293                 return PORT_OTHER;
3294         case MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_NONE:
3295                 return PORT_NONE;
3296         case MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_TP:
3297                 return PORT_TP;
3298         case MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_AUI:
3299                 return PORT_AUI;
3300         case MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_BNC:
3301                 return PORT_BNC;
3302         case MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_MII:
3303                 return PORT_MII;
3304         case MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_FIBRE:
3305                 return PORT_FIBRE;
3306         case MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_DA:
3307                 return PORT_DA;
3308         case MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_OTHER:
3309                 return PORT_OTHER;
3310         default:
3311                 WARN_ON_ONCE(1);
3312                 return PORT_OTHER;
3313         }
3314 }
3315
3316 static int mlxsw_sp_port_get_link_ksettings(struct net_device *dev,
3317                                             struct ethtool_link_ksettings *cmd)
3318 {
3319         u32 eth_proto_cap, eth_proto_admin, eth_proto_oper;
3320         struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
3321         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
3322         const struct mlxsw_sp_port_type_speed_ops *ops;
3323         char ptys_pl[MLXSW_REG_PTYS_LEN];
3324         u8 connector_type;
3325         bool autoneg;
3326         int err;
3327
3328         ops = mlxsw_sp->port_type_speed_ops;
3329
3330         autoneg = mlxsw_sp_port->link.autoneg;
3331         ops->reg_ptys_eth_pack(mlxsw_sp, ptys_pl, mlxsw_sp_port->local_port,
3332                                0, false);
3333         err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl);
3334         if (err)
3335                 return err;
3336         ops->reg_ptys_eth_unpack(mlxsw_sp, ptys_pl, &eth_proto_cap,
3337                                  &eth_proto_admin, &eth_proto_oper);
3338
3339         mlxsw_sp_port_get_link_supported(mlxsw_sp, eth_proto_cap,
3340                                          mlxsw_sp_port->mapping.width, cmd);
3341
3342         mlxsw_sp_port_get_link_advertise(mlxsw_sp, eth_proto_admin, autoneg,
3343                                          mlxsw_sp_port->mapping.width, cmd);
3344
3345         cmd->base.autoneg = autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE;
3346         connector_type = mlxsw_reg_ptys_connector_type_get(ptys_pl);
3347         cmd->base.port = mlxsw_sp_port_connector_port(connector_type);
3348         ops->from_ptys_speed_duplex(mlxsw_sp, netif_carrier_ok(dev),
3349                                     eth_proto_oper, cmd);
3350
3351         return 0;
3352 }
3353
3354 static int
3355 mlxsw_sp_port_set_link_ksettings(struct net_device *dev,
3356                                  const struct ethtool_link_ksettings *cmd)
3357 {
3358         struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
3359         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
3360         const struct mlxsw_sp_port_type_speed_ops *ops;
3361         char ptys_pl[MLXSW_REG_PTYS_LEN];
3362         u32 eth_proto_cap, eth_proto_new;
3363         bool autoneg;
3364         int err;
3365
3366         ops = mlxsw_sp->port_type_speed_ops;
3367
3368         ops->reg_ptys_eth_pack(mlxsw_sp, ptys_pl, mlxsw_sp_port->local_port,
3369                                0, false);
3370         err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl);
3371         if (err)
3372                 return err;
3373         ops->reg_ptys_eth_unpack(mlxsw_sp, ptys_pl, &eth_proto_cap, NULL, NULL);
3374
3375         autoneg = cmd->base.autoneg == AUTONEG_ENABLE;
3376         eth_proto_new = autoneg ?
3377                 ops->to_ptys_advert_link(mlxsw_sp, mlxsw_sp_port->mapping.width,
3378                                          cmd) :
3379                 ops->to_ptys_speed(mlxsw_sp, mlxsw_sp_port->mapping.width,
3380                                    cmd->base.speed);
3381
3382         eth_proto_new = eth_proto_new & eth_proto_cap;
3383         if (!eth_proto_new) {
3384                 netdev_err(dev, "No supported speed requested\n");
3385                 return -EINVAL;
3386         }
3387
3388         ops->reg_ptys_eth_pack(mlxsw_sp, ptys_pl, mlxsw_sp_port->local_port,
3389                                eth_proto_new, autoneg);
3390         err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl);
3391         if (err)
3392                 return err;
3393
3394         mlxsw_sp_port->link.autoneg = autoneg;
3395
3396         if (!netif_running(dev))
3397                 return 0;
3398
3399         mlxsw_sp_port_admin_status_set(mlxsw_sp_port, false);
3400         mlxsw_sp_port_admin_status_set(mlxsw_sp_port, true);
3401
3402         return 0;
3403 }
3404
3405 static int mlxsw_sp_get_module_info(struct net_device *netdev,
3406                                     struct ethtool_modinfo *modinfo)
3407 {
3408         struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(netdev);
3409         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
3410         int err;
3411
3412         err = mlxsw_env_get_module_info(mlxsw_sp->core,
3413                                         mlxsw_sp_port->mapping.module,
3414                                         modinfo);
3415
3416         return err;
3417 }
3418
3419 static int mlxsw_sp_get_module_eeprom(struct net_device *netdev,
3420                                       struct ethtool_eeprom *ee,
3421                                       u8 *data)
3422 {
3423         struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(netdev);
3424         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
3425         int err;
3426
3427         err = mlxsw_env_get_module_eeprom(netdev, mlxsw_sp->core,
3428                                           mlxsw_sp_port->mapping.module, ee,
3429                                           data);
3430
3431         return err;
3432 }
3433
3434 static int
3435 mlxsw_sp_get_ts_info(struct net_device *netdev, struct ethtool_ts_info *info)
3436 {
3437         struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(netdev);
3438         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
3439
3440         return mlxsw_sp->ptp_ops->get_ts_info(mlxsw_sp, info);
3441 }
3442
3443 static const struct ethtool_ops mlxsw_sp_port_ethtool_ops = {
3444         .get_drvinfo            = mlxsw_sp_port_get_drvinfo,
3445         .get_link               = ethtool_op_get_link,
3446         .get_pauseparam         = mlxsw_sp_port_get_pauseparam,
3447         .set_pauseparam         = mlxsw_sp_port_set_pauseparam,
3448         .get_strings            = mlxsw_sp_port_get_strings,
3449         .set_phys_id            = mlxsw_sp_port_set_phys_id,
3450         .get_ethtool_stats      = mlxsw_sp_port_get_stats,
3451         .get_sset_count         = mlxsw_sp_port_get_sset_count,
3452         .get_link_ksettings     = mlxsw_sp_port_get_link_ksettings,
3453         .set_link_ksettings     = mlxsw_sp_port_set_link_ksettings,
3454         .get_module_info        = mlxsw_sp_get_module_info,
3455         .get_module_eeprom      = mlxsw_sp_get_module_eeprom,
3456         .get_ts_info            = mlxsw_sp_get_ts_info,
3457 };
3458
3459 static int
3460 mlxsw_sp_port_speed_by_width_set(struct mlxsw_sp_port *mlxsw_sp_port)
3461 {
3462         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
3463         u32 eth_proto_cap, eth_proto_admin, eth_proto_oper;
3464         const struct mlxsw_sp_port_type_speed_ops *ops;
3465         char ptys_pl[MLXSW_REG_PTYS_LEN];
3466         int err;
3467
3468         ops = mlxsw_sp->port_type_speed_ops;
3469
3470         /* Set advertised speeds to supported speeds. */
3471         ops->reg_ptys_eth_pack(mlxsw_sp, ptys_pl, mlxsw_sp_port->local_port,
3472                                0, false);
3473         err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl);
3474         if (err)
3475                 return err;
3476
3477         ops->reg_ptys_eth_unpack(mlxsw_sp, ptys_pl, &eth_proto_cap,
3478                                  &eth_proto_admin, &eth_proto_oper);
3479         ops->reg_ptys_eth_pack(mlxsw_sp, ptys_pl, mlxsw_sp_port->local_port,
3480                                eth_proto_cap, mlxsw_sp_port->link.autoneg);
3481         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl);
3482 }
3483
3484 int mlxsw_sp_port_speed_get(struct mlxsw_sp_port *mlxsw_sp_port, u32 *speed)
3485 {
3486         const struct mlxsw_sp_port_type_speed_ops *port_type_speed_ops;
3487         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
3488         char ptys_pl[MLXSW_REG_PTYS_LEN];
3489         u32 eth_proto_oper;
3490         int err;
3491
3492         port_type_speed_ops = mlxsw_sp->port_type_speed_ops;
3493         port_type_speed_ops->reg_ptys_eth_pack(mlxsw_sp, ptys_pl,
3494                                                mlxsw_sp_port->local_port, 0,
3495                                                false);
3496         err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl);
3497         if (err)
3498                 return err;
3499         port_type_speed_ops->reg_ptys_eth_unpack(mlxsw_sp, ptys_pl, NULL, NULL,
3500                                                  &eth_proto_oper);
3501         *speed = port_type_speed_ops->from_ptys_speed(mlxsw_sp, eth_proto_oper);
3502         return 0;
3503 }
3504
3505 int mlxsw_sp_port_ets_set(struct mlxsw_sp_port *mlxsw_sp_port,
3506                           enum mlxsw_reg_qeec_hr hr, u8 index, u8 next_index,
3507                           bool dwrr, u8 dwrr_weight)
3508 {
3509         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
3510         char qeec_pl[MLXSW_REG_QEEC_LEN];
3511
3512         mlxsw_reg_qeec_pack(qeec_pl, mlxsw_sp_port->local_port, hr, index,
3513                             next_index);
3514         mlxsw_reg_qeec_de_set(qeec_pl, true);
3515         mlxsw_reg_qeec_dwrr_set(qeec_pl, dwrr);
3516         mlxsw_reg_qeec_dwrr_weight_set(qeec_pl, dwrr_weight);
3517         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(qeec), qeec_pl);
3518 }
3519
3520 int mlxsw_sp_port_ets_maxrate_set(struct mlxsw_sp_port *mlxsw_sp_port,
3521                                   enum mlxsw_reg_qeec_hr hr, u8 index,
3522                                   u8 next_index, u32 maxrate, u8 burst_size)
3523 {
3524         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
3525         char qeec_pl[MLXSW_REG_QEEC_LEN];
3526
3527         mlxsw_reg_qeec_pack(qeec_pl, mlxsw_sp_port->local_port, hr, index,
3528                             next_index);
3529         mlxsw_reg_qeec_mase_set(qeec_pl, true);
3530         mlxsw_reg_qeec_max_shaper_rate_set(qeec_pl, maxrate);
3531         mlxsw_reg_qeec_max_shaper_bs_set(qeec_pl, burst_size);
3532         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(qeec), qeec_pl);
3533 }
3534
3535 static int mlxsw_sp_port_min_bw_set(struct mlxsw_sp_port *mlxsw_sp_port,
3536                                     enum mlxsw_reg_qeec_hr hr, u8 index,
3537                                     u8 next_index, u32 minrate)
3538 {
3539         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
3540         char qeec_pl[MLXSW_REG_QEEC_LEN];
3541
3542         mlxsw_reg_qeec_pack(qeec_pl, mlxsw_sp_port->local_port, hr, index,
3543                             next_index);
3544         mlxsw_reg_qeec_mise_set(qeec_pl, true);
3545         mlxsw_reg_qeec_min_shaper_rate_set(qeec_pl, minrate);
3546
3547         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(qeec), qeec_pl);
3548 }
3549
3550 int mlxsw_sp_port_prio_tc_set(struct mlxsw_sp_port *mlxsw_sp_port,
3551                               u8 switch_prio, u8 tclass)
3552 {
3553         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
3554         char qtct_pl[MLXSW_REG_QTCT_LEN];
3555
3556         mlxsw_reg_qtct_pack(qtct_pl, mlxsw_sp_port->local_port, switch_prio,
3557                             tclass);
3558         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(qtct), qtct_pl);
3559 }
3560
3561 static int mlxsw_sp_port_ets_init(struct mlxsw_sp_port *mlxsw_sp_port)
3562 {
3563         int err, i;
3564
3565         /* Setup the elements hierarcy, so that each TC is linked to
3566          * one subgroup, which are all member in the same group.
3567          */
3568         err = mlxsw_sp_port_ets_set(mlxsw_sp_port,
3569                                     MLXSW_REG_QEEC_HR_GROUP, 0, 0, false, 0);
3570         if (err)
3571                 return err;
3572         for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
3573                 err = mlxsw_sp_port_ets_set(mlxsw_sp_port,
3574                                             MLXSW_REG_QEEC_HR_SUBGROUP, i,
3575                                             0, false, 0);
3576                 if (err)
3577                         return err;
3578         }
3579         for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
3580                 err = mlxsw_sp_port_ets_set(mlxsw_sp_port,
3581                                             MLXSW_REG_QEEC_HR_TC, i, i,
3582                                             false, 0);
3583                 if (err)
3584                         return err;
3585
3586                 err = mlxsw_sp_port_ets_set(mlxsw_sp_port,
3587                                             MLXSW_REG_QEEC_HR_TC,
3588                                             i + 8, i,
3589                                             true, 100);
3590                 if (err)
3591                         return err;
3592         }
3593
3594         /* Make sure the max shaper is disabled in all hierarchies that support
3595          * it. Note that this disables ptps (PTP shaper), but that is intended
3596          * for the initial configuration.
3597          */
3598         err = mlxsw_sp_port_ets_maxrate_set(mlxsw_sp_port,
3599                                             MLXSW_REG_QEEC_HR_PORT, 0, 0,
3600                                             MLXSW_REG_QEEC_MAS_DIS, 0);
3601         if (err)
3602                 return err;
3603         for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
3604                 err = mlxsw_sp_port_ets_maxrate_set(mlxsw_sp_port,
3605                                                     MLXSW_REG_QEEC_HR_SUBGROUP,
3606                                                     i, 0,
3607                                                     MLXSW_REG_QEEC_MAS_DIS, 0);
3608                 if (err)
3609                         return err;
3610         }
3611         for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
3612                 err = mlxsw_sp_port_ets_maxrate_set(mlxsw_sp_port,
3613                                                     MLXSW_REG_QEEC_HR_TC,
3614                                                     i, i,
3615                                                     MLXSW_REG_QEEC_MAS_DIS, 0);
3616                 if (err)
3617                         return err;
3618
3619                 err = mlxsw_sp_port_ets_maxrate_set(mlxsw_sp_port,
3620                                                     MLXSW_REG_QEEC_HR_TC,
3621                                                     i + 8, i,
3622                                                     MLXSW_REG_QEEC_MAS_DIS, 0);
3623                 if (err)
3624                         return err;
3625         }
3626
3627         /* Configure the min shaper for multicast TCs. */
3628         for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
3629                 err = mlxsw_sp_port_min_bw_set(mlxsw_sp_port,
3630                                                MLXSW_REG_QEEC_HR_TC,
3631                                                i + 8, i,
3632                                                MLXSW_REG_QEEC_MIS_MIN);
3633                 if (err)
3634                         return err;
3635         }
3636
3637         /* Map all priorities to traffic class 0. */
3638         for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
3639                 err = mlxsw_sp_port_prio_tc_set(mlxsw_sp_port, i, 0);
3640                 if (err)
3641                         return err;
3642         }
3643
3644         return 0;
3645 }
3646
3647 static int mlxsw_sp_port_tc_mc_mode_set(struct mlxsw_sp_port *mlxsw_sp_port,
3648                                         bool enable)
3649 {
3650         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
3651         char qtctm_pl[MLXSW_REG_QTCTM_LEN];
3652
3653         mlxsw_reg_qtctm_pack(qtctm_pl, mlxsw_sp_port->local_port, enable);
3654         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(qtctm), qtctm_pl);
3655 }
3656
3657 static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
3658                                 u8 split_base_local_port,
3659                                 struct mlxsw_sp_port_mapping *port_mapping)
3660 {
3661         struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
3662         bool split = !!split_base_local_port;
3663         struct mlxsw_sp_port *mlxsw_sp_port;
3664         struct net_device *dev;
3665         int err;
3666
3667         err = mlxsw_core_port_init(mlxsw_sp->core, local_port,
3668                                    port_mapping->module + 1, split,
3669                                    port_mapping->lane / port_mapping->width,
3670                                    mlxsw_sp->base_mac,
3671                                    sizeof(mlxsw_sp->base_mac));
3672         if (err) {
3673                 dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to init core port\n",
3674                         local_port);
3675                 return err;
3676         }
3677
3678         dev = alloc_etherdev(sizeof(struct mlxsw_sp_port));
3679         if (!dev) {
3680                 err = -ENOMEM;
3681                 goto err_alloc_etherdev;
3682         }
3683         SET_NETDEV_DEV(dev, mlxsw_sp->bus_info->dev);
3684         dev_net_set(dev, mlxsw_sp_net(mlxsw_sp));
3685         mlxsw_sp_port = netdev_priv(dev);
3686         mlxsw_sp_port->dev = dev;
3687         mlxsw_sp_port->mlxsw_sp = mlxsw_sp;
3688         mlxsw_sp_port->local_port = local_port;
3689         mlxsw_sp_port->pvid = MLXSW_SP_DEFAULT_VID;
3690         mlxsw_sp_port->split = split;
3691         mlxsw_sp_port->split_base_local_port = split_base_local_port;
3692         mlxsw_sp_port->mapping = *port_mapping;
3693         mlxsw_sp_port->link.autoneg = 1;
3694         INIT_LIST_HEAD(&mlxsw_sp_port->vlans_list);
3695         INIT_LIST_HEAD(&mlxsw_sp_port->mall_tc_list);
3696
3697         mlxsw_sp_port->pcpu_stats =
3698                 netdev_alloc_pcpu_stats(struct mlxsw_sp_port_pcpu_stats);
3699         if (!mlxsw_sp_port->pcpu_stats) {
3700                 err = -ENOMEM;
3701                 goto err_alloc_stats;
3702         }
3703
3704         mlxsw_sp_port->sample = kzalloc(sizeof(*mlxsw_sp_port->sample),
3705                                         GFP_KERNEL);
3706         if (!mlxsw_sp_port->sample) {
3707                 err = -ENOMEM;
3708                 goto err_alloc_sample;
3709         }
3710
3711         INIT_DELAYED_WORK(&mlxsw_sp_port->periodic_hw_stats.update_dw,
3712                           &update_stats_cache);
3713
3714         dev->netdev_ops = &mlxsw_sp_port_netdev_ops;
3715         dev->ethtool_ops = &mlxsw_sp_port_ethtool_ops;
3716
3717         err = mlxsw_sp_port_module_map(mlxsw_sp_port);
3718         if (err) {
3719                 dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to map module\n",
3720                         mlxsw_sp_port->local_port);
3721                 goto err_port_module_map;
3722         }
3723
3724         err = mlxsw_sp_port_swid_set(mlxsw_sp_port, 0);
3725         if (err) {
3726                 dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to set SWID\n",
3727                         mlxsw_sp_port->local_port);
3728                 goto err_port_swid_set;
3729         }
3730
3731         err = mlxsw_sp_port_dev_addr_init(mlxsw_sp_port);
3732         if (err) {
3733                 dev_err(mlxsw_sp->bus_info->dev, "Port %d: Unable to init port mac address\n",
3734                         mlxsw_sp_port->local_port);
3735                 goto err_dev_addr_init;
3736         }
3737
3738         netif_carrier_off(dev);
3739
3740         dev->features |= NETIF_F_NETNS_LOCAL | NETIF_F_LLTX | NETIF_F_SG |
3741                          NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_HW_TC;
3742         dev->hw_features |= NETIF_F_HW_TC | NETIF_F_LOOPBACK;
3743
3744         dev->min_mtu = 0;
3745         dev->max_mtu = ETH_MAX_MTU;
3746
3747         /* Each packet needs to have a Tx header (metadata) on top all other
3748          * headers.
3749          */
3750         dev->needed_headroom = MLXSW_TXHDR_LEN;
3751
3752         err = mlxsw_sp_port_system_port_mapping_set(mlxsw_sp_port);
3753         if (err) {
3754                 dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to set system port mapping\n",
3755                         mlxsw_sp_port->local_port);
3756                 goto err_port_system_port_mapping_set;
3757         }
3758
3759         err = mlxsw_sp_port_speed_by_width_set(mlxsw_sp_port);
3760         if (err) {
3761                 dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to enable speeds\n",
3762                         mlxsw_sp_port->local_port);
3763                 goto err_port_speed_by_width_set;
3764         }
3765
3766         err = mlxsw_sp_port_mtu_set(mlxsw_sp_port, ETH_DATA_LEN);
3767         if (err) {
3768                 dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to set MTU\n",
3769                         mlxsw_sp_port->local_port);
3770                 goto err_port_mtu_set;
3771         }
3772
3773         err = mlxsw_sp_port_admin_status_set(mlxsw_sp_port, false);
3774         if (err)
3775                 goto err_port_admin_status_set;
3776
3777         err = mlxsw_sp_port_buffers_init(mlxsw_sp_port);
3778         if (err) {
3779                 dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to initialize buffers\n",
3780                         mlxsw_sp_port->local_port);
3781                 goto err_port_buffers_init;
3782         }
3783
3784         err = mlxsw_sp_port_ets_init(mlxsw_sp_port);
3785         if (err) {
3786                 dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to initialize ETS\n",
3787                         mlxsw_sp_port->local_port);
3788                 goto err_port_ets_init;
3789         }
3790
3791         err = mlxsw_sp_port_tc_mc_mode_set(mlxsw_sp_port, true);
3792         if (err) {
3793                 dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to initialize TC MC mode\n",
3794                         mlxsw_sp_port->local_port);
3795                 goto err_port_tc_mc_mode;
3796         }
3797
3798         /* ETS and buffers must be initialized before DCB. */
3799         err = mlxsw_sp_port_dcb_init(mlxsw_sp_port);
3800         if (err) {
3801                 dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to initialize DCB\n",
3802                         mlxsw_sp_port->local_port);
3803                 goto err_port_dcb_init;
3804         }
3805
3806         err = mlxsw_sp_port_fids_init(mlxsw_sp_port);
3807         if (err) {
3808                 dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to initialize FIDs\n",
3809                         mlxsw_sp_port->local_port);
3810                 goto err_port_fids_init;
3811         }
3812
3813         err = mlxsw_sp_tc_qdisc_init(mlxsw_sp_port);
3814         if (err) {
3815                 dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to initialize TC qdiscs\n",
3816                         mlxsw_sp_port->local_port);
3817                 goto err_port_qdiscs_init;
3818         }
3819
3820         err = mlxsw_sp_port_vlan_set(mlxsw_sp_port, 0, VLAN_N_VID - 1, false,
3821                                      false);
3822         if (err) {
3823                 dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to clear VLAN filter\n",
3824                         mlxsw_sp_port->local_port);
3825                 goto err_port_vlan_clear;
3826         }
3827
3828         err = mlxsw_sp_port_nve_init(mlxsw_sp_port);
3829         if (err) {
3830                 dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to initialize NVE\n",
3831                         mlxsw_sp_port->local_port);
3832                 goto err_port_nve_init;
3833         }
3834
3835         err = mlxsw_sp_port_pvid_set(mlxsw_sp_port, MLXSW_SP_DEFAULT_VID);
3836         if (err) {
3837                 dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to set PVID\n",
3838                         mlxsw_sp_port->local_port);
3839                 goto err_port_pvid_set;
3840         }
3841
3842         mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_create(mlxsw_sp_port,
3843                                                        MLXSW_SP_DEFAULT_VID);
3844         if (IS_ERR(mlxsw_sp_port_vlan)) {
3845                 dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to create VID 1\n",
3846                         mlxsw_sp_port->local_port);
3847                 err = PTR_ERR(mlxsw_sp_port_vlan);
3848                 goto err_port_vlan_create;
3849         }
3850         mlxsw_sp_port->default_vlan = mlxsw_sp_port_vlan;
3851
3852         INIT_DELAYED_WORK(&mlxsw_sp_port->ptp.shaper_dw,
3853                           mlxsw_sp->ptp_ops->shaper_work);
3854         INIT_DELAYED_WORK(&mlxsw_sp_port->span.speed_update_dw,
3855                           mlxsw_sp_span_speed_update_work);
3856
3857         mlxsw_sp->ports[local_port] = mlxsw_sp_port;
3858         err = register_netdev(dev);
3859         if (err) {
3860                 dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to register netdev\n",
3861                         mlxsw_sp_port->local_port);
3862                 goto err_register_netdev;
3863         }
3864
3865         mlxsw_core_port_eth_set(mlxsw_sp->core, mlxsw_sp_port->local_port,
3866                                 mlxsw_sp_port, dev);
3867         mlxsw_core_schedule_dw(&mlxsw_sp_port->periodic_hw_stats.update_dw, 0);
3868         return 0;
3869
3870 err_register_netdev:
3871         mlxsw_sp->ports[local_port] = NULL;
3872         mlxsw_sp_port_vlan_destroy(mlxsw_sp_port_vlan);
3873 err_port_vlan_create:
3874 err_port_pvid_set:
3875         mlxsw_sp_port_nve_fini(mlxsw_sp_port);
3876 err_port_nve_init:
3877 err_port_vlan_clear:
3878         mlxsw_sp_tc_qdisc_fini(mlxsw_sp_port);
3879 err_port_qdiscs_init:
3880         mlxsw_sp_port_fids_fini(mlxsw_sp_port);
3881 err_port_fids_init:
3882         mlxsw_sp_port_dcb_fini(mlxsw_sp_port);
3883 err_port_dcb_init:
3884         mlxsw_sp_port_tc_mc_mode_set(mlxsw_sp_port, false);
3885 err_port_tc_mc_mode:
3886 err_port_ets_init:
3887 err_port_buffers_init:
3888 err_port_admin_status_set:
3889 err_port_mtu_set:
3890 err_port_speed_by_width_set:
3891 err_port_system_port_mapping_set:
3892 err_dev_addr_init:
3893         mlxsw_sp_port_swid_set(mlxsw_sp_port, MLXSW_PORT_SWID_DISABLED_PORT);
3894 err_port_swid_set:
3895         mlxsw_sp_port_module_unmap(mlxsw_sp_port);
3896 err_port_module_map:
3897         kfree(mlxsw_sp_port->sample);
3898 err_alloc_sample:
3899         free_percpu(mlxsw_sp_port->pcpu_stats);
3900 err_alloc_stats:
3901         free_netdev(dev);
3902 err_alloc_etherdev:
3903         mlxsw_core_port_fini(mlxsw_sp->core, local_port);
3904         return err;
3905 }
3906
3907 static void mlxsw_sp_port_remove(struct mlxsw_sp *mlxsw_sp, u8 local_port)
3908 {
3909         struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp->ports[local_port];
3910
3911         cancel_delayed_work_sync(&mlxsw_sp_port->periodic_hw_stats.update_dw);
3912         cancel_delayed_work_sync(&mlxsw_sp_port->span.speed_update_dw);
3913         cancel_delayed_work_sync(&mlxsw_sp_port->ptp.shaper_dw);
3914         mlxsw_sp_port_ptp_clear(mlxsw_sp_port);
3915         mlxsw_core_port_clear(mlxsw_sp->core, local_port, mlxsw_sp);
3916         unregister_netdev(mlxsw_sp_port->dev); /* This calls ndo_stop */
3917         mlxsw_sp->ports[local_port] = NULL;
3918         mlxsw_sp_port_vlan_flush(mlxsw_sp_port, true);
3919         mlxsw_sp_port_nve_fini(mlxsw_sp_port);
3920         mlxsw_sp_tc_qdisc_fini(mlxsw_sp_port);
3921         mlxsw_sp_port_fids_fini(mlxsw_sp_port);
3922         mlxsw_sp_port_dcb_fini(mlxsw_sp_port);
3923         mlxsw_sp_port_tc_mc_mode_set(mlxsw_sp_port, false);
3924         mlxsw_sp_port_swid_set(mlxsw_sp_port, MLXSW_PORT_SWID_DISABLED_PORT);
3925         mlxsw_sp_port_module_unmap(mlxsw_sp_port);
3926         kfree(mlxsw_sp_port->sample);
3927         free_percpu(mlxsw_sp_port->pcpu_stats);
3928         WARN_ON_ONCE(!list_empty(&mlxsw_sp_port->vlans_list));
3929         free_netdev(mlxsw_sp_port->dev);
3930         mlxsw_core_port_fini(mlxsw_sp->core, local_port);
3931 }
3932
3933 static int mlxsw_sp_cpu_port_create(struct mlxsw_sp *mlxsw_sp)
3934 {
3935         struct mlxsw_sp_port *mlxsw_sp_port;
3936         int err;
3937
3938         mlxsw_sp_port = kzalloc(sizeof(*mlxsw_sp_port), GFP_KERNEL);
3939         if (!mlxsw_sp_port)
3940                 return -ENOMEM;
3941
3942         mlxsw_sp_port->mlxsw_sp = mlxsw_sp;
3943         mlxsw_sp_port->local_port = MLXSW_PORT_CPU_PORT;
3944
3945         err = mlxsw_core_cpu_port_init(mlxsw_sp->core,
3946                                        mlxsw_sp_port,
3947                                        mlxsw_sp->base_mac,
3948                                        sizeof(mlxsw_sp->base_mac));
3949         if (err) {
3950                 dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize core CPU port\n");
3951                 goto err_core_cpu_port_init;
3952         }
3953
3954         mlxsw_sp->ports[MLXSW_PORT_CPU_PORT] = mlxsw_sp_port;
3955         return 0;
3956
3957 err_core_cpu_port_init:
3958         kfree(mlxsw_sp_port);
3959         return err;
3960 }
3961
3962 static void mlxsw_sp_cpu_port_remove(struct mlxsw_sp *mlxsw_sp)
3963 {
3964         struct mlxsw_sp_port *mlxsw_sp_port =
3965                                 mlxsw_sp->ports[MLXSW_PORT_CPU_PORT];
3966
3967         mlxsw_core_cpu_port_fini(mlxsw_sp->core);
3968         mlxsw_sp->ports[MLXSW_PORT_CPU_PORT] = NULL;
3969         kfree(mlxsw_sp_port);
3970 }
3971
3972 static bool mlxsw_sp_port_created(struct mlxsw_sp *mlxsw_sp, u8 local_port)
3973 {
3974         return mlxsw_sp->ports[local_port] != NULL;
3975 }
3976
3977 static void mlxsw_sp_ports_remove(struct mlxsw_sp *mlxsw_sp)
3978 {
3979         int i;
3980
3981         for (i = 1; i < mlxsw_core_max_ports(mlxsw_sp->core); i++)
3982                 if (mlxsw_sp_port_created(mlxsw_sp, i))
3983                         mlxsw_sp_port_remove(mlxsw_sp, i);
3984         mlxsw_sp_cpu_port_remove(mlxsw_sp);
3985         kfree(mlxsw_sp->ports);
3986 }
3987
3988 static int mlxsw_sp_ports_create(struct mlxsw_sp *mlxsw_sp)
3989 {
3990         unsigned int max_ports = mlxsw_core_max_ports(mlxsw_sp->core);
3991         struct mlxsw_sp_port_mapping *port_mapping;
3992         size_t alloc_size;
3993         int i;
3994         int err;
3995
3996         alloc_size = sizeof(struct mlxsw_sp_port *) * max_ports;
3997         mlxsw_sp->ports = kzalloc(alloc_size, GFP_KERNEL);
3998         if (!mlxsw_sp->ports)
3999                 return -ENOMEM;
4000
4001         err = mlxsw_sp_cpu_port_create(mlxsw_sp);
4002         if (err)
4003                 goto err_cpu_port_create;
4004
4005         for (i = 1; i < max_ports; i++) {
4006                 port_mapping = mlxsw_sp->port_mapping[i];
4007                 if (!port_mapping)
4008                         continue;
4009                 err = mlxsw_sp_port_create(mlxsw_sp, i, 0, port_mapping);
4010                 if (err)
4011                         goto err_port_create;
4012         }
4013         return 0;
4014
4015 err_port_create:
4016         for (i--; i >= 1; i--)
4017                 if (mlxsw_sp_port_created(mlxsw_sp, i))
4018                         mlxsw_sp_port_remove(mlxsw_sp, i);
4019         mlxsw_sp_cpu_port_remove(mlxsw_sp);
4020 err_cpu_port_create:
4021         kfree(mlxsw_sp->ports);
4022         return err;
4023 }
4024
4025 static int mlxsw_sp_port_module_info_init(struct mlxsw_sp *mlxsw_sp)
4026 {
4027         unsigned int max_ports = mlxsw_core_max_ports(mlxsw_sp->core);
4028         struct mlxsw_sp_port_mapping port_mapping;
4029         int i;
4030         int err;
4031
4032         mlxsw_sp->port_mapping = kcalloc(max_ports,
4033                                          sizeof(struct mlxsw_sp_port_mapping *),
4034                                          GFP_KERNEL);
4035         if (!mlxsw_sp->port_mapping)
4036                 return -ENOMEM;
4037
4038         for (i = 1; i < max_ports; i++) {
4039                 err = mlxsw_sp_port_module_info_get(mlxsw_sp, i, &port_mapping);
4040                 if (err)
4041                         goto err_port_module_info_get;
4042                 if (!port_mapping.width)
4043                         continue;
4044
4045                 mlxsw_sp->port_mapping[i] = kmemdup(&port_mapping,
4046                                                     sizeof(port_mapping),
4047                                                     GFP_KERNEL);
4048                 if (!mlxsw_sp->port_mapping[i]) {
4049                         err = -ENOMEM;
4050                         goto err_port_module_info_dup;
4051                 }
4052         }
4053         return 0;
4054
4055 err_port_module_info_get:
4056 err_port_module_info_dup:
4057         for (i--; i >= 1; i--)
4058                 kfree(mlxsw_sp->port_mapping[i]);
4059         kfree(mlxsw_sp->port_mapping);
4060         return err;
4061 }
4062
4063 static void mlxsw_sp_port_module_info_fini(struct mlxsw_sp *mlxsw_sp)
4064 {
4065         int i;
4066
4067         for (i = 1; i < mlxsw_core_max_ports(mlxsw_sp->core); i++)
4068                 kfree(mlxsw_sp->port_mapping[i]);
4069         kfree(mlxsw_sp->port_mapping);
4070 }
4071
4072 static u8 mlxsw_sp_cluster_base_port_get(u8 local_port, unsigned int max_width)
4073 {
4074         u8 offset = (local_port - 1) % max_width;
4075
4076         return local_port - offset;
4077 }
4078
4079 static int
4080 mlxsw_sp_port_split_create(struct mlxsw_sp *mlxsw_sp, u8 base_port,
4081                            struct mlxsw_sp_port_mapping *port_mapping,
4082                            unsigned int count, u8 offset)
4083 {
4084         struct mlxsw_sp_port_mapping split_port_mapping;
4085         int err, i;
4086
4087         split_port_mapping = *port_mapping;
4088         split_port_mapping.width /= count;
4089         for (i = 0; i < count; i++) {
4090                 err = mlxsw_sp_port_create(mlxsw_sp, base_port + i * offset,
4091                                            base_port, &split_port_mapping);
4092                 if (err)
4093                         goto err_port_create;
4094                 split_port_mapping.lane += split_port_mapping.width;
4095         }
4096
4097         return 0;
4098
4099 err_port_create:
4100         for (i--; i >= 0; i--)
4101                 if (mlxsw_sp_port_created(mlxsw_sp, base_port + i * offset))
4102                         mlxsw_sp_port_remove(mlxsw_sp, base_port + i * offset);
4103         return err;
4104 }
4105
4106 static void mlxsw_sp_port_unsplit_create(struct mlxsw_sp *mlxsw_sp,
4107                                          u8 base_port,
4108                                          unsigned int count, u8 offset)
4109 {
4110         struct mlxsw_sp_port_mapping *port_mapping;
4111         int i;
4112
4113         /* Go over original unsplit ports in the gap and recreate them. */
4114         for (i = 0; i < count * offset; i++) {
4115                 port_mapping = mlxsw_sp->port_mapping[base_port + i];
4116                 if (!port_mapping)
4117                         continue;
4118                 mlxsw_sp_port_create(mlxsw_sp, base_port + i, 0, port_mapping);
4119         }
4120 }
4121
4122 static int mlxsw_sp_local_ports_offset(struct mlxsw_core *mlxsw_core,
4123                                        unsigned int count,
4124                                        unsigned int max_width)
4125 {
4126         enum mlxsw_res_id local_ports_in_x_res_id;
4127         int split_width = max_width / count;
4128
4129         if (split_width == 1)
4130                 local_ports_in_x_res_id = MLXSW_RES_ID_LOCAL_PORTS_IN_1X;
4131         else if (split_width == 2)
4132                 local_ports_in_x_res_id = MLXSW_RES_ID_LOCAL_PORTS_IN_2X;
4133         else if (split_width == 4)
4134                 local_ports_in_x_res_id = MLXSW_RES_ID_LOCAL_PORTS_IN_4X;
4135         else
4136                 return -EINVAL;
4137
4138         if (!mlxsw_core_res_valid(mlxsw_core, local_ports_in_x_res_id))
4139                 return -EINVAL;
4140         return mlxsw_core_res_get(mlxsw_core, local_ports_in_x_res_id);
4141 }
4142
4143 static int mlxsw_sp_port_split(struct mlxsw_core *mlxsw_core, u8 local_port,
4144                                unsigned int count,
4145                                struct netlink_ext_ack *extack)
4146 {
4147         struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
4148         struct mlxsw_sp_port_mapping port_mapping;
4149         struct mlxsw_sp_port *mlxsw_sp_port;
4150         int max_width;
4151         u8 base_port;
4152         int offset;
4153         int i;
4154         int err;
4155
4156         mlxsw_sp_port = mlxsw_sp->ports[local_port];
4157         if (!mlxsw_sp_port) {
4158                 dev_err(mlxsw_sp->bus_info->dev, "Port number \"%d\" does not exist\n",
4159                         local_port);
4160                 NL_SET_ERR_MSG_MOD(extack, "Port number does not exist");
4161                 return -EINVAL;
4162         }
4163
4164         /* Split ports cannot be split. */
4165         if (mlxsw_sp_port->split) {
4166                 netdev_err(mlxsw_sp_port->dev, "Port cannot be split further\n");
4167                 NL_SET_ERR_MSG_MOD(extack, "Port cannot be split further");
4168                 return -EINVAL;
4169         }
4170
4171         max_width = mlxsw_core_module_max_width(mlxsw_core,
4172                                                 mlxsw_sp_port->mapping.module);
4173         if (max_width < 0) {
4174                 netdev_err(mlxsw_sp_port->dev, "Cannot get max width of port module\n");
4175                 NL_SET_ERR_MSG_MOD(extack, "Cannot get max width of port module");
4176                 return max_width;
4177         }
4178
4179         /* Split port with non-max and 1 module width cannot be split. */
4180         if (mlxsw_sp_port->mapping.width != max_width || max_width == 1) {
4181                 netdev_err(mlxsw_sp_port->dev, "Port cannot be split\n");
4182                 NL_SET_ERR_MSG_MOD(extack, "Port cannot be split");
4183                 return -EINVAL;
4184         }
4185
4186         if (count == 1 || !is_power_of_2(count) || count > max_width) {
4187                 netdev_err(mlxsw_sp_port->dev, "Invalid split count\n");
4188                 NL_SET_ERR_MSG_MOD(extack, "Invalid split count");
4189                 return -EINVAL;
4190         }
4191
4192         offset = mlxsw_sp_local_ports_offset(mlxsw_core, count, max_width);
4193         if (offset < 0) {
4194                 netdev_err(mlxsw_sp_port->dev, "Cannot obtain local port offset\n");
4195                 NL_SET_ERR_MSG_MOD(extack, "Cannot obtain local port offset");
4196                 return -EINVAL;
4197         }
4198
4199         /* Only in case max split is being done, the local port and
4200          * base port may differ.
4201          */
4202         base_port = count == max_width ?
4203                     mlxsw_sp_cluster_base_port_get(local_port, max_width) :
4204                     local_port;
4205
4206         for (i = 0; i < count * offset; i++) {
4207                 /* Expect base port to exist and also the one in the middle in
4208                  * case of maximal split count.
4209                  */
4210                 if (i == 0 || (count == max_width && i == count / 2))
4211                         continue;
4212
4213                 if (mlxsw_sp_port_created(mlxsw_sp, base_port + i)) {
4214                         netdev_err(mlxsw_sp_port->dev, "Invalid split configuration\n");
4215                         NL_SET_ERR_MSG_MOD(extack, "Invalid split configuration");
4216                         return -EINVAL;
4217                 }
4218         }
4219
4220         port_mapping = mlxsw_sp_port->mapping;
4221
4222         for (i = 0; i < count; i++)
4223                 if (mlxsw_sp_port_created(mlxsw_sp, base_port + i * offset))
4224                         mlxsw_sp_port_remove(mlxsw_sp, base_port + i * offset);
4225
4226         err = mlxsw_sp_port_split_create(mlxsw_sp, base_port, &port_mapping,
4227                                          count, offset);
4228         if (err) {
4229                 dev_err(mlxsw_sp->bus_info->dev, "Failed to create split ports\n");
4230                 goto err_port_split_create;
4231         }
4232
4233         return 0;
4234
4235 err_port_split_create:
4236         mlxsw_sp_port_unsplit_create(mlxsw_sp, base_port, count, offset);
4237         return err;
4238 }
4239
4240 static int mlxsw_sp_port_unsplit(struct mlxsw_core *mlxsw_core, u8 local_port,
4241                                  struct netlink_ext_ack *extack)
4242 {
4243         struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
4244         struct mlxsw_sp_port *mlxsw_sp_port;
4245         unsigned int count;
4246         int max_width;
4247         u8 base_port;
4248         int offset;
4249         int i;
4250
4251         mlxsw_sp_port = mlxsw_sp->ports[local_port];
4252         if (!mlxsw_sp_port) {
4253                 dev_err(mlxsw_sp->bus_info->dev, "Port number \"%d\" does not exist\n",
4254                         local_port);
4255                 NL_SET_ERR_MSG_MOD(extack, "Port number does not exist");
4256                 return -EINVAL;
4257         }
4258
4259         if (!mlxsw_sp_port->split) {
4260                 netdev_err(mlxsw_sp_port->dev, "Port was not split\n");
4261                 NL_SET_ERR_MSG_MOD(extack, "Port was not split");
4262                 return -EINVAL;
4263         }
4264
4265         max_width = mlxsw_core_module_max_width(mlxsw_core,
4266                                                 mlxsw_sp_port->mapping.module);
4267         if (max_width < 0) {
4268                 netdev_err(mlxsw_sp_port->dev, "Cannot get max width of port module\n");
4269                 NL_SET_ERR_MSG_MOD(extack, "Cannot get max width of port module");
4270                 return max_width;
4271         }
4272
4273         count = max_width / mlxsw_sp_port->mapping.width;
4274
4275         offset = mlxsw_sp_local_ports_offset(mlxsw_core, count, max_width);
4276         if (WARN_ON(offset < 0)) {
4277                 netdev_err(mlxsw_sp_port->dev, "Cannot obtain local port offset\n");
4278                 NL_SET_ERR_MSG_MOD(extack, "Cannot obtain local port offset");
4279                 return -EINVAL;
4280         }
4281
4282         base_port = mlxsw_sp_port->split_base_local_port;
4283
4284         for (i = 0; i < count; i++)
4285                 if (mlxsw_sp_port_created(mlxsw_sp, base_port + i * offset))
4286                         mlxsw_sp_port_remove(mlxsw_sp, base_port + i * offset);
4287
4288         mlxsw_sp_port_unsplit_create(mlxsw_sp, base_port, count, offset);
4289
4290         return 0;
4291 }
4292
4293 static void
4294 mlxsw_sp_port_down_wipe_counters(struct mlxsw_sp_port *mlxsw_sp_port)
4295 {
4296         int i;
4297
4298         for (i = 0; i < TC_MAX_QUEUE; i++)
4299                 mlxsw_sp_port->periodic_hw_stats.xstats.backlog[i] = 0;
4300 }
4301
4302 static void mlxsw_sp_pude_event_func(const struct mlxsw_reg_info *reg,
4303                                      char *pude_pl, void *priv)
4304 {
4305         struct mlxsw_sp *mlxsw_sp = priv;
4306         struct mlxsw_sp_port *mlxsw_sp_port;
4307         enum mlxsw_reg_pude_oper_status status;
4308         u8 local_port;
4309
4310         local_port = mlxsw_reg_pude_local_port_get(pude_pl);
4311         mlxsw_sp_port = mlxsw_sp->ports[local_port];
4312         if (!mlxsw_sp_port)
4313                 return;
4314
4315         status = mlxsw_reg_pude_oper_status_get(pude_pl);
4316         if (status == MLXSW_PORT_OPER_STATUS_UP) {
4317                 netdev_info(mlxsw_sp_port->dev, "link up\n");
4318                 netif_carrier_on(mlxsw_sp_port->dev);
4319                 mlxsw_core_schedule_dw(&mlxsw_sp_port->ptp.shaper_dw, 0);
4320                 mlxsw_core_schedule_dw(&mlxsw_sp_port->span.speed_update_dw, 0);
4321         } else {
4322                 netdev_info(mlxsw_sp_port->dev, "link down\n");
4323                 netif_carrier_off(mlxsw_sp_port->dev);
4324                 mlxsw_sp_port_down_wipe_counters(mlxsw_sp_port);
4325         }
4326 }
4327
4328 static void mlxsw_sp1_ptp_fifo_event_func(struct mlxsw_sp *mlxsw_sp,
4329                                           char *mtpptr_pl, bool ingress)
4330 {
4331         u8 local_port;
4332         u8 num_rec;
4333         int i;
4334
4335         local_port = mlxsw_reg_mtpptr_local_port_get(mtpptr_pl);
4336         num_rec = mlxsw_reg_mtpptr_num_rec_get(mtpptr_pl);
4337         for (i = 0; i < num_rec; i++) {
4338                 u8 domain_number;
4339                 u8 message_type;
4340                 u16 sequence_id;
4341                 u64 timestamp;
4342
4343                 mlxsw_reg_mtpptr_unpack(mtpptr_pl, i, &message_type,
4344                                         &domain_number, &sequence_id,
4345                                         &timestamp);
4346                 mlxsw_sp1_ptp_got_timestamp(mlxsw_sp, ingress, local_port,
4347                                             message_type, domain_number,
4348                                             sequence_id, timestamp);
4349         }
4350 }
4351
4352 static void mlxsw_sp1_ptp_ing_fifo_event_func(const struct mlxsw_reg_info *reg,
4353                                               char *mtpptr_pl, void *priv)
4354 {
4355         struct mlxsw_sp *mlxsw_sp = priv;
4356
4357         mlxsw_sp1_ptp_fifo_event_func(mlxsw_sp, mtpptr_pl, true);
4358 }
4359
4360 static void mlxsw_sp1_ptp_egr_fifo_event_func(const struct mlxsw_reg_info *reg,
4361                                               char *mtpptr_pl, void *priv)
4362 {
4363         struct mlxsw_sp *mlxsw_sp = priv;
4364
4365         mlxsw_sp1_ptp_fifo_event_func(mlxsw_sp, mtpptr_pl, false);
4366 }
4367
4368 void mlxsw_sp_rx_listener_no_mark_func(struct sk_buff *skb,
4369                                        u8 local_port, void *priv)
4370 {
4371         struct mlxsw_sp *mlxsw_sp = priv;
4372         struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp->ports[local_port];
4373         struct mlxsw_sp_port_pcpu_stats *pcpu_stats;
4374
4375         if (unlikely(!mlxsw_sp_port)) {
4376                 dev_warn_ratelimited(mlxsw_sp->bus_info->dev, "Port %d: skb received for non-existent port\n",
4377                                      local_port);
4378                 return;
4379         }
4380
4381         skb->dev = mlxsw_sp_port->dev;
4382
4383         pcpu_stats = this_cpu_ptr(mlxsw_sp_port->pcpu_stats);
4384         u64_stats_update_begin(&pcpu_stats->syncp);
4385         pcpu_stats->rx_packets++;
4386         pcpu_stats->rx_bytes += skb->len;
4387         u64_stats_update_end(&pcpu_stats->syncp);
4388
4389         skb->protocol = eth_type_trans(skb, skb->dev);
4390         netif_receive_skb(skb);
4391 }
4392
4393 static void mlxsw_sp_rx_listener_mark_func(struct sk_buff *skb, u8 local_port,
4394                                            void *priv)
4395 {
4396         skb->offload_fwd_mark = 1;
4397         return mlxsw_sp_rx_listener_no_mark_func(skb, local_port, priv);
4398 }
4399
4400 static void mlxsw_sp_rx_listener_l3_mark_func(struct sk_buff *skb,
4401                                               u8 local_port, void *priv)
4402 {
4403         skb->offload_l3_fwd_mark = 1;
4404         skb->offload_fwd_mark = 1;
4405         return mlxsw_sp_rx_listener_no_mark_func(skb, local_port, priv);
4406 }
4407
4408 static void mlxsw_sp_rx_listener_sample_func(struct sk_buff *skb, u8 local_port,
4409                                              void *priv)
4410 {
4411         struct mlxsw_sp *mlxsw_sp = priv;
4412         struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp->ports[local_port];
4413         struct psample_group *psample_group;
4414         u32 size;
4415
4416         if (unlikely(!mlxsw_sp_port)) {
4417                 dev_warn_ratelimited(mlxsw_sp->bus_info->dev, "Port %d: sample skb received for non-existent port\n",
4418                                      local_port);
4419                 goto out;
4420         }
4421         if (unlikely(!mlxsw_sp_port->sample)) {
4422                 dev_warn_ratelimited(mlxsw_sp->bus_info->dev, "Port %d: sample skb received on unsupported port\n",
4423                                      local_port);
4424                 goto out;
4425         }
4426
4427         size = mlxsw_sp_port->sample->truncate ?
4428                   mlxsw_sp_port->sample->trunc_size : skb->len;
4429
4430         rcu_read_lock();
4431         psample_group = rcu_dereference(mlxsw_sp_port->sample->psample_group);
4432         if (!psample_group)
4433                 goto out_unlock;
4434         psample_sample_packet(psample_group, skb, size,
4435                               mlxsw_sp_port->dev->ifindex, 0,
4436                               mlxsw_sp_port->sample->rate);
4437 out_unlock:
4438         rcu_read_unlock();
4439 out:
4440         consume_skb(skb);
4441 }
4442
4443 static void mlxsw_sp_rx_listener_ptp(struct sk_buff *skb, u8 local_port,
4444                                      void *priv)
4445 {
4446         struct mlxsw_sp *mlxsw_sp = priv;
4447
4448         mlxsw_sp->ptp_ops->receive(mlxsw_sp, skb, local_port);
4449 }
4450
4451 #define MLXSW_SP_RXL_NO_MARK(_trap_id, _action, _trap_group, _is_ctrl)  \
4452         MLXSW_RXL(mlxsw_sp_rx_listener_no_mark_func, _trap_id, _action, \
4453                   _is_ctrl, SP_##_trap_group, DISCARD)
4454
4455 #define MLXSW_SP_RXL_MARK(_trap_id, _action, _trap_group, _is_ctrl)     \
4456         MLXSW_RXL(mlxsw_sp_rx_listener_mark_func, _trap_id, _action,    \
4457                 _is_ctrl, SP_##_trap_group, DISCARD)
4458
4459 #define MLXSW_SP_RXL_L3_MARK(_trap_id, _action, _trap_group, _is_ctrl)  \
4460         MLXSW_RXL(mlxsw_sp_rx_listener_l3_mark_func, _trap_id, _action, \
4461                 _is_ctrl, SP_##_trap_group, DISCARD)
4462
4463 #define MLXSW_SP_EVENTL(_func, _trap_id)                \
4464         MLXSW_EVENTL(_func, _trap_id, SP_EVENT)
4465
4466 static const struct mlxsw_listener mlxsw_sp_listener[] = {
4467         /* Events */
4468         MLXSW_SP_EVENTL(mlxsw_sp_pude_event_func, PUDE),
4469         /* L2 traps */
4470         MLXSW_SP_RXL_NO_MARK(STP, TRAP_TO_CPU, STP, true),
4471         MLXSW_SP_RXL_NO_MARK(LACP, TRAP_TO_CPU, LACP, true),
4472         MLXSW_RXL(mlxsw_sp_rx_listener_ptp, LLDP, TRAP_TO_CPU,
4473                   false, SP_LLDP, DISCARD),
4474         MLXSW_SP_RXL_MARK(DHCP, MIRROR_TO_CPU, DHCP, false),
4475         MLXSW_SP_RXL_MARK(IGMP_QUERY, MIRROR_TO_CPU, IGMP, false),
4476         MLXSW_SP_RXL_NO_MARK(IGMP_V1_REPORT, TRAP_TO_CPU, IGMP, false),
4477         MLXSW_SP_RXL_NO_MARK(IGMP_V2_REPORT, TRAP_TO_CPU, IGMP, false),
4478         MLXSW_SP_RXL_NO_MARK(IGMP_V2_LEAVE, TRAP_TO_CPU, IGMP, false),
4479         MLXSW_SP_RXL_NO_MARK(IGMP_V3_REPORT, TRAP_TO_CPU, IGMP, false),
4480         MLXSW_SP_RXL_MARK(ARPBC, MIRROR_TO_CPU, ARP, false),
4481         MLXSW_SP_RXL_MARK(ARPUC, MIRROR_TO_CPU, ARP, false),
4482         MLXSW_SP_RXL_NO_MARK(FID_MISS, TRAP_TO_CPU, IP2ME, false),
4483         MLXSW_SP_RXL_MARK(IPV6_MLDV12_LISTENER_QUERY, MIRROR_TO_CPU, IPV6_MLD,
4484                           false),
4485         MLXSW_SP_RXL_NO_MARK(IPV6_MLDV1_LISTENER_REPORT, TRAP_TO_CPU, IPV6_MLD,
4486                              false),
4487         MLXSW_SP_RXL_NO_MARK(IPV6_MLDV1_LISTENER_DONE, TRAP_TO_CPU, IPV6_MLD,
4488                              false),
4489         MLXSW_SP_RXL_NO_MARK(IPV6_MLDV2_LISTENER_REPORT, TRAP_TO_CPU, IPV6_MLD,
4490                              false),
4491         /* L3 traps */
4492         MLXSW_SP_RXL_L3_MARK(LBERROR, MIRROR_TO_CPU, LBERROR, false),
4493         MLXSW_SP_RXL_MARK(IP2ME, TRAP_TO_CPU, IP2ME, false),
4494         MLXSW_SP_RXL_MARK(IPV6_UNSPECIFIED_ADDRESS, TRAP_TO_CPU, ROUTER_EXP,
4495                           false),
4496         MLXSW_SP_RXL_MARK(IPV6_LINK_LOCAL_DEST, TRAP_TO_CPU, ROUTER_EXP, false),
4497         MLXSW_SP_RXL_MARK(IPV6_LINK_LOCAL_SRC, TRAP_TO_CPU, ROUTER_EXP, false),
4498         MLXSW_SP_RXL_MARK(IPV6_ALL_NODES_LINK, TRAP_TO_CPU, ROUTER_EXP, false),
4499         MLXSW_SP_RXL_MARK(IPV6_ALL_ROUTERS_LINK, TRAP_TO_CPU, ROUTER_EXP,
4500                           false),
4501         MLXSW_SP_RXL_MARK(IPV4_OSPF, TRAP_TO_CPU, OSPF, false),
4502         MLXSW_SP_RXL_MARK(IPV6_OSPF, TRAP_TO_CPU, OSPF, false),
4503         MLXSW_SP_RXL_MARK(IPV6_DHCP, TRAP_TO_CPU, DHCP, false),
4504         MLXSW_SP_RXL_MARK(RTR_INGRESS0, TRAP_TO_CPU, REMOTE_ROUTE, false),
4505         MLXSW_SP_RXL_MARK(IPV4_BGP, TRAP_TO_CPU, BGP, false),
4506         MLXSW_SP_RXL_MARK(IPV6_BGP, TRAP_TO_CPU, BGP, false),
4507         MLXSW_SP_RXL_MARK(L3_IPV6_ROUTER_SOLICITATION, TRAP_TO_CPU, IPV6_ND,
4508                           false),
4509         MLXSW_SP_RXL_MARK(L3_IPV6_ROUTER_ADVERTISMENT, TRAP_TO_CPU, IPV6_ND,
4510                           false),
4511         MLXSW_SP_RXL_MARK(L3_IPV6_NEIGHBOR_SOLICITATION, TRAP_TO_CPU, IPV6_ND,
4512                           false),
4513         MLXSW_SP_RXL_MARK(L3_IPV6_NEIGHBOR_ADVERTISMENT, TRAP_TO_CPU, IPV6_ND,
4514                           false),
4515         MLXSW_SP_RXL_MARK(L3_IPV6_REDIRECTION, TRAP_TO_CPU, IPV6_ND, false),
4516         MLXSW_SP_RXL_MARK(IPV6_MC_LINK_LOCAL_DEST, TRAP_TO_CPU, ROUTER_EXP,
4517                           false),
4518         MLXSW_SP_RXL_MARK(ROUTER_ALERT_IPV4, TRAP_TO_CPU, ROUTER_EXP, false),
4519         MLXSW_SP_RXL_MARK(ROUTER_ALERT_IPV6, TRAP_TO_CPU, ROUTER_EXP, false),
4520         MLXSW_SP_RXL_MARK(IPV4_VRRP, TRAP_TO_CPU, VRRP, false),
4521         MLXSW_SP_RXL_MARK(IPV6_VRRP, TRAP_TO_CPU, VRRP, false),
4522         MLXSW_SP_RXL_NO_MARK(DISCARD_ING_ROUTER_SIP_CLASS_E, FORWARD,
4523                              ROUTER_EXP, false),
4524         MLXSW_SP_RXL_NO_MARK(DISCARD_ING_ROUTER_MC_DMAC, FORWARD,
4525                              ROUTER_EXP, false),
4526         MLXSW_SP_RXL_NO_MARK(DISCARD_ING_ROUTER_SIP_DIP, FORWARD,
4527                              ROUTER_EXP, false),
4528         MLXSW_SP_RXL_NO_MARK(DISCARD_ING_ROUTER_DIP_LINK_LOCAL, FORWARD,
4529                              ROUTER_EXP, false),
4530         /* PKT Sample trap */
4531         MLXSW_RXL(mlxsw_sp_rx_listener_sample_func, PKT_SAMPLE, MIRROR_TO_CPU,
4532                   false, SP_IP2ME, DISCARD),
4533         /* ACL trap */
4534         MLXSW_SP_RXL_NO_MARK(ACL0, TRAP_TO_CPU, IP2ME, false),
4535         /* Multicast Router Traps */
4536         MLXSW_SP_RXL_MARK(IPV4_PIM, TRAP_TO_CPU, PIM, false),
4537         MLXSW_SP_RXL_MARK(IPV6_PIM, TRAP_TO_CPU, PIM, false),
4538         MLXSW_SP_RXL_MARK(ACL1, TRAP_TO_CPU, MULTICAST, false),
4539         MLXSW_SP_RXL_L3_MARK(ACL2, TRAP_TO_CPU, MULTICAST, false),
4540         /* NVE traps */
4541         MLXSW_SP_RXL_MARK(NVE_ENCAP_ARP, TRAP_TO_CPU, ARP, false),
4542         MLXSW_SP_RXL_NO_MARK(NVE_DECAP_ARP, TRAP_TO_CPU, ARP, false),
4543         /* PTP traps */
4544         MLXSW_RXL(mlxsw_sp_rx_listener_ptp, PTP0, TRAP_TO_CPU,
4545                   false, SP_PTP0, DISCARD),
4546         MLXSW_SP_RXL_NO_MARK(PTP1, TRAP_TO_CPU, PTP1, false),
4547 };
4548
4549 static const struct mlxsw_listener mlxsw_sp1_listener[] = {
4550         /* Events */
4551         MLXSW_EVENTL(mlxsw_sp1_ptp_egr_fifo_event_func, PTP_EGR_FIFO, SP_PTP0),
4552         MLXSW_EVENTL(mlxsw_sp1_ptp_ing_fifo_event_func, PTP_ING_FIFO, SP_PTP0),
4553 };
4554
4555 static int mlxsw_sp_cpu_policers_set(struct mlxsw_core *mlxsw_core)
4556 {
4557         char qpcr_pl[MLXSW_REG_QPCR_LEN];
4558         enum mlxsw_reg_qpcr_ir_units ir_units;
4559         int max_cpu_policers;
4560         bool is_bytes;
4561         u8 burst_size;
4562         u32 rate;
4563         int i, err;
4564
4565         if (!MLXSW_CORE_RES_VALID(mlxsw_core, MAX_CPU_POLICERS))
4566                 return -EIO;
4567
4568         max_cpu_policers = MLXSW_CORE_RES_GET(mlxsw_core, MAX_CPU_POLICERS);
4569
4570         ir_units = MLXSW_REG_QPCR_IR_UNITS_M;
4571         for (i = 0; i < max_cpu_policers; i++) {
4572                 is_bytes = false;
4573                 switch (i) {
4574                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_STP:
4575                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_LACP:
4576                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_LLDP:
4577                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_OSPF:
4578                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_PIM:
4579                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_RPF:
4580                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_LBERROR:
4581                         rate = 128;
4582                         burst_size = 7;
4583                         break;
4584                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_IGMP:
4585                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_IPV6_MLD:
4586                         rate = 16 * 1024;
4587                         burst_size = 10;
4588                         break;
4589                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_BGP:
4590                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_ARP:
4591                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_DHCP:
4592                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_HOST_MISS:
4593                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_ROUTER_EXP:
4594                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_REMOTE_ROUTE:
4595                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_IPV6_ND:
4596                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_MULTICAST:
4597                         rate = 1024;
4598                         burst_size = 7;
4599                         break;
4600                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_IP2ME:
4601                         rate = 1024;
4602                         burst_size = 7;
4603                         break;
4604                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_PTP0:
4605                         rate = 24 * 1024;
4606                         burst_size = 12;
4607                         break;
4608                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_PTP1:
4609                         rate = 19 * 1024;
4610                         burst_size = 12;
4611                         break;
4612                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_VRRP:
4613                         rate = 360;
4614                         burst_size = 7;
4615                         break;
4616                 default:
4617                         continue;
4618                 }
4619
4620                 mlxsw_reg_qpcr_pack(qpcr_pl, i, ir_units, is_bytes, rate,
4621                                     burst_size);
4622                 err = mlxsw_reg_write(mlxsw_core, MLXSW_REG(qpcr), qpcr_pl);
4623                 if (err)
4624                         return err;
4625         }
4626
4627         return 0;
4628 }
4629
4630 static int mlxsw_sp_trap_groups_set(struct mlxsw_core *mlxsw_core)
4631 {
4632         char htgt_pl[MLXSW_REG_HTGT_LEN];
4633         enum mlxsw_reg_htgt_trap_group i;
4634         int max_cpu_policers;
4635         int max_trap_groups;
4636         u8 priority, tc;
4637         u16 policer_id;
4638         int err;
4639
4640         if (!MLXSW_CORE_RES_VALID(mlxsw_core, MAX_TRAP_GROUPS))
4641                 return -EIO;
4642
4643         max_trap_groups = MLXSW_CORE_RES_GET(mlxsw_core, MAX_TRAP_GROUPS);
4644         max_cpu_policers = MLXSW_CORE_RES_GET(mlxsw_core, MAX_CPU_POLICERS);
4645
4646         for (i = 0; i < max_trap_groups; i++) {
4647                 policer_id = i;
4648                 switch (i) {
4649                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_STP:
4650                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_LACP:
4651                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_LLDP:
4652                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_OSPF:
4653                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_PIM:
4654                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_PTP0:
4655                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_VRRP:
4656                         priority = 5;
4657                         tc = 5;
4658                         break;
4659                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_BGP:
4660                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_DHCP:
4661                         priority = 4;
4662                         tc = 4;
4663                         break;
4664                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_IGMP:
4665                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_IP2ME:
4666                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_IPV6_MLD:
4667                         priority = 3;
4668                         tc = 3;
4669                         break;
4670                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_ARP:
4671                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_IPV6_ND:
4672                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_RPF:
4673                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_PTP1:
4674                         priority = 2;
4675                         tc = 2;
4676                         break;
4677                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_HOST_MISS:
4678                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_ROUTER_EXP:
4679                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_REMOTE_ROUTE:
4680                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_MULTICAST:
4681                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_LBERROR:
4682                         priority = 1;
4683                         tc = 1;
4684                         break;
4685                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_EVENT:
4686                         priority = MLXSW_REG_HTGT_DEFAULT_PRIORITY;
4687                         tc = MLXSW_REG_HTGT_DEFAULT_TC;
4688                         policer_id = MLXSW_REG_HTGT_INVALID_POLICER;
4689                         break;
4690                 default:
4691                         continue;
4692                 }
4693
4694                 if (max_cpu_policers <= policer_id &&
4695                     policer_id != MLXSW_REG_HTGT_INVALID_POLICER)
4696                         return -EIO;
4697
4698                 mlxsw_reg_htgt_pack(htgt_pl, i, policer_id, priority, tc);
4699                 err = mlxsw_reg_write(mlxsw_core, MLXSW_REG(htgt), htgt_pl);
4700                 if (err)
4701                         return err;
4702         }
4703
4704         return 0;
4705 }
4706
4707 static int mlxsw_sp_traps_register(struct mlxsw_sp *mlxsw_sp,
4708                                    const struct mlxsw_listener listeners[],
4709                                    size_t listeners_count)
4710 {
4711         int i;
4712         int err;
4713
4714         for (i = 0; i < listeners_count; i++) {
4715                 err = mlxsw_core_trap_register(mlxsw_sp->core,
4716                                                &listeners[i],
4717                                                mlxsw_sp);
4718                 if (err)
4719                         goto err_listener_register;
4720
4721         }
4722         return 0;
4723
4724 err_listener_register:
4725         for (i--; i >= 0; i--) {
4726                 mlxsw_core_trap_unregister(mlxsw_sp->core,
4727                                            &listeners[i],
4728                                            mlxsw_sp);
4729         }
4730         return err;
4731 }
4732
4733 static void mlxsw_sp_traps_unregister(struct mlxsw_sp *mlxsw_sp,
4734                                       const struct mlxsw_listener listeners[],
4735                                       size_t listeners_count)
4736 {
4737         int i;
4738
4739         for (i = 0; i < listeners_count; i++) {
4740                 mlxsw_core_trap_unregister(mlxsw_sp->core,
4741                                            &listeners[i],
4742                                            mlxsw_sp);
4743         }
4744 }
4745
4746 static int mlxsw_sp_traps_init(struct mlxsw_sp *mlxsw_sp)
4747 {
4748         int err;
4749
4750         err = mlxsw_sp_cpu_policers_set(mlxsw_sp->core);
4751         if (err)
4752                 return err;
4753
4754         err = mlxsw_sp_trap_groups_set(mlxsw_sp->core);
4755         if (err)
4756                 return err;
4757
4758         err = mlxsw_sp_traps_register(mlxsw_sp, mlxsw_sp_listener,
4759                                       ARRAY_SIZE(mlxsw_sp_listener));
4760         if (err)
4761                 return err;
4762
4763         err = mlxsw_sp_traps_register(mlxsw_sp, mlxsw_sp->listeners,
4764                                       mlxsw_sp->listeners_count);
4765         if (err)
4766                 goto err_extra_traps_init;
4767
4768         return 0;
4769
4770 err_extra_traps_init:
4771         mlxsw_sp_traps_unregister(mlxsw_sp, mlxsw_sp_listener,
4772                                   ARRAY_SIZE(mlxsw_sp_listener));
4773         return err;
4774 }
4775
4776 static void mlxsw_sp_traps_fini(struct mlxsw_sp *mlxsw_sp)
4777 {
4778         mlxsw_sp_traps_unregister(mlxsw_sp, mlxsw_sp->listeners,
4779                                   mlxsw_sp->listeners_count);
4780         mlxsw_sp_traps_unregister(mlxsw_sp, mlxsw_sp_listener,
4781                                   ARRAY_SIZE(mlxsw_sp_listener));
4782 }
4783
4784 #define MLXSW_SP_LAG_SEED_INIT 0xcafecafe
4785
4786 static int mlxsw_sp_lag_init(struct mlxsw_sp *mlxsw_sp)
4787 {
4788         char slcr_pl[MLXSW_REG_SLCR_LEN];
4789         u32 seed;
4790         int err;
4791
4792         seed = jhash(mlxsw_sp->base_mac, sizeof(mlxsw_sp->base_mac),
4793                      MLXSW_SP_LAG_SEED_INIT);
4794         mlxsw_reg_slcr_pack(slcr_pl, MLXSW_REG_SLCR_LAG_HASH_SMAC |
4795                                      MLXSW_REG_SLCR_LAG_HASH_DMAC |
4796                                      MLXSW_REG_SLCR_LAG_HASH_ETHERTYPE |
4797                                      MLXSW_REG_SLCR_LAG_HASH_VLANID |
4798                                      MLXSW_REG_SLCR_LAG_HASH_SIP |
4799                                      MLXSW_REG_SLCR_LAG_HASH_DIP |
4800                                      MLXSW_REG_SLCR_LAG_HASH_SPORT |
4801                                      MLXSW_REG_SLCR_LAG_HASH_DPORT |
4802                                      MLXSW_REG_SLCR_LAG_HASH_IPPROTO, seed);
4803         err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(slcr), slcr_pl);
4804         if (err)
4805                 return err;
4806
4807         if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_LAG) ||
4808             !MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_LAG_MEMBERS))
4809                 return -EIO;
4810
4811         mlxsw_sp->lags = kcalloc(MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_LAG),
4812                                  sizeof(struct mlxsw_sp_upper),
4813                                  GFP_KERNEL);
4814         if (!mlxsw_sp->lags)
4815                 return -ENOMEM;
4816
4817         return 0;
4818 }
4819
4820 static void mlxsw_sp_lag_fini(struct mlxsw_sp *mlxsw_sp)
4821 {
4822         kfree(mlxsw_sp->lags);
4823 }
4824
4825 static int mlxsw_sp_basic_trap_groups_set(struct mlxsw_core *mlxsw_core)
4826 {
4827         char htgt_pl[MLXSW_REG_HTGT_LEN];
4828
4829         mlxsw_reg_htgt_pack(htgt_pl, MLXSW_REG_HTGT_TRAP_GROUP_EMAD,
4830                             MLXSW_REG_HTGT_INVALID_POLICER,
4831                             MLXSW_REG_HTGT_DEFAULT_PRIORITY,
4832                             MLXSW_REG_HTGT_DEFAULT_TC);
4833         return mlxsw_reg_write(mlxsw_core, MLXSW_REG(htgt), htgt_pl);
4834 }
4835
4836 static const struct mlxsw_sp_ptp_ops mlxsw_sp1_ptp_ops = {
4837         .clock_init     = mlxsw_sp1_ptp_clock_init,
4838         .clock_fini     = mlxsw_sp1_ptp_clock_fini,
4839         .init           = mlxsw_sp1_ptp_init,
4840         .fini           = mlxsw_sp1_ptp_fini,
4841         .receive        = mlxsw_sp1_ptp_receive,
4842         .transmitted    = mlxsw_sp1_ptp_transmitted,
4843         .hwtstamp_get   = mlxsw_sp1_ptp_hwtstamp_get,
4844         .hwtstamp_set   = mlxsw_sp1_ptp_hwtstamp_set,
4845         .shaper_work    = mlxsw_sp1_ptp_shaper_work,
4846         .get_ts_info    = mlxsw_sp1_ptp_get_ts_info,
4847         .get_stats_count = mlxsw_sp1_get_stats_count,
4848         .get_stats_strings = mlxsw_sp1_get_stats_strings,
4849         .get_stats      = mlxsw_sp1_get_stats,
4850 };
4851
4852 static const struct mlxsw_sp_ptp_ops mlxsw_sp2_ptp_ops = {
4853         .clock_init     = mlxsw_sp2_ptp_clock_init,
4854         .clock_fini     = mlxsw_sp2_ptp_clock_fini,
4855         .init           = mlxsw_sp2_ptp_init,
4856         .fini           = mlxsw_sp2_ptp_fini,
4857         .receive        = mlxsw_sp2_ptp_receive,
4858         .transmitted    = mlxsw_sp2_ptp_transmitted,
4859         .hwtstamp_get   = mlxsw_sp2_ptp_hwtstamp_get,
4860         .hwtstamp_set   = mlxsw_sp2_ptp_hwtstamp_set,
4861         .shaper_work    = mlxsw_sp2_ptp_shaper_work,
4862         .get_ts_info    = mlxsw_sp2_ptp_get_ts_info,
4863         .get_stats_count = mlxsw_sp2_get_stats_count,
4864         .get_stats_strings = mlxsw_sp2_get_stats_strings,
4865         .get_stats      = mlxsw_sp2_get_stats,
4866 };
4867
4868 static u32 mlxsw_sp1_span_buffsize_get(int mtu, u32 speed)
4869 {
4870         return mtu * 5 / 2;
4871 }
4872
4873 static const struct mlxsw_sp_span_ops mlxsw_sp1_span_ops = {
4874         .buffsize_get = mlxsw_sp1_span_buffsize_get,
4875 };
4876
4877 #define MLXSW_SP2_SPAN_EG_MIRROR_BUFFER_FACTOR 38
4878 #define MLXSW_SP3_SPAN_EG_MIRROR_BUFFER_FACTOR 50
4879
4880 static u32 __mlxsw_sp_span_buffsize_get(int mtu, u32 speed, u32 buffer_factor)
4881 {
4882         return 3 * mtu + buffer_factor * speed / 1000;
4883 }
4884
4885 static u32 mlxsw_sp2_span_buffsize_get(int mtu, u32 speed)
4886 {
4887         int factor = MLXSW_SP2_SPAN_EG_MIRROR_BUFFER_FACTOR;
4888
4889         return __mlxsw_sp_span_buffsize_get(mtu, speed, factor);
4890 }
4891
4892 static const struct mlxsw_sp_span_ops mlxsw_sp2_span_ops = {
4893         .buffsize_get = mlxsw_sp2_span_buffsize_get,
4894 };
4895
4896 static u32 mlxsw_sp3_span_buffsize_get(int mtu, u32 speed)
4897 {
4898         int factor = MLXSW_SP3_SPAN_EG_MIRROR_BUFFER_FACTOR;
4899
4900         return __mlxsw_sp_span_buffsize_get(mtu, speed, factor);
4901 }
4902
4903 static const struct mlxsw_sp_span_ops mlxsw_sp3_span_ops = {
4904         .buffsize_get = mlxsw_sp3_span_buffsize_get,
4905 };
4906
4907 u32 mlxsw_sp_span_buffsize_get(struct mlxsw_sp *mlxsw_sp, int mtu, u32 speed)
4908 {
4909         u32 buffsize = mlxsw_sp->span_ops->buffsize_get(speed, mtu);
4910
4911         return mlxsw_sp_bytes_cells(mlxsw_sp, buffsize) + 1;
4912 }
4913
4914 static int mlxsw_sp_netdevice_event(struct notifier_block *unused,
4915                                     unsigned long event, void *ptr);
4916
4917 static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core,
4918                          const struct mlxsw_bus_info *mlxsw_bus_info,
4919                          struct netlink_ext_ack *extack)
4920 {
4921         struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
4922         int err;
4923
4924         mlxsw_sp->core = mlxsw_core;
4925         mlxsw_sp->bus_info = mlxsw_bus_info;
4926
4927         err = mlxsw_sp_fw_rev_validate(mlxsw_sp);
4928         if (err)
4929                 return err;
4930
4931         mlxsw_core_emad_string_tlv_enable(mlxsw_core);
4932
4933         err = mlxsw_sp_base_mac_get(mlxsw_sp);
4934         if (err) {
4935                 dev_err(mlxsw_sp->bus_info->dev, "Failed to get base mac\n");
4936                 return err;
4937         }
4938
4939         err = mlxsw_sp_kvdl_init(mlxsw_sp);
4940         if (err) {
4941                 dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize KVDL\n");
4942                 return err;
4943         }
4944
4945         err = mlxsw_sp_fids_init(mlxsw_sp);
4946         if (err) {
4947                 dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize FIDs\n");
4948                 goto err_fids_init;
4949         }
4950
4951         err = mlxsw_sp_traps_init(mlxsw_sp);
4952         if (err) {
4953                 dev_err(mlxsw_sp->bus_info->dev, "Failed to set traps\n");
4954                 goto err_traps_init;
4955         }
4956
4957         err = mlxsw_sp_devlink_traps_init(mlxsw_sp);
4958         if (err) {
4959                 dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize devlink traps\n");
4960                 goto err_devlink_traps_init;
4961         }
4962
4963         err = mlxsw_sp_buffers_init(mlxsw_sp);
4964         if (err) {
4965                 dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize buffers\n");
4966                 goto err_buffers_init;
4967         }
4968
4969         err = mlxsw_sp_lag_init(mlxsw_sp);
4970         if (err) {
4971                 dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize LAG\n");
4972                 goto err_lag_init;
4973         }
4974
4975         /* Initialize SPAN before router and switchdev, so that those components
4976          * can call mlxsw_sp_span_respin().
4977          */
4978         err = mlxsw_sp_span_init(mlxsw_sp);
4979         if (err) {
4980                 dev_err(mlxsw_sp->bus_info->dev, "Failed to init span system\n");
4981                 goto err_span_init;
4982         }
4983
4984         err = mlxsw_sp_switchdev_init(mlxsw_sp);
4985         if (err) {
4986                 dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize switchdev\n");
4987                 goto err_switchdev_init;
4988         }
4989
4990         err = mlxsw_sp_counter_pool_init(mlxsw_sp);
4991         if (err) {
4992                 dev_err(mlxsw_sp->bus_info->dev, "Failed to init counter pool\n");
4993                 goto err_counter_pool_init;
4994         }
4995
4996         err = mlxsw_sp_afa_init(mlxsw_sp);
4997         if (err) {
4998                 dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize ACL actions\n");
4999                 goto err_afa_init;
5000         }
5001
5002         err = mlxsw_sp_nve_init(mlxsw_sp);
5003         if (err) {
5004                 dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize NVE\n");
5005                 goto err_nve_init;
5006         }
5007
5008         err = mlxsw_sp_acl_init(mlxsw_sp);
5009         if (err) {
5010                 dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize ACL\n");
5011                 goto err_acl_init;
5012         }
5013
5014         err = mlxsw_sp_router_init(mlxsw_sp, extack);
5015         if (err) {
5016                 dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize router\n");
5017                 goto err_router_init;
5018         }
5019
5020         if (mlxsw_sp->bus_info->read_frc_capable) {
5021                 /* NULL is a valid return value from clock_init */
5022                 mlxsw_sp->clock =
5023                         mlxsw_sp->ptp_ops->clock_init(mlxsw_sp,
5024                                                       mlxsw_sp->bus_info->dev);
5025                 if (IS_ERR(mlxsw_sp->clock)) {
5026                         err = PTR_ERR(mlxsw_sp->clock);
5027                         dev_err(mlxsw_sp->bus_info->dev, "Failed to init ptp clock\n");
5028                         goto err_ptp_clock_init;
5029                 }
5030         }
5031
5032         if (mlxsw_sp->clock) {
5033                 /* NULL is a valid return value from ptp_ops->init */
5034                 mlxsw_sp->ptp_state = mlxsw_sp->ptp_ops->init(mlxsw_sp);
5035                 if (IS_ERR(mlxsw_sp->ptp_state)) {
5036                         err = PTR_ERR(mlxsw_sp->ptp_state);
5037                         dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize PTP\n");
5038                         goto err_ptp_init;
5039                 }
5040         }
5041
5042         /* Initialize netdevice notifier after router and SPAN is initialized,
5043          * so that the event handler can use router structures and call SPAN
5044          * respin.
5045          */
5046         mlxsw_sp->netdevice_nb.notifier_call = mlxsw_sp_netdevice_event;
5047         err = register_netdevice_notifier_net(mlxsw_sp_net(mlxsw_sp),
5048                                               &mlxsw_sp->netdevice_nb);
5049         if (err) {
5050                 dev_err(mlxsw_sp->bus_info->dev, "Failed to register netdev notifier\n");
5051                 goto err_netdev_notifier;
5052         }
5053
5054         err = mlxsw_sp_dpipe_init(mlxsw_sp);
5055         if (err) {
5056                 dev_err(mlxsw_sp->bus_info->dev, "Failed to init pipeline debug\n");
5057                 goto err_dpipe_init;
5058         }
5059
5060         err = mlxsw_sp_port_module_info_init(mlxsw_sp);
5061         if (err) {
5062                 dev_err(mlxsw_sp->bus_info->dev, "Failed to init port module info\n");
5063                 goto err_port_module_info_init;
5064         }
5065
5066         err = mlxsw_sp_ports_create(mlxsw_sp);
5067         if (err) {
5068                 dev_err(mlxsw_sp->bus_info->dev, "Failed to create ports\n");
5069                 goto err_ports_create;
5070         }
5071
5072         return 0;
5073
5074 err_ports_create:
5075         mlxsw_sp_port_module_info_fini(mlxsw_sp);
5076 err_port_module_info_init:
5077         mlxsw_sp_dpipe_fini(mlxsw_sp);
5078 err_dpipe_init:
5079         unregister_netdevice_notifier_net(mlxsw_sp_net(mlxsw_sp),
5080                                           &mlxsw_sp->netdevice_nb);
5081 err_netdev_notifier:
5082         if (mlxsw_sp->clock)
5083                 mlxsw_sp->ptp_ops->fini(mlxsw_sp->ptp_state);
5084 err_ptp_init:
5085         if (mlxsw_sp->clock)
5086                 mlxsw_sp->ptp_ops->clock_fini(mlxsw_sp->clock);
5087 err_ptp_clock_init:
5088         mlxsw_sp_router_fini(mlxsw_sp);
5089 err_router_init:
5090         mlxsw_sp_acl_fini(mlxsw_sp);
5091 err_acl_init:
5092         mlxsw_sp_nve_fini(mlxsw_sp);
5093 err_nve_init:
5094         mlxsw_sp_afa_fini(mlxsw_sp);
5095 err_afa_init:
5096         mlxsw_sp_counter_pool_fini(mlxsw_sp);
5097 err_counter_pool_init:
5098         mlxsw_sp_switchdev_fini(mlxsw_sp);
5099 err_switchdev_init:
5100         mlxsw_sp_span_fini(mlxsw_sp);
5101 err_span_init:
5102         mlxsw_sp_lag_fini(mlxsw_sp);
5103 err_lag_init:
5104         mlxsw_sp_buffers_fini(mlxsw_sp);
5105 err_buffers_init:
5106         mlxsw_sp_devlink_traps_fini(mlxsw_sp);
5107 err_devlink_traps_init:
5108         mlxsw_sp_traps_fini(mlxsw_sp);
5109 err_traps_init:
5110         mlxsw_sp_fids_fini(mlxsw_sp);
5111 err_fids_init:
5112         mlxsw_sp_kvdl_fini(mlxsw_sp);
5113         return err;
5114 }
5115
5116 static int mlxsw_sp1_init(struct mlxsw_core *mlxsw_core,
5117                           const struct mlxsw_bus_info *mlxsw_bus_info,
5118                           struct netlink_ext_ack *extack)
5119 {
5120         struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
5121
5122         mlxsw_sp->req_rev = &mlxsw_sp1_fw_rev;
5123         mlxsw_sp->fw_filename = MLXSW_SP1_FW_FILENAME;
5124         mlxsw_sp->kvdl_ops = &mlxsw_sp1_kvdl_ops;
5125         mlxsw_sp->afa_ops = &mlxsw_sp1_act_afa_ops;
5126         mlxsw_sp->afk_ops = &mlxsw_sp1_afk_ops;
5127         mlxsw_sp->mr_tcam_ops = &mlxsw_sp1_mr_tcam_ops;
5128         mlxsw_sp->acl_tcam_ops = &mlxsw_sp1_acl_tcam_ops;
5129         mlxsw_sp->nve_ops_arr = mlxsw_sp1_nve_ops_arr;
5130         mlxsw_sp->mac_mask = mlxsw_sp1_mac_mask;
5131         mlxsw_sp->rif_ops_arr = mlxsw_sp1_rif_ops_arr;
5132         mlxsw_sp->sb_vals = &mlxsw_sp1_sb_vals;
5133         mlxsw_sp->port_type_speed_ops = &mlxsw_sp1_port_type_speed_ops;
5134         mlxsw_sp->ptp_ops = &mlxsw_sp1_ptp_ops;
5135         mlxsw_sp->span_ops = &mlxsw_sp1_span_ops;
5136         mlxsw_sp->listeners = mlxsw_sp1_listener;
5137         mlxsw_sp->listeners_count = ARRAY_SIZE(mlxsw_sp1_listener);
5138         mlxsw_sp->lowest_shaper_bs = MLXSW_REG_QEEC_LOWEST_SHAPER_BS_SP1;
5139
5140         return mlxsw_sp_init(mlxsw_core, mlxsw_bus_info, extack);
5141 }
5142
5143 static int mlxsw_sp2_init(struct mlxsw_core *mlxsw_core,
5144                           const struct mlxsw_bus_info *mlxsw_bus_info,
5145                           struct netlink_ext_ack *extack)
5146 {
5147         struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
5148
5149         mlxsw_sp->req_rev = &mlxsw_sp2_fw_rev;
5150         mlxsw_sp->fw_filename = MLXSW_SP2_FW_FILENAME;
5151         mlxsw_sp->kvdl_ops = &mlxsw_sp2_kvdl_ops;
5152         mlxsw_sp->afa_ops = &mlxsw_sp2_act_afa_ops;
5153         mlxsw_sp->afk_ops = &mlxsw_sp2_afk_ops;
5154         mlxsw_sp->mr_tcam_ops = &mlxsw_sp2_mr_tcam_ops;
5155         mlxsw_sp->acl_tcam_ops = &mlxsw_sp2_acl_tcam_ops;
5156         mlxsw_sp->nve_ops_arr = mlxsw_sp2_nve_ops_arr;
5157         mlxsw_sp->mac_mask = mlxsw_sp2_mac_mask;
5158         mlxsw_sp->rif_ops_arr = mlxsw_sp2_rif_ops_arr;
5159         mlxsw_sp->sb_vals = &mlxsw_sp2_sb_vals;
5160         mlxsw_sp->port_type_speed_ops = &mlxsw_sp2_port_type_speed_ops;
5161         mlxsw_sp->ptp_ops = &mlxsw_sp2_ptp_ops;
5162         mlxsw_sp->span_ops = &mlxsw_sp2_span_ops;
5163         mlxsw_sp->lowest_shaper_bs = MLXSW_REG_QEEC_LOWEST_SHAPER_BS_SP2;
5164
5165         return mlxsw_sp_init(mlxsw_core, mlxsw_bus_info, extack);
5166 }
5167
5168 static int mlxsw_sp3_init(struct mlxsw_core *mlxsw_core,
5169                           const struct mlxsw_bus_info *mlxsw_bus_info,
5170                           struct netlink_ext_ack *extack)
5171 {
5172         struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
5173
5174         mlxsw_sp->kvdl_ops = &mlxsw_sp2_kvdl_ops;
5175         mlxsw_sp->afa_ops = &mlxsw_sp2_act_afa_ops;
5176         mlxsw_sp->afk_ops = &mlxsw_sp2_afk_ops;
5177         mlxsw_sp->mr_tcam_ops = &mlxsw_sp2_mr_tcam_ops;
5178         mlxsw_sp->acl_tcam_ops = &mlxsw_sp2_acl_tcam_ops;
5179         mlxsw_sp->nve_ops_arr = mlxsw_sp2_nve_ops_arr;
5180         mlxsw_sp->mac_mask = mlxsw_sp2_mac_mask;
5181         mlxsw_sp->rif_ops_arr = mlxsw_sp2_rif_ops_arr;
5182         mlxsw_sp->sb_vals = &mlxsw_sp2_sb_vals;
5183         mlxsw_sp->port_type_speed_ops = &mlxsw_sp2_port_type_speed_ops;
5184         mlxsw_sp->ptp_ops = &mlxsw_sp2_ptp_ops;
5185         mlxsw_sp->span_ops = &mlxsw_sp3_span_ops;
5186         mlxsw_sp->lowest_shaper_bs = MLXSW_REG_QEEC_LOWEST_SHAPER_BS_SP3;
5187
5188         return mlxsw_sp_init(mlxsw_core, mlxsw_bus_info, extack);
5189 }
5190
5191 static void mlxsw_sp_fini(struct mlxsw_core *mlxsw_core)
5192 {
5193         struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
5194
5195         mlxsw_sp_ports_remove(mlxsw_sp);
5196         mlxsw_sp_port_module_info_fini(mlxsw_sp);
5197         mlxsw_sp_dpipe_fini(mlxsw_sp);
5198         unregister_netdevice_notifier_net(mlxsw_sp_net(mlxsw_sp),
5199                                           &mlxsw_sp->netdevice_nb);
5200         if (mlxsw_sp->clock) {
5201                 mlxsw_sp->ptp_ops->fini(mlxsw_sp->ptp_state);
5202                 mlxsw_sp->ptp_ops->clock_fini(mlxsw_sp->clock);
5203         }
5204         mlxsw_sp_router_fini(mlxsw_sp);
5205         mlxsw_sp_acl_fini(mlxsw_sp);
5206         mlxsw_sp_nve_fini(mlxsw_sp);
5207         mlxsw_sp_afa_fini(mlxsw_sp);
5208         mlxsw_sp_counter_pool_fini(mlxsw_sp);
5209         mlxsw_sp_switchdev_fini(mlxsw_sp);
5210         mlxsw_sp_span_fini(mlxsw_sp);
5211         mlxsw_sp_lag_fini(mlxsw_sp);
5212         mlxsw_sp_buffers_fini(mlxsw_sp);
5213         mlxsw_sp_devlink_traps_fini(mlxsw_sp);
5214         mlxsw_sp_traps_fini(mlxsw_sp);
5215         mlxsw_sp_fids_fini(mlxsw_sp);
5216         mlxsw_sp_kvdl_fini(mlxsw_sp);
5217 }
5218
5219 /* Per-FID flood tables are used for both "true" 802.1D FIDs and emulated
5220  * 802.1Q FIDs
5221  */
5222 #define MLXSW_SP_FID_FLOOD_TABLE_SIZE   (MLXSW_SP_FID_8021D_MAX + \
5223                                          VLAN_VID_MASK - 1)
5224
5225 static const struct mlxsw_config_profile mlxsw_sp1_config_profile = {
5226         .used_max_mid                   = 1,
5227         .max_mid                        = MLXSW_SP_MID_MAX,
5228         .used_flood_tables              = 1,
5229         .used_flood_mode                = 1,
5230         .flood_mode                     = 3,
5231         .max_fid_flood_tables           = 3,
5232         .fid_flood_table_size           = MLXSW_SP_FID_FLOOD_TABLE_SIZE,
5233         .used_max_ib_mc                 = 1,
5234         .max_ib_mc                      = 0,
5235         .used_max_pkey                  = 1,
5236         .max_pkey                       = 0,
5237         .used_kvd_sizes                 = 1,
5238         .kvd_hash_single_parts          = 59,
5239         .kvd_hash_double_parts          = 41,
5240         .kvd_linear_size                = MLXSW_SP_KVD_LINEAR_SIZE,
5241         .swid_config                    = {
5242                 {
5243                         .used_type      = 1,
5244                         .type           = MLXSW_PORT_SWID_TYPE_ETH,
5245                 }
5246         },
5247 };
5248
5249 static const struct mlxsw_config_profile mlxsw_sp2_config_profile = {
5250         .used_max_mid                   = 1,
5251         .max_mid                        = MLXSW_SP_MID_MAX,
5252         .used_flood_tables              = 1,
5253         .used_flood_mode                = 1,
5254         .flood_mode                     = 3,
5255         .max_fid_flood_tables           = 3,
5256         .fid_flood_table_size           = MLXSW_SP_FID_FLOOD_TABLE_SIZE,
5257         .used_max_ib_mc                 = 1,
5258         .max_ib_mc                      = 0,
5259         .used_max_pkey                  = 1,
5260         .max_pkey                       = 0,
5261         .swid_config                    = {
5262                 {
5263                         .used_type      = 1,
5264                         .type           = MLXSW_PORT_SWID_TYPE_ETH,
5265                 }
5266         },
5267 };
5268
5269 static void
5270 mlxsw_sp_resource_size_params_prepare(struct mlxsw_core *mlxsw_core,
5271                                       struct devlink_resource_size_params *kvd_size_params,
5272                                       struct devlink_resource_size_params *linear_size_params,
5273                                       struct devlink_resource_size_params *hash_double_size_params,
5274                                       struct devlink_resource_size_params *hash_single_size_params)
5275 {
5276         u32 single_size_min = MLXSW_CORE_RES_GET(mlxsw_core,
5277                                                  KVD_SINGLE_MIN_SIZE);
5278         u32 double_size_min = MLXSW_CORE_RES_GET(mlxsw_core,
5279                                                  KVD_DOUBLE_MIN_SIZE);
5280         u32 kvd_size = MLXSW_CORE_RES_GET(mlxsw_core, KVD_SIZE);
5281         u32 linear_size_min = 0;
5282
5283         devlink_resource_size_params_init(kvd_size_params, kvd_size, kvd_size,
5284                                           MLXSW_SP_KVD_GRANULARITY,
5285                                           DEVLINK_RESOURCE_UNIT_ENTRY);
5286         devlink_resource_size_params_init(linear_size_params, linear_size_min,
5287                                           kvd_size - single_size_min -
5288                                           double_size_min,
5289                                           MLXSW_SP_KVD_GRANULARITY,
5290                                           DEVLINK_RESOURCE_UNIT_ENTRY);
5291         devlink_resource_size_params_init(hash_double_size_params,
5292                                           double_size_min,
5293                                           kvd_size - single_size_min -
5294                                           linear_size_min,
5295                                           MLXSW_SP_KVD_GRANULARITY,
5296                                           DEVLINK_RESOURCE_UNIT_ENTRY);
5297         devlink_resource_size_params_init(hash_single_size_params,
5298                                           single_size_min,
5299                                           kvd_size - double_size_min -
5300                                           linear_size_min,
5301                                           MLXSW_SP_KVD_GRANULARITY,
5302                                           DEVLINK_RESOURCE_UNIT_ENTRY);
5303 }
5304
5305 static int mlxsw_sp1_resources_kvd_register(struct mlxsw_core *mlxsw_core)
5306 {
5307         struct devlink *devlink = priv_to_devlink(mlxsw_core);
5308         struct devlink_resource_size_params hash_single_size_params;
5309         struct devlink_resource_size_params hash_double_size_params;
5310         struct devlink_resource_size_params linear_size_params;
5311         struct devlink_resource_size_params kvd_size_params;
5312         u32 kvd_size, single_size, double_size, linear_size;
5313         const struct mlxsw_config_profile *profile;
5314         int err;
5315
5316         profile = &mlxsw_sp1_config_profile;
5317         if (!MLXSW_CORE_RES_VALID(mlxsw_core, KVD_SIZE))
5318                 return -EIO;
5319
5320         mlxsw_sp_resource_size_params_prepare(mlxsw_core, &kvd_size_params,
5321                                               &linear_size_params,
5322                                               &hash_double_size_params,
5323                                               &hash_single_size_params);
5324
5325         kvd_size = MLXSW_CORE_RES_GET(mlxsw_core, KVD_SIZE);
5326         err = devlink_resource_register(devlink, MLXSW_SP_RESOURCE_NAME_KVD,
5327                                         kvd_size, MLXSW_SP_RESOURCE_KVD,
5328                                         DEVLINK_RESOURCE_ID_PARENT_TOP,
5329                                         &kvd_size_params);
5330         if (err)
5331                 return err;
5332
5333         linear_size = profile->kvd_linear_size;
5334         err = devlink_resource_register(devlink, MLXSW_SP_RESOURCE_NAME_KVD_LINEAR,
5335                                         linear_size,
5336                                         MLXSW_SP_RESOURCE_KVD_LINEAR,
5337                                         MLXSW_SP_RESOURCE_KVD,
5338                                         &linear_size_params);
5339         if (err)
5340                 return err;
5341
5342         err = mlxsw_sp1_kvdl_resources_register(mlxsw_core);
5343         if  (err)
5344                 return err;
5345
5346         double_size = kvd_size - linear_size;
5347         double_size *= profile->kvd_hash_double_parts;
5348         double_size /= profile->kvd_hash_double_parts +
5349                        profile->kvd_hash_single_parts;
5350         double_size = rounddown(double_size, MLXSW_SP_KVD_GRANULARITY);
5351         err = devlink_resource_register(devlink, MLXSW_SP_RESOURCE_NAME_KVD_HASH_DOUBLE,
5352                                         double_size,
5353                                         MLXSW_SP_RESOURCE_KVD_HASH_DOUBLE,
5354                                         MLXSW_SP_RESOURCE_KVD,
5355                                         &hash_double_size_params);
5356         if (err)
5357                 return err;
5358
5359         single_size = kvd_size - double_size - linear_size;
5360         err = devlink_resource_register(devlink, MLXSW_SP_RESOURCE_NAME_KVD_HASH_SINGLE,
5361                                         single_size,
5362                                         MLXSW_SP_RESOURCE_KVD_HASH_SINGLE,
5363                                         MLXSW_SP_RESOURCE_KVD,
5364                                         &hash_single_size_params);
5365         if (err)
5366                 return err;
5367
5368         return 0;
5369 }
5370
5371 static int mlxsw_sp2_resources_kvd_register(struct mlxsw_core *mlxsw_core)
5372 {
5373         struct devlink *devlink = priv_to_devlink(mlxsw_core);
5374         struct devlink_resource_size_params kvd_size_params;
5375         u32 kvd_size;
5376
5377         if (!MLXSW_CORE_RES_VALID(mlxsw_core, KVD_SIZE))
5378                 return -EIO;
5379
5380         kvd_size = MLXSW_CORE_RES_GET(mlxsw_core, KVD_SIZE);
5381         devlink_resource_size_params_init(&kvd_size_params, kvd_size, kvd_size,
5382                                           MLXSW_SP_KVD_GRANULARITY,
5383                                           DEVLINK_RESOURCE_UNIT_ENTRY);
5384
5385         return devlink_resource_register(devlink, MLXSW_SP_RESOURCE_NAME_KVD,
5386                                          kvd_size, MLXSW_SP_RESOURCE_KVD,
5387                                          DEVLINK_RESOURCE_ID_PARENT_TOP,
5388                                          &kvd_size_params);
5389 }
5390
5391 static int mlxsw_sp_resources_span_register(struct mlxsw_core *mlxsw_core)
5392 {
5393         struct devlink *devlink = priv_to_devlink(mlxsw_core);
5394         struct devlink_resource_size_params span_size_params;
5395         u32 max_span;
5396
5397         if (!MLXSW_CORE_RES_VALID(mlxsw_core, MAX_SPAN))
5398                 return -EIO;
5399
5400         max_span = MLXSW_CORE_RES_GET(mlxsw_core, MAX_SPAN);
5401         devlink_resource_size_params_init(&span_size_params, max_span, max_span,
5402                                           1, DEVLINK_RESOURCE_UNIT_ENTRY);
5403
5404         return devlink_resource_register(devlink, MLXSW_SP_RESOURCE_NAME_SPAN,
5405                                          max_span, MLXSW_SP_RESOURCE_SPAN,
5406                                          DEVLINK_RESOURCE_ID_PARENT_TOP,
5407                                          &span_size_params);
5408 }
5409
5410 static int mlxsw_sp1_resources_register(struct mlxsw_core *mlxsw_core)
5411 {
5412         int err;
5413
5414         err = mlxsw_sp1_resources_kvd_register(mlxsw_core);
5415         if (err)
5416                 return err;
5417
5418         err = mlxsw_sp_resources_span_register(mlxsw_core);
5419         if (err)
5420                 goto err_resources_span_register;
5421
5422         return 0;
5423
5424 err_resources_span_register:
5425         devlink_resources_unregister(priv_to_devlink(mlxsw_core), NULL);
5426         return err;
5427 }
5428
5429 static int mlxsw_sp2_resources_register(struct mlxsw_core *mlxsw_core)
5430 {
5431         int err;
5432
5433         err = mlxsw_sp2_resources_kvd_register(mlxsw_core);
5434         if (err)
5435                 return err;
5436
5437         err = mlxsw_sp_resources_span_register(mlxsw_core);
5438         if (err)
5439                 goto err_resources_span_register;
5440
5441         return 0;
5442
5443 err_resources_span_register:
5444         devlink_resources_unregister(priv_to_devlink(mlxsw_core), NULL);
5445         return err;
5446 }
5447
5448 static int mlxsw_sp_kvd_sizes_get(struct mlxsw_core *mlxsw_core,
5449                                   const struct mlxsw_config_profile *profile,
5450                                   u64 *p_single_size, u64 *p_double_size,
5451                                   u64 *p_linear_size)
5452 {
5453         struct devlink *devlink = priv_to_devlink(mlxsw_core);
5454         u32 double_size;
5455         int err;
5456
5457         if (!MLXSW_CORE_RES_VALID(mlxsw_core, KVD_SINGLE_MIN_SIZE) ||
5458             !MLXSW_CORE_RES_VALID(mlxsw_core, KVD_DOUBLE_MIN_SIZE))
5459                 return -EIO;
5460
5461         /* The hash part is what left of the kvd without the
5462          * linear part. It is split to the single size and
5463          * double size by the parts ratio from the profile.
5464          * Both sizes must be a multiplications of the
5465          * granularity from the profile. In case the user
5466          * provided the sizes they are obtained via devlink.
5467          */
5468         err = devlink_resource_size_get(devlink,
5469                                         MLXSW_SP_RESOURCE_KVD_LINEAR,
5470                                         p_linear_size);
5471         if (err)
5472                 *p_linear_size = profile->kvd_linear_size;
5473
5474         err = devlink_resource_size_get(devlink,
5475                                         MLXSW_SP_RESOURCE_KVD_HASH_DOUBLE,
5476                                         p_double_size);
5477         if (err) {
5478                 double_size = MLXSW_CORE_RES_GET(mlxsw_core, KVD_SIZE) -
5479                               *p_linear_size;
5480                 double_size *= profile->kvd_hash_double_parts;
5481                 double_size /= profile->kvd_hash_double_parts +
5482                                profile->kvd_hash_single_parts;
5483                 *p_double_size = rounddown(double_size,
5484                                            MLXSW_SP_KVD_GRANULARITY);
5485         }
5486
5487         err = devlink_resource_size_get(devlink,
5488                                         MLXSW_SP_RESOURCE_KVD_HASH_SINGLE,
5489                                         p_single_size);
5490         if (err)
5491                 *p_single_size = MLXSW_CORE_RES_GET(mlxsw_core, KVD_SIZE) -
5492                                  *p_double_size - *p_linear_size;
5493
5494         /* Check results are legal. */
5495         if (*p_single_size < MLXSW_CORE_RES_GET(mlxsw_core, KVD_SINGLE_MIN_SIZE) ||
5496             *p_double_size < MLXSW_CORE_RES_GET(mlxsw_core, KVD_DOUBLE_MIN_SIZE) ||
5497             MLXSW_CORE_RES_GET(mlxsw_core, KVD_SIZE) < *p_linear_size)
5498                 return -EIO;
5499
5500         return 0;
5501 }
5502
5503 static int
5504 mlxsw_sp_devlink_param_fw_load_policy_validate(struct devlink *devlink, u32 id,
5505                                                union devlink_param_value val,
5506                                                struct netlink_ext_ack *extack)
5507 {
5508         if ((val.vu8 != DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_DRIVER) &&
5509             (val.vu8 != DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_FLASH)) {
5510                 NL_SET_ERR_MSG_MOD(extack, "'fw_load_policy' must be 'driver' or 'flash'");
5511                 return -EINVAL;
5512         }
5513
5514         return 0;
5515 }
5516
5517 static const struct devlink_param mlxsw_sp_devlink_params[] = {
5518         DEVLINK_PARAM_GENERIC(FW_LOAD_POLICY,
5519                               BIT(DEVLINK_PARAM_CMODE_DRIVERINIT),
5520                               NULL, NULL,
5521                               mlxsw_sp_devlink_param_fw_load_policy_validate),
5522 };
5523
5524 static int mlxsw_sp_params_register(struct mlxsw_core *mlxsw_core)
5525 {
5526         struct devlink *devlink = priv_to_devlink(mlxsw_core);
5527         union devlink_param_value value;
5528         int err;
5529
5530         err = devlink_params_register(devlink, mlxsw_sp_devlink_params,
5531                                       ARRAY_SIZE(mlxsw_sp_devlink_params));
5532         if (err)
5533                 return err;
5534
5535         value.vu8 = DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_DRIVER;
5536         devlink_param_driverinit_value_set(devlink,
5537                                            DEVLINK_PARAM_GENERIC_ID_FW_LOAD_POLICY,
5538                                            value);
5539         return 0;
5540 }
5541
5542 static void mlxsw_sp_params_unregister(struct mlxsw_core *mlxsw_core)
5543 {
5544         devlink_params_unregister(priv_to_devlink(mlxsw_core),
5545                                   mlxsw_sp_devlink_params,
5546                                   ARRAY_SIZE(mlxsw_sp_devlink_params));
5547 }
5548
5549 static int
5550 mlxsw_sp_params_acl_region_rehash_intrvl_get(struct devlink *devlink, u32 id,
5551                                              struct devlink_param_gset_ctx *ctx)
5552 {
5553         struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
5554         struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
5555
5556         ctx->val.vu32 = mlxsw_sp_acl_region_rehash_intrvl_get(mlxsw_sp);
5557         return 0;
5558 }
5559
5560 static int
5561 mlxsw_sp_params_acl_region_rehash_intrvl_set(struct devlink *devlink, u32 id,
5562                                              struct devlink_param_gset_ctx *ctx)
5563 {
5564         struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
5565         struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
5566
5567         return mlxsw_sp_acl_region_rehash_intrvl_set(mlxsw_sp, ctx->val.vu32);
5568 }
5569
5570 static const struct devlink_param mlxsw_sp2_devlink_params[] = {
5571         DEVLINK_PARAM_DRIVER(MLXSW_DEVLINK_PARAM_ID_ACL_REGION_REHASH_INTERVAL,
5572                              "acl_region_rehash_interval",
5573                              DEVLINK_PARAM_TYPE_U32,
5574                              BIT(DEVLINK_PARAM_CMODE_RUNTIME),
5575                              mlxsw_sp_params_acl_region_rehash_intrvl_get,
5576                              mlxsw_sp_params_acl_region_rehash_intrvl_set,
5577                              NULL),
5578 };
5579
5580 static int mlxsw_sp2_params_register(struct mlxsw_core *mlxsw_core)
5581 {
5582         struct devlink *devlink = priv_to_devlink(mlxsw_core);
5583         union devlink_param_value value;
5584         int err;
5585
5586         err = mlxsw_sp_params_register(mlxsw_core);
5587         if (err)
5588                 return err;
5589
5590         err = devlink_params_register(devlink, mlxsw_sp2_devlink_params,
5591                                       ARRAY_SIZE(mlxsw_sp2_devlink_params));
5592         if (err)
5593                 goto err_devlink_params_register;
5594
5595         value.vu32 = 0;
5596         devlink_param_driverinit_value_set(devlink,
5597                                            MLXSW_DEVLINK_PARAM_ID_ACL_REGION_REHASH_INTERVAL,
5598                                            value);
5599         return 0;
5600
5601 err_devlink_params_register:
5602         mlxsw_sp_params_unregister(mlxsw_core);
5603         return err;
5604 }
5605
5606 static void mlxsw_sp2_params_unregister(struct mlxsw_core *mlxsw_core)
5607 {
5608         devlink_params_unregister(priv_to_devlink(mlxsw_core),
5609                                   mlxsw_sp2_devlink_params,
5610                                   ARRAY_SIZE(mlxsw_sp2_devlink_params));
5611         mlxsw_sp_params_unregister(mlxsw_core);
5612 }
5613
5614 static void mlxsw_sp_ptp_transmitted(struct mlxsw_core *mlxsw_core,
5615                                      struct sk_buff *skb, u8 local_port)
5616 {
5617         struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
5618
5619         skb_pull(skb, MLXSW_TXHDR_LEN);
5620         mlxsw_sp->ptp_ops->transmitted(mlxsw_sp, skb, local_port);
5621 }
5622
5623 static struct mlxsw_driver mlxsw_sp1_driver = {
5624         .kind                           = mlxsw_sp1_driver_name,
5625         .priv_size                      = sizeof(struct mlxsw_sp),
5626         .init                           = mlxsw_sp1_init,
5627         .fini                           = mlxsw_sp_fini,
5628         .basic_trap_groups_set          = mlxsw_sp_basic_trap_groups_set,
5629         .port_split                     = mlxsw_sp_port_split,
5630         .port_unsplit                   = mlxsw_sp_port_unsplit,
5631         .sb_pool_get                    = mlxsw_sp_sb_pool_get,
5632         .sb_pool_set                    = mlxsw_sp_sb_pool_set,
5633         .sb_port_pool_get               = mlxsw_sp_sb_port_pool_get,
5634         .sb_port_pool_set               = mlxsw_sp_sb_port_pool_set,
5635         .sb_tc_pool_bind_get            = mlxsw_sp_sb_tc_pool_bind_get,
5636         .sb_tc_pool_bind_set            = mlxsw_sp_sb_tc_pool_bind_set,
5637         .sb_occ_snapshot                = mlxsw_sp_sb_occ_snapshot,
5638         .sb_occ_max_clear               = mlxsw_sp_sb_occ_max_clear,
5639         .sb_occ_port_pool_get           = mlxsw_sp_sb_occ_port_pool_get,
5640         .sb_occ_tc_port_bind_get        = mlxsw_sp_sb_occ_tc_port_bind_get,
5641         .flash_update                   = mlxsw_sp_flash_update,
5642         .trap_init                      = mlxsw_sp_trap_init,
5643         .trap_fini                      = mlxsw_sp_trap_fini,
5644         .trap_action_set                = mlxsw_sp_trap_action_set,
5645         .trap_group_init                = mlxsw_sp_trap_group_init,
5646         .txhdr_construct                = mlxsw_sp_txhdr_construct,
5647         .resources_register             = mlxsw_sp1_resources_register,
5648         .kvd_sizes_get                  = mlxsw_sp_kvd_sizes_get,
5649         .params_register                = mlxsw_sp_params_register,
5650         .params_unregister              = mlxsw_sp_params_unregister,
5651         .ptp_transmitted                = mlxsw_sp_ptp_transmitted,
5652         .txhdr_len                      = MLXSW_TXHDR_LEN,
5653         .profile                        = &mlxsw_sp1_config_profile,
5654         .res_query_enabled              = true,
5655 };
5656
5657 static struct mlxsw_driver mlxsw_sp2_driver = {
5658         .kind                           = mlxsw_sp2_driver_name,
5659         .priv_size                      = sizeof(struct mlxsw_sp),
5660         .init                           = mlxsw_sp2_init,
5661         .fini                           = mlxsw_sp_fini,
5662         .basic_trap_groups_set          = mlxsw_sp_basic_trap_groups_set,
5663         .port_split                     = mlxsw_sp_port_split,
5664         .port_unsplit                   = mlxsw_sp_port_unsplit,
5665         .sb_pool_get                    = mlxsw_sp_sb_pool_get,
5666         .sb_pool_set                    = mlxsw_sp_sb_pool_set,
5667         .sb_port_pool_get               = mlxsw_sp_sb_port_pool_get,
5668         .sb_port_pool_set               = mlxsw_sp_sb_port_pool_set,
5669         .sb_tc_pool_bind_get            = mlxsw_sp_sb_tc_pool_bind_get,
5670         .sb_tc_pool_bind_set            = mlxsw_sp_sb_tc_pool_bind_set,
5671         .sb_occ_snapshot                = mlxsw_sp_sb_occ_snapshot,
5672         .sb_occ_max_clear               = mlxsw_sp_sb_occ_max_clear,
5673         .sb_occ_port_pool_get           = mlxsw_sp_sb_occ_port_pool_get,
5674         .sb_occ_tc_port_bind_get        = mlxsw_sp_sb_occ_tc_port_bind_get,
5675         .flash_update                   = mlxsw_sp_flash_update,
5676         .trap_init                      = mlxsw_sp_trap_init,
5677         .trap_fini                      = mlxsw_sp_trap_fini,
5678         .trap_action_set                = mlxsw_sp_trap_action_set,
5679         .trap_group_init                = mlxsw_sp_trap_group_init,
5680         .txhdr_construct                = mlxsw_sp_txhdr_construct,
5681         .resources_register             = mlxsw_sp2_resources_register,
5682         .params_register                = mlxsw_sp2_params_register,
5683         .params_unregister              = mlxsw_sp2_params_unregister,
5684         .ptp_transmitted                = mlxsw_sp_ptp_transmitted,
5685         .txhdr_len                      = MLXSW_TXHDR_LEN,
5686         .profile                        = &mlxsw_sp2_config_profile,
5687         .res_query_enabled              = true,
5688 };
5689
5690 static struct mlxsw_driver mlxsw_sp3_driver = {
5691         .kind                           = mlxsw_sp3_driver_name,
5692         .priv_size                      = sizeof(struct mlxsw_sp),
5693         .init                           = mlxsw_sp3_init,
5694         .fini                           = mlxsw_sp_fini,
5695         .basic_trap_groups_set          = mlxsw_sp_basic_trap_groups_set,
5696         .port_split                     = mlxsw_sp_port_split,
5697         .port_unsplit                   = mlxsw_sp_port_unsplit,
5698         .sb_pool_get                    = mlxsw_sp_sb_pool_get,
5699         .sb_pool_set                    = mlxsw_sp_sb_pool_set,
5700         .sb_port_pool_get               = mlxsw_sp_sb_port_pool_get,
5701         .sb_port_pool_set               = mlxsw_sp_sb_port_pool_set,
5702         .sb_tc_pool_bind_get            = mlxsw_sp_sb_tc_pool_bind_get,
5703         .sb_tc_pool_bind_set            = mlxsw_sp_sb_tc_pool_bind_set,
5704         .sb_occ_snapshot                = mlxsw_sp_sb_occ_snapshot,
5705         .sb_occ_max_clear               = mlxsw_sp_sb_occ_max_clear,
5706         .sb_occ_port_pool_get           = mlxsw_sp_sb_occ_port_pool_get,
5707         .sb_occ_tc_port_bind_get        = mlxsw_sp_sb_occ_tc_port_bind_get,
5708         .flash_update                   = mlxsw_sp_flash_update,
5709         .trap_init                      = mlxsw_sp_trap_init,
5710         .trap_fini                      = mlxsw_sp_trap_fini,
5711         .trap_action_set                = mlxsw_sp_trap_action_set,
5712         .trap_group_init                = mlxsw_sp_trap_group_init,
5713         .txhdr_construct                = mlxsw_sp_txhdr_construct,
5714         .resources_register             = mlxsw_sp2_resources_register,
5715         .params_register                = mlxsw_sp2_params_register,
5716         .params_unregister              = mlxsw_sp2_params_unregister,
5717         .ptp_transmitted                = mlxsw_sp_ptp_transmitted,
5718         .txhdr_len                      = MLXSW_TXHDR_LEN,
5719         .profile                        = &mlxsw_sp2_config_profile,
5720         .res_query_enabled              = true,
5721 };
5722
5723 bool mlxsw_sp_port_dev_check(const struct net_device *dev)
5724 {
5725         return dev->netdev_ops == &mlxsw_sp_port_netdev_ops;
5726 }
5727
5728 static int mlxsw_sp_lower_dev_walk(struct net_device *lower_dev, void *data)
5729 {
5730         struct mlxsw_sp_port **p_mlxsw_sp_port = data;
5731         int ret = 0;
5732
5733         if (mlxsw_sp_port_dev_check(lower_dev)) {
5734                 *p_mlxsw_sp_port = netdev_priv(lower_dev);
5735                 ret = 1;
5736         }
5737
5738         return ret;
5739 }
5740
5741 struct mlxsw_sp_port *mlxsw_sp_port_dev_lower_find(struct net_device *dev)
5742 {
5743         struct mlxsw_sp_port *mlxsw_sp_port;
5744
5745         if (mlxsw_sp_port_dev_check(dev))
5746                 return netdev_priv(dev);
5747
5748         mlxsw_sp_port = NULL;
5749         netdev_walk_all_lower_dev(dev, mlxsw_sp_lower_dev_walk, &mlxsw_sp_port);
5750
5751         return mlxsw_sp_port;
5752 }
5753
5754 struct mlxsw_sp *mlxsw_sp_lower_get(struct net_device *dev)
5755 {
5756         struct mlxsw_sp_port *mlxsw_sp_port;
5757
5758         mlxsw_sp_port = mlxsw_sp_port_dev_lower_find(dev);
5759         return mlxsw_sp_port ? mlxsw_sp_port->mlxsw_sp : NULL;
5760 }
5761
5762 struct mlxsw_sp_port *mlxsw_sp_port_dev_lower_find_rcu(struct net_device *dev)
5763 {
5764         struct mlxsw_sp_port *mlxsw_sp_port;
5765
5766         if (mlxsw_sp_port_dev_check(dev))
5767                 return netdev_priv(dev);
5768
5769         mlxsw_sp_port = NULL;
5770         netdev_walk_all_lower_dev_rcu(dev, mlxsw_sp_lower_dev_walk,
5771                                       &mlxsw_sp_port);
5772
5773         return mlxsw_sp_port;
5774 }
5775
5776 struct mlxsw_sp_port *mlxsw_sp_port_lower_dev_hold(struct net_device *dev)
5777 {
5778         struct mlxsw_sp_port *mlxsw_sp_port;
5779
5780         rcu_read_lock();
5781         mlxsw_sp_port = mlxsw_sp_port_dev_lower_find_rcu(dev);
5782         if (mlxsw_sp_port)
5783                 dev_hold(mlxsw_sp_port->dev);
5784         rcu_read_unlock();
5785         return mlxsw_sp_port;
5786 }
5787
5788 void mlxsw_sp_port_dev_put(struct mlxsw_sp_port *mlxsw_sp_port)
5789 {
5790         dev_put(mlxsw_sp_port->dev);
5791 }
5792
5793 static void
5794 mlxsw_sp_port_lag_uppers_cleanup(struct mlxsw_sp_port *mlxsw_sp_port,
5795                                  struct net_device *lag_dev)
5796 {
5797         struct net_device *br_dev = netdev_master_upper_dev_get(lag_dev);
5798         struct net_device *upper_dev;
5799         struct list_head *iter;
5800
5801         if (netif_is_bridge_port(lag_dev))
5802                 mlxsw_sp_port_bridge_leave(mlxsw_sp_port, lag_dev, br_dev);
5803
5804         netdev_for_each_upper_dev_rcu(lag_dev, upper_dev, iter) {
5805                 if (!netif_is_bridge_port(upper_dev))
5806                         continue;
5807                 br_dev = netdev_master_upper_dev_get(upper_dev);
5808                 mlxsw_sp_port_bridge_leave(mlxsw_sp_port, upper_dev, br_dev);
5809         }
5810 }
5811
5812 static int mlxsw_sp_lag_create(struct mlxsw_sp *mlxsw_sp, u16 lag_id)
5813 {
5814         char sldr_pl[MLXSW_REG_SLDR_LEN];
5815
5816         mlxsw_reg_sldr_lag_create_pack(sldr_pl, lag_id);
5817         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sldr), sldr_pl);
5818 }
5819
5820 static int mlxsw_sp_lag_destroy(struct mlxsw_sp *mlxsw_sp, u16 lag_id)
5821 {
5822         char sldr_pl[MLXSW_REG_SLDR_LEN];
5823
5824         mlxsw_reg_sldr_lag_destroy_pack(sldr_pl, lag_id);
5825         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sldr), sldr_pl);
5826 }
5827
5828 static int mlxsw_sp_lag_col_port_add(struct mlxsw_sp_port *mlxsw_sp_port,
5829                                      u16 lag_id, u8 port_index)
5830 {
5831         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
5832         char slcor_pl[MLXSW_REG_SLCOR_LEN];
5833
5834         mlxsw_reg_slcor_port_add_pack(slcor_pl, mlxsw_sp_port->local_port,
5835                                       lag_id, port_index);
5836         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(slcor), slcor_pl);
5837 }
5838
5839 static int mlxsw_sp_lag_col_port_remove(struct mlxsw_sp_port *mlxsw_sp_port,
5840                                         u16 lag_id)
5841 {
5842         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
5843         char slcor_pl[MLXSW_REG_SLCOR_LEN];
5844
5845         mlxsw_reg_slcor_port_remove_pack(slcor_pl, mlxsw_sp_port->local_port,
5846                                          lag_id);
5847         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(slcor), slcor_pl);
5848 }
5849
5850 static int mlxsw_sp_lag_col_port_enable(struct mlxsw_sp_port *mlxsw_sp_port,
5851                                         u16 lag_id)
5852 {
5853         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
5854         char slcor_pl[MLXSW_REG_SLCOR_LEN];
5855
5856         mlxsw_reg_slcor_col_enable_pack(slcor_pl, mlxsw_sp_port->local_port,
5857                                         lag_id);
5858         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(slcor), slcor_pl);
5859 }
5860
5861 static int mlxsw_sp_lag_col_port_disable(struct mlxsw_sp_port *mlxsw_sp_port,
5862                                          u16 lag_id)
5863 {
5864         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
5865         char slcor_pl[MLXSW_REG_SLCOR_LEN];
5866
5867         mlxsw_reg_slcor_col_disable_pack(slcor_pl, mlxsw_sp_port->local_port,
5868                                          lag_id);
5869         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(slcor), slcor_pl);
5870 }
5871
5872 static int mlxsw_sp_lag_index_get(struct mlxsw_sp *mlxsw_sp,
5873                                   struct net_device *lag_dev,
5874                                   u16 *p_lag_id)
5875 {
5876         struct mlxsw_sp_upper *lag;
5877         int free_lag_id = -1;
5878         u64 max_lag;
5879         int i;
5880
5881         max_lag = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_LAG);
5882         for (i = 0; i < max_lag; i++) {
5883                 lag = mlxsw_sp_lag_get(mlxsw_sp, i);
5884                 if (lag->ref_count) {
5885                         if (lag->dev == lag_dev) {
5886                                 *p_lag_id = i;
5887                                 return 0;
5888                         }
5889                 } else if (free_lag_id < 0) {
5890                         free_lag_id = i;
5891                 }
5892         }
5893         if (free_lag_id < 0)
5894                 return -EBUSY;
5895         *p_lag_id = free_lag_id;
5896         return 0;
5897 }
5898
5899 static bool
5900 mlxsw_sp_master_lag_check(struct mlxsw_sp *mlxsw_sp,
5901                           struct net_device *lag_dev,
5902                           struct netdev_lag_upper_info *lag_upper_info,
5903                           struct netlink_ext_ack *extack)
5904 {
5905         u16 lag_id;
5906
5907         if (mlxsw_sp_lag_index_get(mlxsw_sp, lag_dev, &lag_id) != 0) {
5908                 NL_SET_ERR_MSG_MOD(extack, "Exceeded number of supported LAG devices");
5909                 return false;
5910         }
5911         if (lag_upper_info->tx_type != NETDEV_LAG_TX_TYPE_HASH) {
5912                 NL_SET_ERR_MSG_MOD(extack, "LAG device using unsupported Tx type");
5913                 return false;
5914         }
5915         return true;
5916 }
5917
5918 static int mlxsw_sp_port_lag_index_get(struct mlxsw_sp *mlxsw_sp,
5919                                        u16 lag_id, u8 *p_port_index)
5920 {
5921         u64 max_lag_members;
5922         int i;
5923
5924         max_lag_members = MLXSW_CORE_RES_GET(mlxsw_sp->core,
5925                                              MAX_LAG_MEMBERS);
5926         for (i = 0; i < max_lag_members; i++) {
5927                 if (!mlxsw_sp_port_lagged_get(mlxsw_sp, lag_id, i)) {
5928                         *p_port_index = i;
5929                         return 0;
5930                 }
5931         }
5932         return -EBUSY;
5933 }
5934
5935 static int mlxsw_sp_port_lag_join(struct mlxsw_sp_port *mlxsw_sp_port,
5936                                   struct net_device *lag_dev)
5937 {
5938         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
5939         struct mlxsw_sp_upper *lag;
5940         u16 lag_id;
5941         u8 port_index;
5942         int err;
5943
5944         err = mlxsw_sp_lag_index_get(mlxsw_sp, lag_dev, &lag_id);
5945         if (err)
5946                 return err;
5947         lag = mlxsw_sp_lag_get(mlxsw_sp, lag_id);
5948         if (!lag->ref_count) {
5949                 err = mlxsw_sp_lag_create(mlxsw_sp, lag_id);
5950                 if (err)
5951                         return err;
5952                 lag->dev = lag_dev;
5953         }
5954
5955         err = mlxsw_sp_port_lag_index_get(mlxsw_sp, lag_id, &port_index);
5956         if (err)
5957                 return err;
5958         err = mlxsw_sp_lag_col_port_add(mlxsw_sp_port, lag_id, port_index);
5959         if (err)
5960                 goto err_col_port_add;
5961
5962         mlxsw_core_lag_mapping_set(mlxsw_sp->core, lag_id, port_index,
5963                                    mlxsw_sp_port->local_port);
5964         mlxsw_sp_port->lag_id = lag_id;
5965         mlxsw_sp_port->lagged = 1;
5966         lag->ref_count++;
5967
5968         /* Port is no longer usable as a router interface */
5969         if (mlxsw_sp_port->default_vlan->fid)
5970                 mlxsw_sp_port_vlan_router_leave(mlxsw_sp_port->default_vlan);
5971
5972         return 0;
5973
5974 err_col_port_add:
5975         if (!lag->ref_count)
5976                 mlxsw_sp_lag_destroy(mlxsw_sp, lag_id);
5977         return err;
5978 }
5979
5980 static void mlxsw_sp_port_lag_leave(struct mlxsw_sp_port *mlxsw_sp_port,
5981                                     struct net_device *lag_dev)
5982 {
5983         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
5984         u16 lag_id = mlxsw_sp_port->lag_id;
5985         struct mlxsw_sp_upper *lag;
5986
5987         if (!mlxsw_sp_port->lagged)
5988                 return;
5989         lag = mlxsw_sp_lag_get(mlxsw_sp, lag_id);
5990         WARN_ON(lag->ref_count == 0);
5991
5992         mlxsw_sp_lag_col_port_remove(mlxsw_sp_port, lag_id);
5993
5994         /* Any VLANs configured on the port are no longer valid */
5995         mlxsw_sp_port_vlan_flush(mlxsw_sp_port, false);
5996         mlxsw_sp_port_vlan_cleanup(mlxsw_sp_port->default_vlan);
5997         /* Make the LAG and its directly linked uppers leave bridges they
5998          * are memeber in
5999          */
6000         mlxsw_sp_port_lag_uppers_cleanup(mlxsw_sp_port, lag_dev);
6001
6002         if (lag->ref_count == 1)
6003                 mlxsw_sp_lag_destroy(mlxsw_sp, lag_id);
6004
6005         mlxsw_core_lag_mapping_clear(mlxsw_sp->core, lag_id,
6006                                      mlxsw_sp_port->local_port);
6007         mlxsw_sp_port->lagged = 0;
6008         lag->ref_count--;
6009
6010         /* Make sure untagged frames are allowed to ingress */
6011         mlxsw_sp_port_pvid_set(mlxsw_sp_port, MLXSW_SP_DEFAULT_VID);
6012 }
6013
6014 static int mlxsw_sp_lag_dist_port_add(struct mlxsw_sp_port *mlxsw_sp_port,
6015                                       u16 lag_id)
6016 {
6017         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
6018         char sldr_pl[MLXSW_REG_SLDR_LEN];
6019
6020         mlxsw_reg_sldr_lag_add_port_pack(sldr_pl, lag_id,
6021                                          mlxsw_sp_port->local_port);
6022         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sldr), sldr_pl);
6023 }
6024
6025 static int mlxsw_sp_lag_dist_port_remove(struct mlxsw_sp_port *mlxsw_sp_port,
6026                                          u16 lag_id)
6027 {
6028         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
6029         char sldr_pl[MLXSW_REG_SLDR_LEN];
6030
6031         mlxsw_reg_sldr_lag_remove_port_pack(sldr_pl, lag_id,
6032                                             mlxsw_sp_port->local_port);
6033         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sldr), sldr_pl);
6034 }
6035
6036 static int
6037 mlxsw_sp_port_lag_col_dist_enable(struct mlxsw_sp_port *mlxsw_sp_port)
6038 {
6039         int err;
6040
6041         err = mlxsw_sp_lag_col_port_enable(mlxsw_sp_port,
6042                                            mlxsw_sp_port->lag_id);
6043         if (err)
6044                 return err;
6045
6046         err = mlxsw_sp_lag_dist_port_add(mlxsw_sp_port, mlxsw_sp_port->lag_id);
6047         if (err)
6048                 goto err_dist_port_add;
6049
6050         return 0;
6051
6052 err_dist_port_add:
6053         mlxsw_sp_lag_col_port_disable(mlxsw_sp_port, mlxsw_sp_port->lag_id);
6054         return err;
6055 }
6056
6057 static int
6058 mlxsw_sp_port_lag_col_dist_disable(struct mlxsw_sp_port *mlxsw_sp_port)
6059 {
6060         int err;
6061
6062         err = mlxsw_sp_lag_dist_port_remove(mlxsw_sp_port,
6063                                             mlxsw_sp_port->lag_id);
6064         if (err)
6065                 return err;
6066
6067         err = mlxsw_sp_lag_col_port_disable(mlxsw_sp_port,
6068                                             mlxsw_sp_port->lag_id);
6069         if (err)
6070                 goto err_col_port_disable;
6071
6072         return 0;
6073
6074 err_col_port_disable:
6075         mlxsw_sp_lag_dist_port_add(mlxsw_sp_port, mlxsw_sp_port->lag_id);
6076         return err;
6077 }
6078
6079 static int mlxsw_sp_port_lag_changed(struct mlxsw_sp_port *mlxsw_sp_port,
6080                                      struct netdev_lag_lower_state_info *info)
6081 {
6082         if (info->tx_enabled)
6083                 return mlxsw_sp_port_lag_col_dist_enable(mlxsw_sp_port);
6084         else
6085                 return mlxsw_sp_port_lag_col_dist_disable(mlxsw_sp_port);
6086 }
6087
6088 static int mlxsw_sp_port_stp_set(struct mlxsw_sp_port *mlxsw_sp_port,
6089                                  bool enable)
6090 {
6091         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
6092         enum mlxsw_reg_spms_state spms_state;
6093         char *spms_pl;
6094         u16 vid;
6095         int err;
6096
6097         spms_state = enable ? MLXSW_REG_SPMS_STATE_FORWARDING :
6098                               MLXSW_REG_SPMS_STATE_DISCARDING;
6099
6100         spms_pl = kmalloc(MLXSW_REG_SPMS_LEN, GFP_KERNEL);
6101         if (!spms_pl)
6102                 return -ENOMEM;
6103         mlxsw_reg_spms_pack(spms_pl, mlxsw_sp_port->local_port);
6104
6105         for (vid = 0; vid < VLAN_N_VID; vid++)
6106                 mlxsw_reg_spms_vid_pack(spms_pl, vid, spms_state);
6107
6108         err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(spms), spms_pl);
6109         kfree(spms_pl);
6110         return err;
6111 }
6112
6113 static int mlxsw_sp_port_ovs_join(struct mlxsw_sp_port *mlxsw_sp_port)
6114 {
6115         u16 vid = 1;
6116         int err;
6117
6118         err = mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, true);
6119         if (err)
6120                 return err;
6121         err = mlxsw_sp_port_stp_set(mlxsw_sp_port, true);
6122         if (err)
6123                 goto err_port_stp_set;
6124         err = mlxsw_sp_port_vlan_set(mlxsw_sp_port, 1, VLAN_N_VID - 2,
6125                                      true, false);
6126         if (err)
6127                 goto err_port_vlan_set;
6128
6129         for (; vid <= VLAN_N_VID - 1; vid++) {
6130                 err = mlxsw_sp_port_vid_learning_set(mlxsw_sp_port,
6131                                                      vid, false);
6132                 if (err)
6133                         goto err_vid_learning_set;
6134         }
6135
6136         return 0;
6137
6138 err_vid_learning_set:
6139         for (vid--; vid >= 1; vid--)
6140                 mlxsw_sp_port_vid_learning_set(mlxsw_sp_port, vid, true);
6141 err_port_vlan_set:
6142         mlxsw_sp_port_stp_set(mlxsw_sp_port, false);
6143 err_port_stp_set:
6144         mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, false);
6145         return err;
6146 }
6147
6148 static void mlxsw_sp_port_ovs_leave(struct mlxsw_sp_port *mlxsw_sp_port)
6149 {
6150         u16 vid;
6151
6152         for (vid = VLAN_N_VID - 1; vid >= 1; vid--)
6153                 mlxsw_sp_port_vid_learning_set(mlxsw_sp_port,
6154                                                vid, true);
6155
6156         mlxsw_sp_port_vlan_set(mlxsw_sp_port, 1, VLAN_N_VID - 2,
6157                                false, false);
6158         mlxsw_sp_port_stp_set(mlxsw_sp_port, false);
6159         mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, false);
6160 }
6161
6162 static bool mlxsw_sp_bridge_has_multiple_vxlans(struct net_device *br_dev)
6163 {
6164         unsigned int num_vxlans = 0;
6165         struct net_device *dev;
6166         struct list_head *iter;
6167
6168         netdev_for_each_lower_dev(br_dev, dev, iter) {
6169                 if (netif_is_vxlan(dev))
6170                         num_vxlans++;
6171         }
6172
6173         return num_vxlans > 1;
6174 }
6175
6176 static bool mlxsw_sp_bridge_vxlan_vlan_is_valid(struct net_device *br_dev)
6177 {
6178         DECLARE_BITMAP(vlans, VLAN_N_VID) = {0};
6179         struct net_device *dev;
6180         struct list_head *iter;
6181
6182         netdev_for_each_lower_dev(br_dev, dev, iter) {
6183                 u16 pvid;
6184                 int err;
6185
6186                 if (!netif_is_vxlan(dev))
6187                         continue;
6188
6189                 err = mlxsw_sp_vxlan_mapped_vid(dev, &pvid);
6190                 if (err || !pvid)
6191                         continue;
6192
6193                 if (test_and_set_bit(pvid, vlans))
6194                         return false;
6195         }
6196
6197         return true;
6198 }
6199
6200 static bool mlxsw_sp_bridge_vxlan_is_valid(struct net_device *br_dev,
6201                                            struct netlink_ext_ack *extack)
6202 {
6203         if (br_multicast_enabled(br_dev)) {
6204                 NL_SET_ERR_MSG_MOD(extack, "Multicast can not be enabled on a bridge with a VxLAN device");
6205                 return false;
6206         }
6207
6208         if (!br_vlan_enabled(br_dev) &&
6209             mlxsw_sp_bridge_has_multiple_vxlans(br_dev)) {
6210                 NL_SET_ERR_MSG_MOD(extack, "Multiple VxLAN devices are not supported in a VLAN-unaware bridge");
6211                 return false;
6212         }
6213
6214         if (br_vlan_enabled(br_dev) &&
6215             !mlxsw_sp_bridge_vxlan_vlan_is_valid(br_dev)) {
6216                 NL_SET_ERR_MSG_MOD(extack, "Multiple VxLAN devices cannot have the same VLAN as PVID and egress untagged");
6217                 return false;
6218         }
6219
6220         return true;
6221 }
6222
6223 static int mlxsw_sp_netdevice_port_upper_event(struct net_device *lower_dev,
6224                                                struct net_device *dev,
6225                                                unsigned long event, void *ptr)
6226 {
6227         struct netdev_notifier_changeupper_info *info;
6228         struct mlxsw_sp_port *mlxsw_sp_port;
6229         struct netlink_ext_ack *extack;
6230         struct net_device *upper_dev;
6231         struct mlxsw_sp *mlxsw_sp;
6232         int err = 0;
6233
6234         mlxsw_sp_port = netdev_priv(dev);
6235         mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
6236         info = ptr;
6237         extack = netdev_notifier_info_to_extack(&info->info);
6238
6239         switch (event) {
6240         case NETDEV_PRECHANGEUPPER:
6241                 upper_dev = info->upper_dev;
6242                 if (!is_vlan_dev(upper_dev) &&
6243                     !netif_is_lag_master(upper_dev) &&
6244                     !netif_is_bridge_master(upper_dev) &&
6245                     !netif_is_ovs_master(upper_dev) &&
6246                     !netif_is_macvlan(upper_dev)) {
6247                         NL_SET_ERR_MSG_MOD(extack, "Unknown upper device type");
6248                         return -EINVAL;
6249                 }
6250                 if (!info->linking)
6251                         break;
6252                 if (netif_is_bridge_master(upper_dev) &&
6253                     !mlxsw_sp_bridge_device_is_offloaded(mlxsw_sp, upper_dev) &&
6254                     mlxsw_sp_bridge_has_vxlan(upper_dev) &&
6255                     !mlxsw_sp_bridge_vxlan_is_valid(upper_dev, extack))
6256                         return -EOPNOTSUPP;
6257                 if (netdev_has_any_upper_dev(upper_dev) &&
6258                     (!netif_is_bridge_master(upper_dev) ||
6259                      !mlxsw_sp_bridge_device_is_offloaded(mlxsw_sp,
6260                                                           upper_dev))) {
6261                         NL_SET_ERR_MSG_MOD(extack, "Enslaving a port to a device that already has an upper device is not supported");
6262                         return -EINVAL;
6263                 }
6264                 if (netif_is_lag_master(upper_dev) &&
6265                     !mlxsw_sp_master_lag_check(mlxsw_sp, upper_dev,
6266                                                info->upper_info, extack))
6267                         return -EINVAL;
6268                 if (netif_is_lag_master(upper_dev) && vlan_uses_dev(dev)) {
6269                         NL_SET_ERR_MSG_MOD(extack, "Master device is a LAG master and this device has a VLAN");
6270                         return -EINVAL;
6271                 }
6272                 if (netif_is_lag_port(dev) && is_vlan_dev(upper_dev) &&
6273                     !netif_is_lag_master(vlan_dev_real_dev(upper_dev))) {
6274                         NL_SET_ERR_MSG_MOD(extack, "Can not put a VLAN on a LAG port");
6275                         return -EINVAL;
6276                 }
6277                 if (netif_is_macvlan(upper_dev) &&
6278                     !mlxsw_sp_rif_exists(mlxsw_sp, lower_dev)) {
6279                         NL_SET_ERR_MSG_MOD(extack, "macvlan is only supported on top of router interfaces");
6280                         return -EOPNOTSUPP;
6281                 }
6282                 if (netif_is_ovs_master(upper_dev) && vlan_uses_dev(dev)) {
6283                         NL_SET_ERR_MSG_MOD(extack, "Master device is an OVS master and this device has a VLAN");
6284                         return -EINVAL;
6285                 }
6286                 if (netif_is_ovs_port(dev) && is_vlan_dev(upper_dev)) {
6287                         NL_SET_ERR_MSG_MOD(extack, "Can not put a VLAN on an OVS port");
6288                         return -EINVAL;
6289                 }
6290                 break;
6291         case NETDEV_CHANGEUPPER:
6292                 upper_dev = info->upper_dev;
6293                 if (netif_is_bridge_master(upper_dev)) {
6294                         if (info->linking)
6295                                 err = mlxsw_sp_port_bridge_join(mlxsw_sp_port,
6296                                                                 lower_dev,
6297                                                                 upper_dev,
6298                                                                 extack);
6299                         else
6300                                 mlxsw_sp_port_bridge_leave(mlxsw_sp_port,
6301                                                            lower_dev,
6302                                                            upper_dev);
6303                 } else if (netif_is_lag_master(upper_dev)) {
6304                         if (info->linking) {
6305                                 err = mlxsw_sp_port_lag_join(mlxsw_sp_port,
6306                                                              upper_dev);
6307                         } else {
6308                                 mlxsw_sp_port_lag_col_dist_disable(mlxsw_sp_port);
6309                                 mlxsw_sp_port_lag_leave(mlxsw_sp_port,
6310                                                         upper_dev);
6311                         }
6312                 } else if (netif_is_ovs_master(upper_dev)) {
6313                         if (info->linking)
6314                                 err = mlxsw_sp_port_ovs_join(mlxsw_sp_port);
6315                         else
6316                                 mlxsw_sp_port_ovs_leave(mlxsw_sp_port);
6317                 } else if (netif_is_macvlan(upper_dev)) {
6318                         if (!info->linking)
6319                                 mlxsw_sp_rif_macvlan_del(mlxsw_sp, upper_dev);
6320                 } else if (is_vlan_dev(upper_dev)) {
6321                         struct net_device *br_dev;
6322
6323                         if (!netif_is_bridge_port(upper_dev))
6324                                 break;
6325                         if (info->linking)
6326                                 break;
6327                         br_dev = netdev_master_upper_dev_get(upper_dev);
6328                         mlxsw_sp_port_bridge_leave(mlxsw_sp_port, upper_dev,
6329                                                    br_dev);
6330                 }
6331                 break;
6332         }
6333
6334         return err;
6335 }
6336
6337 static int mlxsw_sp_netdevice_port_lower_event(struct net_device *dev,
6338                                                unsigned long event, void *ptr)
6339 {
6340         struct netdev_notifier_changelowerstate_info *info;
6341         struct mlxsw_sp_port *mlxsw_sp_port;
6342         int err;
6343
6344         mlxsw_sp_port = netdev_priv(dev);
6345         info = ptr;
6346
6347         switch (event) {
6348         case NETDEV_CHANGELOWERSTATE:
6349                 if (netif_is_lag_port(dev) && mlxsw_sp_port->lagged) {
6350                         err = mlxsw_sp_port_lag_changed(mlxsw_sp_port,
6351                                                         info->lower_state_info);
6352                         if (err)
6353                                 netdev_err(dev, "Failed to reflect link aggregation lower state change\n");
6354                 }
6355                 break;
6356         }
6357
6358         return 0;
6359 }
6360
6361 static int mlxsw_sp_netdevice_port_event(struct net_device *lower_dev,
6362                                          struct net_device *port_dev,
6363                                          unsigned long event, void *ptr)
6364 {
6365         switch (event) {
6366         case NETDEV_PRECHANGEUPPER:
6367         case NETDEV_CHANGEUPPER:
6368                 return mlxsw_sp_netdevice_port_upper_event(lower_dev, port_dev,
6369                                                            event, ptr);
6370         case NETDEV_CHANGELOWERSTATE:
6371                 return mlxsw_sp_netdevice_port_lower_event(port_dev, event,
6372                                                            ptr);
6373         }
6374
6375         return 0;
6376 }
6377
6378 static int mlxsw_sp_netdevice_lag_event(struct net_device *lag_dev,
6379                                         unsigned long event, void *ptr)
6380 {
6381         struct net_device *dev;
6382         struct list_head *iter;
6383         int ret;
6384
6385         netdev_for_each_lower_dev(lag_dev, dev, iter) {
6386                 if (mlxsw_sp_port_dev_check(dev)) {
6387                         ret = mlxsw_sp_netdevice_port_event(lag_dev, dev, event,
6388                                                             ptr);
6389                         if (ret)
6390                                 return ret;
6391                 }
6392         }
6393
6394         return 0;
6395 }
6396
6397 static int mlxsw_sp_netdevice_port_vlan_event(struct net_device *vlan_dev,
6398                                               struct net_device *dev,
6399                                               unsigned long event, void *ptr,
6400                                               u16 vid)
6401 {
6402         struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
6403         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
6404         struct netdev_notifier_changeupper_info *info = ptr;
6405         struct netlink_ext_ack *extack;
6406         struct net_device *upper_dev;
6407         int err = 0;
6408
6409         extack = netdev_notifier_info_to_extack(&info->info);
6410
6411         switch (event) {
6412         case NETDEV_PRECHANGEUPPER:
6413                 upper_dev = info->upper_dev;
6414                 if (!netif_is_bridge_master(upper_dev) &&
6415                     !netif_is_macvlan(upper_dev)) {
6416                         NL_SET_ERR_MSG_MOD(extack, "Unknown upper device type");
6417                         return -EINVAL;
6418                 }
6419                 if (!info->linking)
6420                         break;
6421                 if (netif_is_bridge_master(upper_dev) &&
6422                     !mlxsw_sp_bridge_device_is_offloaded(mlxsw_sp, upper_dev) &&
6423                     mlxsw_sp_bridge_has_vxlan(upper_dev) &&
6424                     !mlxsw_sp_bridge_vxlan_is_valid(upper_dev, extack))
6425                         return -EOPNOTSUPP;
6426                 if (netdev_has_any_upper_dev(upper_dev) &&
6427                     (!netif_is_bridge_master(upper_dev) ||
6428                      !mlxsw_sp_bridge_device_is_offloaded(mlxsw_sp,
6429                                                           upper_dev))) {
6430                         NL_SET_ERR_MSG_MOD(extack, "Enslaving a port to a device that already has an upper device is not supported");
6431                         return -EINVAL;
6432                 }
6433                 if (netif_is_macvlan(upper_dev) &&
6434                     !mlxsw_sp_rif_exists(mlxsw_sp, vlan_dev)) {
6435                         NL_SET_ERR_MSG_MOD(extack, "macvlan is only supported on top of router interfaces");
6436                         return -EOPNOTSUPP;
6437                 }
6438                 break;
6439         case NETDEV_CHANGEUPPER:
6440                 upper_dev = info->upper_dev;
6441                 if (netif_is_bridge_master(upper_dev)) {
6442                         if (info->linking)
6443                                 err = mlxsw_sp_port_bridge_join(mlxsw_sp_port,
6444                                                                 vlan_dev,
6445                                                                 upper_dev,
6446                                                                 extack);
6447                         else
6448                                 mlxsw_sp_port_bridge_leave(mlxsw_sp_port,
6449                                                            vlan_dev,
6450                                                            upper_dev);
6451                 } else if (netif_is_macvlan(upper_dev)) {
6452                         if (!info->linking)
6453                                 mlxsw_sp_rif_macvlan_del(mlxsw_sp, upper_dev);
6454                 } else {
6455                         err = -EINVAL;
6456                         WARN_ON(1);
6457                 }
6458                 break;
6459         }
6460
6461         return err;
6462 }
6463
6464 static int mlxsw_sp_netdevice_lag_port_vlan_event(struct net_device *vlan_dev,
6465                                                   struct net_device *lag_dev,
6466                                                   unsigned long event,
6467                                                   void *ptr, u16 vid)
6468 {
6469         struct net_device *dev;
6470         struct list_head *iter;
6471         int ret;
6472
6473         netdev_for_each_lower_dev(lag_dev, dev, iter) {
6474                 if (mlxsw_sp_port_dev_check(dev)) {
6475                         ret = mlxsw_sp_netdevice_port_vlan_event(vlan_dev, dev,
6476                                                                  event, ptr,
6477                                                                  vid);
6478                         if (ret)
6479                                 return ret;
6480                 }
6481         }
6482
6483         return 0;
6484 }
6485
6486 static int mlxsw_sp_netdevice_bridge_vlan_event(struct net_device *vlan_dev,
6487                                                 struct net_device *br_dev,
6488                                                 unsigned long event, void *ptr,
6489                                                 u16 vid)
6490 {
6491         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_lower_get(vlan_dev);
6492         struct netdev_notifier_changeupper_info *info = ptr;
6493         struct netlink_ext_ack *extack;
6494         struct net_device *upper_dev;
6495
6496         if (!mlxsw_sp)
6497                 return 0;
6498
6499         extack = netdev_notifier_info_to_extack(&info->info);
6500
6501         switch (event) {
6502         case NETDEV_PRECHANGEUPPER:
6503                 upper_dev = info->upper_dev;
6504                 if (!netif_is_macvlan(upper_dev)) {
6505                         NL_SET_ERR_MSG_MOD(extack, "Unknown upper device type");
6506                         return -EOPNOTSUPP;
6507                 }
6508                 if (!info->linking)
6509                         break;
6510                 if (netif_is_macvlan(upper_dev) &&
6511                     !mlxsw_sp_rif_exists(mlxsw_sp, vlan_dev)) {
6512                         NL_SET_ERR_MSG_MOD(extack, "macvlan is only supported on top of router interfaces");
6513                         return -EOPNOTSUPP;
6514                 }
6515                 break;
6516         case NETDEV_CHANGEUPPER:
6517                 upper_dev = info->upper_dev;
6518                 if (info->linking)
6519                         break;
6520                 if (netif_is_macvlan(upper_dev))
6521                         mlxsw_sp_rif_macvlan_del(mlxsw_sp, upper_dev);
6522                 break;
6523         }
6524
6525         return 0;
6526 }
6527
6528 static int mlxsw_sp_netdevice_vlan_event(struct net_device *vlan_dev,
6529                                          unsigned long event, void *ptr)
6530 {
6531         struct net_device *real_dev = vlan_dev_real_dev(vlan_dev);
6532         u16 vid = vlan_dev_vlan_id(vlan_dev);
6533
6534         if (mlxsw_sp_port_dev_check(real_dev))
6535                 return mlxsw_sp_netdevice_port_vlan_event(vlan_dev, real_dev,
6536                                                           event, ptr, vid);
6537         else if (netif_is_lag_master(real_dev))
6538                 return mlxsw_sp_netdevice_lag_port_vlan_event(vlan_dev,
6539                                                               real_dev, event,
6540                                                               ptr, vid);
6541         else if (netif_is_bridge_master(real_dev))
6542                 return mlxsw_sp_netdevice_bridge_vlan_event(vlan_dev, real_dev,
6543                                                             event, ptr, vid);
6544
6545         return 0;
6546 }
6547
6548 static int mlxsw_sp_netdevice_bridge_event(struct net_device *br_dev,
6549                                            unsigned long event, void *ptr)
6550 {
6551         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_lower_get(br_dev);
6552         struct netdev_notifier_changeupper_info *info = ptr;
6553         struct netlink_ext_ack *extack;
6554         struct net_device *upper_dev;
6555
6556         if (!mlxsw_sp)
6557                 return 0;
6558
6559         extack = netdev_notifier_info_to_extack(&info->info);
6560
6561         switch (event) {
6562         case NETDEV_PRECHANGEUPPER:
6563                 upper_dev = info->upper_dev;
6564                 if (!is_vlan_dev(upper_dev) && !netif_is_macvlan(upper_dev)) {
6565                         NL_SET_ERR_MSG_MOD(extack, "Unknown upper device type");
6566                         return -EOPNOTSUPP;
6567                 }
6568                 if (!info->linking)
6569                         break;
6570                 if (netif_is_macvlan(upper_dev) &&
6571                     !mlxsw_sp_rif_exists(mlxsw_sp, br_dev)) {
6572                         NL_SET_ERR_MSG_MOD(extack, "macvlan is only supported on top of router interfaces");
6573                         return -EOPNOTSUPP;
6574                 }
6575                 break;
6576         case NETDEV_CHANGEUPPER:
6577                 upper_dev = info->upper_dev;
6578                 if (info->linking)
6579                         break;
6580                 if (is_vlan_dev(upper_dev))
6581                         mlxsw_sp_rif_destroy_by_dev(mlxsw_sp, upper_dev);
6582                 if (netif_is_macvlan(upper_dev))
6583                         mlxsw_sp_rif_macvlan_del(mlxsw_sp, upper_dev);
6584                 break;
6585         }
6586
6587         return 0;
6588 }
6589
6590 static int mlxsw_sp_netdevice_macvlan_event(struct net_device *macvlan_dev,
6591                                             unsigned long event, void *ptr)
6592 {
6593         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_lower_get(macvlan_dev);
6594         struct netdev_notifier_changeupper_info *info = ptr;
6595         struct netlink_ext_ack *extack;
6596
6597         if (!mlxsw_sp || event != NETDEV_PRECHANGEUPPER)
6598                 return 0;
6599
6600         extack = netdev_notifier_info_to_extack(&info->info);
6601
6602         /* VRF enslavement is handled in mlxsw_sp_netdevice_vrf_event() */
6603         NL_SET_ERR_MSG_MOD(extack, "Unknown upper device type");
6604
6605         return -EOPNOTSUPP;
6606 }
6607
6608 static bool mlxsw_sp_is_vrf_event(unsigned long event, void *ptr)
6609 {
6610         struct netdev_notifier_changeupper_info *info = ptr;
6611
6612         if (event != NETDEV_PRECHANGEUPPER && event != NETDEV_CHANGEUPPER)
6613                 return false;
6614         return netif_is_l3_master(info->upper_dev);
6615 }
6616
6617 static int mlxsw_sp_netdevice_vxlan_event(struct mlxsw_sp *mlxsw_sp,
6618                                           struct net_device *dev,
6619                                           unsigned long event, void *ptr)
6620 {
6621         struct netdev_notifier_changeupper_info *cu_info;
6622         struct netdev_notifier_info *info = ptr;
6623         struct netlink_ext_ack *extack;
6624         struct net_device *upper_dev;
6625
6626         extack = netdev_notifier_info_to_extack(info);
6627
6628         switch (event) {
6629         case NETDEV_CHANGEUPPER:
6630                 cu_info = container_of(info,
6631                                        struct netdev_notifier_changeupper_info,
6632                                        info);
6633                 upper_dev = cu_info->upper_dev;
6634                 if (!netif_is_bridge_master(upper_dev))
6635                         return 0;
6636                 if (!mlxsw_sp_lower_get(upper_dev))
6637                         return 0;
6638                 if (!mlxsw_sp_bridge_vxlan_is_valid(upper_dev, extack))
6639                         return -EOPNOTSUPP;
6640                 if (cu_info->linking) {
6641                         if (!netif_running(dev))
6642                                 return 0;
6643                         /* When the bridge is VLAN-aware, the VNI of the VxLAN
6644                          * device needs to be mapped to a VLAN, but at this
6645                          * point no VLANs are configured on the VxLAN device
6646                          */
6647                         if (br_vlan_enabled(upper_dev))
6648                                 return 0;
6649                         return mlxsw_sp_bridge_vxlan_join(mlxsw_sp, upper_dev,
6650                                                           dev, 0, extack);
6651                 } else {
6652                         /* VLANs were already flushed, which triggered the
6653                          * necessary cleanup
6654                          */
6655                         if (br_vlan_enabled(upper_dev))
6656                                 return 0;
6657                         mlxsw_sp_bridge_vxlan_leave(mlxsw_sp, dev);
6658                 }
6659                 break;
6660         case NETDEV_PRE_UP:
6661                 upper_dev = netdev_master_upper_dev_get(dev);
6662                 if (!upper_dev)
6663                         return 0;
6664                 if (!netif_is_bridge_master(upper_dev))
6665                         return 0;
6666                 if (!mlxsw_sp_lower_get(upper_dev))
6667                         return 0;
6668                 return mlxsw_sp_bridge_vxlan_join(mlxsw_sp, upper_dev, dev, 0,
6669                                                   extack);
6670         case NETDEV_DOWN:
6671                 upper_dev = netdev_master_upper_dev_get(dev);
6672                 if (!upper_dev)
6673                         return 0;
6674                 if (!netif_is_bridge_master(upper_dev))
6675                         return 0;
6676                 if (!mlxsw_sp_lower_get(upper_dev))
6677                         return 0;
6678                 mlxsw_sp_bridge_vxlan_leave(mlxsw_sp, dev);
6679                 break;
6680         }
6681
6682         return 0;
6683 }
6684
6685 static int mlxsw_sp_netdevice_event(struct notifier_block *nb,
6686                                     unsigned long event, void *ptr)
6687 {
6688         struct net_device *dev = netdev_notifier_info_to_dev(ptr);
6689         struct mlxsw_sp_span_entry *span_entry;
6690         struct mlxsw_sp *mlxsw_sp;
6691         int err = 0;
6692
6693         mlxsw_sp = container_of(nb, struct mlxsw_sp, netdevice_nb);
6694         if (event == NETDEV_UNREGISTER) {
6695                 span_entry = mlxsw_sp_span_entry_find_by_port(mlxsw_sp, dev);
6696                 if (span_entry)
6697                         mlxsw_sp_span_entry_invalidate(mlxsw_sp, span_entry);
6698         }
6699         mlxsw_sp_span_respin(mlxsw_sp);
6700
6701         if (netif_is_vxlan(dev))
6702                 err = mlxsw_sp_netdevice_vxlan_event(mlxsw_sp, dev, event, ptr);
6703         if (mlxsw_sp_netdev_is_ipip_ol(mlxsw_sp, dev))
6704                 err = mlxsw_sp_netdevice_ipip_ol_event(mlxsw_sp, dev,
6705                                                        event, ptr);
6706         else if (mlxsw_sp_netdev_is_ipip_ul(mlxsw_sp, dev))
6707                 err = mlxsw_sp_netdevice_ipip_ul_event(mlxsw_sp, dev,
6708                                                        event, ptr);
6709         else if (event == NETDEV_PRE_CHANGEADDR ||
6710                  event == NETDEV_CHANGEADDR ||
6711                  event == NETDEV_CHANGEMTU)
6712                 err = mlxsw_sp_netdevice_router_port_event(dev, event, ptr);
6713         else if (mlxsw_sp_is_vrf_event(event, ptr))
6714                 err = mlxsw_sp_netdevice_vrf_event(dev, event, ptr);
6715         else if (mlxsw_sp_port_dev_check(dev))
6716                 err = mlxsw_sp_netdevice_port_event(dev, dev, event, ptr);
6717         else if (netif_is_lag_master(dev))
6718                 err = mlxsw_sp_netdevice_lag_event(dev, event, ptr);
6719         else if (is_vlan_dev(dev))
6720                 err = mlxsw_sp_netdevice_vlan_event(dev, event, ptr);
6721         else if (netif_is_bridge_master(dev))
6722                 err = mlxsw_sp_netdevice_bridge_event(dev, event, ptr);
6723         else if (netif_is_macvlan(dev))
6724                 err = mlxsw_sp_netdevice_macvlan_event(dev, event, ptr);
6725
6726         return notifier_from_errno(err);
6727 }
6728
6729 static struct notifier_block mlxsw_sp_inetaddr_valid_nb __read_mostly = {
6730         .notifier_call = mlxsw_sp_inetaddr_valid_event,
6731 };
6732
6733 static struct notifier_block mlxsw_sp_inet6addr_valid_nb __read_mostly = {
6734         .notifier_call = mlxsw_sp_inet6addr_valid_event,
6735 };
6736
6737 static const struct pci_device_id mlxsw_sp1_pci_id_table[] = {
6738         {PCI_VDEVICE(MELLANOX, PCI_DEVICE_ID_MELLANOX_SPECTRUM), 0},
6739         {0, },
6740 };
6741
6742 static struct pci_driver mlxsw_sp1_pci_driver = {
6743         .name = mlxsw_sp1_driver_name,
6744         .id_table = mlxsw_sp1_pci_id_table,
6745 };
6746
6747 static const struct pci_device_id mlxsw_sp2_pci_id_table[] = {
6748         {PCI_VDEVICE(MELLANOX, PCI_DEVICE_ID_MELLANOX_SPECTRUM2), 0},
6749         {0, },
6750 };
6751
6752 static struct pci_driver mlxsw_sp2_pci_driver = {
6753         .name = mlxsw_sp2_driver_name,
6754         .id_table = mlxsw_sp2_pci_id_table,
6755 };
6756
6757 static const struct pci_device_id mlxsw_sp3_pci_id_table[] = {
6758         {PCI_VDEVICE(MELLANOX, PCI_DEVICE_ID_MELLANOX_SPECTRUM3), 0},
6759         {0, },
6760 };
6761
6762 static struct pci_driver mlxsw_sp3_pci_driver = {
6763         .name = mlxsw_sp3_driver_name,
6764         .id_table = mlxsw_sp3_pci_id_table,
6765 };
6766
6767 static int __init mlxsw_sp_module_init(void)
6768 {
6769         int err;
6770
6771         register_inetaddr_validator_notifier(&mlxsw_sp_inetaddr_valid_nb);
6772         register_inet6addr_validator_notifier(&mlxsw_sp_inet6addr_valid_nb);
6773
6774         err = mlxsw_core_driver_register(&mlxsw_sp1_driver);
6775         if (err)
6776                 goto err_sp1_core_driver_register;
6777
6778         err = mlxsw_core_driver_register(&mlxsw_sp2_driver);
6779         if (err)
6780                 goto err_sp2_core_driver_register;
6781
6782         err = mlxsw_core_driver_register(&mlxsw_sp3_driver);
6783         if (err)
6784                 goto err_sp3_core_driver_register;
6785
6786         err = mlxsw_pci_driver_register(&mlxsw_sp1_pci_driver);
6787         if (err)
6788                 goto err_sp1_pci_driver_register;
6789
6790         err = mlxsw_pci_driver_register(&mlxsw_sp2_pci_driver);
6791         if (err)
6792                 goto err_sp2_pci_driver_register;
6793
6794         err = mlxsw_pci_driver_register(&mlxsw_sp3_pci_driver);
6795         if (err)
6796                 goto err_sp3_pci_driver_register;
6797
6798         return 0;
6799
6800 err_sp3_pci_driver_register:
6801         mlxsw_pci_driver_unregister(&mlxsw_sp2_pci_driver);
6802 err_sp2_pci_driver_register:
6803         mlxsw_pci_driver_unregister(&mlxsw_sp1_pci_driver);
6804 err_sp1_pci_driver_register:
6805         mlxsw_core_driver_unregister(&mlxsw_sp3_driver);
6806 err_sp3_core_driver_register:
6807         mlxsw_core_driver_unregister(&mlxsw_sp2_driver);
6808 err_sp2_core_driver_register:
6809         mlxsw_core_driver_unregister(&mlxsw_sp1_driver);
6810 err_sp1_core_driver_register:
6811         unregister_inet6addr_validator_notifier(&mlxsw_sp_inet6addr_valid_nb);
6812         unregister_inetaddr_validator_notifier(&mlxsw_sp_inetaddr_valid_nb);
6813         return err;
6814 }
6815
6816 static void __exit mlxsw_sp_module_exit(void)
6817 {
6818         mlxsw_pci_driver_unregister(&mlxsw_sp3_pci_driver);
6819         mlxsw_pci_driver_unregister(&mlxsw_sp2_pci_driver);
6820         mlxsw_pci_driver_unregister(&mlxsw_sp1_pci_driver);
6821         mlxsw_core_driver_unregister(&mlxsw_sp3_driver);
6822         mlxsw_core_driver_unregister(&mlxsw_sp2_driver);
6823         mlxsw_core_driver_unregister(&mlxsw_sp1_driver);
6824         unregister_inet6addr_validator_notifier(&mlxsw_sp_inet6addr_valid_nb);
6825         unregister_inetaddr_validator_notifier(&mlxsw_sp_inetaddr_valid_nb);
6826 }
6827
6828 module_init(mlxsw_sp_module_init);
6829 module_exit(mlxsw_sp_module_exit);
6830
6831 MODULE_LICENSE("Dual BSD/GPL");
6832 MODULE_AUTHOR("Jiri Pirko <jiri@mellanox.com>");
6833 MODULE_DESCRIPTION("Mellanox Spectrum driver");
6834 MODULE_DEVICE_TABLE(pci, mlxsw_sp1_pci_id_table);
6835 MODULE_DEVICE_TABLE(pci, mlxsw_sp2_pci_id_table);
6836 MODULE_DEVICE_TABLE(pci, mlxsw_sp3_pci_id_table);
6837 MODULE_FIRMWARE(MLXSW_SP1_FW_FILENAME);
6838 MODULE_FIRMWARE(MLXSW_SP2_FW_FILENAME);