Merge tag 'sched-for-bpf-2020-02-20' of git://git.kernel.org/pub/scm/linux/kernel...
[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_discard_stats[] = {
2232         {
2233                 .str = "discard_ingress_general",
2234                 .getter = mlxsw_reg_ppcnt_ingress_general_get,
2235         },
2236         {
2237                 .str = "discard_ingress_policy_engine",
2238                 .getter = mlxsw_reg_ppcnt_ingress_policy_engine_get,
2239         },
2240         {
2241                 .str = "discard_ingress_vlan_membership",
2242                 .getter = mlxsw_reg_ppcnt_ingress_vlan_membership_get,
2243         },
2244         {
2245                 .str = "discard_ingress_tag_frame_type",
2246                 .getter = mlxsw_reg_ppcnt_ingress_tag_frame_type_get,
2247         },
2248         {
2249                 .str = "discard_egress_vlan_membership",
2250                 .getter = mlxsw_reg_ppcnt_egress_vlan_membership_get,
2251         },
2252         {
2253                 .str = "discard_loopback_filter",
2254                 .getter = mlxsw_reg_ppcnt_loopback_filter_get,
2255         },
2256         {
2257                 .str = "discard_egress_general",
2258                 .getter = mlxsw_reg_ppcnt_egress_general_get,
2259         },
2260         {
2261                 .str = "discard_egress_hoq",
2262                 .getter = mlxsw_reg_ppcnt_egress_hoq_get,
2263         },
2264         {
2265                 .str = "discard_egress_policy_engine",
2266                 .getter = mlxsw_reg_ppcnt_egress_policy_engine_get,
2267         },
2268         {
2269                 .str = "discard_ingress_tx_link_down",
2270                 .getter = mlxsw_reg_ppcnt_ingress_tx_link_down_get,
2271         },
2272         {
2273                 .str = "discard_egress_stp_filter",
2274                 .getter = mlxsw_reg_ppcnt_egress_stp_filter_get,
2275         },
2276         {
2277                 .str = "discard_egress_sll",
2278                 .getter = mlxsw_reg_ppcnt_egress_sll_get,
2279         },
2280 };
2281
2282 #define MLXSW_SP_PORT_HW_DISCARD_STATS_LEN \
2283         ARRAY_SIZE(mlxsw_sp_port_hw_discard_stats)
2284
2285 static struct mlxsw_sp_port_hw_stats mlxsw_sp_port_hw_prio_stats[] = {
2286         {
2287                 .str = "rx_octets_prio",
2288                 .getter = mlxsw_reg_ppcnt_rx_octets_get,
2289         },
2290         {
2291                 .str = "rx_frames_prio",
2292                 .getter = mlxsw_reg_ppcnt_rx_frames_get,
2293         },
2294         {
2295                 .str = "tx_octets_prio",
2296                 .getter = mlxsw_reg_ppcnt_tx_octets_get,
2297         },
2298         {
2299                 .str = "tx_frames_prio",
2300                 .getter = mlxsw_reg_ppcnt_tx_frames_get,
2301         },
2302         {
2303                 .str = "rx_pause_prio",
2304                 .getter = mlxsw_reg_ppcnt_rx_pause_get,
2305         },
2306         {
2307                 .str = "rx_pause_duration_prio",
2308                 .getter = mlxsw_reg_ppcnt_rx_pause_duration_get,
2309         },
2310         {
2311                 .str = "tx_pause_prio",
2312                 .getter = mlxsw_reg_ppcnt_tx_pause_get,
2313         },
2314         {
2315                 .str = "tx_pause_duration_prio",
2316                 .getter = mlxsw_reg_ppcnt_tx_pause_duration_get,
2317         },
2318 };
2319
2320 #define MLXSW_SP_PORT_HW_PRIO_STATS_LEN ARRAY_SIZE(mlxsw_sp_port_hw_prio_stats)
2321
2322 static struct mlxsw_sp_port_hw_stats mlxsw_sp_port_hw_tc_stats[] = {
2323         {
2324                 .str = "tc_transmit_queue_tc",
2325                 .getter = mlxsw_reg_ppcnt_tc_transmit_queue_get,
2326                 .cells_bytes = true,
2327         },
2328         {
2329                 .str = "tc_no_buffer_discard_uc_tc",
2330                 .getter = mlxsw_reg_ppcnt_tc_no_buffer_discard_uc_get,
2331         },
2332 };
2333
2334 #define MLXSW_SP_PORT_HW_TC_STATS_LEN ARRAY_SIZE(mlxsw_sp_port_hw_tc_stats)
2335
2336 #define MLXSW_SP_PORT_ETHTOOL_STATS_LEN (MLXSW_SP_PORT_HW_STATS_LEN + \
2337                                          MLXSW_SP_PORT_HW_RFC_2863_STATS_LEN + \
2338                                          MLXSW_SP_PORT_HW_RFC_2819_STATS_LEN + \
2339                                          MLXSW_SP_PORT_HW_RFC_3635_STATS_LEN + \
2340                                          MLXSW_SP_PORT_HW_DISCARD_STATS_LEN + \
2341                                          (MLXSW_SP_PORT_HW_PRIO_STATS_LEN * \
2342                                           IEEE_8021QAZ_MAX_TCS) + \
2343                                          (MLXSW_SP_PORT_HW_TC_STATS_LEN * \
2344                                           TC_MAX_QUEUE))
2345
2346 static void mlxsw_sp_port_get_prio_strings(u8 **p, int prio)
2347 {
2348         int i;
2349
2350         for (i = 0; i < MLXSW_SP_PORT_HW_PRIO_STATS_LEN; i++) {
2351                 snprintf(*p, ETH_GSTRING_LEN, "%.29s_%.1d",
2352                          mlxsw_sp_port_hw_prio_stats[i].str, prio);
2353                 *p += ETH_GSTRING_LEN;
2354         }
2355 }
2356
2357 static void mlxsw_sp_port_get_tc_strings(u8 **p, int tc)
2358 {
2359         int i;
2360
2361         for (i = 0; i < MLXSW_SP_PORT_HW_TC_STATS_LEN; i++) {
2362                 snprintf(*p, ETH_GSTRING_LEN, "%.29s_%.1d",
2363                          mlxsw_sp_port_hw_tc_stats[i].str, tc);
2364                 *p += ETH_GSTRING_LEN;
2365         }
2366 }
2367
2368 static void mlxsw_sp_port_get_strings(struct net_device *dev,
2369                                       u32 stringset, u8 *data)
2370 {
2371         struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
2372         u8 *p = data;
2373         int i;
2374
2375         switch (stringset) {
2376         case ETH_SS_STATS:
2377                 for (i = 0; i < MLXSW_SP_PORT_HW_STATS_LEN; i++) {
2378                         memcpy(p, mlxsw_sp_port_hw_stats[i].str,
2379                                ETH_GSTRING_LEN);
2380                         p += ETH_GSTRING_LEN;
2381                 }
2382
2383                 for (i = 0; i < MLXSW_SP_PORT_HW_RFC_2863_STATS_LEN; i++) {
2384                         memcpy(p, mlxsw_sp_port_hw_rfc_2863_stats[i].str,
2385                                ETH_GSTRING_LEN);
2386                         p += ETH_GSTRING_LEN;
2387                 }
2388
2389                 for (i = 0; i < MLXSW_SP_PORT_HW_RFC_2819_STATS_LEN; i++) {
2390                         memcpy(p, mlxsw_sp_port_hw_rfc_2819_stats[i].str,
2391                                ETH_GSTRING_LEN);
2392                         p += ETH_GSTRING_LEN;
2393                 }
2394
2395                 for (i = 0; i < MLXSW_SP_PORT_HW_RFC_3635_STATS_LEN; i++) {
2396                         memcpy(p, mlxsw_sp_port_hw_rfc_3635_stats[i].str,
2397                                ETH_GSTRING_LEN);
2398                         p += ETH_GSTRING_LEN;
2399                 }
2400
2401                 for (i = 0; i < MLXSW_SP_PORT_HW_DISCARD_STATS_LEN; i++) {
2402                         memcpy(p, mlxsw_sp_port_hw_discard_stats[i].str,
2403                                ETH_GSTRING_LEN);
2404                         p += ETH_GSTRING_LEN;
2405                 }
2406
2407                 for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++)
2408                         mlxsw_sp_port_get_prio_strings(&p, i);
2409
2410                 for (i = 0; i < TC_MAX_QUEUE; i++)
2411                         mlxsw_sp_port_get_tc_strings(&p, i);
2412
2413                 mlxsw_sp_port->mlxsw_sp->ptp_ops->get_stats_strings(&p);
2414                 break;
2415         }
2416 }
2417
2418 static int mlxsw_sp_port_set_phys_id(struct net_device *dev,
2419                                      enum ethtool_phys_id_state state)
2420 {
2421         struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
2422         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
2423         char mlcr_pl[MLXSW_REG_MLCR_LEN];
2424         bool active;
2425
2426         switch (state) {
2427         case ETHTOOL_ID_ACTIVE:
2428                 active = true;
2429                 break;
2430         case ETHTOOL_ID_INACTIVE:
2431                 active = false;
2432                 break;
2433         default:
2434                 return -EOPNOTSUPP;
2435         }
2436
2437         mlxsw_reg_mlcr_pack(mlcr_pl, mlxsw_sp_port->local_port, active);
2438         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mlcr), mlcr_pl);
2439 }
2440
2441 static int
2442 mlxsw_sp_get_hw_stats_by_group(struct mlxsw_sp_port_hw_stats **p_hw_stats,
2443                                int *p_len, enum mlxsw_reg_ppcnt_grp grp)
2444 {
2445         switch (grp) {
2446         case MLXSW_REG_PPCNT_IEEE_8023_CNT:
2447                 *p_hw_stats = mlxsw_sp_port_hw_stats;
2448                 *p_len = MLXSW_SP_PORT_HW_STATS_LEN;
2449                 break;
2450         case MLXSW_REG_PPCNT_RFC_2863_CNT:
2451                 *p_hw_stats = mlxsw_sp_port_hw_rfc_2863_stats;
2452                 *p_len = MLXSW_SP_PORT_HW_RFC_2863_STATS_LEN;
2453                 break;
2454         case MLXSW_REG_PPCNT_RFC_2819_CNT:
2455                 *p_hw_stats = mlxsw_sp_port_hw_rfc_2819_stats;
2456                 *p_len = MLXSW_SP_PORT_HW_RFC_2819_STATS_LEN;
2457                 break;
2458         case MLXSW_REG_PPCNT_RFC_3635_CNT:
2459                 *p_hw_stats = mlxsw_sp_port_hw_rfc_3635_stats;
2460                 *p_len = MLXSW_SP_PORT_HW_RFC_3635_STATS_LEN;
2461                 break;
2462         case MLXSW_REG_PPCNT_DISCARD_CNT:
2463                 *p_hw_stats = mlxsw_sp_port_hw_discard_stats;
2464                 *p_len = MLXSW_SP_PORT_HW_DISCARD_STATS_LEN;
2465                 break;
2466         case MLXSW_REG_PPCNT_PRIO_CNT:
2467                 *p_hw_stats = mlxsw_sp_port_hw_prio_stats;
2468                 *p_len = MLXSW_SP_PORT_HW_PRIO_STATS_LEN;
2469                 break;
2470         case MLXSW_REG_PPCNT_TC_CNT:
2471                 *p_hw_stats = mlxsw_sp_port_hw_tc_stats;
2472                 *p_len = MLXSW_SP_PORT_HW_TC_STATS_LEN;
2473                 break;
2474         default:
2475                 WARN_ON(1);
2476                 return -EOPNOTSUPP;
2477         }
2478         return 0;
2479 }
2480
2481 static void __mlxsw_sp_port_get_stats(struct net_device *dev,
2482                                       enum mlxsw_reg_ppcnt_grp grp, int prio,
2483                                       u64 *data, int data_index)
2484 {
2485         struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
2486         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
2487         struct mlxsw_sp_port_hw_stats *hw_stats;
2488         char ppcnt_pl[MLXSW_REG_PPCNT_LEN];
2489         int i, len;
2490         int err;
2491
2492         err = mlxsw_sp_get_hw_stats_by_group(&hw_stats, &len, grp);
2493         if (err)
2494                 return;
2495         mlxsw_sp_port_get_stats_raw(dev, grp, prio, ppcnt_pl);
2496         for (i = 0; i < len; i++) {
2497                 data[data_index + i] = hw_stats[i].getter(ppcnt_pl);
2498                 if (!hw_stats[i].cells_bytes)
2499                         continue;
2500                 data[data_index + i] = mlxsw_sp_cells_bytes(mlxsw_sp,
2501                                                             data[data_index + i]);
2502         }
2503 }
2504
2505 static void mlxsw_sp_port_get_stats(struct net_device *dev,
2506                                     struct ethtool_stats *stats, u64 *data)
2507 {
2508         struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
2509         int i, data_index = 0;
2510
2511         /* IEEE 802.3 Counters */
2512         __mlxsw_sp_port_get_stats(dev, MLXSW_REG_PPCNT_IEEE_8023_CNT, 0,
2513                                   data, data_index);
2514         data_index = MLXSW_SP_PORT_HW_STATS_LEN;
2515
2516         /* RFC 2863 Counters */
2517         __mlxsw_sp_port_get_stats(dev, MLXSW_REG_PPCNT_RFC_2863_CNT, 0,
2518                                   data, data_index);
2519         data_index += MLXSW_SP_PORT_HW_RFC_2863_STATS_LEN;
2520
2521         /* RFC 2819 Counters */
2522         __mlxsw_sp_port_get_stats(dev, MLXSW_REG_PPCNT_RFC_2819_CNT, 0,
2523                                   data, data_index);
2524         data_index += MLXSW_SP_PORT_HW_RFC_2819_STATS_LEN;
2525
2526         /* RFC 3635 Counters */
2527         __mlxsw_sp_port_get_stats(dev, MLXSW_REG_PPCNT_RFC_3635_CNT, 0,
2528                                   data, data_index);
2529         data_index += MLXSW_SP_PORT_HW_RFC_3635_STATS_LEN;
2530
2531         /* Discard Counters */
2532         __mlxsw_sp_port_get_stats(dev, MLXSW_REG_PPCNT_DISCARD_CNT, 0,
2533                                   data, data_index);
2534         data_index += MLXSW_SP_PORT_HW_DISCARD_STATS_LEN;
2535
2536         /* Per-Priority Counters */
2537         for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
2538                 __mlxsw_sp_port_get_stats(dev, MLXSW_REG_PPCNT_PRIO_CNT, i,
2539                                           data, data_index);
2540                 data_index += MLXSW_SP_PORT_HW_PRIO_STATS_LEN;
2541         }
2542
2543         /* Per-TC Counters */
2544         for (i = 0; i < TC_MAX_QUEUE; i++) {
2545                 __mlxsw_sp_port_get_stats(dev, MLXSW_REG_PPCNT_TC_CNT, i,
2546                                           data, data_index);
2547                 data_index += MLXSW_SP_PORT_HW_TC_STATS_LEN;
2548         }
2549
2550         /* PTP counters */
2551         mlxsw_sp_port->mlxsw_sp->ptp_ops->get_stats(mlxsw_sp_port,
2552                                                     data, data_index);
2553         data_index += mlxsw_sp_port->mlxsw_sp->ptp_ops->get_stats_count();
2554 }
2555
2556 static int mlxsw_sp_port_get_sset_count(struct net_device *dev, int sset)
2557 {
2558         struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
2559
2560         switch (sset) {
2561         case ETH_SS_STATS:
2562                 return MLXSW_SP_PORT_ETHTOOL_STATS_LEN +
2563                        mlxsw_sp_port->mlxsw_sp->ptp_ops->get_stats_count();
2564         default:
2565                 return -EOPNOTSUPP;
2566         }
2567 }
2568
2569 struct mlxsw_sp1_port_link_mode {
2570         enum ethtool_link_mode_bit_indices mask_ethtool;
2571         u32 mask;
2572         u32 speed;
2573 };
2574
2575 static const struct mlxsw_sp1_port_link_mode mlxsw_sp1_port_link_mode[] = {
2576         {
2577                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_100BASE_T,
2578                 .mask_ethtool   = ETHTOOL_LINK_MODE_100baseT_Full_BIT,
2579                 .speed          = SPEED_100,
2580         },
2581         {
2582                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_SGMII |
2583                                   MLXSW_REG_PTYS_ETH_SPEED_1000BASE_KX,
2584                 .mask_ethtool   = ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
2585                 .speed          = SPEED_1000,
2586         },
2587         {
2588                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_10GBASE_T,
2589                 .mask_ethtool   = ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
2590                 .speed          = SPEED_10000,
2591         },
2592         {
2593                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_10GBASE_CX4 |
2594                                   MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KX4,
2595                 .mask_ethtool   = ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT,
2596                 .speed          = SPEED_10000,
2597         },
2598         {
2599                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KR |
2600                                   MLXSW_REG_PTYS_ETH_SPEED_10GBASE_CR |
2601                                   MLXSW_REG_PTYS_ETH_SPEED_10GBASE_SR |
2602                                   MLXSW_REG_PTYS_ETH_SPEED_10GBASE_ER_LR,
2603                 .mask_ethtool   = ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
2604                 .speed          = SPEED_10000,
2605         },
2606         {
2607                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_20GBASE_KR2,
2608                 .mask_ethtool   = ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT,
2609                 .speed          = SPEED_20000,
2610         },
2611         {
2612                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_40GBASE_CR4,
2613                 .mask_ethtool   = ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT,
2614                 .speed          = SPEED_40000,
2615         },
2616         {
2617                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_40GBASE_KR4,
2618                 .mask_ethtool   = ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT,
2619                 .speed          = SPEED_40000,
2620         },
2621         {
2622                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_40GBASE_SR4,
2623                 .mask_ethtool   = ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT,
2624                 .speed          = SPEED_40000,
2625         },
2626         {
2627                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_40GBASE_LR4_ER4,
2628                 .mask_ethtool   = ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT,
2629                 .speed          = SPEED_40000,
2630         },
2631         {
2632                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_25GBASE_CR,
2633                 .mask_ethtool   = ETHTOOL_LINK_MODE_25000baseCR_Full_BIT,
2634                 .speed          = SPEED_25000,
2635         },
2636         {
2637                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_25GBASE_KR,
2638                 .mask_ethtool   = ETHTOOL_LINK_MODE_25000baseKR_Full_BIT,
2639                 .speed          = SPEED_25000,
2640         },
2641         {
2642                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_25GBASE_SR,
2643                 .mask_ethtool   = ETHTOOL_LINK_MODE_25000baseSR_Full_BIT,
2644                 .speed          = SPEED_25000,
2645         },
2646         {
2647                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_50GBASE_CR2,
2648                 .mask_ethtool   = ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT,
2649                 .speed          = SPEED_50000,
2650         },
2651         {
2652                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_50GBASE_KR2,
2653                 .mask_ethtool   = ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT,
2654                 .speed          = SPEED_50000,
2655         },
2656         {
2657                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_50GBASE_SR2,
2658                 .mask_ethtool   = ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT,
2659                 .speed          = SPEED_50000,
2660         },
2661         {
2662                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_100GBASE_CR4,
2663                 .mask_ethtool   = ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT,
2664                 .speed          = SPEED_100000,
2665         },
2666         {
2667                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_100GBASE_SR4,
2668                 .mask_ethtool   = ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT,
2669                 .speed          = SPEED_100000,
2670         },
2671         {
2672                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_100GBASE_KR4,
2673                 .mask_ethtool   = ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT,
2674                 .speed          = SPEED_100000,
2675         },
2676         {
2677                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_100GBASE_LR4_ER4,
2678                 .mask_ethtool   = ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT,
2679                 .speed          = SPEED_100000,
2680         },
2681 };
2682
2683 #define MLXSW_SP1_PORT_LINK_MODE_LEN ARRAY_SIZE(mlxsw_sp1_port_link_mode)
2684
2685 static void
2686 mlxsw_sp1_from_ptys_supported_port(struct mlxsw_sp *mlxsw_sp,
2687                                    u32 ptys_eth_proto,
2688                                    struct ethtool_link_ksettings *cmd)
2689 {
2690         if (ptys_eth_proto & (MLXSW_REG_PTYS_ETH_SPEED_10GBASE_CR |
2691                               MLXSW_REG_PTYS_ETH_SPEED_10GBASE_SR |
2692                               MLXSW_REG_PTYS_ETH_SPEED_40GBASE_CR4 |
2693                               MLXSW_REG_PTYS_ETH_SPEED_40GBASE_SR4 |
2694                               MLXSW_REG_PTYS_ETH_SPEED_100GBASE_SR4 |
2695                               MLXSW_REG_PTYS_ETH_SPEED_SGMII))
2696                 ethtool_link_ksettings_add_link_mode(cmd, supported, FIBRE);
2697
2698         if (ptys_eth_proto & (MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KR |
2699                               MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KX4 |
2700                               MLXSW_REG_PTYS_ETH_SPEED_40GBASE_KR4 |
2701                               MLXSW_REG_PTYS_ETH_SPEED_100GBASE_KR4 |
2702                               MLXSW_REG_PTYS_ETH_SPEED_1000BASE_KX))
2703                 ethtool_link_ksettings_add_link_mode(cmd, supported, Backplane);
2704 }
2705
2706 static void
2707 mlxsw_sp1_from_ptys_link(struct mlxsw_sp *mlxsw_sp, u32 ptys_eth_proto,
2708                          u8 width, unsigned long *mode)
2709 {
2710         int i;
2711
2712         for (i = 0; i < MLXSW_SP1_PORT_LINK_MODE_LEN; i++) {
2713                 if (ptys_eth_proto & mlxsw_sp1_port_link_mode[i].mask)
2714                         __set_bit(mlxsw_sp1_port_link_mode[i].mask_ethtool,
2715                                   mode);
2716         }
2717 }
2718
2719 static u32
2720 mlxsw_sp1_from_ptys_speed(struct mlxsw_sp *mlxsw_sp, u32 ptys_eth_proto)
2721 {
2722         int i;
2723
2724         for (i = 0; i < MLXSW_SP1_PORT_LINK_MODE_LEN; i++) {
2725                 if (ptys_eth_proto & mlxsw_sp1_port_link_mode[i].mask)
2726                         return mlxsw_sp1_port_link_mode[i].speed;
2727         }
2728
2729         return SPEED_UNKNOWN;
2730 }
2731
2732 static void
2733 mlxsw_sp1_from_ptys_speed_duplex(struct mlxsw_sp *mlxsw_sp, bool carrier_ok,
2734                                  u32 ptys_eth_proto,
2735                                  struct ethtool_link_ksettings *cmd)
2736 {
2737         cmd->base.speed = SPEED_UNKNOWN;
2738         cmd->base.duplex = DUPLEX_UNKNOWN;
2739
2740         if (!carrier_ok)
2741                 return;
2742
2743         cmd->base.speed = mlxsw_sp1_from_ptys_speed(mlxsw_sp, ptys_eth_proto);
2744         if (cmd->base.speed != SPEED_UNKNOWN)
2745                 cmd->base.duplex = DUPLEX_FULL;
2746 }
2747
2748 static u32
2749 mlxsw_sp1_to_ptys_advert_link(struct mlxsw_sp *mlxsw_sp, u8 width,
2750                               const struct ethtool_link_ksettings *cmd)
2751 {
2752         u32 ptys_proto = 0;
2753         int i;
2754
2755         for (i = 0; i < MLXSW_SP1_PORT_LINK_MODE_LEN; i++) {
2756                 if (test_bit(mlxsw_sp1_port_link_mode[i].mask_ethtool,
2757                              cmd->link_modes.advertising))
2758                         ptys_proto |= mlxsw_sp1_port_link_mode[i].mask;
2759         }
2760         return ptys_proto;
2761 }
2762
2763 static u32 mlxsw_sp1_to_ptys_speed(struct mlxsw_sp *mlxsw_sp, u8 width,
2764                                    u32 speed)
2765 {
2766         u32 ptys_proto = 0;
2767         int i;
2768
2769         for (i = 0; i < MLXSW_SP1_PORT_LINK_MODE_LEN; i++) {
2770                 if (speed == mlxsw_sp1_port_link_mode[i].speed)
2771                         ptys_proto |= mlxsw_sp1_port_link_mode[i].mask;
2772         }
2773         return ptys_proto;
2774 }
2775
2776 static u32
2777 mlxsw_sp1_to_ptys_upper_speed(struct mlxsw_sp *mlxsw_sp, u32 upper_speed)
2778 {
2779         u32 ptys_proto = 0;
2780         int i;
2781
2782         for (i = 0; i < MLXSW_SP1_PORT_LINK_MODE_LEN; i++) {
2783                 if (mlxsw_sp1_port_link_mode[i].speed <= upper_speed)
2784                         ptys_proto |= mlxsw_sp1_port_link_mode[i].mask;
2785         }
2786         return ptys_proto;
2787 }
2788
2789 static int
2790 mlxsw_sp1_port_speed_base(struct mlxsw_sp *mlxsw_sp, u8 local_port,
2791                           u32 *base_speed)
2792 {
2793         *base_speed = MLXSW_SP_PORT_BASE_SPEED_25G;
2794         return 0;
2795 }
2796
2797 static void
2798 mlxsw_sp1_reg_ptys_eth_pack(struct mlxsw_sp *mlxsw_sp, char *payload,
2799                             u8 local_port, u32 proto_admin, bool autoneg)
2800 {
2801         mlxsw_reg_ptys_eth_pack(payload, local_port, proto_admin, autoneg);
2802 }
2803
2804 static void
2805 mlxsw_sp1_reg_ptys_eth_unpack(struct mlxsw_sp *mlxsw_sp, char *payload,
2806                               u32 *p_eth_proto_cap, u32 *p_eth_proto_admin,
2807                               u32 *p_eth_proto_oper)
2808 {
2809         mlxsw_reg_ptys_eth_unpack(payload, p_eth_proto_cap, p_eth_proto_admin,
2810                                   p_eth_proto_oper);
2811 }
2812
2813 static const struct mlxsw_sp_port_type_speed_ops
2814 mlxsw_sp1_port_type_speed_ops = {
2815         .from_ptys_supported_port       = mlxsw_sp1_from_ptys_supported_port,
2816         .from_ptys_link                 = mlxsw_sp1_from_ptys_link,
2817         .from_ptys_speed                = mlxsw_sp1_from_ptys_speed,
2818         .from_ptys_speed_duplex         = mlxsw_sp1_from_ptys_speed_duplex,
2819         .to_ptys_advert_link            = mlxsw_sp1_to_ptys_advert_link,
2820         .to_ptys_speed                  = mlxsw_sp1_to_ptys_speed,
2821         .to_ptys_upper_speed            = mlxsw_sp1_to_ptys_upper_speed,
2822         .port_speed_base                = mlxsw_sp1_port_speed_base,
2823         .reg_ptys_eth_pack              = mlxsw_sp1_reg_ptys_eth_pack,
2824         .reg_ptys_eth_unpack            = mlxsw_sp1_reg_ptys_eth_unpack,
2825 };
2826
2827 static const enum ethtool_link_mode_bit_indices
2828 mlxsw_sp2_mask_ethtool_sgmii_100m[] = {
2829         ETHTOOL_LINK_MODE_100baseT_Full_BIT,
2830 };
2831
2832 #define MLXSW_SP2_MASK_ETHTOOL_SGMII_100M_LEN \
2833         ARRAY_SIZE(mlxsw_sp2_mask_ethtool_sgmii_100m)
2834
2835 static const enum ethtool_link_mode_bit_indices
2836 mlxsw_sp2_mask_ethtool_1000base_x_sgmii[] = {
2837         ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
2838         ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
2839 };
2840
2841 #define MLXSW_SP2_MASK_ETHTOOL_1000BASE_X_SGMII_LEN \
2842         ARRAY_SIZE(mlxsw_sp2_mask_ethtool_1000base_x_sgmii)
2843
2844 static const enum ethtool_link_mode_bit_indices
2845 mlxsw_sp2_mask_ethtool_2_5gbase_x_2_5gmii[] = {
2846         ETHTOOL_LINK_MODE_2500baseX_Full_BIT,
2847 };
2848
2849 #define MLXSW_SP2_MASK_ETHTOOL_2_5GBASE_X_2_5GMII_LEN \
2850         ARRAY_SIZE(mlxsw_sp2_mask_ethtool_2_5gbase_x_2_5gmii)
2851
2852 static const enum ethtool_link_mode_bit_indices
2853 mlxsw_sp2_mask_ethtool_5gbase_r[] = {
2854         ETHTOOL_LINK_MODE_5000baseT_Full_BIT,
2855 };
2856
2857 #define MLXSW_SP2_MASK_ETHTOOL_5GBASE_R_LEN \
2858         ARRAY_SIZE(mlxsw_sp2_mask_ethtool_5gbase_r)
2859
2860 static const enum ethtool_link_mode_bit_indices
2861 mlxsw_sp2_mask_ethtool_xfi_xaui_1_10g[] = {
2862         ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
2863         ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
2864         ETHTOOL_LINK_MODE_10000baseR_FEC_BIT,
2865         ETHTOOL_LINK_MODE_10000baseCR_Full_BIT,
2866         ETHTOOL_LINK_MODE_10000baseSR_Full_BIT,
2867         ETHTOOL_LINK_MODE_10000baseLR_Full_BIT,
2868         ETHTOOL_LINK_MODE_10000baseER_Full_BIT,
2869 };
2870
2871 #define MLXSW_SP2_MASK_ETHTOOL_XFI_XAUI_1_10G_LEN \
2872         ARRAY_SIZE(mlxsw_sp2_mask_ethtool_xfi_xaui_1_10g)
2873
2874 static const enum ethtool_link_mode_bit_indices
2875 mlxsw_sp2_mask_ethtool_xlaui_4_xlppi_4_40g[] = {
2876         ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT,
2877         ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT,
2878         ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT,
2879         ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT,
2880 };
2881
2882 #define MLXSW_SP2_MASK_ETHTOOL_XLAUI_4_XLPPI_4_40G_LEN \
2883         ARRAY_SIZE(mlxsw_sp2_mask_ethtool_xlaui_4_xlppi_4_40g)
2884
2885 static const enum ethtool_link_mode_bit_indices
2886 mlxsw_sp2_mask_ethtool_25gaui_1_25gbase_cr_kr[] = {
2887         ETHTOOL_LINK_MODE_25000baseCR_Full_BIT,
2888         ETHTOOL_LINK_MODE_25000baseKR_Full_BIT,
2889         ETHTOOL_LINK_MODE_25000baseSR_Full_BIT,
2890 };
2891
2892 #define MLXSW_SP2_MASK_ETHTOOL_25GAUI_1_25GBASE_CR_KR_LEN \
2893         ARRAY_SIZE(mlxsw_sp2_mask_ethtool_25gaui_1_25gbase_cr_kr)
2894
2895 static const enum ethtool_link_mode_bit_indices
2896 mlxsw_sp2_mask_ethtool_50gaui_2_laui_2_50gbase_cr2_kr2[] = {
2897         ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT,
2898         ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT,
2899         ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT,
2900 };
2901
2902 #define MLXSW_SP2_MASK_ETHTOOL_50GAUI_2_LAUI_2_50GBASE_CR2_KR2_LEN \
2903         ARRAY_SIZE(mlxsw_sp2_mask_ethtool_50gaui_2_laui_2_50gbase_cr2_kr2)
2904
2905 static const enum ethtool_link_mode_bit_indices
2906 mlxsw_sp2_mask_ethtool_50gaui_1_laui_1_50gbase_cr_kr[] = {
2907         ETHTOOL_LINK_MODE_50000baseKR_Full_BIT,
2908         ETHTOOL_LINK_MODE_50000baseSR_Full_BIT,
2909         ETHTOOL_LINK_MODE_50000baseCR_Full_BIT,
2910         ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT,
2911         ETHTOOL_LINK_MODE_50000baseDR_Full_BIT,
2912 };
2913
2914 #define MLXSW_SP2_MASK_ETHTOOL_50GAUI_1_LAUI_1_50GBASE_CR_KR_LEN \
2915         ARRAY_SIZE(mlxsw_sp2_mask_ethtool_50gaui_1_laui_1_50gbase_cr_kr)
2916
2917 static const enum ethtool_link_mode_bit_indices
2918 mlxsw_sp2_mask_ethtool_caui_4_100gbase_cr4_kr4[] = {
2919         ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT,
2920         ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT,
2921         ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT,
2922         ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT,
2923 };
2924
2925 #define MLXSW_SP2_MASK_ETHTOOL_CAUI_4_100GBASE_CR4_KR4_LEN \
2926         ARRAY_SIZE(mlxsw_sp2_mask_ethtool_caui_4_100gbase_cr4_kr4)
2927
2928 static const enum ethtool_link_mode_bit_indices
2929 mlxsw_sp2_mask_ethtool_100gaui_2_100gbase_cr2_kr2[] = {
2930         ETHTOOL_LINK_MODE_100000baseKR2_Full_BIT,
2931         ETHTOOL_LINK_MODE_100000baseSR2_Full_BIT,
2932         ETHTOOL_LINK_MODE_100000baseCR2_Full_BIT,
2933         ETHTOOL_LINK_MODE_100000baseLR2_ER2_FR2_Full_BIT,
2934         ETHTOOL_LINK_MODE_100000baseDR2_Full_BIT,
2935 };
2936
2937 #define MLXSW_SP2_MASK_ETHTOOL_100GAUI_2_100GBASE_CR2_KR2_LEN \
2938         ARRAY_SIZE(mlxsw_sp2_mask_ethtool_100gaui_2_100gbase_cr2_kr2)
2939
2940 static const enum ethtool_link_mode_bit_indices
2941 mlxsw_sp2_mask_ethtool_200gaui_4_200gbase_cr4_kr4[] = {
2942         ETHTOOL_LINK_MODE_200000baseKR4_Full_BIT,
2943         ETHTOOL_LINK_MODE_200000baseSR4_Full_BIT,
2944         ETHTOOL_LINK_MODE_200000baseLR4_ER4_FR4_Full_BIT,
2945         ETHTOOL_LINK_MODE_200000baseDR4_Full_BIT,
2946         ETHTOOL_LINK_MODE_200000baseCR4_Full_BIT,
2947 };
2948
2949 #define MLXSW_SP2_MASK_ETHTOOL_200GAUI_4_200GBASE_CR4_KR4_LEN \
2950         ARRAY_SIZE(mlxsw_sp2_mask_ethtool_200gaui_4_200gbase_cr4_kr4)
2951
2952 static const enum ethtool_link_mode_bit_indices
2953 mlxsw_sp2_mask_ethtool_400gaui_8[] = {
2954         ETHTOOL_LINK_MODE_400000baseKR8_Full_BIT,
2955         ETHTOOL_LINK_MODE_400000baseSR8_Full_BIT,
2956         ETHTOOL_LINK_MODE_400000baseLR8_ER8_FR8_Full_BIT,
2957         ETHTOOL_LINK_MODE_400000baseDR8_Full_BIT,
2958         ETHTOOL_LINK_MODE_400000baseCR8_Full_BIT,
2959 };
2960
2961 #define MLXSW_SP2_MASK_ETHTOOL_400GAUI_8_LEN \
2962         ARRAY_SIZE(mlxsw_sp2_mask_ethtool_400gaui_8)
2963
2964 #define MLXSW_SP_PORT_MASK_WIDTH_1X     BIT(0)
2965 #define MLXSW_SP_PORT_MASK_WIDTH_2X     BIT(1)
2966 #define MLXSW_SP_PORT_MASK_WIDTH_4X     BIT(2)
2967 #define MLXSW_SP_PORT_MASK_WIDTH_8X     BIT(3)
2968
2969 static u8 mlxsw_sp_port_mask_width_get(u8 width)
2970 {
2971         switch (width) {
2972         case 1:
2973                 return MLXSW_SP_PORT_MASK_WIDTH_1X;
2974         case 2:
2975                 return MLXSW_SP_PORT_MASK_WIDTH_2X;
2976         case 4:
2977                 return MLXSW_SP_PORT_MASK_WIDTH_4X;
2978         case 8:
2979                 return MLXSW_SP_PORT_MASK_WIDTH_8X;
2980         default:
2981                 WARN_ON_ONCE(1);
2982                 return 0;
2983         }
2984 }
2985
2986 struct mlxsw_sp2_port_link_mode {
2987         const enum ethtool_link_mode_bit_indices *mask_ethtool;
2988         int m_ethtool_len;
2989         u32 mask;
2990         u32 speed;
2991         u8 mask_width;
2992 };
2993
2994 static const struct mlxsw_sp2_port_link_mode mlxsw_sp2_port_link_mode[] = {
2995         {
2996                 .mask           = MLXSW_REG_PTYS_EXT_ETH_SPEED_SGMII_100M,
2997                 .mask_ethtool   = mlxsw_sp2_mask_ethtool_sgmii_100m,
2998                 .m_ethtool_len  = MLXSW_SP2_MASK_ETHTOOL_SGMII_100M_LEN,
2999                 .mask_width     = MLXSW_SP_PORT_MASK_WIDTH_1X |
3000                                   MLXSW_SP_PORT_MASK_WIDTH_2X |
3001                                   MLXSW_SP_PORT_MASK_WIDTH_4X |
3002                                   MLXSW_SP_PORT_MASK_WIDTH_8X,
3003                 .speed          = SPEED_100,
3004         },
3005         {
3006                 .mask           = MLXSW_REG_PTYS_EXT_ETH_SPEED_1000BASE_X_SGMII,
3007                 .mask_ethtool   = mlxsw_sp2_mask_ethtool_1000base_x_sgmii,
3008                 .m_ethtool_len  = MLXSW_SP2_MASK_ETHTOOL_1000BASE_X_SGMII_LEN,
3009                 .mask_width     = MLXSW_SP_PORT_MASK_WIDTH_1X |
3010                                   MLXSW_SP_PORT_MASK_WIDTH_2X |
3011                                   MLXSW_SP_PORT_MASK_WIDTH_4X |
3012                                   MLXSW_SP_PORT_MASK_WIDTH_8X,
3013                 .speed          = SPEED_1000,
3014         },
3015         {
3016                 .mask           = MLXSW_REG_PTYS_EXT_ETH_SPEED_2_5GBASE_X_2_5GMII,
3017                 .mask_ethtool   = mlxsw_sp2_mask_ethtool_2_5gbase_x_2_5gmii,
3018                 .m_ethtool_len  = MLXSW_SP2_MASK_ETHTOOL_2_5GBASE_X_2_5GMII_LEN,
3019                 .mask_width     = MLXSW_SP_PORT_MASK_WIDTH_1X |
3020                                   MLXSW_SP_PORT_MASK_WIDTH_2X |
3021                                   MLXSW_SP_PORT_MASK_WIDTH_4X |
3022                                   MLXSW_SP_PORT_MASK_WIDTH_8X,
3023                 .speed          = SPEED_2500,
3024         },
3025         {
3026                 .mask           = MLXSW_REG_PTYS_EXT_ETH_SPEED_5GBASE_R,
3027                 .mask_ethtool   = mlxsw_sp2_mask_ethtool_5gbase_r,
3028                 .m_ethtool_len  = MLXSW_SP2_MASK_ETHTOOL_5GBASE_R_LEN,
3029                 .mask_width     = MLXSW_SP_PORT_MASK_WIDTH_1X |
3030                                   MLXSW_SP_PORT_MASK_WIDTH_2X |
3031                                   MLXSW_SP_PORT_MASK_WIDTH_4X |
3032                                   MLXSW_SP_PORT_MASK_WIDTH_8X,
3033                 .speed          = SPEED_5000,
3034         },
3035         {
3036                 .mask           = MLXSW_REG_PTYS_EXT_ETH_SPEED_XFI_XAUI_1_10G,
3037                 .mask_ethtool   = mlxsw_sp2_mask_ethtool_xfi_xaui_1_10g,
3038                 .m_ethtool_len  = MLXSW_SP2_MASK_ETHTOOL_XFI_XAUI_1_10G_LEN,
3039                 .mask_width     = MLXSW_SP_PORT_MASK_WIDTH_1X |
3040                                   MLXSW_SP_PORT_MASK_WIDTH_2X |
3041                                   MLXSW_SP_PORT_MASK_WIDTH_4X |
3042                                   MLXSW_SP_PORT_MASK_WIDTH_8X,
3043                 .speed          = SPEED_10000,
3044         },
3045         {
3046                 .mask           = MLXSW_REG_PTYS_EXT_ETH_SPEED_XLAUI_4_XLPPI_4_40G,
3047                 .mask_ethtool   = mlxsw_sp2_mask_ethtool_xlaui_4_xlppi_4_40g,
3048                 .m_ethtool_len  = MLXSW_SP2_MASK_ETHTOOL_XLAUI_4_XLPPI_4_40G_LEN,
3049                 .mask_width     = MLXSW_SP_PORT_MASK_WIDTH_4X |
3050                                   MLXSW_SP_PORT_MASK_WIDTH_8X,
3051                 .speed          = SPEED_40000,
3052         },
3053         {
3054                 .mask           = MLXSW_REG_PTYS_EXT_ETH_SPEED_25GAUI_1_25GBASE_CR_KR,
3055                 .mask_ethtool   = mlxsw_sp2_mask_ethtool_25gaui_1_25gbase_cr_kr,
3056                 .m_ethtool_len  = MLXSW_SP2_MASK_ETHTOOL_25GAUI_1_25GBASE_CR_KR_LEN,
3057                 .mask_width     = MLXSW_SP_PORT_MASK_WIDTH_1X |
3058                                   MLXSW_SP_PORT_MASK_WIDTH_2X |
3059                                   MLXSW_SP_PORT_MASK_WIDTH_4X |
3060                                   MLXSW_SP_PORT_MASK_WIDTH_8X,
3061                 .speed          = SPEED_25000,
3062         },
3063         {
3064                 .mask           = MLXSW_REG_PTYS_EXT_ETH_SPEED_50GAUI_2_LAUI_2_50GBASE_CR2_KR2,
3065                 .mask_ethtool   = mlxsw_sp2_mask_ethtool_50gaui_2_laui_2_50gbase_cr2_kr2,
3066                 .m_ethtool_len  = MLXSW_SP2_MASK_ETHTOOL_50GAUI_2_LAUI_2_50GBASE_CR2_KR2_LEN,
3067                 .mask_width     = MLXSW_SP_PORT_MASK_WIDTH_2X |
3068                                   MLXSW_SP_PORT_MASK_WIDTH_4X |
3069                                   MLXSW_SP_PORT_MASK_WIDTH_8X,
3070                 .speed          = SPEED_50000,
3071         },
3072         {
3073                 .mask           = MLXSW_REG_PTYS_EXT_ETH_SPEED_50GAUI_1_LAUI_1_50GBASE_CR_KR,
3074                 .mask_ethtool   = mlxsw_sp2_mask_ethtool_50gaui_1_laui_1_50gbase_cr_kr,
3075                 .m_ethtool_len  = MLXSW_SP2_MASK_ETHTOOL_50GAUI_1_LAUI_1_50GBASE_CR_KR_LEN,
3076                 .mask_width     = MLXSW_SP_PORT_MASK_WIDTH_1X,
3077                 .speed          = SPEED_50000,
3078         },
3079         {
3080                 .mask           = MLXSW_REG_PTYS_EXT_ETH_SPEED_CAUI_4_100GBASE_CR4_KR4,
3081                 .mask_ethtool   = mlxsw_sp2_mask_ethtool_caui_4_100gbase_cr4_kr4,
3082                 .m_ethtool_len  = MLXSW_SP2_MASK_ETHTOOL_CAUI_4_100GBASE_CR4_KR4_LEN,
3083                 .mask_width     = MLXSW_SP_PORT_MASK_WIDTH_4X |
3084                                   MLXSW_SP_PORT_MASK_WIDTH_8X,
3085                 .speed          = SPEED_100000,
3086         },
3087         {
3088                 .mask           = MLXSW_REG_PTYS_EXT_ETH_SPEED_100GAUI_2_100GBASE_CR2_KR2,
3089                 .mask_ethtool   = mlxsw_sp2_mask_ethtool_100gaui_2_100gbase_cr2_kr2,
3090                 .m_ethtool_len  = MLXSW_SP2_MASK_ETHTOOL_100GAUI_2_100GBASE_CR2_KR2_LEN,
3091                 .mask_width     = MLXSW_SP_PORT_MASK_WIDTH_2X,
3092                 .speed          = SPEED_100000,
3093         },
3094         {
3095                 .mask           = MLXSW_REG_PTYS_EXT_ETH_SPEED_200GAUI_4_200GBASE_CR4_KR4,
3096                 .mask_ethtool   = mlxsw_sp2_mask_ethtool_200gaui_4_200gbase_cr4_kr4,
3097                 .m_ethtool_len  = MLXSW_SP2_MASK_ETHTOOL_200GAUI_4_200GBASE_CR4_KR4_LEN,
3098                 .mask_width     = MLXSW_SP_PORT_MASK_WIDTH_4X |
3099                                   MLXSW_SP_PORT_MASK_WIDTH_8X,
3100                 .speed          = SPEED_200000,
3101         },
3102         {
3103                 .mask           = MLXSW_REG_PTYS_EXT_ETH_SPEED_400GAUI_8,
3104                 .mask_ethtool   = mlxsw_sp2_mask_ethtool_400gaui_8,
3105                 .m_ethtool_len  = MLXSW_SP2_MASK_ETHTOOL_400GAUI_8_LEN,
3106                 .mask_width     = MLXSW_SP_PORT_MASK_WIDTH_8X,
3107                 .speed          = SPEED_400000,
3108         },
3109 };
3110
3111 #define MLXSW_SP2_PORT_LINK_MODE_LEN ARRAY_SIZE(mlxsw_sp2_port_link_mode)
3112
3113 static void
3114 mlxsw_sp2_from_ptys_supported_port(struct mlxsw_sp *mlxsw_sp,
3115                                    u32 ptys_eth_proto,
3116                                    struct ethtool_link_ksettings *cmd)
3117 {
3118         ethtool_link_ksettings_add_link_mode(cmd, supported, FIBRE);
3119         ethtool_link_ksettings_add_link_mode(cmd, supported, Backplane);
3120 }
3121
3122 static void
3123 mlxsw_sp2_set_bit_ethtool(const struct mlxsw_sp2_port_link_mode *link_mode,
3124                           unsigned long *mode)
3125 {
3126         int i;
3127
3128         for (i = 0; i < link_mode->m_ethtool_len; i++)
3129                 __set_bit(link_mode->mask_ethtool[i], mode);
3130 }
3131
3132 static void
3133 mlxsw_sp2_from_ptys_link(struct mlxsw_sp *mlxsw_sp, u32 ptys_eth_proto,
3134                          u8 width, unsigned long *mode)
3135 {
3136         u8 mask_width = mlxsw_sp_port_mask_width_get(width);
3137         int i;
3138
3139         for (i = 0; i < MLXSW_SP2_PORT_LINK_MODE_LEN; i++) {
3140                 if ((ptys_eth_proto & mlxsw_sp2_port_link_mode[i].mask) &&
3141                     (mask_width & mlxsw_sp2_port_link_mode[i].mask_width))
3142                         mlxsw_sp2_set_bit_ethtool(&mlxsw_sp2_port_link_mode[i],
3143                                                   mode);
3144         }
3145 }
3146
3147 static u32
3148 mlxsw_sp2_from_ptys_speed(struct mlxsw_sp *mlxsw_sp, u32 ptys_eth_proto)
3149 {
3150         int i;
3151
3152         for (i = 0; i < MLXSW_SP2_PORT_LINK_MODE_LEN; i++) {
3153                 if (ptys_eth_proto & mlxsw_sp2_port_link_mode[i].mask)
3154                         return mlxsw_sp2_port_link_mode[i].speed;
3155         }
3156
3157         return SPEED_UNKNOWN;
3158 }
3159
3160 static void
3161 mlxsw_sp2_from_ptys_speed_duplex(struct mlxsw_sp *mlxsw_sp, bool carrier_ok,
3162                                  u32 ptys_eth_proto,
3163                                  struct ethtool_link_ksettings *cmd)
3164 {
3165         cmd->base.speed = SPEED_UNKNOWN;
3166         cmd->base.duplex = DUPLEX_UNKNOWN;
3167
3168         if (!carrier_ok)
3169                 return;
3170
3171         cmd->base.speed = mlxsw_sp2_from_ptys_speed(mlxsw_sp, ptys_eth_proto);
3172         if (cmd->base.speed != SPEED_UNKNOWN)
3173                 cmd->base.duplex = DUPLEX_FULL;
3174 }
3175
3176 static bool
3177 mlxsw_sp2_test_bit_ethtool(const struct mlxsw_sp2_port_link_mode *link_mode,
3178                            const unsigned long *mode)
3179 {
3180         int cnt = 0;
3181         int i;
3182
3183         for (i = 0; i < link_mode->m_ethtool_len; i++) {
3184                 if (test_bit(link_mode->mask_ethtool[i], mode))
3185                         cnt++;
3186         }
3187
3188         return cnt == link_mode->m_ethtool_len;
3189 }
3190
3191 static u32
3192 mlxsw_sp2_to_ptys_advert_link(struct mlxsw_sp *mlxsw_sp, u8 width,
3193                               const struct ethtool_link_ksettings *cmd)
3194 {
3195         u8 mask_width = mlxsw_sp_port_mask_width_get(width);
3196         u32 ptys_proto = 0;
3197         int i;
3198
3199         for (i = 0; i < MLXSW_SP2_PORT_LINK_MODE_LEN; i++) {
3200                 if ((mask_width & mlxsw_sp2_port_link_mode[i].mask_width) &&
3201                     mlxsw_sp2_test_bit_ethtool(&mlxsw_sp2_port_link_mode[i],
3202                                                cmd->link_modes.advertising))
3203                         ptys_proto |= mlxsw_sp2_port_link_mode[i].mask;
3204         }
3205         return ptys_proto;
3206 }
3207
3208 static u32 mlxsw_sp2_to_ptys_speed(struct mlxsw_sp *mlxsw_sp,
3209                                    u8 width, u32 speed)
3210 {
3211         u8 mask_width = mlxsw_sp_port_mask_width_get(width);
3212         u32 ptys_proto = 0;
3213         int i;
3214
3215         for (i = 0; i < MLXSW_SP2_PORT_LINK_MODE_LEN; i++) {
3216                 if ((speed == mlxsw_sp2_port_link_mode[i].speed) &&
3217                     (mask_width & mlxsw_sp2_port_link_mode[i].mask_width))
3218                         ptys_proto |= mlxsw_sp2_port_link_mode[i].mask;
3219         }
3220         return ptys_proto;
3221 }
3222
3223 static u32
3224 mlxsw_sp2_to_ptys_upper_speed(struct mlxsw_sp *mlxsw_sp, u32 upper_speed)
3225 {
3226         u32 ptys_proto = 0;
3227         int i;
3228
3229         for (i = 0; i < MLXSW_SP2_PORT_LINK_MODE_LEN; i++) {
3230                 if (mlxsw_sp2_port_link_mode[i].speed <= upper_speed)
3231                         ptys_proto |= mlxsw_sp2_port_link_mode[i].mask;
3232         }
3233         return ptys_proto;
3234 }
3235
3236 static int
3237 mlxsw_sp2_port_speed_base(struct mlxsw_sp *mlxsw_sp, u8 local_port,
3238                           u32 *base_speed)
3239 {
3240         char ptys_pl[MLXSW_REG_PTYS_LEN];
3241         u32 eth_proto_cap;
3242         int err;
3243
3244         /* In Spectrum-2, the speed of 1x can change from port to port, so query
3245          * it from firmware.
3246          */
3247         mlxsw_reg_ptys_ext_eth_pack(ptys_pl, local_port, 0, false);
3248         err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl);
3249         if (err)
3250                 return err;
3251         mlxsw_reg_ptys_ext_eth_unpack(ptys_pl, &eth_proto_cap, NULL, NULL);
3252
3253         if (eth_proto_cap &
3254             MLXSW_REG_PTYS_EXT_ETH_SPEED_50GAUI_1_LAUI_1_50GBASE_CR_KR) {
3255                 *base_speed = MLXSW_SP_PORT_BASE_SPEED_50G;
3256                 return 0;
3257         }
3258
3259         if (eth_proto_cap &
3260             MLXSW_REG_PTYS_EXT_ETH_SPEED_25GAUI_1_25GBASE_CR_KR) {
3261                 *base_speed = MLXSW_SP_PORT_BASE_SPEED_25G;
3262                 return 0;
3263         }
3264
3265         return -EIO;
3266 }
3267
3268 static void
3269 mlxsw_sp2_reg_ptys_eth_pack(struct mlxsw_sp *mlxsw_sp, char *payload,
3270                             u8 local_port, u32 proto_admin,
3271                             bool autoneg)
3272 {
3273         mlxsw_reg_ptys_ext_eth_pack(payload, local_port, proto_admin, autoneg);
3274 }
3275
3276 static void
3277 mlxsw_sp2_reg_ptys_eth_unpack(struct mlxsw_sp *mlxsw_sp, char *payload,
3278                               u32 *p_eth_proto_cap, u32 *p_eth_proto_admin,
3279                               u32 *p_eth_proto_oper)
3280 {
3281         mlxsw_reg_ptys_ext_eth_unpack(payload, p_eth_proto_cap,
3282                                       p_eth_proto_admin, p_eth_proto_oper);
3283 }
3284
3285 static const struct mlxsw_sp_port_type_speed_ops
3286 mlxsw_sp2_port_type_speed_ops = {
3287         .from_ptys_supported_port       = mlxsw_sp2_from_ptys_supported_port,
3288         .from_ptys_link                 = mlxsw_sp2_from_ptys_link,
3289         .from_ptys_speed                = mlxsw_sp2_from_ptys_speed,
3290         .from_ptys_speed_duplex         = mlxsw_sp2_from_ptys_speed_duplex,
3291         .to_ptys_advert_link            = mlxsw_sp2_to_ptys_advert_link,
3292         .to_ptys_speed                  = mlxsw_sp2_to_ptys_speed,
3293         .to_ptys_upper_speed            = mlxsw_sp2_to_ptys_upper_speed,
3294         .port_speed_base                = mlxsw_sp2_port_speed_base,
3295         .reg_ptys_eth_pack              = mlxsw_sp2_reg_ptys_eth_pack,
3296         .reg_ptys_eth_unpack            = mlxsw_sp2_reg_ptys_eth_unpack,
3297 };
3298
3299 static void
3300 mlxsw_sp_port_get_link_supported(struct mlxsw_sp *mlxsw_sp, u32 eth_proto_cap,
3301                                  u8 width, struct ethtool_link_ksettings *cmd)
3302 {
3303         const struct mlxsw_sp_port_type_speed_ops *ops;
3304
3305         ops = mlxsw_sp->port_type_speed_ops;
3306
3307         ethtool_link_ksettings_add_link_mode(cmd, supported, Asym_Pause);
3308         ethtool_link_ksettings_add_link_mode(cmd, supported, Autoneg);
3309         ethtool_link_ksettings_add_link_mode(cmd, supported, Pause);
3310
3311         ops->from_ptys_supported_port(mlxsw_sp, eth_proto_cap, cmd);
3312         ops->from_ptys_link(mlxsw_sp, eth_proto_cap, width,
3313                             cmd->link_modes.supported);
3314 }
3315
3316 static void
3317 mlxsw_sp_port_get_link_advertise(struct mlxsw_sp *mlxsw_sp,
3318                                  u32 eth_proto_admin, bool autoneg, u8 width,
3319                                  struct ethtool_link_ksettings *cmd)
3320 {
3321         const struct mlxsw_sp_port_type_speed_ops *ops;
3322
3323         ops = mlxsw_sp->port_type_speed_ops;
3324
3325         if (!autoneg)
3326                 return;
3327
3328         ethtool_link_ksettings_add_link_mode(cmd, advertising, Autoneg);
3329         ops->from_ptys_link(mlxsw_sp, eth_proto_admin, width,
3330                             cmd->link_modes.advertising);
3331 }
3332
3333 static u8
3334 mlxsw_sp_port_connector_port(enum mlxsw_reg_ptys_connector_type connector_type)
3335 {
3336         switch (connector_type) {
3337         case MLXSW_REG_PTYS_CONNECTOR_TYPE_UNKNOWN_OR_NO_CONNECTOR:
3338                 return PORT_OTHER;
3339         case MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_NONE:
3340                 return PORT_NONE;
3341         case MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_TP:
3342                 return PORT_TP;
3343         case MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_AUI:
3344                 return PORT_AUI;
3345         case MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_BNC:
3346                 return PORT_BNC;
3347         case MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_MII:
3348                 return PORT_MII;
3349         case MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_FIBRE:
3350                 return PORT_FIBRE;
3351         case MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_DA:
3352                 return PORT_DA;
3353         case MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_OTHER:
3354                 return PORT_OTHER;
3355         default:
3356                 WARN_ON_ONCE(1);
3357                 return PORT_OTHER;
3358         }
3359 }
3360
3361 static int mlxsw_sp_port_get_link_ksettings(struct net_device *dev,
3362                                             struct ethtool_link_ksettings *cmd)
3363 {
3364         u32 eth_proto_cap, eth_proto_admin, eth_proto_oper;
3365         struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
3366         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
3367         const struct mlxsw_sp_port_type_speed_ops *ops;
3368         char ptys_pl[MLXSW_REG_PTYS_LEN];
3369         u8 connector_type;
3370         bool autoneg;
3371         int err;
3372
3373         ops = mlxsw_sp->port_type_speed_ops;
3374
3375         autoneg = mlxsw_sp_port->link.autoneg;
3376         ops->reg_ptys_eth_pack(mlxsw_sp, ptys_pl, mlxsw_sp_port->local_port,
3377                                0, false);
3378         err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl);
3379         if (err)
3380                 return err;
3381         ops->reg_ptys_eth_unpack(mlxsw_sp, ptys_pl, &eth_proto_cap,
3382                                  &eth_proto_admin, &eth_proto_oper);
3383
3384         mlxsw_sp_port_get_link_supported(mlxsw_sp, eth_proto_cap,
3385                                          mlxsw_sp_port->mapping.width, cmd);
3386
3387         mlxsw_sp_port_get_link_advertise(mlxsw_sp, eth_proto_admin, autoneg,
3388                                          mlxsw_sp_port->mapping.width, cmd);
3389
3390         cmd->base.autoneg = autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE;
3391         connector_type = mlxsw_reg_ptys_connector_type_get(ptys_pl);
3392         cmd->base.port = mlxsw_sp_port_connector_port(connector_type);
3393         ops->from_ptys_speed_duplex(mlxsw_sp, netif_carrier_ok(dev),
3394                                     eth_proto_oper, cmd);
3395
3396         return 0;
3397 }
3398
3399 static int
3400 mlxsw_sp_port_set_link_ksettings(struct net_device *dev,
3401                                  const struct ethtool_link_ksettings *cmd)
3402 {
3403         struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
3404         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
3405         const struct mlxsw_sp_port_type_speed_ops *ops;
3406         char ptys_pl[MLXSW_REG_PTYS_LEN];
3407         u32 eth_proto_cap, eth_proto_new;
3408         bool autoneg;
3409         int err;
3410
3411         ops = mlxsw_sp->port_type_speed_ops;
3412
3413         ops->reg_ptys_eth_pack(mlxsw_sp, ptys_pl, mlxsw_sp_port->local_port,
3414                                0, false);
3415         err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl);
3416         if (err)
3417                 return err;
3418         ops->reg_ptys_eth_unpack(mlxsw_sp, ptys_pl, &eth_proto_cap, NULL, NULL);
3419
3420         autoneg = cmd->base.autoneg == AUTONEG_ENABLE;
3421         eth_proto_new = autoneg ?
3422                 ops->to_ptys_advert_link(mlxsw_sp, mlxsw_sp_port->mapping.width,
3423                                          cmd) :
3424                 ops->to_ptys_speed(mlxsw_sp, mlxsw_sp_port->mapping.width,
3425                                    cmd->base.speed);
3426
3427         eth_proto_new = eth_proto_new & eth_proto_cap;
3428         if (!eth_proto_new) {
3429                 netdev_err(dev, "No supported speed requested\n");
3430                 return -EINVAL;
3431         }
3432
3433         ops->reg_ptys_eth_pack(mlxsw_sp, ptys_pl, mlxsw_sp_port->local_port,
3434                                eth_proto_new, autoneg);
3435         err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl);
3436         if (err)
3437                 return err;
3438
3439         mlxsw_sp_port->link.autoneg = autoneg;
3440
3441         if (!netif_running(dev))
3442                 return 0;
3443
3444         mlxsw_sp_port_admin_status_set(mlxsw_sp_port, false);
3445         mlxsw_sp_port_admin_status_set(mlxsw_sp_port, true);
3446
3447         return 0;
3448 }
3449
3450 static int mlxsw_sp_get_module_info(struct net_device *netdev,
3451                                     struct ethtool_modinfo *modinfo)
3452 {
3453         struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(netdev);
3454         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
3455         int err;
3456
3457         err = mlxsw_env_get_module_info(mlxsw_sp->core,
3458                                         mlxsw_sp_port->mapping.module,
3459                                         modinfo);
3460
3461         return err;
3462 }
3463
3464 static int mlxsw_sp_get_module_eeprom(struct net_device *netdev,
3465                                       struct ethtool_eeprom *ee,
3466                                       u8 *data)
3467 {
3468         struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(netdev);
3469         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
3470         int err;
3471
3472         err = mlxsw_env_get_module_eeprom(netdev, mlxsw_sp->core,
3473                                           mlxsw_sp_port->mapping.module, ee,
3474                                           data);
3475
3476         return err;
3477 }
3478
3479 static int
3480 mlxsw_sp_get_ts_info(struct net_device *netdev, struct ethtool_ts_info *info)
3481 {
3482         struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(netdev);
3483         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
3484
3485         return mlxsw_sp->ptp_ops->get_ts_info(mlxsw_sp, info);
3486 }
3487
3488 static const struct ethtool_ops mlxsw_sp_port_ethtool_ops = {
3489         .get_drvinfo            = mlxsw_sp_port_get_drvinfo,
3490         .get_link               = ethtool_op_get_link,
3491         .get_pauseparam         = mlxsw_sp_port_get_pauseparam,
3492         .set_pauseparam         = mlxsw_sp_port_set_pauseparam,
3493         .get_strings            = mlxsw_sp_port_get_strings,
3494         .set_phys_id            = mlxsw_sp_port_set_phys_id,
3495         .get_ethtool_stats      = mlxsw_sp_port_get_stats,
3496         .get_sset_count         = mlxsw_sp_port_get_sset_count,
3497         .get_link_ksettings     = mlxsw_sp_port_get_link_ksettings,
3498         .set_link_ksettings     = mlxsw_sp_port_set_link_ksettings,
3499         .get_module_info        = mlxsw_sp_get_module_info,
3500         .get_module_eeprom      = mlxsw_sp_get_module_eeprom,
3501         .get_ts_info            = mlxsw_sp_get_ts_info,
3502 };
3503
3504 static int
3505 mlxsw_sp_port_speed_by_width_set(struct mlxsw_sp_port *mlxsw_sp_port)
3506 {
3507         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
3508         const struct mlxsw_sp_port_type_speed_ops *ops;
3509         char ptys_pl[MLXSW_REG_PTYS_LEN];
3510         u32 eth_proto_admin;
3511         u32 upper_speed;
3512         u32 base_speed;
3513         int err;
3514
3515         ops = mlxsw_sp->port_type_speed_ops;
3516
3517         err = ops->port_speed_base(mlxsw_sp, mlxsw_sp_port->local_port,
3518                                    &base_speed);
3519         if (err)
3520                 return err;
3521         upper_speed = base_speed * mlxsw_sp_port->mapping.width;
3522
3523         eth_proto_admin = ops->to_ptys_upper_speed(mlxsw_sp, upper_speed);
3524         ops->reg_ptys_eth_pack(mlxsw_sp, ptys_pl, mlxsw_sp_port->local_port,
3525                                eth_proto_admin, mlxsw_sp_port->link.autoneg);
3526         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl);
3527 }
3528
3529 int mlxsw_sp_port_speed_get(struct mlxsw_sp_port *mlxsw_sp_port, u32 *speed)
3530 {
3531         const struct mlxsw_sp_port_type_speed_ops *port_type_speed_ops;
3532         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
3533         char ptys_pl[MLXSW_REG_PTYS_LEN];
3534         u32 eth_proto_oper;
3535         int err;
3536
3537         port_type_speed_ops = mlxsw_sp->port_type_speed_ops;
3538         port_type_speed_ops->reg_ptys_eth_pack(mlxsw_sp, ptys_pl,
3539                                                mlxsw_sp_port->local_port, 0,
3540                                                false);
3541         err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl);
3542         if (err)
3543                 return err;
3544         port_type_speed_ops->reg_ptys_eth_unpack(mlxsw_sp, ptys_pl, NULL, NULL,
3545                                                  &eth_proto_oper);
3546         *speed = port_type_speed_ops->from_ptys_speed(mlxsw_sp, eth_proto_oper);
3547         return 0;
3548 }
3549
3550 int mlxsw_sp_port_ets_set(struct mlxsw_sp_port *mlxsw_sp_port,
3551                           enum mlxsw_reg_qeec_hr hr, u8 index, u8 next_index,
3552                           bool dwrr, u8 dwrr_weight)
3553 {
3554         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
3555         char qeec_pl[MLXSW_REG_QEEC_LEN];
3556
3557         mlxsw_reg_qeec_pack(qeec_pl, mlxsw_sp_port->local_port, hr, index,
3558                             next_index);
3559         mlxsw_reg_qeec_de_set(qeec_pl, true);
3560         mlxsw_reg_qeec_dwrr_set(qeec_pl, dwrr);
3561         mlxsw_reg_qeec_dwrr_weight_set(qeec_pl, dwrr_weight);
3562         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(qeec), qeec_pl);
3563 }
3564
3565 int mlxsw_sp_port_ets_maxrate_set(struct mlxsw_sp_port *mlxsw_sp_port,
3566                                   enum mlxsw_reg_qeec_hr hr, u8 index,
3567                                   u8 next_index, u32 maxrate, u8 burst_size)
3568 {
3569         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
3570         char qeec_pl[MLXSW_REG_QEEC_LEN];
3571
3572         mlxsw_reg_qeec_pack(qeec_pl, mlxsw_sp_port->local_port, hr, index,
3573                             next_index);
3574         mlxsw_reg_qeec_mase_set(qeec_pl, true);
3575         mlxsw_reg_qeec_max_shaper_rate_set(qeec_pl, maxrate);
3576         mlxsw_reg_qeec_max_shaper_bs_set(qeec_pl, burst_size);
3577         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(qeec), qeec_pl);
3578 }
3579
3580 static int mlxsw_sp_port_min_bw_set(struct mlxsw_sp_port *mlxsw_sp_port,
3581                                     enum mlxsw_reg_qeec_hr hr, u8 index,
3582                                     u8 next_index, u32 minrate)
3583 {
3584         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
3585         char qeec_pl[MLXSW_REG_QEEC_LEN];
3586
3587         mlxsw_reg_qeec_pack(qeec_pl, mlxsw_sp_port->local_port, hr, index,
3588                             next_index);
3589         mlxsw_reg_qeec_mise_set(qeec_pl, true);
3590         mlxsw_reg_qeec_min_shaper_rate_set(qeec_pl, minrate);
3591
3592         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(qeec), qeec_pl);
3593 }
3594
3595 int mlxsw_sp_port_prio_tc_set(struct mlxsw_sp_port *mlxsw_sp_port,
3596                               u8 switch_prio, u8 tclass)
3597 {
3598         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
3599         char qtct_pl[MLXSW_REG_QTCT_LEN];
3600
3601         mlxsw_reg_qtct_pack(qtct_pl, mlxsw_sp_port->local_port, switch_prio,
3602                             tclass);
3603         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(qtct), qtct_pl);
3604 }
3605
3606 static int mlxsw_sp_port_ets_init(struct mlxsw_sp_port *mlxsw_sp_port)
3607 {
3608         int err, i;
3609
3610         /* Setup the elements hierarcy, so that each TC is linked to
3611          * one subgroup, which are all member in the same group.
3612          */
3613         err = mlxsw_sp_port_ets_set(mlxsw_sp_port,
3614                                     MLXSW_REG_QEEC_HR_GROUP, 0, 0, false, 0);
3615         if (err)
3616                 return err;
3617         for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
3618                 err = mlxsw_sp_port_ets_set(mlxsw_sp_port,
3619                                             MLXSW_REG_QEEC_HR_SUBGROUP, i,
3620                                             0, false, 0);
3621                 if (err)
3622                         return err;
3623         }
3624         for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
3625                 err = mlxsw_sp_port_ets_set(mlxsw_sp_port,
3626                                             MLXSW_REG_QEEC_HR_TC, i, i,
3627                                             false, 0);
3628                 if (err)
3629                         return err;
3630
3631                 err = mlxsw_sp_port_ets_set(mlxsw_sp_port,
3632                                             MLXSW_REG_QEEC_HR_TC,
3633                                             i + 8, i,
3634                                             true, 100);
3635                 if (err)
3636                         return err;
3637         }
3638
3639         /* Make sure the max shaper is disabled in all hierarchies that support
3640          * it. Note that this disables ptps (PTP shaper), but that is intended
3641          * for the initial configuration.
3642          */
3643         err = mlxsw_sp_port_ets_maxrate_set(mlxsw_sp_port,
3644                                             MLXSW_REG_QEEC_HR_PORT, 0, 0,
3645                                             MLXSW_REG_QEEC_MAS_DIS, 0);
3646         if (err)
3647                 return err;
3648         for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
3649                 err = mlxsw_sp_port_ets_maxrate_set(mlxsw_sp_port,
3650                                                     MLXSW_REG_QEEC_HR_SUBGROUP,
3651                                                     i, 0,
3652                                                     MLXSW_REG_QEEC_MAS_DIS, 0);
3653                 if (err)
3654                         return err;
3655         }
3656         for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
3657                 err = mlxsw_sp_port_ets_maxrate_set(mlxsw_sp_port,
3658                                                     MLXSW_REG_QEEC_HR_TC,
3659                                                     i, i,
3660                                                     MLXSW_REG_QEEC_MAS_DIS, 0);
3661                 if (err)
3662                         return err;
3663
3664                 err = mlxsw_sp_port_ets_maxrate_set(mlxsw_sp_port,
3665                                                     MLXSW_REG_QEEC_HR_TC,
3666                                                     i + 8, i,
3667                                                     MLXSW_REG_QEEC_MAS_DIS, 0);
3668                 if (err)
3669                         return err;
3670         }
3671
3672         /* Configure the min shaper for multicast TCs. */
3673         for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
3674                 err = mlxsw_sp_port_min_bw_set(mlxsw_sp_port,
3675                                                MLXSW_REG_QEEC_HR_TC,
3676                                                i + 8, i,
3677                                                MLXSW_REG_QEEC_MIS_MIN);
3678                 if (err)
3679                         return err;
3680         }
3681
3682         /* Map all priorities to traffic class 0. */
3683         for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
3684                 err = mlxsw_sp_port_prio_tc_set(mlxsw_sp_port, i, 0);
3685                 if (err)
3686                         return err;
3687         }
3688
3689         return 0;
3690 }
3691
3692 static int mlxsw_sp_port_tc_mc_mode_set(struct mlxsw_sp_port *mlxsw_sp_port,
3693                                         bool enable)
3694 {
3695         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
3696         char qtctm_pl[MLXSW_REG_QTCTM_LEN];
3697
3698         mlxsw_reg_qtctm_pack(qtctm_pl, mlxsw_sp_port->local_port, enable);
3699         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(qtctm), qtctm_pl);
3700 }
3701
3702 static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
3703                                 u8 split_base_local_port,
3704                                 struct mlxsw_sp_port_mapping *port_mapping)
3705 {
3706         struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
3707         bool split = !!split_base_local_port;
3708         struct mlxsw_sp_port *mlxsw_sp_port;
3709         struct net_device *dev;
3710         int err;
3711
3712         err = mlxsw_core_port_init(mlxsw_sp->core, local_port,
3713                                    port_mapping->module + 1, split,
3714                                    port_mapping->lane / port_mapping->width,
3715                                    mlxsw_sp->base_mac,
3716                                    sizeof(mlxsw_sp->base_mac));
3717         if (err) {
3718                 dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to init core port\n",
3719                         local_port);
3720                 return err;
3721         }
3722
3723         dev = alloc_etherdev(sizeof(struct mlxsw_sp_port));
3724         if (!dev) {
3725                 err = -ENOMEM;
3726                 goto err_alloc_etherdev;
3727         }
3728         SET_NETDEV_DEV(dev, mlxsw_sp->bus_info->dev);
3729         dev_net_set(dev, mlxsw_sp_net(mlxsw_sp));
3730         mlxsw_sp_port = netdev_priv(dev);
3731         mlxsw_sp_port->dev = dev;
3732         mlxsw_sp_port->mlxsw_sp = mlxsw_sp;
3733         mlxsw_sp_port->local_port = local_port;
3734         mlxsw_sp_port->pvid = MLXSW_SP_DEFAULT_VID;
3735         mlxsw_sp_port->split = split;
3736         mlxsw_sp_port->split_base_local_port = split_base_local_port;
3737         mlxsw_sp_port->mapping = *port_mapping;
3738         mlxsw_sp_port->link.autoneg = 1;
3739         INIT_LIST_HEAD(&mlxsw_sp_port->vlans_list);
3740         INIT_LIST_HEAD(&mlxsw_sp_port->mall_tc_list);
3741
3742         mlxsw_sp_port->pcpu_stats =
3743                 netdev_alloc_pcpu_stats(struct mlxsw_sp_port_pcpu_stats);
3744         if (!mlxsw_sp_port->pcpu_stats) {
3745                 err = -ENOMEM;
3746                 goto err_alloc_stats;
3747         }
3748
3749         mlxsw_sp_port->sample = kzalloc(sizeof(*mlxsw_sp_port->sample),
3750                                         GFP_KERNEL);
3751         if (!mlxsw_sp_port->sample) {
3752                 err = -ENOMEM;
3753                 goto err_alloc_sample;
3754         }
3755
3756         INIT_DELAYED_WORK(&mlxsw_sp_port->periodic_hw_stats.update_dw,
3757                           &update_stats_cache);
3758
3759         dev->netdev_ops = &mlxsw_sp_port_netdev_ops;
3760         dev->ethtool_ops = &mlxsw_sp_port_ethtool_ops;
3761
3762         err = mlxsw_sp_port_module_map(mlxsw_sp_port);
3763         if (err) {
3764                 dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to map module\n",
3765                         mlxsw_sp_port->local_port);
3766                 goto err_port_module_map;
3767         }
3768
3769         err = mlxsw_sp_port_swid_set(mlxsw_sp_port, 0);
3770         if (err) {
3771                 dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to set SWID\n",
3772                         mlxsw_sp_port->local_port);
3773                 goto err_port_swid_set;
3774         }
3775
3776         err = mlxsw_sp_port_dev_addr_init(mlxsw_sp_port);
3777         if (err) {
3778                 dev_err(mlxsw_sp->bus_info->dev, "Port %d: Unable to init port mac address\n",
3779                         mlxsw_sp_port->local_port);
3780                 goto err_dev_addr_init;
3781         }
3782
3783         netif_carrier_off(dev);
3784
3785         dev->features |= NETIF_F_NETNS_LOCAL | NETIF_F_LLTX | NETIF_F_SG |
3786                          NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_HW_TC;
3787         dev->hw_features |= NETIF_F_HW_TC | NETIF_F_LOOPBACK;
3788
3789         dev->min_mtu = 0;
3790         dev->max_mtu = ETH_MAX_MTU;
3791
3792         /* Each packet needs to have a Tx header (metadata) on top all other
3793          * headers.
3794          */
3795         dev->needed_headroom = MLXSW_TXHDR_LEN;
3796
3797         err = mlxsw_sp_port_system_port_mapping_set(mlxsw_sp_port);
3798         if (err) {
3799                 dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to set system port mapping\n",
3800                         mlxsw_sp_port->local_port);
3801                 goto err_port_system_port_mapping_set;
3802         }
3803
3804         err = mlxsw_sp_port_speed_by_width_set(mlxsw_sp_port);
3805         if (err) {
3806                 dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to enable speeds\n",
3807                         mlxsw_sp_port->local_port);
3808                 goto err_port_speed_by_width_set;
3809         }
3810
3811         err = mlxsw_sp_port_mtu_set(mlxsw_sp_port, ETH_DATA_LEN);
3812         if (err) {
3813                 dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to set MTU\n",
3814                         mlxsw_sp_port->local_port);
3815                 goto err_port_mtu_set;
3816         }
3817
3818         err = mlxsw_sp_port_admin_status_set(mlxsw_sp_port, false);
3819         if (err)
3820                 goto err_port_admin_status_set;
3821
3822         err = mlxsw_sp_port_buffers_init(mlxsw_sp_port);
3823         if (err) {
3824                 dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to initialize buffers\n",
3825                         mlxsw_sp_port->local_port);
3826                 goto err_port_buffers_init;
3827         }
3828
3829         err = mlxsw_sp_port_ets_init(mlxsw_sp_port);
3830         if (err) {
3831                 dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to initialize ETS\n",
3832                         mlxsw_sp_port->local_port);
3833                 goto err_port_ets_init;
3834         }
3835
3836         err = mlxsw_sp_port_tc_mc_mode_set(mlxsw_sp_port, true);
3837         if (err) {
3838                 dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to initialize TC MC mode\n",
3839                         mlxsw_sp_port->local_port);
3840                 goto err_port_tc_mc_mode;
3841         }
3842
3843         /* ETS and buffers must be initialized before DCB. */
3844         err = mlxsw_sp_port_dcb_init(mlxsw_sp_port);
3845         if (err) {
3846                 dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to initialize DCB\n",
3847                         mlxsw_sp_port->local_port);
3848                 goto err_port_dcb_init;
3849         }
3850
3851         err = mlxsw_sp_port_fids_init(mlxsw_sp_port);
3852         if (err) {
3853                 dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to initialize FIDs\n",
3854                         mlxsw_sp_port->local_port);
3855                 goto err_port_fids_init;
3856         }
3857
3858         err = mlxsw_sp_tc_qdisc_init(mlxsw_sp_port);
3859         if (err) {
3860                 dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to initialize TC qdiscs\n",
3861                         mlxsw_sp_port->local_port);
3862                 goto err_port_qdiscs_init;
3863         }
3864
3865         err = mlxsw_sp_port_vlan_set(mlxsw_sp_port, 0, VLAN_N_VID - 1, false,
3866                                      false);
3867         if (err) {
3868                 dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to clear VLAN filter\n",
3869                         mlxsw_sp_port->local_port);
3870                 goto err_port_vlan_clear;
3871         }
3872
3873         err = mlxsw_sp_port_nve_init(mlxsw_sp_port);
3874         if (err) {
3875                 dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to initialize NVE\n",
3876                         mlxsw_sp_port->local_port);
3877                 goto err_port_nve_init;
3878         }
3879
3880         err = mlxsw_sp_port_pvid_set(mlxsw_sp_port, MLXSW_SP_DEFAULT_VID);
3881         if (err) {
3882                 dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to set PVID\n",
3883                         mlxsw_sp_port->local_port);
3884                 goto err_port_pvid_set;
3885         }
3886
3887         mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_create(mlxsw_sp_port,
3888                                                        MLXSW_SP_DEFAULT_VID);
3889         if (IS_ERR(mlxsw_sp_port_vlan)) {
3890                 dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to create VID 1\n",
3891                         mlxsw_sp_port->local_port);
3892                 err = PTR_ERR(mlxsw_sp_port_vlan);
3893                 goto err_port_vlan_create;
3894         }
3895         mlxsw_sp_port->default_vlan = mlxsw_sp_port_vlan;
3896
3897         INIT_DELAYED_WORK(&mlxsw_sp_port->ptp.shaper_dw,
3898                           mlxsw_sp->ptp_ops->shaper_work);
3899         INIT_DELAYED_WORK(&mlxsw_sp_port->span.speed_update_dw,
3900                           mlxsw_sp_span_speed_update_work);
3901
3902         mlxsw_sp->ports[local_port] = mlxsw_sp_port;
3903         err = register_netdev(dev);
3904         if (err) {
3905                 dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to register netdev\n",
3906                         mlxsw_sp_port->local_port);
3907                 goto err_register_netdev;
3908         }
3909
3910         mlxsw_core_port_eth_set(mlxsw_sp->core, mlxsw_sp_port->local_port,
3911                                 mlxsw_sp_port, dev);
3912         mlxsw_core_schedule_dw(&mlxsw_sp_port->periodic_hw_stats.update_dw, 0);
3913         return 0;
3914
3915 err_register_netdev:
3916         mlxsw_sp->ports[local_port] = NULL;
3917         mlxsw_sp_port_vlan_destroy(mlxsw_sp_port_vlan);
3918 err_port_vlan_create:
3919 err_port_pvid_set:
3920         mlxsw_sp_port_nve_fini(mlxsw_sp_port);
3921 err_port_nve_init:
3922 err_port_vlan_clear:
3923         mlxsw_sp_tc_qdisc_fini(mlxsw_sp_port);
3924 err_port_qdiscs_init:
3925         mlxsw_sp_port_fids_fini(mlxsw_sp_port);
3926 err_port_fids_init:
3927         mlxsw_sp_port_dcb_fini(mlxsw_sp_port);
3928 err_port_dcb_init:
3929         mlxsw_sp_port_tc_mc_mode_set(mlxsw_sp_port, false);
3930 err_port_tc_mc_mode:
3931 err_port_ets_init:
3932 err_port_buffers_init:
3933 err_port_admin_status_set:
3934 err_port_mtu_set:
3935 err_port_speed_by_width_set:
3936 err_port_system_port_mapping_set:
3937 err_dev_addr_init:
3938         mlxsw_sp_port_swid_set(mlxsw_sp_port, MLXSW_PORT_SWID_DISABLED_PORT);
3939 err_port_swid_set:
3940         mlxsw_sp_port_module_unmap(mlxsw_sp_port);
3941 err_port_module_map:
3942         kfree(mlxsw_sp_port->sample);
3943 err_alloc_sample:
3944         free_percpu(mlxsw_sp_port->pcpu_stats);
3945 err_alloc_stats:
3946         free_netdev(dev);
3947 err_alloc_etherdev:
3948         mlxsw_core_port_fini(mlxsw_sp->core, local_port);
3949         return err;
3950 }
3951
3952 static void mlxsw_sp_port_remove(struct mlxsw_sp *mlxsw_sp, u8 local_port)
3953 {
3954         struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp->ports[local_port];
3955
3956         cancel_delayed_work_sync(&mlxsw_sp_port->periodic_hw_stats.update_dw);
3957         cancel_delayed_work_sync(&mlxsw_sp_port->span.speed_update_dw);
3958         cancel_delayed_work_sync(&mlxsw_sp_port->ptp.shaper_dw);
3959         mlxsw_sp_port_ptp_clear(mlxsw_sp_port);
3960         mlxsw_core_port_clear(mlxsw_sp->core, local_port, mlxsw_sp);
3961         unregister_netdev(mlxsw_sp_port->dev); /* This calls ndo_stop */
3962         mlxsw_sp->ports[local_port] = NULL;
3963         mlxsw_sp_port_vlan_flush(mlxsw_sp_port, true);
3964         mlxsw_sp_port_nve_fini(mlxsw_sp_port);
3965         mlxsw_sp_tc_qdisc_fini(mlxsw_sp_port);
3966         mlxsw_sp_port_fids_fini(mlxsw_sp_port);
3967         mlxsw_sp_port_dcb_fini(mlxsw_sp_port);
3968         mlxsw_sp_port_tc_mc_mode_set(mlxsw_sp_port, false);
3969         mlxsw_sp_port_swid_set(mlxsw_sp_port, MLXSW_PORT_SWID_DISABLED_PORT);
3970         mlxsw_sp_port_module_unmap(mlxsw_sp_port);
3971         kfree(mlxsw_sp_port->sample);
3972         free_percpu(mlxsw_sp_port->pcpu_stats);
3973         WARN_ON_ONCE(!list_empty(&mlxsw_sp_port->vlans_list));
3974         free_netdev(mlxsw_sp_port->dev);
3975         mlxsw_core_port_fini(mlxsw_sp->core, local_port);
3976 }
3977
3978 static int mlxsw_sp_cpu_port_create(struct mlxsw_sp *mlxsw_sp)
3979 {
3980         struct mlxsw_sp_port *mlxsw_sp_port;
3981         int err;
3982
3983         mlxsw_sp_port = kzalloc(sizeof(*mlxsw_sp_port), GFP_KERNEL);
3984         if (!mlxsw_sp_port)
3985                 return -ENOMEM;
3986
3987         mlxsw_sp_port->mlxsw_sp = mlxsw_sp;
3988         mlxsw_sp_port->local_port = MLXSW_PORT_CPU_PORT;
3989
3990         err = mlxsw_core_cpu_port_init(mlxsw_sp->core,
3991                                        mlxsw_sp_port,
3992                                        mlxsw_sp->base_mac,
3993                                        sizeof(mlxsw_sp->base_mac));
3994         if (err) {
3995                 dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize core CPU port\n");
3996                 goto err_core_cpu_port_init;
3997         }
3998
3999         mlxsw_sp->ports[MLXSW_PORT_CPU_PORT] = mlxsw_sp_port;
4000         return 0;
4001
4002 err_core_cpu_port_init:
4003         kfree(mlxsw_sp_port);
4004         return err;
4005 }
4006
4007 static void mlxsw_sp_cpu_port_remove(struct mlxsw_sp *mlxsw_sp)
4008 {
4009         struct mlxsw_sp_port *mlxsw_sp_port =
4010                                 mlxsw_sp->ports[MLXSW_PORT_CPU_PORT];
4011
4012         mlxsw_core_cpu_port_fini(mlxsw_sp->core);
4013         mlxsw_sp->ports[MLXSW_PORT_CPU_PORT] = NULL;
4014         kfree(mlxsw_sp_port);
4015 }
4016
4017 static bool mlxsw_sp_port_created(struct mlxsw_sp *mlxsw_sp, u8 local_port)
4018 {
4019         return mlxsw_sp->ports[local_port] != NULL;
4020 }
4021
4022 static void mlxsw_sp_ports_remove(struct mlxsw_sp *mlxsw_sp)
4023 {
4024         int i;
4025
4026         for (i = 1; i < mlxsw_core_max_ports(mlxsw_sp->core); i++)
4027                 if (mlxsw_sp_port_created(mlxsw_sp, i))
4028                         mlxsw_sp_port_remove(mlxsw_sp, i);
4029         mlxsw_sp_cpu_port_remove(mlxsw_sp);
4030         kfree(mlxsw_sp->ports);
4031 }
4032
4033 static int mlxsw_sp_ports_create(struct mlxsw_sp *mlxsw_sp)
4034 {
4035         unsigned int max_ports = mlxsw_core_max_ports(mlxsw_sp->core);
4036         struct mlxsw_sp_port_mapping *port_mapping;
4037         size_t alloc_size;
4038         int i;
4039         int err;
4040
4041         alloc_size = sizeof(struct mlxsw_sp_port *) * max_ports;
4042         mlxsw_sp->ports = kzalloc(alloc_size, GFP_KERNEL);
4043         if (!mlxsw_sp->ports)
4044                 return -ENOMEM;
4045
4046         err = mlxsw_sp_cpu_port_create(mlxsw_sp);
4047         if (err)
4048                 goto err_cpu_port_create;
4049
4050         for (i = 1; i < max_ports; i++) {
4051                 port_mapping = mlxsw_sp->port_mapping[i];
4052                 if (!port_mapping)
4053                         continue;
4054                 err = mlxsw_sp_port_create(mlxsw_sp, i, 0, port_mapping);
4055                 if (err)
4056                         goto err_port_create;
4057         }
4058         return 0;
4059
4060 err_port_create:
4061         for (i--; i >= 1; i--)
4062                 if (mlxsw_sp_port_created(mlxsw_sp, i))
4063                         mlxsw_sp_port_remove(mlxsw_sp, i);
4064         mlxsw_sp_cpu_port_remove(mlxsw_sp);
4065 err_cpu_port_create:
4066         kfree(mlxsw_sp->ports);
4067         return err;
4068 }
4069
4070 static int mlxsw_sp_port_module_info_init(struct mlxsw_sp *mlxsw_sp)
4071 {
4072         unsigned int max_ports = mlxsw_core_max_ports(mlxsw_sp->core);
4073         struct mlxsw_sp_port_mapping port_mapping;
4074         int i;
4075         int err;
4076
4077         mlxsw_sp->port_mapping = kcalloc(max_ports,
4078                                          sizeof(struct mlxsw_sp_port_mapping *),
4079                                          GFP_KERNEL);
4080         if (!mlxsw_sp->port_mapping)
4081                 return -ENOMEM;
4082
4083         for (i = 1; i < max_ports; i++) {
4084                 err = mlxsw_sp_port_module_info_get(mlxsw_sp, i, &port_mapping);
4085                 if (err)
4086                         goto err_port_module_info_get;
4087                 if (!port_mapping.width)
4088                         continue;
4089
4090                 mlxsw_sp->port_mapping[i] = kmemdup(&port_mapping,
4091                                                     sizeof(port_mapping),
4092                                                     GFP_KERNEL);
4093                 if (!mlxsw_sp->port_mapping[i]) {
4094                         err = -ENOMEM;
4095                         goto err_port_module_info_dup;
4096                 }
4097         }
4098         return 0;
4099
4100 err_port_module_info_get:
4101 err_port_module_info_dup:
4102         for (i--; i >= 1; i--)
4103                 kfree(mlxsw_sp->port_mapping[i]);
4104         kfree(mlxsw_sp->port_mapping);
4105         return err;
4106 }
4107
4108 static void mlxsw_sp_port_module_info_fini(struct mlxsw_sp *mlxsw_sp)
4109 {
4110         int i;
4111
4112         for (i = 1; i < mlxsw_core_max_ports(mlxsw_sp->core); i++)
4113                 kfree(mlxsw_sp->port_mapping[i]);
4114         kfree(mlxsw_sp->port_mapping);
4115 }
4116
4117 static u8 mlxsw_sp_cluster_base_port_get(u8 local_port, unsigned int max_width)
4118 {
4119         u8 offset = (local_port - 1) % max_width;
4120
4121         return local_port - offset;
4122 }
4123
4124 static int
4125 mlxsw_sp_port_split_create(struct mlxsw_sp *mlxsw_sp, u8 base_port,
4126                            struct mlxsw_sp_port_mapping *port_mapping,
4127                            unsigned int count, u8 offset)
4128 {
4129         struct mlxsw_sp_port_mapping split_port_mapping;
4130         int err, i;
4131
4132         split_port_mapping = *port_mapping;
4133         split_port_mapping.width /= count;
4134         for (i = 0; i < count; i++) {
4135                 err = mlxsw_sp_port_create(mlxsw_sp, base_port + i * offset,
4136                                            base_port, &split_port_mapping);
4137                 if (err)
4138                         goto err_port_create;
4139                 split_port_mapping.lane += split_port_mapping.width;
4140         }
4141
4142         return 0;
4143
4144 err_port_create:
4145         for (i--; i >= 0; i--)
4146                 if (mlxsw_sp_port_created(mlxsw_sp, base_port + i * offset))
4147                         mlxsw_sp_port_remove(mlxsw_sp, base_port + i * offset);
4148         return err;
4149 }
4150
4151 static void mlxsw_sp_port_unsplit_create(struct mlxsw_sp *mlxsw_sp,
4152                                          u8 base_port,
4153                                          unsigned int count, u8 offset)
4154 {
4155         struct mlxsw_sp_port_mapping *port_mapping;
4156         int i;
4157
4158         /* Go over original unsplit ports in the gap and recreate them. */
4159         for (i = 0; i < count * offset; i++) {
4160                 port_mapping = mlxsw_sp->port_mapping[base_port + i];
4161                 if (!port_mapping)
4162                         continue;
4163                 mlxsw_sp_port_create(mlxsw_sp, base_port + i, 0, port_mapping);
4164         }
4165 }
4166
4167 static int mlxsw_sp_local_ports_offset(struct mlxsw_core *mlxsw_core,
4168                                        unsigned int count,
4169                                        unsigned int max_width)
4170 {
4171         enum mlxsw_res_id local_ports_in_x_res_id;
4172         int split_width = max_width / count;
4173
4174         if (split_width == 1)
4175                 local_ports_in_x_res_id = MLXSW_RES_ID_LOCAL_PORTS_IN_1X;
4176         else if (split_width == 2)
4177                 local_ports_in_x_res_id = MLXSW_RES_ID_LOCAL_PORTS_IN_2X;
4178         else if (split_width == 4)
4179                 local_ports_in_x_res_id = MLXSW_RES_ID_LOCAL_PORTS_IN_4X;
4180         else
4181                 return -EINVAL;
4182
4183         if (!mlxsw_core_res_valid(mlxsw_core, local_ports_in_x_res_id))
4184                 return -EINVAL;
4185         return mlxsw_core_res_get(mlxsw_core, local_ports_in_x_res_id);
4186 }
4187
4188 static int mlxsw_sp_port_split(struct mlxsw_core *mlxsw_core, u8 local_port,
4189                                unsigned int count,
4190                                struct netlink_ext_ack *extack)
4191 {
4192         struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
4193         struct mlxsw_sp_port_mapping port_mapping;
4194         struct mlxsw_sp_port *mlxsw_sp_port;
4195         int max_width;
4196         u8 base_port;
4197         int offset;
4198         int i;
4199         int err;
4200
4201         mlxsw_sp_port = mlxsw_sp->ports[local_port];
4202         if (!mlxsw_sp_port) {
4203                 dev_err(mlxsw_sp->bus_info->dev, "Port number \"%d\" does not exist\n",
4204                         local_port);
4205                 NL_SET_ERR_MSG_MOD(extack, "Port number does not exist");
4206                 return -EINVAL;
4207         }
4208
4209         /* Split ports cannot be split. */
4210         if (mlxsw_sp_port->split) {
4211                 netdev_err(mlxsw_sp_port->dev, "Port cannot be split further\n");
4212                 NL_SET_ERR_MSG_MOD(extack, "Port cannot be split further");
4213                 return -EINVAL;
4214         }
4215
4216         max_width = mlxsw_core_module_max_width(mlxsw_core,
4217                                                 mlxsw_sp_port->mapping.module);
4218         if (max_width < 0) {
4219                 netdev_err(mlxsw_sp_port->dev, "Cannot get max width of port module\n");
4220                 NL_SET_ERR_MSG_MOD(extack, "Cannot get max width of port module");
4221                 return max_width;
4222         }
4223
4224         /* Split port with non-max and 1 module width cannot be split. */
4225         if (mlxsw_sp_port->mapping.width != max_width || max_width == 1) {
4226                 netdev_err(mlxsw_sp_port->dev, "Port cannot be split\n");
4227                 NL_SET_ERR_MSG_MOD(extack, "Port cannot be split");
4228                 return -EINVAL;
4229         }
4230
4231         if (count == 1 || !is_power_of_2(count) || count > max_width) {
4232                 netdev_err(mlxsw_sp_port->dev, "Invalid split count\n");
4233                 NL_SET_ERR_MSG_MOD(extack, "Invalid split count");
4234                 return -EINVAL;
4235         }
4236
4237         offset = mlxsw_sp_local_ports_offset(mlxsw_core, count, max_width);
4238         if (offset < 0) {
4239                 netdev_err(mlxsw_sp_port->dev, "Cannot obtain local port offset\n");
4240                 NL_SET_ERR_MSG_MOD(extack, "Cannot obtain local port offset");
4241                 return -EINVAL;
4242         }
4243
4244         /* Only in case max split is being done, the local port and
4245          * base port may differ.
4246          */
4247         base_port = count == max_width ?
4248                     mlxsw_sp_cluster_base_port_get(local_port, max_width) :
4249                     local_port;
4250
4251         for (i = 0; i < count * offset; i++) {
4252                 /* Expect base port to exist and also the one in the middle in
4253                  * case of maximal split count.
4254                  */
4255                 if (i == 0 || (count == max_width && i == count / 2))
4256                         continue;
4257
4258                 if (mlxsw_sp_port_created(mlxsw_sp, base_port + i)) {
4259                         netdev_err(mlxsw_sp_port->dev, "Invalid split configuration\n");
4260                         NL_SET_ERR_MSG_MOD(extack, "Invalid split configuration");
4261                         return -EINVAL;
4262                 }
4263         }
4264
4265         port_mapping = mlxsw_sp_port->mapping;
4266
4267         for (i = 0; i < count; i++)
4268                 if (mlxsw_sp_port_created(mlxsw_sp, base_port + i * offset))
4269                         mlxsw_sp_port_remove(mlxsw_sp, base_port + i * offset);
4270
4271         err = mlxsw_sp_port_split_create(mlxsw_sp, base_port, &port_mapping,
4272                                          count, offset);
4273         if (err) {
4274                 dev_err(mlxsw_sp->bus_info->dev, "Failed to create split ports\n");
4275                 goto err_port_split_create;
4276         }
4277
4278         return 0;
4279
4280 err_port_split_create:
4281         mlxsw_sp_port_unsplit_create(mlxsw_sp, base_port, count, offset);
4282         return err;
4283 }
4284
4285 static int mlxsw_sp_port_unsplit(struct mlxsw_core *mlxsw_core, u8 local_port,
4286                                  struct netlink_ext_ack *extack)
4287 {
4288         struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
4289         struct mlxsw_sp_port *mlxsw_sp_port;
4290         unsigned int count;
4291         int max_width;
4292         u8 base_port;
4293         int offset;
4294         int i;
4295
4296         mlxsw_sp_port = mlxsw_sp->ports[local_port];
4297         if (!mlxsw_sp_port) {
4298                 dev_err(mlxsw_sp->bus_info->dev, "Port number \"%d\" does not exist\n",
4299                         local_port);
4300                 NL_SET_ERR_MSG_MOD(extack, "Port number does not exist");
4301                 return -EINVAL;
4302         }
4303
4304         if (!mlxsw_sp_port->split) {
4305                 netdev_err(mlxsw_sp_port->dev, "Port was not split\n");
4306                 NL_SET_ERR_MSG_MOD(extack, "Port was not split");
4307                 return -EINVAL;
4308         }
4309
4310         max_width = mlxsw_core_module_max_width(mlxsw_core,
4311                                                 mlxsw_sp_port->mapping.module);
4312         if (max_width < 0) {
4313                 netdev_err(mlxsw_sp_port->dev, "Cannot get max width of port module\n");
4314                 NL_SET_ERR_MSG_MOD(extack, "Cannot get max width of port module");
4315                 return max_width;
4316         }
4317
4318         count = max_width / mlxsw_sp_port->mapping.width;
4319
4320         offset = mlxsw_sp_local_ports_offset(mlxsw_core, count, max_width);
4321         if (WARN_ON(offset < 0)) {
4322                 netdev_err(mlxsw_sp_port->dev, "Cannot obtain local port offset\n");
4323                 NL_SET_ERR_MSG_MOD(extack, "Cannot obtain local port offset");
4324                 return -EINVAL;
4325         }
4326
4327         base_port = mlxsw_sp_port->split_base_local_port;
4328
4329         for (i = 0; i < count; i++)
4330                 if (mlxsw_sp_port_created(mlxsw_sp, base_port + i * offset))
4331                         mlxsw_sp_port_remove(mlxsw_sp, base_port + i * offset);
4332
4333         mlxsw_sp_port_unsplit_create(mlxsw_sp, base_port, count, offset);
4334
4335         return 0;
4336 }
4337
4338 static void
4339 mlxsw_sp_port_down_wipe_counters(struct mlxsw_sp_port *mlxsw_sp_port)
4340 {
4341         int i;
4342
4343         for (i = 0; i < TC_MAX_QUEUE; i++)
4344                 mlxsw_sp_port->periodic_hw_stats.xstats.backlog[i] = 0;
4345 }
4346
4347 static void mlxsw_sp_pude_event_func(const struct mlxsw_reg_info *reg,
4348                                      char *pude_pl, void *priv)
4349 {
4350         struct mlxsw_sp *mlxsw_sp = priv;
4351         struct mlxsw_sp_port *mlxsw_sp_port;
4352         enum mlxsw_reg_pude_oper_status status;
4353         u8 local_port;
4354
4355         local_port = mlxsw_reg_pude_local_port_get(pude_pl);
4356         mlxsw_sp_port = mlxsw_sp->ports[local_port];
4357         if (!mlxsw_sp_port)
4358                 return;
4359
4360         status = mlxsw_reg_pude_oper_status_get(pude_pl);
4361         if (status == MLXSW_PORT_OPER_STATUS_UP) {
4362                 netdev_info(mlxsw_sp_port->dev, "link up\n");
4363                 netif_carrier_on(mlxsw_sp_port->dev);
4364                 mlxsw_core_schedule_dw(&mlxsw_sp_port->ptp.shaper_dw, 0);
4365                 mlxsw_core_schedule_dw(&mlxsw_sp_port->span.speed_update_dw, 0);
4366         } else {
4367                 netdev_info(mlxsw_sp_port->dev, "link down\n");
4368                 netif_carrier_off(mlxsw_sp_port->dev);
4369                 mlxsw_sp_port_down_wipe_counters(mlxsw_sp_port);
4370         }
4371 }
4372
4373 static void mlxsw_sp1_ptp_fifo_event_func(struct mlxsw_sp *mlxsw_sp,
4374                                           char *mtpptr_pl, bool ingress)
4375 {
4376         u8 local_port;
4377         u8 num_rec;
4378         int i;
4379
4380         local_port = mlxsw_reg_mtpptr_local_port_get(mtpptr_pl);
4381         num_rec = mlxsw_reg_mtpptr_num_rec_get(mtpptr_pl);
4382         for (i = 0; i < num_rec; i++) {
4383                 u8 domain_number;
4384                 u8 message_type;
4385                 u16 sequence_id;
4386                 u64 timestamp;
4387
4388                 mlxsw_reg_mtpptr_unpack(mtpptr_pl, i, &message_type,
4389                                         &domain_number, &sequence_id,
4390                                         &timestamp);
4391                 mlxsw_sp1_ptp_got_timestamp(mlxsw_sp, ingress, local_port,
4392                                             message_type, domain_number,
4393                                             sequence_id, timestamp);
4394         }
4395 }
4396
4397 static void mlxsw_sp1_ptp_ing_fifo_event_func(const struct mlxsw_reg_info *reg,
4398                                               char *mtpptr_pl, void *priv)
4399 {
4400         struct mlxsw_sp *mlxsw_sp = priv;
4401
4402         mlxsw_sp1_ptp_fifo_event_func(mlxsw_sp, mtpptr_pl, true);
4403 }
4404
4405 static void mlxsw_sp1_ptp_egr_fifo_event_func(const struct mlxsw_reg_info *reg,
4406                                               char *mtpptr_pl, void *priv)
4407 {
4408         struct mlxsw_sp *mlxsw_sp = priv;
4409
4410         mlxsw_sp1_ptp_fifo_event_func(mlxsw_sp, mtpptr_pl, false);
4411 }
4412
4413 void mlxsw_sp_rx_listener_no_mark_func(struct sk_buff *skb,
4414                                        u8 local_port, void *priv)
4415 {
4416         struct mlxsw_sp *mlxsw_sp = priv;
4417         struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp->ports[local_port];
4418         struct mlxsw_sp_port_pcpu_stats *pcpu_stats;
4419
4420         if (unlikely(!mlxsw_sp_port)) {
4421                 dev_warn_ratelimited(mlxsw_sp->bus_info->dev, "Port %d: skb received for non-existent port\n",
4422                                      local_port);
4423                 return;
4424         }
4425
4426         skb->dev = mlxsw_sp_port->dev;
4427
4428         pcpu_stats = this_cpu_ptr(mlxsw_sp_port->pcpu_stats);
4429         u64_stats_update_begin(&pcpu_stats->syncp);
4430         pcpu_stats->rx_packets++;
4431         pcpu_stats->rx_bytes += skb->len;
4432         u64_stats_update_end(&pcpu_stats->syncp);
4433
4434         skb->protocol = eth_type_trans(skb, skb->dev);
4435         netif_receive_skb(skb);
4436 }
4437
4438 static void mlxsw_sp_rx_listener_mark_func(struct sk_buff *skb, u8 local_port,
4439                                            void *priv)
4440 {
4441         skb->offload_fwd_mark = 1;
4442         return mlxsw_sp_rx_listener_no_mark_func(skb, local_port, priv);
4443 }
4444
4445 static void mlxsw_sp_rx_listener_l3_mark_func(struct sk_buff *skb,
4446                                               u8 local_port, void *priv)
4447 {
4448         skb->offload_l3_fwd_mark = 1;
4449         skb->offload_fwd_mark = 1;
4450         return mlxsw_sp_rx_listener_no_mark_func(skb, local_port, priv);
4451 }
4452
4453 static void mlxsw_sp_rx_listener_sample_func(struct sk_buff *skb, u8 local_port,
4454                                              void *priv)
4455 {
4456         struct mlxsw_sp *mlxsw_sp = priv;
4457         struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp->ports[local_port];
4458         struct psample_group *psample_group;
4459         u32 size;
4460
4461         if (unlikely(!mlxsw_sp_port)) {
4462                 dev_warn_ratelimited(mlxsw_sp->bus_info->dev, "Port %d: sample skb received for non-existent port\n",
4463                                      local_port);
4464                 goto out;
4465         }
4466         if (unlikely(!mlxsw_sp_port->sample)) {
4467                 dev_warn_ratelimited(mlxsw_sp->bus_info->dev, "Port %d: sample skb received on unsupported port\n",
4468                                      local_port);
4469                 goto out;
4470         }
4471
4472         size = mlxsw_sp_port->sample->truncate ?
4473                   mlxsw_sp_port->sample->trunc_size : skb->len;
4474
4475         rcu_read_lock();
4476         psample_group = rcu_dereference(mlxsw_sp_port->sample->psample_group);
4477         if (!psample_group)
4478                 goto out_unlock;
4479         psample_sample_packet(psample_group, skb, size,
4480                               mlxsw_sp_port->dev->ifindex, 0,
4481                               mlxsw_sp_port->sample->rate);
4482 out_unlock:
4483         rcu_read_unlock();
4484 out:
4485         consume_skb(skb);
4486 }
4487
4488 static void mlxsw_sp_rx_listener_ptp(struct sk_buff *skb, u8 local_port,
4489                                      void *priv)
4490 {
4491         struct mlxsw_sp *mlxsw_sp = priv;
4492
4493         mlxsw_sp->ptp_ops->receive(mlxsw_sp, skb, local_port);
4494 }
4495
4496 #define MLXSW_SP_RXL_NO_MARK(_trap_id, _action, _trap_group, _is_ctrl)  \
4497         MLXSW_RXL(mlxsw_sp_rx_listener_no_mark_func, _trap_id, _action, \
4498                   _is_ctrl, SP_##_trap_group, DISCARD)
4499
4500 #define MLXSW_SP_RXL_MARK(_trap_id, _action, _trap_group, _is_ctrl)     \
4501         MLXSW_RXL(mlxsw_sp_rx_listener_mark_func, _trap_id, _action,    \
4502                 _is_ctrl, SP_##_trap_group, DISCARD)
4503
4504 #define MLXSW_SP_RXL_L3_MARK(_trap_id, _action, _trap_group, _is_ctrl)  \
4505         MLXSW_RXL(mlxsw_sp_rx_listener_l3_mark_func, _trap_id, _action, \
4506                 _is_ctrl, SP_##_trap_group, DISCARD)
4507
4508 #define MLXSW_SP_EVENTL(_func, _trap_id)                \
4509         MLXSW_EVENTL(_func, _trap_id, SP_EVENT)
4510
4511 static const struct mlxsw_listener mlxsw_sp_listener[] = {
4512         /* Events */
4513         MLXSW_SP_EVENTL(mlxsw_sp_pude_event_func, PUDE),
4514         /* L2 traps */
4515         MLXSW_SP_RXL_NO_MARK(STP, TRAP_TO_CPU, STP, true),
4516         MLXSW_SP_RXL_NO_MARK(LACP, TRAP_TO_CPU, LACP, true),
4517         MLXSW_RXL(mlxsw_sp_rx_listener_ptp, LLDP, TRAP_TO_CPU,
4518                   false, SP_LLDP, DISCARD),
4519         MLXSW_SP_RXL_MARK(DHCP, MIRROR_TO_CPU, DHCP, false),
4520         MLXSW_SP_RXL_MARK(IGMP_QUERY, MIRROR_TO_CPU, IGMP, false),
4521         MLXSW_SP_RXL_NO_MARK(IGMP_V1_REPORT, TRAP_TO_CPU, IGMP, false),
4522         MLXSW_SP_RXL_NO_MARK(IGMP_V2_REPORT, TRAP_TO_CPU, IGMP, false),
4523         MLXSW_SP_RXL_NO_MARK(IGMP_V2_LEAVE, TRAP_TO_CPU, IGMP, false),
4524         MLXSW_SP_RXL_NO_MARK(IGMP_V3_REPORT, TRAP_TO_CPU, IGMP, false),
4525         MLXSW_SP_RXL_MARK(ARPBC, MIRROR_TO_CPU, ARP, false),
4526         MLXSW_SP_RXL_MARK(ARPUC, MIRROR_TO_CPU, ARP, false),
4527         MLXSW_SP_RXL_NO_MARK(FID_MISS, TRAP_TO_CPU, IP2ME, false),
4528         MLXSW_SP_RXL_MARK(IPV6_MLDV12_LISTENER_QUERY, MIRROR_TO_CPU, IPV6_MLD,
4529                           false),
4530         MLXSW_SP_RXL_NO_MARK(IPV6_MLDV1_LISTENER_REPORT, TRAP_TO_CPU, IPV6_MLD,
4531                              false),
4532         MLXSW_SP_RXL_NO_MARK(IPV6_MLDV1_LISTENER_DONE, TRAP_TO_CPU, IPV6_MLD,
4533                              false),
4534         MLXSW_SP_RXL_NO_MARK(IPV6_MLDV2_LISTENER_REPORT, TRAP_TO_CPU, IPV6_MLD,
4535                              false),
4536         /* L3 traps */
4537         MLXSW_SP_RXL_L3_MARK(LBERROR, MIRROR_TO_CPU, LBERROR, false),
4538         MLXSW_SP_RXL_MARK(IP2ME, TRAP_TO_CPU, IP2ME, false),
4539         MLXSW_SP_RXL_MARK(IPV6_UNSPECIFIED_ADDRESS, TRAP_TO_CPU, ROUTER_EXP,
4540                           false),
4541         MLXSW_SP_RXL_MARK(IPV6_LINK_LOCAL_DEST, TRAP_TO_CPU, ROUTER_EXP, false),
4542         MLXSW_SP_RXL_MARK(IPV6_LINK_LOCAL_SRC, TRAP_TO_CPU, ROUTER_EXP, false),
4543         MLXSW_SP_RXL_MARK(IPV6_ALL_NODES_LINK, TRAP_TO_CPU, ROUTER_EXP, false),
4544         MLXSW_SP_RXL_MARK(IPV6_ALL_ROUTERS_LINK, TRAP_TO_CPU, ROUTER_EXP,
4545                           false),
4546         MLXSW_SP_RXL_MARK(IPV4_OSPF, TRAP_TO_CPU, OSPF, false),
4547         MLXSW_SP_RXL_MARK(IPV6_OSPF, TRAP_TO_CPU, OSPF, false),
4548         MLXSW_SP_RXL_MARK(IPV6_DHCP, TRAP_TO_CPU, DHCP, false),
4549         MLXSW_SP_RXL_MARK(RTR_INGRESS0, TRAP_TO_CPU, REMOTE_ROUTE, false),
4550         MLXSW_SP_RXL_MARK(IPV4_BGP, TRAP_TO_CPU, BGP, false),
4551         MLXSW_SP_RXL_MARK(IPV6_BGP, TRAP_TO_CPU, BGP, false),
4552         MLXSW_SP_RXL_MARK(L3_IPV6_ROUTER_SOLICITATION, TRAP_TO_CPU, IPV6_ND,
4553                           false),
4554         MLXSW_SP_RXL_MARK(L3_IPV6_ROUTER_ADVERTISMENT, TRAP_TO_CPU, IPV6_ND,
4555                           false),
4556         MLXSW_SP_RXL_MARK(L3_IPV6_NEIGHBOR_SOLICITATION, TRAP_TO_CPU, IPV6_ND,
4557                           false),
4558         MLXSW_SP_RXL_MARK(L3_IPV6_NEIGHBOR_ADVERTISMENT, TRAP_TO_CPU, IPV6_ND,
4559                           false),
4560         MLXSW_SP_RXL_MARK(L3_IPV6_REDIRECTION, TRAP_TO_CPU, IPV6_ND, false),
4561         MLXSW_SP_RXL_MARK(IPV6_MC_LINK_LOCAL_DEST, TRAP_TO_CPU, ROUTER_EXP,
4562                           false),
4563         MLXSW_SP_RXL_MARK(ROUTER_ALERT_IPV4, TRAP_TO_CPU, ROUTER_EXP, false),
4564         MLXSW_SP_RXL_MARK(ROUTER_ALERT_IPV6, TRAP_TO_CPU, ROUTER_EXP, false),
4565         MLXSW_SP_RXL_MARK(IPV4_VRRP, TRAP_TO_CPU, VRRP, false),
4566         MLXSW_SP_RXL_MARK(IPV6_VRRP, TRAP_TO_CPU, VRRP, false),
4567         MLXSW_SP_RXL_NO_MARK(DISCARD_ING_ROUTER_SIP_CLASS_E, FORWARD,
4568                              ROUTER_EXP, false),
4569         MLXSW_SP_RXL_NO_MARK(DISCARD_ING_ROUTER_MC_DMAC, FORWARD,
4570                              ROUTER_EXP, false),
4571         MLXSW_SP_RXL_NO_MARK(DISCARD_ING_ROUTER_SIP_DIP, FORWARD,
4572                              ROUTER_EXP, false),
4573         MLXSW_SP_RXL_NO_MARK(DISCARD_ING_ROUTER_DIP_LINK_LOCAL, FORWARD,
4574                              ROUTER_EXP, false),
4575         /* PKT Sample trap */
4576         MLXSW_RXL(mlxsw_sp_rx_listener_sample_func, PKT_SAMPLE, MIRROR_TO_CPU,
4577                   false, SP_IP2ME, DISCARD),
4578         /* ACL trap */
4579         MLXSW_SP_RXL_NO_MARK(ACL0, TRAP_TO_CPU, IP2ME, false),
4580         /* Multicast Router Traps */
4581         MLXSW_SP_RXL_MARK(IPV4_PIM, TRAP_TO_CPU, PIM, false),
4582         MLXSW_SP_RXL_MARK(IPV6_PIM, TRAP_TO_CPU, PIM, false),
4583         MLXSW_SP_RXL_MARK(ACL1, TRAP_TO_CPU, MULTICAST, false),
4584         MLXSW_SP_RXL_L3_MARK(ACL2, TRAP_TO_CPU, MULTICAST, false),
4585         /* NVE traps */
4586         MLXSW_SP_RXL_MARK(NVE_ENCAP_ARP, TRAP_TO_CPU, ARP, false),
4587         MLXSW_SP_RXL_NO_MARK(NVE_DECAP_ARP, TRAP_TO_CPU, ARP, false),
4588         /* PTP traps */
4589         MLXSW_RXL(mlxsw_sp_rx_listener_ptp, PTP0, TRAP_TO_CPU,
4590                   false, SP_PTP0, DISCARD),
4591         MLXSW_SP_RXL_NO_MARK(PTP1, TRAP_TO_CPU, PTP1, false),
4592 };
4593
4594 static const struct mlxsw_listener mlxsw_sp1_listener[] = {
4595         /* Events */
4596         MLXSW_EVENTL(mlxsw_sp1_ptp_egr_fifo_event_func, PTP_EGR_FIFO, SP_PTP0),
4597         MLXSW_EVENTL(mlxsw_sp1_ptp_ing_fifo_event_func, PTP_ING_FIFO, SP_PTP0),
4598 };
4599
4600 static int mlxsw_sp_cpu_policers_set(struct mlxsw_core *mlxsw_core)
4601 {
4602         char qpcr_pl[MLXSW_REG_QPCR_LEN];
4603         enum mlxsw_reg_qpcr_ir_units ir_units;
4604         int max_cpu_policers;
4605         bool is_bytes;
4606         u8 burst_size;
4607         u32 rate;
4608         int i, err;
4609
4610         if (!MLXSW_CORE_RES_VALID(mlxsw_core, MAX_CPU_POLICERS))
4611                 return -EIO;
4612
4613         max_cpu_policers = MLXSW_CORE_RES_GET(mlxsw_core, MAX_CPU_POLICERS);
4614
4615         ir_units = MLXSW_REG_QPCR_IR_UNITS_M;
4616         for (i = 0; i < max_cpu_policers; i++) {
4617                 is_bytes = false;
4618                 switch (i) {
4619                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_STP:
4620                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_LACP:
4621                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_LLDP:
4622                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_OSPF:
4623                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_PIM:
4624                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_RPF:
4625                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_LBERROR:
4626                         rate = 128;
4627                         burst_size = 7;
4628                         break;
4629                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_IGMP:
4630                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_IPV6_MLD:
4631                         rate = 16 * 1024;
4632                         burst_size = 10;
4633                         break;
4634                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_BGP:
4635                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_ARP:
4636                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_DHCP:
4637                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_HOST_MISS:
4638                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_ROUTER_EXP:
4639                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_REMOTE_ROUTE:
4640                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_IPV6_ND:
4641                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_MULTICAST:
4642                         rate = 1024;
4643                         burst_size = 7;
4644                         break;
4645                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_IP2ME:
4646                         rate = 1024;
4647                         burst_size = 7;
4648                         break;
4649                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_PTP0:
4650                         rate = 24 * 1024;
4651                         burst_size = 12;
4652                         break;
4653                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_PTP1:
4654                         rate = 19 * 1024;
4655                         burst_size = 12;
4656                         break;
4657                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_VRRP:
4658                         rate = 360;
4659                         burst_size = 7;
4660                         break;
4661                 default:
4662                         continue;
4663                 }
4664
4665                 mlxsw_reg_qpcr_pack(qpcr_pl, i, ir_units, is_bytes, rate,
4666                                     burst_size);
4667                 err = mlxsw_reg_write(mlxsw_core, MLXSW_REG(qpcr), qpcr_pl);
4668                 if (err)
4669                         return err;
4670         }
4671
4672         return 0;
4673 }
4674
4675 static int mlxsw_sp_trap_groups_set(struct mlxsw_core *mlxsw_core)
4676 {
4677         char htgt_pl[MLXSW_REG_HTGT_LEN];
4678         enum mlxsw_reg_htgt_trap_group i;
4679         int max_cpu_policers;
4680         int max_trap_groups;
4681         u8 priority, tc;
4682         u16 policer_id;
4683         int err;
4684
4685         if (!MLXSW_CORE_RES_VALID(mlxsw_core, MAX_TRAP_GROUPS))
4686                 return -EIO;
4687
4688         max_trap_groups = MLXSW_CORE_RES_GET(mlxsw_core, MAX_TRAP_GROUPS);
4689         max_cpu_policers = MLXSW_CORE_RES_GET(mlxsw_core, MAX_CPU_POLICERS);
4690
4691         for (i = 0; i < max_trap_groups; i++) {
4692                 policer_id = i;
4693                 switch (i) {
4694                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_STP:
4695                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_LACP:
4696                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_LLDP:
4697                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_OSPF:
4698                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_PIM:
4699                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_PTP0:
4700                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_VRRP:
4701                         priority = 5;
4702                         tc = 5;
4703                         break;
4704                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_BGP:
4705                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_DHCP:
4706                         priority = 4;
4707                         tc = 4;
4708                         break;
4709                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_IGMP:
4710                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_IP2ME:
4711                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_IPV6_MLD:
4712                         priority = 3;
4713                         tc = 3;
4714                         break;
4715                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_ARP:
4716                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_IPV6_ND:
4717                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_RPF:
4718                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_PTP1:
4719                         priority = 2;
4720                         tc = 2;
4721                         break;
4722                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_HOST_MISS:
4723                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_ROUTER_EXP:
4724                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_REMOTE_ROUTE:
4725                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_MULTICAST:
4726                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_LBERROR:
4727                         priority = 1;
4728                         tc = 1;
4729                         break;
4730                 case MLXSW_REG_HTGT_TRAP_GROUP_SP_EVENT:
4731                         priority = MLXSW_REG_HTGT_DEFAULT_PRIORITY;
4732                         tc = MLXSW_REG_HTGT_DEFAULT_TC;
4733                         policer_id = MLXSW_REG_HTGT_INVALID_POLICER;
4734                         break;
4735                 default:
4736                         continue;
4737                 }
4738
4739                 if (max_cpu_policers <= policer_id &&
4740                     policer_id != MLXSW_REG_HTGT_INVALID_POLICER)
4741                         return -EIO;
4742
4743                 mlxsw_reg_htgt_pack(htgt_pl, i, policer_id, priority, tc);
4744                 err = mlxsw_reg_write(mlxsw_core, MLXSW_REG(htgt), htgt_pl);
4745                 if (err)
4746                         return err;
4747         }
4748
4749         return 0;
4750 }
4751
4752 static int mlxsw_sp_traps_register(struct mlxsw_sp *mlxsw_sp,
4753                                    const struct mlxsw_listener listeners[],
4754                                    size_t listeners_count)
4755 {
4756         int i;
4757         int err;
4758
4759         for (i = 0; i < listeners_count; i++) {
4760                 err = mlxsw_core_trap_register(mlxsw_sp->core,
4761                                                &listeners[i],
4762                                                mlxsw_sp);
4763                 if (err)
4764                         goto err_listener_register;
4765
4766         }
4767         return 0;
4768
4769 err_listener_register:
4770         for (i--; i >= 0; i--) {
4771                 mlxsw_core_trap_unregister(mlxsw_sp->core,
4772                                            &listeners[i],
4773                                            mlxsw_sp);
4774         }
4775         return err;
4776 }
4777
4778 static void mlxsw_sp_traps_unregister(struct mlxsw_sp *mlxsw_sp,
4779                                       const struct mlxsw_listener listeners[],
4780                                       size_t listeners_count)
4781 {
4782         int i;
4783
4784         for (i = 0; i < listeners_count; i++) {
4785                 mlxsw_core_trap_unregister(mlxsw_sp->core,
4786                                            &listeners[i],
4787                                            mlxsw_sp);
4788         }
4789 }
4790
4791 static int mlxsw_sp_traps_init(struct mlxsw_sp *mlxsw_sp)
4792 {
4793         int err;
4794
4795         err = mlxsw_sp_cpu_policers_set(mlxsw_sp->core);
4796         if (err)
4797                 return err;
4798
4799         err = mlxsw_sp_trap_groups_set(mlxsw_sp->core);
4800         if (err)
4801                 return err;
4802
4803         err = mlxsw_sp_traps_register(mlxsw_sp, mlxsw_sp_listener,
4804                                       ARRAY_SIZE(mlxsw_sp_listener));
4805         if (err)
4806                 return err;
4807
4808         err = mlxsw_sp_traps_register(mlxsw_sp, mlxsw_sp->listeners,
4809                                       mlxsw_sp->listeners_count);
4810         if (err)
4811                 goto err_extra_traps_init;
4812
4813         return 0;
4814
4815 err_extra_traps_init:
4816         mlxsw_sp_traps_unregister(mlxsw_sp, mlxsw_sp_listener,
4817                                   ARRAY_SIZE(mlxsw_sp_listener));
4818         return err;
4819 }
4820
4821 static void mlxsw_sp_traps_fini(struct mlxsw_sp *mlxsw_sp)
4822 {
4823         mlxsw_sp_traps_unregister(mlxsw_sp, mlxsw_sp->listeners,
4824                                   mlxsw_sp->listeners_count);
4825         mlxsw_sp_traps_unregister(mlxsw_sp, mlxsw_sp_listener,
4826                                   ARRAY_SIZE(mlxsw_sp_listener));
4827 }
4828
4829 #define MLXSW_SP_LAG_SEED_INIT 0xcafecafe
4830
4831 static int mlxsw_sp_lag_init(struct mlxsw_sp *mlxsw_sp)
4832 {
4833         char slcr_pl[MLXSW_REG_SLCR_LEN];
4834         u32 seed;
4835         int err;
4836
4837         seed = jhash(mlxsw_sp->base_mac, sizeof(mlxsw_sp->base_mac),
4838                      MLXSW_SP_LAG_SEED_INIT);
4839         mlxsw_reg_slcr_pack(slcr_pl, MLXSW_REG_SLCR_LAG_HASH_SMAC |
4840                                      MLXSW_REG_SLCR_LAG_HASH_DMAC |
4841                                      MLXSW_REG_SLCR_LAG_HASH_ETHERTYPE |
4842                                      MLXSW_REG_SLCR_LAG_HASH_VLANID |
4843                                      MLXSW_REG_SLCR_LAG_HASH_SIP |
4844                                      MLXSW_REG_SLCR_LAG_HASH_DIP |
4845                                      MLXSW_REG_SLCR_LAG_HASH_SPORT |
4846                                      MLXSW_REG_SLCR_LAG_HASH_DPORT |
4847                                      MLXSW_REG_SLCR_LAG_HASH_IPPROTO, seed);
4848         err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(slcr), slcr_pl);
4849         if (err)
4850                 return err;
4851
4852         if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_LAG) ||
4853             !MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_LAG_MEMBERS))
4854                 return -EIO;
4855
4856         mlxsw_sp->lags = kcalloc(MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_LAG),
4857                                  sizeof(struct mlxsw_sp_upper),
4858                                  GFP_KERNEL);
4859         if (!mlxsw_sp->lags)
4860                 return -ENOMEM;
4861
4862         return 0;
4863 }
4864
4865 static void mlxsw_sp_lag_fini(struct mlxsw_sp *mlxsw_sp)
4866 {
4867         kfree(mlxsw_sp->lags);
4868 }
4869
4870 static int mlxsw_sp_basic_trap_groups_set(struct mlxsw_core *mlxsw_core)
4871 {
4872         char htgt_pl[MLXSW_REG_HTGT_LEN];
4873
4874         mlxsw_reg_htgt_pack(htgt_pl, MLXSW_REG_HTGT_TRAP_GROUP_EMAD,
4875                             MLXSW_REG_HTGT_INVALID_POLICER,
4876                             MLXSW_REG_HTGT_DEFAULT_PRIORITY,
4877                             MLXSW_REG_HTGT_DEFAULT_TC);
4878         return mlxsw_reg_write(mlxsw_core, MLXSW_REG(htgt), htgt_pl);
4879 }
4880
4881 static const struct mlxsw_sp_ptp_ops mlxsw_sp1_ptp_ops = {
4882         .clock_init     = mlxsw_sp1_ptp_clock_init,
4883         .clock_fini     = mlxsw_sp1_ptp_clock_fini,
4884         .init           = mlxsw_sp1_ptp_init,
4885         .fini           = mlxsw_sp1_ptp_fini,
4886         .receive        = mlxsw_sp1_ptp_receive,
4887         .transmitted    = mlxsw_sp1_ptp_transmitted,
4888         .hwtstamp_get   = mlxsw_sp1_ptp_hwtstamp_get,
4889         .hwtstamp_set   = mlxsw_sp1_ptp_hwtstamp_set,
4890         .shaper_work    = mlxsw_sp1_ptp_shaper_work,
4891         .get_ts_info    = mlxsw_sp1_ptp_get_ts_info,
4892         .get_stats_count = mlxsw_sp1_get_stats_count,
4893         .get_stats_strings = mlxsw_sp1_get_stats_strings,
4894         .get_stats      = mlxsw_sp1_get_stats,
4895 };
4896
4897 static const struct mlxsw_sp_ptp_ops mlxsw_sp2_ptp_ops = {
4898         .clock_init     = mlxsw_sp2_ptp_clock_init,
4899         .clock_fini     = mlxsw_sp2_ptp_clock_fini,
4900         .init           = mlxsw_sp2_ptp_init,
4901         .fini           = mlxsw_sp2_ptp_fini,
4902         .receive        = mlxsw_sp2_ptp_receive,
4903         .transmitted    = mlxsw_sp2_ptp_transmitted,
4904         .hwtstamp_get   = mlxsw_sp2_ptp_hwtstamp_get,
4905         .hwtstamp_set   = mlxsw_sp2_ptp_hwtstamp_set,
4906         .shaper_work    = mlxsw_sp2_ptp_shaper_work,
4907         .get_ts_info    = mlxsw_sp2_ptp_get_ts_info,
4908         .get_stats_count = mlxsw_sp2_get_stats_count,
4909         .get_stats_strings = mlxsw_sp2_get_stats_strings,
4910         .get_stats      = mlxsw_sp2_get_stats,
4911 };
4912
4913 static u32 mlxsw_sp1_span_buffsize_get(int mtu, u32 speed)
4914 {
4915         return mtu * 5 / 2;
4916 }
4917
4918 static const struct mlxsw_sp_span_ops mlxsw_sp1_span_ops = {
4919         .buffsize_get = mlxsw_sp1_span_buffsize_get,
4920 };
4921
4922 #define MLXSW_SP2_SPAN_EG_MIRROR_BUFFER_FACTOR 38
4923
4924 static u32 mlxsw_sp2_span_buffsize_get(int mtu, u32 speed)
4925 {
4926         return 3 * mtu + MLXSW_SP2_SPAN_EG_MIRROR_BUFFER_FACTOR * speed / 1000;
4927 }
4928
4929 static const struct mlxsw_sp_span_ops mlxsw_sp2_span_ops = {
4930         .buffsize_get = mlxsw_sp2_span_buffsize_get,
4931 };
4932
4933 u32 mlxsw_sp_span_buffsize_get(struct mlxsw_sp *mlxsw_sp, int mtu, u32 speed)
4934 {
4935         u32 buffsize = mlxsw_sp->span_ops->buffsize_get(speed, mtu);
4936
4937         return mlxsw_sp_bytes_cells(mlxsw_sp, buffsize) + 1;
4938 }
4939
4940 static int mlxsw_sp_netdevice_event(struct notifier_block *unused,
4941                                     unsigned long event, void *ptr);
4942
4943 static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core,
4944                          const struct mlxsw_bus_info *mlxsw_bus_info,
4945                          struct netlink_ext_ack *extack)
4946 {
4947         struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
4948         int err;
4949
4950         mlxsw_sp->core = mlxsw_core;
4951         mlxsw_sp->bus_info = mlxsw_bus_info;
4952
4953         err = mlxsw_sp_fw_rev_validate(mlxsw_sp);
4954         if (err)
4955                 return err;
4956
4957         mlxsw_core_emad_string_tlv_enable(mlxsw_core);
4958
4959         err = mlxsw_sp_base_mac_get(mlxsw_sp);
4960         if (err) {
4961                 dev_err(mlxsw_sp->bus_info->dev, "Failed to get base mac\n");
4962                 return err;
4963         }
4964
4965         err = mlxsw_sp_kvdl_init(mlxsw_sp);
4966         if (err) {
4967                 dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize KVDL\n");
4968                 return err;
4969         }
4970
4971         err = mlxsw_sp_fids_init(mlxsw_sp);
4972         if (err) {
4973                 dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize FIDs\n");
4974                 goto err_fids_init;
4975         }
4976
4977         err = mlxsw_sp_traps_init(mlxsw_sp);
4978         if (err) {
4979                 dev_err(mlxsw_sp->bus_info->dev, "Failed to set traps\n");
4980                 goto err_traps_init;
4981         }
4982
4983         err = mlxsw_sp_devlink_traps_init(mlxsw_sp);
4984         if (err) {
4985                 dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize devlink traps\n");
4986                 goto err_devlink_traps_init;
4987         }
4988
4989         err = mlxsw_sp_buffers_init(mlxsw_sp);
4990         if (err) {
4991                 dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize buffers\n");
4992                 goto err_buffers_init;
4993         }
4994
4995         err = mlxsw_sp_lag_init(mlxsw_sp);
4996         if (err) {
4997                 dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize LAG\n");
4998                 goto err_lag_init;
4999         }
5000
5001         /* Initialize SPAN before router and switchdev, so that those components
5002          * can call mlxsw_sp_span_respin().
5003          */
5004         err = mlxsw_sp_span_init(mlxsw_sp);
5005         if (err) {
5006                 dev_err(mlxsw_sp->bus_info->dev, "Failed to init span system\n");
5007                 goto err_span_init;
5008         }
5009
5010         err = mlxsw_sp_switchdev_init(mlxsw_sp);
5011         if (err) {
5012                 dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize switchdev\n");
5013                 goto err_switchdev_init;
5014         }
5015
5016         err = mlxsw_sp_counter_pool_init(mlxsw_sp);
5017         if (err) {
5018                 dev_err(mlxsw_sp->bus_info->dev, "Failed to init counter pool\n");
5019                 goto err_counter_pool_init;
5020         }
5021
5022         err = mlxsw_sp_afa_init(mlxsw_sp);
5023         if (err) {
5024                 dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize ACL actions\n");
5025                 goto err_afa_init;
5026         }
5027
5028         err = mlxsw_sp_nve_init(mlxsw_sp);
5029         if (err) {
5030                 dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize NVE\n");
5031                 goto err_nve_init;
5032         }
5033
5034         err = mlxsw_sp_acl_init(mlxsw_sp);
5035         if (err) {
5036                 dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize ACL\n");
5037                 goto err_acl_init;
5038         }
5039
5040         err = mlxsw_sp_router_init(mlxsw_sp, extack);
5041         if (err) {
5042                 dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize router\n");
5043                 goto err_router_init;
5044         }
5045
5046         if (mlxsw_sp->bus_info->read_frc_capable) {
5047                 /* NULL is a valid return value from clock_init */
5048                 mlxsw_sp->clock =
5049                         mlxsw_sp->ptp_ops->clock_init(mlxsw_sp,
5050                                                       mlxsw_sp->bus_info->dev);
5051                 if (IS_ERR(mlxsw_sp->clock)) {
5052                         err = PTR_ERR(mlxsw_sp->clock);
5053                         dev_err(mlxsw_sp->bus_info->dev, "Failed to init ptp clock\n");
5054                         goto err_ptp_clock_init;
5055                 }
5056         }
5057
5058         if (mlxsw_sp->clock) {
5059                 /* NULL is a valid return value from ptp_ops->init */
5060                 mlxsw_sp->ptp_state = mlxsw_sp->ptp_ops->init(mlxsw_sp);
5061                 if (IS_ERR(mlxsw_sp->ptp_state)) {
5062                         err = PTR_ERR(mlxsw_sp->ptp_state);
5063                         dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize PTP\n");
5064                         goto err_ptp_init;
5065                 }
5066         }
5067
5068         /* Initialize netdevice notifier after router and SPAN is initialized,
5069          * so that the event handler can use router structures and call SPAN
5070          * respin.
5071          */
5072         mlxsw_sp->netdevice_nb.notifier_call = mlxsw_sp_netdevice_event;
5073         err = register_netdevice_notifier_net(mlxsw_sp_net(mlxsw_sp),
5074                                               &mlxsw_sp->netdevice_nb);
5075         if (err) {
5076                 dev_err(mlxsw_sp->bus_info->dev, "Failed to register netdev notifier\n");
5077                 goto err_netdev_notifier;
5078         }
5079
5080         err = mlxsw_sp_dpipe_init(mlxsw_sp);
5081         if (err) {
5082                 dev_err(mlxsw_sp->bus_info->dev, "Failed to init pipeline debug\n");
5083                 goto err_dpipe_init;
5084         }
5085
5086         err = mlxsw_sp_port_module_info_init(mlxsw_sp);
5087         if (err) {
5088                 dev_err(mlxsw_sp->bus_info->dev, "Failed to init port module info\n");
5089                 goto err_port_module_info_init;
5090         }
5091
5092         err = mlxsw_sp_ports_create(mlxsw_sp);
5093         if (err) {
5094                 dev_err(mlxsw_sp->bus_info->dev, "Failed to create ports\n");
5095                 goto err_ports_create;
5096         }
5097
5098         return 0;
5099
5100 err_ports_create:
5101         mlxsw_sp_port_module_info_fini(mlxsw_sp);
5102 err_port_module_info_init:
5103         mlxsw_sp_dpipe_fini(mlxsw_sp);
5104 err_dpipe_init:
5105         unregister_netdevice_notifier_net(mlxsw_sp_net(mlxsw_sp),
5106                                           &mlxsw_sp->netdevice_nb);
5107 err_netdev_notifier:
5108         if (mlxsw_sp->clock)
5109                 mlxsw_sp->ptp_ops->fini(mlxsw_sp->ptp_state);
5110 err_ptp_init:
5111         if (mlxsw_sp->clock)
5112                 mlxsw_sp->ptp_ops->clock_fini(mlxsw_sp->clock);
5113 err_ptp_clock_init:
5114         mlxsw_sp_router_fini(mlxsw_sp);
5115 err_router_init:
5116         mlxsw_sp_acl_fini(mlxsw_sp);
5117 err_acl_init:
5118         mlxsw_sp_nve_fini(mlxsw_sp);
5119 err_nve_init:
5120         mlxsw_sp_afa_fini(mlxsw_sp);
5121 err_afa_init:
5122         mlxsw_sp_counter_pool_fini(mlxsw_sp);
5123 err_counter_pool_init:
5124         mlxsw_sp_switchdev_fini(mlxsw_sp);
5125 err_switchdev_init:
5126         mlxsw_sp_span_fini(mlxsw_sp);
5127 err_span_init:
5128         mlxsw_sp_lag_fini(mlxsw_sp);
5129 err_lag_init:
5130         mlxsw_sp_buffers_fini(mlxsw_sp);
5131 err_buffers_init:
5132         mlxsw_sp_devlink_traps_fini(mlxsw_sp);
5133 err_devlink_traps_init:
5134         mlxsw_sp_traps_fini(mlxsw_sp);
5135 err_traps_init:
5136         mlxsw_sp_fids_fini(mlxsw_sp);
5137 err_fids_init:
5138         mlxsw_sp_kvdl_fini(mlxsw_sp);
5139         return err;
5140 }
5141
5142 static int mlxsw_sp1_init(struct mlxsw_core *mlxsw_core,
5143                           const struct mlxsw_bus_info *mlxsw_bus_info,
5144                           struct netlink_ext_ack *extack)
5145 {
5146         struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
5147
5148         mlxsw_sp->req_rev = &mlxsw_sp1_fw_rev;
5149         mlxsw_sp->fw_filename = MLXSW_SP1_FW_FILENAME;
5150         mlxsw_sp->kvdl_ops = &mlxsw_sp1_kvdl_ops;
5151         mlxsw_sp->afa_ops = &mlxsw_sp1_act_afa_ops;
5152         mlxsw_sp->afk_ops = &mlxsw_sp1_afk_ops;
5153         mlxsw_sp->mr_tcam_ops = &mlxsw_sp1_mr_tcam_ops;
5154         mlxsw_sp->acl_tcam_ops = &mlxsw_sp1_acl_tcam_ops;
5155         mlxsw_sp->nve_ops_arr = mlxsw_sp1_nve_ops_arr;
5156         mlxsw_sp->mac_mask = mlxsw_sp1_mac_mask;
5157         mlxsw_sp->rif_ops_arr = mlxsw_sp1_rif_ops_arr;
5158         mlxsw_sp->sb_vals = &mlxsw_sp1_sb_vals;
5159         mlxsw_sp->port_type_speed_ops = &mlxsw_sp1_port_type_speed_ops;
5160         mlxsw_sp->ptp_ops = &mlxsw_sp1_ptp_ops;
5161         mlxsw_sp->span_ops = &mlxsw_sp1_span_ops;
5162         mlxsw_sp->listeners = mlxsw_sp1_listener;
5163         mlxsw_sp->listeners_count = ARRAY_SIZE(mlxsw_sp1_listener);
5164         mlxsw_sp->lowest_shaper_bs = MLXSW_REG_QEEC_LOWEST_SHAPER_BS_SP1;
5165
5166         return mlxsw_sp_init(mlxsw_core, mlxsw_bus_info, extack);
5167 }
5168
5169 static int mlxsw_sp2_init(struct mlxsw_core *mlxsw_core,
5170                           const struct mlxsw_bus_info *mlxsw_bus_info,
5171                           struct netlink_ext_ack *extack)
5172 {
5173         struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
5174
5175         mlxsw_sp->req_rev = &mlxsw_sp2_fw_rev;
5176         mlxsw_sp->fw_filename = MLXSW_SP2_FW_FILENAME;
5177         mlxsw_sp->kvdl_ops = &mlxsw_sp2_kvdl_ops;
5178         mlxsw_sp->afa_ops = &mlxsw_sp2_act_afa_ops;
5179         mlxsw_sp->afk_ops = &mlxsw_sp2_afk_ops;
5180         mlxsw_sp->mr_tcam_ops = &mlxsw_sp2_mr_tcam_ops;
5181         mlxsw_sp->acl_tcam_ops = &mlxsw_sp2_acl_tcam_ops;
5182         mlxsw_sp->nve_ops_arr = mlxsw_sp2_nve_ops_arr;
5183         mlxsw_sp->mac_mask = mlxsw_sp2_mac_mask;
5184         mlxsw_sp->rif_ops_arr = mlxsw_sp2_rif_ops_arr;
5185         mlxsw_sp->sb_vals = &mlxsw_sp2_sb_vals;
5186         mlxsw_sp->port_type_speed_ops = &mlxsw_sp2_port_type_speed_ops;
5187         mlxsw_sp->ptp_ops = &mlxsw_sp2_ptp_ops;
5188         mlxsw_sp->span_ops = &mlxsw_sp2_span_ops;
5189         mlxsw_sp->lowest_shaper_bs = MLXSW_REG_QEEC_LOWEST_SHAPER_BS_SP2;
5190
5191         return mlxsw_sp_init(mlxsw_core, mlxsw_bus_info, extack);
5192 }
5193
5194 static int mlxsw_sp3_init(struct mlxsw_core *mlxsw_core,
5195                           const struct mlxsw_bus_info *mlxsw_bus_info,
5196                           struct netlink_ext_ack *extack)
5197 {
5198         struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
5199
5200         mlxsw_sp->kvdl_ops = &mlxsw_sp2_kvdl_ops;
5201         mlxsw_sp->afa_ops = &mlxsw_sp2_act_afa_ops;
5202         mlxsw_sp->afk_ops = &mlxsw_sp2_afk_ops;
5203         mlxsw_sp->mr_tcam_ops = &mlxsw_sp2_mr_tcam_ops;
5204         mlxsw_sp->acl_tcam_ops = &mlxsw_sp2_acl_tcam_ops;
5205         mlxsw_sp->nve_ops_arr = mlxsw_sp2_nve_ops_arr;
5206         mlxsw_sp->mac_mask = mlxsw_sp2_mac_mask;
5207         mlxsw_sp->rif_ops_arr = mlxsw_sp2_rif_ops_arr;
5208         mlxsw_sp->sb_vals = &mlxsw_sp2_sb_vals;
5209         mlxsw_sp->port_type_speed_ops = &mlxsw_sp2_port_type_speed_ops;
5210         mlxsw_sp->ptp_ops = &mlxsw_sp2_ptp_ops;
5211         mlxsw_sp->span_ops = &mlxsw_sp2_span_ops;
5212         mlxsw_sp->lowest_shaper_bs = MLXSW_REG_QEEC_LOWEST_SHAPER_BS_SP3;
5213
5214         return mlxsw_sp_init(mlxsw_core, mlxsw_bus_info, extack);
5215 }
5216
5217 static void mlxsw_sp_fini(struct mlxsw_core *mlxsw_core)
5218 {
5219         struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
5220
5221         mlxsw_sp_ports_remove(mlxsw_sp);
5222         mlxsw_sp_port_module_info_fini(mlxsw_sp);
5223         mlxsw_sp_dpipe_fini(mlxsw_sp);
5224         unregister_netdevice_notifier_net(mlxsw_sp_net(mlxsw_sp),
5225                                           &mlxsw_sp->netdevice_nb);
5226         if (mlxsw_sp->clock) {
5227                 mlxsw_sp->ptp_ops->fini(mlxsw_sp->ptp_state);
5228                 mlxsw_sp->ptp_ops->clock_fini(mlxsw_sp->clock);
5229         }
5230         mlxsw_sp_router_fini(mlxsw_sp);
5231         mlxsw_sp_acl_fini(mlxsw_sp);
5232         mlxsw_sp_nve_fini(mlxsw_sp);
5233         mlxsw_sp_afa_fini(mlxsw_sp);
5234         mlxsw_sp_counter_pool_fini(mlxsw_sp);
5235         mlxsw_sp_switchdev_fini(mlxsw_sp);
5236         mlxsw_sp_span_fini(mlxsw_sp);
5237         mlxsw_sp_lag_fini(mlxsw_sp);
5238         mlxsw_sp_buffers_fini(mlxsw_sp);
5239         mlxsw_sp_devlink_traps_fini(mlxsw_sp);
5240         mlxsw_sp_traps_fini(mlxsw_sp);
5241         mlxsw_sp_fids_fini(mlxsw_sp);
5242         mlxsw_sp_kvdl_fini(mlxsw_sp);
5243 }
5244
5245 /* Per-FID flood tables are used for both "true" 802.1D FIDs and emulated
5246  * 802.1Q FIDs
5247  */
5248 #define MLXSW_SP_FID_FLOOD_TABLE_SIZE   (MLXSW_SP_FID_8021D_MAX + \
5249                                          VLAN_VID_MASK - 1)
5250
5251 static const struct mlxsw_config_profile mlxsw_sp1_config_profile = {
5252         .used_max_mid                   = 1,
5253         .max_mid                        = MLXSW_SP_MID_MAX,
5254         .used_flood_tables              = 1,
5255         .used_flood_mode                = 1,
5256         .flood_mode                     = 3,
5257         .max_fid_flood_tables           = 3,
5258         .fid_flood_table_size           = MLXSW_SP_FID_FLOOD_TABLE_SIZE,
5259         .used_max_ib_mc                 = 1,
5260         .max_ib_mc                      = 0,
5261         .used_max_pkey                  = 1,
5262         .max_pkey                       = 0,
5263         .used_kvd_sizes                 = 1,
5264         .kvd_hash_single_parts          = 59,
5265         .kvd_hash_double_parts          = 41,
5266         .kvd_linear_size                = MLXSW_SP_KVD_LINEAR_SIZE,
5267         .swid_config                    = {
5268                 {
5269                         .used_type      = 1,
5270                         .type           = MLXSW_PORT_SWID_TYPE_ETH,
5271                 }
5272         },
5273 };
5274
5275 static const struct mlxsw_config_profile mlxsw_sp2_config_profile = {
5276         .used_max_mid                   = 1,
5277         .max_mid                        = MLXSW_SP_MID_MAX,
5278         .used_flood_tables              = 1,
5279         .used_flood_mode                = 1,
5280         .flood_mode                     = 3,
5281         .max_fid_flood_tables           = 3,
5282         .fid_flood_table_size           = MLXSW_SP_FID_FLOOD_TABLE_SIZE,
5283         .used_max_ib_mc                 = 1,
5284         .max_ib_mc                      = 0,
5285         .used_max_pkey                  = 1,
5286         .max_pkey                       = 0,
5287         .swid_config                    = {
5288                 {
5289                         .used_type      = 1,
5290                         .type           = MLXSW_PORT_SWID_TYPE_ETH,
5291                 }
5292         },
5293 };
5294
5295 static void
5296 mlxsw_sp_resource_size_params_prepare(struct mlxsw_core *mlxsw_core,
5297                                       struct devlink_resource_size_params *kvd_size_params,
5298                                       struct devlink_resource_size_params *linear_size_params,
5299                                       struct devlink_resource_size_params *hash_double_size_params,
5300                                       struct devlink_resource_size_params *hash_single_size_params)
5301 {
5302         u32 single_size_min = MLXSW_CORE_RES_GET(mlxsw_core,
5303                                                  KVD_SINGLE_MIN_SIZE);
5304         u32 double_size_min = MLXSW_CORE_RES_GET(mlxsw_core,
5305                                                  KVD_DOUBLE_MIN_SIZE);
5306         u32 kvd_size = MLXSW_CORE_RES_GET(mlxsw_core, KVD_SIZE);
5307         u32 linear_size_min = 0;
5308
5309         devlink_resource_size_params_init(kvd_size_params, kvd_size, kvd_size,
5310                                           MLXSW_SP_KVD_GRANULARITY,
5311                                           DEVLINK_RESOURCE_UNIT_ENTRY);
5312         devlink_resource_size_params_init(linear_size_params, linear_size_min,
5313                                           kvd_size - single_size_min -
5314                                           double_size_min,
5315                                           MLXSW_SP_KVD_GRANULARITY,
5316                                           DEVLINK_RESOURCE_UNIT_ENTRY);
5317         devlink_resource_size_params_init(hash_double_size_params,
5318                                           double_size_min,
5319                                           kvd_size - single_size_min -
5320                                           linear_size_min,
5321                                           MLXSW_SP_KVD_GRANULARITY,
5322                                           DEVLINK_RESOURCE_UNIT_ENTRY);
5323         devlink_resource_size_params_init(hash_single_size_params,
5324                                           single_size_min,
5325                                           kvd_size - double_size_min -
5326                                           linear_size_min,
5327                                           MLXSW_SP_KVD_GRANULARITY,
5328                                           DEVLINK_RESOURCE_UNIT_ENTRY);
5329 }
5330
5331 static int mlxsw_sp1_resources_kvd_register(struct mlxsw_core *mlxsw_core)
5332 {
5333         struct devlink *devlink = priv_to_devlink(mlxsw_core);
5334         struct devlink_resource_size_params hash_single_size_params;
5335         struct devlink_resource_size_params hash_double_size_params;
5336         struct devlink_resource_size_params linear_size_params;
5337         struct devlink_resource_size_params kvd_size_params;
5338         u32 kvd_size, single_size, double_size, linear_size;
5339         const struct mlxsw_config_profile *profile;
5340         int err;
5341
5342         profile = &mlxsw_sp1_config_profile;
5343         if (!MLXSW_CORE_RES_VALID(mlxsw_core, KVD_SIZE))
5344                 return -EIO;
5345
5346         mlxsw_sp_resource_size_params_prepare(mlxsw_core, &kvd_size_params,
5347                                               &linear_size_params,
5348                                               &hash_double_size_params,
5349                                               &hash_single_size_params);
5350
5351         kvd_size = MLXSW_CORE_RES_GET(mlxsw_core, KVD_SIZE);
5352         err = devlink_resource_register(devlink, MLXSW_SP_RESOURCE_NAME_KVD,
5353                                         kvd_size, MLXSW_SP_RESOURCE_KVD,
5354                                         DEVLINK_RESOURCE_ID_PARENT_TOP,
5355                                         &kvd_size_params);
5356         if (err)
5357                 return err;
5358
5359         linear_size = profile->kvd_linear_size;
5360         err = devlink_resource_register(devlink, MLXSW_SP_RESOURCE_NAME_KVD_LINEAR,
5361                                         linear_size,
5362                                         MLXSW_SP_RESOURCE_KVD_LINEAR,
5363                                         MLXSW_SP_RESOURCE_KVD,
5364                                         &linear_size_params);
5365         if (err)
5366                 return err;
5367
5368         err = mlxsw_sp1_kvdl_resources_register(mlxsw_core);
5369         if  (err)
5370                 return err;
5371
5372         double_size = kvd_size - linear_size;
5373         double_size *= profile->kvd_hash_double_parts;
5374         double_size /= profile->kvd_hash_double_parts +
5375                        profile->kvd_hash_single_parts;
5376         double_size = rounddown(double_size, MLXSW_SP_KVD_GRANULARITY);
5377         err = devlink_resource_register(devlink, MLXSW_SP_RESOURCE_NAME_KVD_HASH_DOUBLE,
5378                                         double_size,
5379                                         MLXSW_SP_RESOURCE_KVD_HASH_DOUBLE,
5380                                         MLXSW_SP_RESOURCE_KVD,
5381                                         &hash_double_size_params);
5382         if (err)
5383                 return err;
5384
5385         single_size = kvd_size - double_size - linear_size;
5386         err = devlink_resource_register(devlink, MLXSW_SP_RESOURCE_NAME_KVD_HASH_SINGLE,
5387                                         single_size,
5388                                         MLXSW_SP_RESOURCE_KVD_HASH_SINGLE,
5389                                         MLXSW_SP_RESOURCE_KVD,
5390                                         &hash_single_size_params);
5391         if (err)
5392                 return err;
5393
5394         return 0;
5395 }
5396
5397 static int mlxsw_sp2_resources_kvd_register(struct mlxsw_core *mlxsw_core)
5398 {
5399         struct devlink *devlink = priv_to_devlink(mlxsw_core);
5400         struct devlink_resource_size_params kvd_size_params;
5401         u32 kvd_size;
5402
5403         if (!MLXSW_CORE_RES_VALID(mlxsw_core, KVD_SIZE))
5404                 return -EIO;
5405
5406         kvd_size = MLXSW_CORE_RES_GET(mlxsw_core, KVD_SIZE);
5407         devlink_resource_size_params_init(&kvd_size_params, kvd_size, kvd_size,
5408                                           MLXSW_SP_KVD_GRANULARITY,
5409                                           DEVLINK_RESOURCE_UNIT_ENTRY);
5410
5411         return devlink_resource_register(devlink, MLXSW_SP_RESOURCE_NAME_KVD,
5412                                          kvd_size, MLXSW_SP_RESOURCE_KVD,
5413                                          DEVLINK_RESOURCE_ID_PARENT_TOP,
5414                                          &kvd_size_params);
5415 }
5416
5417 static int mlxsw_sp_resources_span_register(struct mlxsw_core *mlxsw_core)
5418 {
5419         struct devlink *devlink = priv_to_devlink(mlxsw_core);
5420         struct devlink_resource_size_params span_size_params;
5421         u32 max_span;
5422
5423         if (!MLXSW_CORE_RES_VALID(mlxsw_core, MAX_SPAN))
5424                 return -EIO;
5425
5426         max_span = MLXSW_CORE_RES_GET(mlxsw_core, MAX_SPAN);
5427         devlink_resource_size_params_init(&span_size_params, max_span, max_span,
5428                                           1, DEVLINK_RESOURCE_UNIT_ENTRY);
5429
5430         return devlink_resource_register(devlink, MLXSW_SP_RESOURCE_NAME_SPAN,
5431                                          max_span, MLXSW_SP_RESOURCE_SPAN,
5432                                          DEVLINK_RESOURCE_ID_PARENT_TOP,
5433                                          &span_size_params);
5434 }
5435
5436 static int mlxsw_sp1_resources_register(struct mlxsw_core *mlxsw_core)
5437 {
5438         int err;
5439
5440         err = mlxsw_sp1_resources_kvd_register(mlxsw_core);
5441         if (err)
5442                 return err;
5443
5444         err = mlxsw_sp_resources_span_register(mlxsw_core);
5445         if (err)
5446                 goto err_resources_span_register;
5447
5448         return 0;
5449
5450 err_resources_span_register:
5451         devlink_resources_unregister(priv_to_devlink(mlxsw_core), NULL);
5452         return err;
5453 }
5454
5455 static int mlxsw_sp2_resources_register(struct mlxsw_core *mlxsw_core)
5456 {
5457         int err;
5458
5459         err = mlxsw_sp2_resources_kvd_register(mlxsw_core);
5460         if (err)
5461                 return err;
5462
5463         err = mlxsw_sp_resources_span_register(mlxsw_core);
5464         if (err)
5465                 goto err_resources_span_register;
5466
5467         return 0;
5468
5469 err_resources_span_register:
5470         devlink_resources_unregister(priv_to_devlink(mlxsw_core), NULL);
5471         return err;
5472 }
5473
5474 static int mlxsw_sp_kvd_sizes_get(struct mlxsw_core *mlxsw_core,
5475                                   const struct mlxsw_config_profile *profile,
5476                                   u64 *p_single_size, u64 *p_double_size,
5477                                   u64 *p_linear_size)
5478 {
5479         struct devlink *devlink = priv_to_devlink(mlxsw_core);
5480         u32 double_size;
5481         int err;
5482
5483         if (!MLXSW_CORE_RES_VALID(mlxsw_core, KVD_SINGLE_MIN_SIZE) ||
5484             !MLXSW_CORE_RES_VALID(mlxsw_core, KVD_DOUBLE_MIN_SIZE))
5485                 return -EIO;
5486
5487         /* The hash part is what left of the kvd without the
5488          * linear part. It is split to the single size and
5489          * double size by the parts ratio from the profile.
5490          * Both sizes must be a multiplications of the
5491          * granularity from the profile. In case the user
5492          * provided the sizes they are obtained via devlink.
5493          */
5494         err = devlink_resource_size_get(devlink,
5495                                         MLXSW_SP_RESOURCE_KVD_LINEAR,
5496                                         p_linear_size);
5497         if (err)
5498                 *p_linear_size = profile->kvd_linear_size;
5499
5500         err = devlink_resource_size_get(devlink,
5501                                         MLXSW_SP_RESOURCE_KVD_HASH_DOUBLE,
5502                                         p_double_size);
5503         if (err) {
5504                 double_size = MLXSW_CORE_RES_GET(mlxsw_core, KVD_SIZE) -
5505                               *p_linear_size;
5506                 double_size *= profile->kvd_hash_double_parts;
5507                 double_size /= profile->kvd_hash_double_parts +
5508                                profile->kvd_hash_single_parts;
5509                 *p_double_size = rounddown(double_size,
5510                                            MLXSW_SP_KVD_GRANULARITY);
5511         }
5512
5513         err = devlink_resource_size_get(devlink,
5514                                         MLXSW_SP_RESOURCE_KVD_HASH_SINGLE,
5515                                         p_single_size);
5516         if (err)
5517                 *p_single_size = MLXSW_CORE_RES_GET(mlxsw_core, KVD_SIZE) -
5518                                  *p_double_size - *p_linear_size;
5519
5520         /* Check results are legal. */
5521         if (*p_single_size < MLXSW_CORE_RES_GET(mlxsw_core, KVD_SINGLE_MIN_SIZE) ||
5522             *p_double_size < MLXSW_CORE_RES_GET(mlxsw_core, KVD_DOUBLE_MIN_SIZE) ||
5523             MLXSW_CORE_RES_GET(mlxsw_core, KVD_SIZE) < *p_linear_size)
5524                 return -EIO;
5525
5526         return 0;
5527 }
5528
5529 static int
5530 mlxsw_sp_devlink_param_fw_load_policy_validate(struct devlink *devlink, u32 id,
5531                                                union devlink_param_value val,
5532                                                struct netlink_ext_ack *extack)
5533 {
5534         if ((val.vu8 != DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_DRIVER) &&
5535             (val.vu8 != DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_FLASH)) {
5536                 NL_SET_ERR_MSG_MOD(extack, "'fw_load_policy' must be 'driver' or 'flash'");
5537                 return -EINVAL;
5538         }
5539
5540         return 0;
5541 }
5542
5543 static const struct devlink_param mlxsw_sp_devlink_params[] = {
5544         DEVLINK_PARAM_GENERIC(FW_LOAD_POLICY,
5545                               BIT(DEVLINK_PARAM_CMODE_DRIVERINIT),
5546                               NULL, NULL,
5547                               mlxsw_sp_devlink_param_fw_load_policy_validate),
5548 };
5549
5550 static int mlxsw_sp_params_register(struct mlxsw_core *mlxsw_core)
5551 {
5552         struct devlink *devlink = priv_to_devlink(mlxsw_core);
5553         union devlink_param_value value;
5554         int err;
5555
5556         err = devlink_params_register(devlink, mlxsw_sp_devlink_params,
5557                                       ARRAY_SIZE(mlxsw_sp_devlink_params));
5558         if (err)
5559                 return err;
5560
5561         value.vu8 = DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_DRIVER;
5562         devlink_param_driverinit_value_set(devlink,
5563                                            DEVLINK_PARAM_GENERIC_ID_FW_LOAD_POLICY,
5564                                            value);
5565         return 0;
5566 }
5567
5568 static void mlxsw_sp_params_unregister(struct mlxsw_core *mlxsw_core)
5569 {
5570         devlink_params_unregister(priv_to_devlink(mlxsw_core),
5571                                   mlxsw_sp_devlink_params,
5572                                   ARRAY_SIZE(mlxsw_sp_devlink_params));
5573 }
5574
5575 static int
5576 mlxsw_sp_params_acl_region_rehash_intrvl_get(struct devlink *devlink, u32 id,
5577                                              struct devlink_param_gset_ctx *ctx)
5578 {
5579         struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
5580         struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
5581
5582         ctx->val.vu32 = mlxsw_sp_acl_region_rehash_intrvl_get(mlxsw_sp);
5583         return 0;
5584 }
5585
5586 static int
5587 mlxsw_sp_params_acl_region_rehash_intrvl_set(struct devlink *devlink, u32 id,
5588                                              struct devlink_param_gset_ctx *ctx)
5589 {
5590         struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
5591         struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
5592
5593         return mlxsw_sp_acl_region_rehash_intrvl_set(mlxsw_sp, ctx->val.vu32);
5594 }
5595
5596 static const struct devlink_param mlxsw_sp2_devlink_params[] = {
5597         DEVLINK_PARAM_DRIVER(MLXSW_DEVLINK_PARAM_ID_ACL_REGION_REHASH_INTERVAL,
5598                              "acl_region_rehash_interval",
5599                              DEVLINK_PARAM_TYPE_U32,
5600                              BIT(DEVLINK_PARAM_CMODE_RUNTIME),
5601                              mlxsw_sp_params_acl_region_rehash_intrvl_get,
5602                              mlxsw_sp_params_acl_region_rehash_intrvl_set,
5603                              NULL),
5604 };
5605
5606 static int mlxsw_sp2_params_register(struct mlxsw_core *mlxsw_core)
5607 {
5608         struct devlink *devlink = priv_to_devlink(mlxsw_core);
5609         union devlink_param_value value;
5610         int err;
5611
5612         err = mlxsw_sp_params_register(mlxsw_core);
5613         if (err)
5614                 return err;
5615
5616         err = devlink_params_register(devlink, mlxsw_sp2_devlink_params,
5617                                       ARRAY_SIZE(mlxsw_sp2_devlink_params));
5618         if (err)
5619                 goto err_devlink_params_register;
5620
5621         value.vu32 = 0;
5622         devlink_param_driverinit_value_set(devlink,
5623                                            MLXSW_DEVLINK_PARAM_ID_ACL_REGION_REHASH_INTERVAL,
5624                                            value);
5625         return 0;
5626
5627 err_devlink_params_register:
5628         mlxsw_sp_params_unregister(mlxsw_core);
5629         return err;
5630 }
5631
5632 static void mlxsw_sp2_params_unregister(struct mlxsw_core *mlxsw_core)
5633 {
5634         devlink_params_unregister(priv_to_devlink(mlxsw_core),
5635                                   mlxsw_sp2_devlink_params,
5636                                   ARRAY_SIZE(mlxsw_sp2_devlink_params));
5637         mlxsw_sp_params_unregister(mlxsw_core);
5638 }
5639
5640 static void mlxsw_sp_ptp_transmitted(struct mlxsw_core *mlxsw_core,
5641                                      struct sk_buff *skb, u8 local_port)
5642 {
5643         struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
5644
5645         skb_pull(skb, MLXSW_TXHDR_LEN);
5646         mlxsw_sp->ptp_ops->transmitted(mlxsw_sp, skb, local_port);
5647 }
5648
5649 static struct mlxsw_driver mlxsw_sp1_driver = {
5650         .kind                           = mlxsw_sp1_driver_name,
5651         .priv_size                      = sizeof(struct mlxsw_sp),
5652         .init                           = mlxsw_sp1_init,
5653         .fini                           = mlxsw_sp_fini,
5654         .basic_trap_groups_set          = mlxsw_sp_basic_trap_groups_set,
5655         .port_split                     = mlxsw_sp_port_split,
5656         .port_unsplit                   = mlxsw_sp_port_unsplit,
5657         .sb_pool_get                    = mlxsw_sp_sb_pool_get,
5658         .sb_pool_set                    = mlxsw_sp_sb_pool_set,
5659         .sb_port_pool_get               = mlxsw_sp_sb_port_pool_get,
5660         .sb_port_pool_set               = mlxsw_sp_sb_port_pool_set,
5661         .sb_tc_pool_bind_get            = mlxsw_sp_sb_tc_pool_bind_get,
5662         .sb_tc_pool_bind_set            = mlxsw_sp_sb_tc_pool_bind_set,
5663         .sb_occ_snapshot                = mlxsw_sp_sb_occ_snapshot,
5664         .sb_occ_max_clear               = mlxsw_sp_sb_occ_max_clear,
5665         .sb_occ_port_pool_get           = mlxsw_sp_sb_occ_port_pool_get,
5666         .sb_occ_tc_port_bind_get        = mlxsw_sp_sb_occ_tc_port_bind_get,
5667         .flash_update                   = mlxsw_sp_flash_update,
5668         .trap_init                      = mlxsw_sp_trap_init,
5669         .trap_fini                      = mlxsw_sp_trap_fini,
5670         .trap_action_set                = mlxsw_sp_trap_action_set,
5671         .trap_group_init                = mlxsw_sp_trap_group_init,
5672         .txhdr_construct                = mlxsw_sp_txhdr_construct,
5673         .resources_register             = mlxsw_sp1_resources_register,
5674         .kvd_sizes_get                  = mlxsw_sp_kvd_sizes_get,
5675         .params_register                = mlxsw_sp_params_register,
5676         .params_unregister              = mlxsw_sp_params_unregister,
5677         .ptp_transmitted                = mlxsw_sp_ptp_transmitted,
5678         .txhdr_len                      = MLXSW_TXHDR_LEN,
5679         .profile                        = &mlxsw_sp1_config_profile,
5680         .res_query_enabled              = true,
5681 };
5682
5683 static struct mlxsw_driver mlxsw_sp2_driver = {
5684         .kind                           = mlxsw_sp2_driver_name,
5685         .priv_size                      = sizeof(struct mlxsw_sp),
5686         .init                           = mlxsw_sp2_init,
5687         .fini                           = mlxsw_sp_fini,
5688         .basic_trap_groups_set          = mlxsw_sp_basic_trap_groups_set,
5689         .port_split                     = mlxsw_sp_port_split,
5690         .port_unsplit                   = mlxsw_sp_port_unsplit,
5691         .sb_pool_get                    = mlxsw_sp_sb_pool_get,
5692         .sb_pool_set                    = mlxsw_sp_sb_pool_set,
5693         .sb_port_pool_get               = mlxsw_sp_sb_port_pool_get,
5694         .sb_port_pool_set               = mlxsw_sp_sb_port_pool_set,
5695         .sb_tc_pool_bind_get            = mlxsw_sp_sb_tc_pool_bind_get,
5696         .sb_tc_pool_bind_set            = mlxsw_sp_sb_tc_pool_bind_set,
5697         .sb_occ_snapshot                = mlxsw_sp_sb_occ_snapshot,
5698         .sb_occ_max_clear               = mlxsw_sp_sb_occ_max_clear,
5699         .sb_occ_port_pool_get           = mlxsw_sp_sb_occ_port_pool_get,
5700         .sb_occ_tc_port_bind_get        = mlxsw_sp_sb_occ_tc_port_bind_get,
5701         .flash_update                   = mlxsw_sp_flash_update,
5702         .trap_init                      = mlxsw_sp_trap_init,
5703         .trap_fini                      = mlxsw_sp_trap_fini,
5704         .trap_action_set                = mlxsw_sp_trap_action_set,
5705         .trap_group_init                = mlxsw_sp_trap_group_init,
5706         .txhdr_construct                = mlxsw_sp_txhdr_construct,
5707         .resources_register             = mlxsw_sp2_resources_register,
5708         .params_register                = mlxsw_sp2_params_register,
5709         .params_unregister              = mlxsw_sp2_params_unregister,
5710         .ptp_transmitted                = mlxsw_sp_ptp_transmitted,
5711         .txhdr_len                      = MLXSW_TXHDR_LEN,
5712         .profile                        = &mlxsw_sp2_config_profile,
5713         .res_query_enabled              = true,
5714 };
5715
5716 static struct mlxsw_driver mlxsw_sp3_driver = {
5717         .kind                           = mlxsw_sp3_driver_name,
5718         .priv_size                      = sizeof(struct mlxsw_sp),
5719         .init                           = mlxsw_sp3_init,
5720         .fini                           = mlxsw_sp_fini,
5721         .basic_trap_groups_set          = mlxsw_sp_basic_trap_groups_set,
5722         .port_split                     = mlxsw_sp_port_split,
5723         .port_unsplit                   = mlxsw_sp_port_unsplit,
5724         .sb_pool_get                    = mlxsw_sp_sb_pool_get,
5725         .sb_pool_set                    = mlxsw_sp_sb_pool_set,
5726         .sb_port_pool_get               = mlxsw_sp_sb_port_pool_get,
5727         .sb_port_pool_set               = mlxsw_sp_sb_port_pool_set,
5728         .sb_tc_pool_bind_get            = mlxsw_sp_sb_tc_pool_bind_get,
5729         .sb_tc_pool_bind_set            = mlxsw_sp_sb_tc_pool_bind_set,
5730         .sb_occ_snapshot                = mlxsw_sp_sb_occ_snapshot,
5731         .sb_occ_max_clear               = mlxsw_sp_sb_occ_max_clear,
5732         .sb_occ_port_pool_get           = mlxsw_sp_sb_occ_port_pool_get,
5733         .sb_occ_tc_port_bind_get        = mlxsw_sp_sb_occ_tc_port_bind_get,
5734         .flash_update                   = mlxsw_sp_flash_update,
5735         .trap_init                      = mlxsw_sp_trap_init,
5736         .trap_fini                      = mlxsw_sp_trap_fini,
5737         .trap_action_set                = mlxsw_sp_trap_action_set,
5738         .trap_group_init                = mlxsw_sp_trap_group_init,
5739         .txhdr_construct                = mlxsw_sp_txhdr_construct,
5740         .resources_register             = mlxsw_sp2_resources_register,
5741         .params_register                = mlxsw_sp2_params_register,
5742         .params_unregister              = mlxsw_sp2_params_unregister,
5743         .ptp_transmitted                = mlxsw_sp_ptp_transmitted,
5744         .txhdr_len                      = MLXSW_TXHDR_LEN,
5745         .profile                        = &mlxsw_sp2_config_profile,
5746         .res_query_enabled              = true,
5747 };
5748
5749 bool mlxsw_sp_port_dev_check(const struct net_device *dev)
5750 {
5751         return dev->netdev_ops == &mlxsw_sp_port_netdev_ops;
5752 }
5753
5754 static int mlxsw_sp_lower_dev_walk(struct net_device *lower_dev, void *data)
5755 {
5756         struct mlxsw_sp_port **p_mlxsw_sp_port = data;
5757         int ret = 0;
5758
5759         if (mlxsw_sp_port_dev_check(lower_dev)) {
5760                 *p_mlxsw_sp_port = netdev_priv(lower_dev);
5761                 ret = 1;
5762         }
5763
5764         return ret;
5765 }
5766
5767 struct mlxsw_sp_port *mlxsw_sp_port_dev_lower_find(struct net_device *dev)
5768 {
5769         struct mlxsw_sp_port *mlxsw_sp_port;
5770
5771         if (mlxsw_sp_port_dev_check(dev))
5772                 return netdev_priv(dev);
5773
5774         mlxsw_sp_port = NULL;
5775         netdev_walk_all_lower_dev(dev, mlxsw_sp_lower_dev_walk, &mlxsw_sp_port);
5776
5777         return mlxsw_sp_port;
5778 }
5779
5780 struct mlxsw_sp *mlxsw_sp_lower_get(struct net_device *dev)
5781 {
5782         struct mlxsw_sp_port *mlxsw_sp_port;
5783
5784         mlxsw_sp_port = mlxsw_sp_port_dev_lower_find(dev);
5785         return mlxsw_sp_port ? mlxsw_sp_port->mlxsw_sp : NULL;
5786 }
5787
5788 struct mlxsw_sp_port *mlxsw_sp_port_dev_lower_find_rcu(struct net_device *dev)
5789 {
5790         struct mlxsw_sp_port *mlxsw_sp_port;
5791
5792         if (mlxsw_sp_port_dev_check(dev))
5793                 return netdev_priv(dev);
5794
5795         mlxsw_sp_port = NULL;
5796         netdev_walk_all_lower_dev_rcu(dev, mlxsw_sp_lower_dev_walk,
5797                                       &mlxsw_sp_port);
5798
5799         return mlxsw_sp_port;
5800 }
5801
5802 struct mlxsw_sp_port *mlxsw_sp_port_lower_dev_hold(struct net_device *dev)
5803 {
5804         struct mlxsw_sp_port *mlxsw_sp_port;
5805
5806         rcu_read_lock();
5807         mlxsw_sp_port = mlxsw_sp_port_dev_lower_find_rcu(dev);
5808         if (mlxsw_sp_port)
5809                 dev_hold(mlxsw_sp_port->dev);
5810         rcu_read_unlock();
5811         return mlxsw_sp_port;
5812 }
5813
5814 void mlxsw_sp_port_dev_put(struct mlxsw_sp_port *mlxsw_sp_port)
5815 {
5816         dev_put(mlxsw_sp_port->dev);
5817 }
5818
5819 static void
5820 mlxsw_sp_port_lag_uppers_cleanup(struct mlxsw_sp_port *mlxsw_sp_port,
5821                                  struct net_device *lag_dev)
5822 {
5823         struct net_device *br_dev = netdev_master_upper_dev_get(lag_dev);
5824         struct net_device *upper_dev;
5825         struct list_head *iter;
5826
5827         if (netif_is_bridge_port(lag_dev))
5828                 mlxsw_sp_port_bridge_leave(mlxsw_sp_port, lag_dev, br_dev);
5829
5830         netdev_for_each_upper_dev_rcu(lag_dev, upper_dev, iter) {
5831                 if (!netif_is_bridge_port(upper_dev))
5832                         continue;
5833                 br_dev = netdev_master_upper_dev_get(upper_dev);
5834                 mlxsw_sp_port_bridge_leave(mlxsw_sp_port, upper_dev, br_dev);
5835         }
5836 }
5837
5838 static int mlxsw_sp_lag_create(struct mlxsw_sp *mlxsw_sp, u16 lag_id)
5839 {
5840         char sldr_pl[MLXSW_REG_SLDR_LEN];
5841
5842         mlxsw_reg_sldr_lag_create_pack(sldr_pl, lag_id);
5843         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sldr), sldr_pl);
5844 }
5845
5846 static int mlxsw_sp_lag_destroy(struct mlxsw_sp *mlxsw_sp, u16 lag_id)
5847 {
5848         char sldr_pl[MLXSW_REG_SLDR_LEN];
5849
5850         mlxsw_reg_sldr_lag_destroy_pack(sldr_pl, lag_id);
5851         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sldr), sldr_pl);
5852 }
5853
5854 static int mlxsw_sp_lag_col_port_add(struct mlxsw_sp_port *mlxsw_sp_port,
5855                                      u16 lag_id, u8 port_index)
5856 {
5857         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
5858         char slcor_pl[MLXSW_REG_SLCOR_LEN];
5859
5860         mlxsw_reg_slcor_port_add_pack(slcor_pl, mlxsw_sp_port->local_port,
5861                                       lag_id, port_index);
5862         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(slcor), slcor_pl);
5863 }
5864
5865 static int mlxsw_sp_lag_col_port_remove(struct mlxsw_sp_port *mlxsw_sp_port,
5866                                         u16 lag_id)
5867 {
5868         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
5869         char slcor_pl[MLXSW_REG_SLCOR_LEN];
5870
5871         mlxsw_reg_slcor_port_remove_pack(slcor_pl, mlxsw_sp_port->local_port,
5872                                          lag_id);
5873         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(slcor), slcor_pl);
5874 }
5875
5876 static int mlxsw_sp_lag_col_port_enable(struct mlxsw_sp_port *mlxsw_sp_port,
5877                                         u16 lag_id)
5878 {
5879         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
5880         char slcor_pl[MLXSW_REG_SLCOR_LEN];
5881
5882         mlxsw_reg_slcor_col_enable_pack(slcor_pl, mlxsw_sp_port->local_port,
5883                                         lag_id);
5884         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(slcor), slcor_pl);
5885 }
5886
5887 static int mlxsw_sp_lag_col_port_disable(struct mlxsw_sp_port *mlxsw_sp_port,
5888                                          u16 lag_id)
5889 {
5890         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
5891         char slcor_pl[MLXSW_REG_SLCOR_LEN];
5892
5893         mlxsw_reg_slcor_col_disable_pack(slcor_pl, mlxsw_sp_port->local_port,
5894                                          lag_id);
5895         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(slcor), slcor_pl);
5896 }
5897
5898 static int mlxsw_sp_lag_index_get(struct mlxsw_sp *mlxsw_sp,
5899                                   struct net_device *lag_dev,
5900                                   u16 *p_lag_id)
5901 {
5902         struct mlxsw_sp_upper *lag;
5903         int free_lag_id = -1;
5904         u64 max_lag;
5905         int i;
5906
5907         max_lag = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_LAG);
5908         for (i = 0; i < max_lag; i++) {
5909                 lag = mlxsw_sp_lag_get(mlxsw_sp, i);
5910                 if (lag->ref_count) {
5911                         if (lag->dev == lag_dev) {
5912                                 *p_lag_id = i;
5913                                 return 0;
5914                         }
5915                 } else if (free_lag_id < 0) {
5916                         free_lag_id = i;
5917                 }
5918         }
5919         if (free_lag_id < 0)
5920                 return -EBUSY;
5921         *p_lag_id = free_lag_id;
5922         return 0;
5923 }
5924
5925 static bool
5926 mlxsw_sp_master_lag_check(struct mlxsw_sp *mlxsw_sp,
5927                           struct net_device *lag_dev,
5928                           struct netdev_lag_upper_info *lag_upper_info,
5929                           struct netlink_ext_ack *extack)
5930 {
5931         u16 lag_id;
5932
5933         if (mlxsw_sp_lag_index_get(mlxsw_sp, lag_dev, &lag_id) != 0) {
5934                 NL_SET_ERR_MSG_MOD(extack, "Exceeded number of supported LAG devices");
5935                 return false;
5936         }
5937         if (lag_upper_info->tx_type != NETDEV_LAG_TX_TYPE_HASH) {
5938                 NL_SET_ERR_MSG_MOD(extack, "LAG device using unsupported Tx type");
5939                 return false;
5940         }
5941         return true;
5942 }
5943
5944 static int mlxsw_sp_port_lag_index_get(struct mlxsw_sp *mlxsw_sp,
5945                                        u16 lag_id, u8 *p_port_index)
5946 {
5947         u64 max_lag_members;
5948         int i;
5949
5950         max_lag_members = MLXSW_CORE_RES_GET(mlxsw_sp->core,
5951                                              MAX_LAG_MEMBERS);
5952         for (i = 0; i < max_lag_members; i++) {
5953                 if (!mlxsw_sp_port_lagged_get(mlxsw_sp, lag_id, i)) {
5954                         *p_port_index = i;
5955                         return 0;
5956                 }
5957         }
5958         return -EBUSY;
5959 }
5960
5961 static int mlxsw_sp_port_lag_join(struct mlxsw_sp_port *mlxsw_sp_port,
5962                                   struct net_device *lag_dev)
5963 {
5964         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
5965         struct mlxsw_sp_upper *lag;
5966         u16 lag_id;
5967         u8 port_index;
5968         int err;
5969
5970         err = mlxsw_sp_lag_index_get(mlxsw_sp, lag_dev, &lag_id);
5971         if (err)
5972                 return err;
5973         lag = mlxsw_sp_lag_get(mlxsw_sp, lag_id);
5974         if (!lag->ref_count) {
5975                 err = mlxsw_sp_lag_create(mlxsw_sp, lag_id);
5976                 if (err)
5977                         return err;
5978                 lag->dev = lag_dev;
5979         }
5980
5981         err = mlxsw_sp_port_lag_index_get(mlxsw_sp, lag_id, &port_index);
5982         if (err)
5983                 return err;
5984         err = mlxsw_sp_lag_col_port_add(mlxsw_sp_port, lag_id, port_index);
5985         if (err)
5986                 goto err_col_port_add;
5987
5988         mlxsw_core_lag_mapping_set(mlxsw_sp->core, lag_id, port_index,
5989                                    mlxsw_sp_port->local_port);
5990         mlxsw_sp_port->lag_id = lag_id;
5991         mlxsw_sp_port->lagged = 1;
5992         lag->ref_count++;
5993
5994         /* Port is no longer usable as a router interface */
5995         if (mlxsw_sp_port->default_vlan->fid)
5996                 mlxsw_sp_port_vlan_router_leave(mlxsw_sp_port->default_vlan);
5997
5998         return 0;
5999
6000 err_col_port_add:
6001         if (!lag->ref_count)
6002                 mlxsw_sp_lag_destroy(mlxsw_sp, lag_id);
6003         return err;
6004 }
6005
6006 static void mlxsw_sp_port_lag_leave(struct mlxsw_sp_port *mlxsw_sp_port,
6007                                     struct net_device *lag_dev)
6008 {
6009         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
6010         u16 lag_id = mlxsw_sp_port->lag_id;
6011         struct mlxsw_sp_upper *lag;
6012
6013         if (!mlxsw_sp_port->lagged)
6014                 return;
6015         lag = mlxsw_sp_lag_get(mlxsw_sp, lag_id);
6016         WARN_ON(lag->ref_count == 0);
6017
6018         mlxsw_sp_lag_col_port_remove(mlxsw_sp_port, lag_id);
6019
6020         /* Any VLANs configured on the port are no longer valid */
6021         mlxsw_sp_port_vlan_flush(mlxsw_sp_port, false);
6022         mlxsw_sp_port_vlan_cleanup(mlxsw_sp_port->default_vlan);
6023         /* Make the LAG and its directly linked uppers leave bridges they
6024          * are memeber in
6025          */
6026         mlxsw_sp_port_lag_uppers_cleanup(mlxsw_sp_port, lag_dev);
6027
6028         if (lag->ref_count == 1)
6029                 mlxsw_sp_lag_destroy(mlxsw_sp, lag_id);
6030
6031         mlxsw_core_lag_mapping_clear(mlxsw_sp->core, lag_id,
6032                                      mlxsw_sp_port->local_port);
6033         mlxsw_sp_port->lagged = 0;
6034         lag->ref_count--;
6035
6036         /* Make sure untagged frames are allowed to ingress */
6037         mlxsw_sp_port_pvid_set(mlxsw_sp_port, MLXSW_SP_DEFAULT_VID);
6038 }
6039
6040 static int mlxsw_sp_lag_dist_port_add(struct mlxsw_sp_port *mlxsw_sp_port,
6041                                       u16 lag_id)
6042 {
6043         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
6044         char sldr_pl[MLXSW_REG_SLDR_LEN];
6045
6046         mlxsw_reg_sldr_lag_add_port_pack(sldr_pl, lag_id,
6047                                          mlxsw_sp_port->local_port);
6048         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sldr), sldr_pl);
6049 }
6050
6051 static int mlxsw_sp_lag_dist_port_remove(struct mlxsw_sp_port *mlxsw_sp_port,
6052                                          u16 lag_id)
6053 {
6054         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
6055         char sldr_pl[MLXSW_REG_SLDR_LEN];
6056
6057         mlxsw_reg_sldr_lag_remove_port_pack(sldr_pl, lag_id,
6058                                             mlxsw_sp_port->local_port);
6059         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sldr), sldr_pl);
6060 }
6061
6062 static int
6063 mlxsw_sp_port_lag_col_dist_enable(struct mlxsw_sp_port *mlxsw_sp_port)
6064 {
6065         int err;
6066
6067         err = mlxsw_sp_lag_col_port_enable(mlxsw_sp_port,
6068                                            mlxsw_sp_port->lag_id);
6069         if (err)
6070                 return err;
6071
6072         err = mlxsw_sp_lag_dist_port_add(mlxsw_sp_port, mlxsw_sp_port->lag_id);
6073         if (err)
6074                 goto err_dist_port_add;
6075
6076         return 0;
6077
6078 err_dist_port_add:
6079         mlxsw_sp_lag_col_port_disable(mlxsw_sp_port, mlxsw_sp_port->lag_id);
6080         return err;
6081 }
6082
6083 static int
6084 mlxsw_sp_port_lag_col_dist_disable(struct mlxsw_sp_port *mlxsw_sp_port)
6085 {
6086         int err;
6087
6088         err = mlxsw_sp_lag_dist_port_remove(mlxsw_sp_port,
6089                                             mlxsw_sp_port->lag_id);
6090         if (err)
6091                 return err;
6092
6093         err = mlxsw_sp_lag_col_port_disable(mlxsw_sp_port,
6094                                             mlxsw_sp_port->lag_id);
6095         if (err)
6096                 goto err_col_port_disable;
6097
6098         return 0;
6099
6100 err_col_port_disable:
6101         mlxsw_sp_lag_dist_port_add(mlxsw_sp_port, mlxsw_sp_port->lag_id);
6102         return err;
6103 }
6104
6105 static int mlxsw_sp_port_lag_changed(struct mlxsw_sp_port *mlxsw_sp_port,
6106                                      struct netdev_lag_lower_state_info *info)
6107 {
6108         if (info->tx_enabled)
6109                 return mlxsw_sp_port_lag_col_dist_enable(mlxsw_sp_port);
6110         else
6111                 return mlxsw_sp_port_lag_col_dist_disable(mlxsw_sp_port);
6112 }
6113
6114 static int mlxsw_sp_port_stp_set(struct mlxsw_sp_port *mlxsw_sp_port,
6115                                  bool enable)
6116 {
6117         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
6118         enum mlxsw_reg_spms_state spms_state;
6119         char *spms_pl;
6120         u16 vid;
6121         int err;
6122
6123         spms_state = enable ? MLXSW_REG_SPMS_STATE_FORWARDING :
6124                               MLXSW_REG_SPMS_STATE_DISCARDING;
6125
6126         spms_pl = kmalloc(MLXSW_REG_SPMS_LEN, GFP_KERNEL);
6127         if (!spms_pl)
6128                 return -ENOMEM;
6129         mlxsw_reg_spms_pack(spms_pl, mlxsw_sp_port->local_port);
6130
6131         for (vid = 0; vid < VLAN_N_VID; vid++)
6132                 mlxsw_reg_spms_vid_pack(spms_pl, vid, spms_state);
6133
6134         err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(spms), spms_pl);
6135         kfree(spms_pl);
6136         return err;
6137 }
6138
6139 static int mlxsw_sp_port_ovs_join(struct mlxsw_sp_port *mlxsw_sp_port)
6140 {
6141         u16 vid = 1;
6142         int err;
6143
6144         err = mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, true);
6145         if (err)
6146                 return err;
6147         err = mlxsw_sp_port_stp_set(mlxsw_sp_port, true);
6148         if (err)
6149                 goto err_port_stp_set;
6150         err = mlxsw_sp_port_vlan_set(mlxsw_sp_port, 1, VLAN_N_VID - 2,
6151                                      true, false);
6152         if (err)
6153                 goto err_port_vlan_set;
6154
6155         for (; vid <= VLAN_N_VID - 1; vid++) {
6156                 err = mlxsw_sp_port_vid_learning_set(mlxsw_sp_port,
6157                                                      vid, false);
6158                 if (err)
6159                         goto err_vid_learning_set;
6160         }
6161
6162         return 0;
6163
6164 err_vid_learning_set:
6165         for (vid--; vid >= 1; vid--)
6166                 mlxsw_sp_port_vid_learning_set(mlxsw_sp_port, vid, true);
6167 err_port_vlan_set:
6168         mlxsw_sp_port_stp_set(mlxsw_sp_port, false);
6169 err_port_stp_set:
6170         mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, false);
6171         return err;
6172 }
6173
6174 static void mlxsw_sp_port_ovs_leave(struct mlxsw_sp_port *mlxsw_sp_port)
6175 {
6176         u16 vid;
6177
6178         for (vid = VLAN_N_VID - 1; vid >= 1; vid--)
6179                 mlxsw_sp_port_vid_learning_set(mlxsw_sp_port,
6180                                                vid, true);
6181
6182         mlxsw_sp_port_vlan_set(mlxsw_sp_port, 1, VLAN_N_VID - 2,
6183                                false, false);
6184         mlxsw_sp_port_stp_set(mlxsw_sp_port, false);
6185         mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, false);
6186 }
6187
6188 static bool mlxsw_sp_bridge_has_multiple_vxlans(struct net_device *br_dev)
6189 {
6190         unsigned int num_vxlans = 0;
6191         struct net_device *dev;
6192         struct list_head *iter;
6193
6194         netdev_for_each_lower_dev(br_dev, dev, iter) {
6195                 if (netif_is_vxlan(dev))
6196                         num_vxlans++;
6197         }
6198
6199         return num_vxlans > 1;
6200 }
6201
6202 static bool mlxsw_sp_bridge_vxlan_vlan_is_valid(struct net_device *br_dev)
6203 {
6204         DECLARE_BITMAP(vlans, VLAN_N_VID) = {0};
6205         struct net_device *dev;
6206         struct list_head *iter;
6207
6208         netdev_for_each_lower_dev(br_dev, dev, iter) {
6209                 u16 pvid;
6210                 int err;
6211
6212                 if (!netif_is_vxlan(dev))
6213                         continue;
6214
6215                 err = mlxsw_sp_vxlan_mapped_vid(dev, &pvid);
6216                 if (err || !pvid)
6217                         continue;
6218
6219                 if (test_and_set_bit(pvid, vlans))
6220                         return false;
6221         }
6222
6223         return true;
6224 }
6225
6226 static bool mlxsw_sp_bridge_vxlan_is_valid(struct net_device *br_dev,
6227                                            struct netlink_ext_ack *extack)
6228 {
6229         if (br_multicast_enabled(br_dev)) {
6230                 NL_SET_ERR_MSG_MOD(extack, "Multicast can not be enabled on a bridge with a VxLAN device");
6231                 return false;
6232         }
6233
6234         if (!br_vlan_enabled(br_dev) &&
6235             mlxsw_sp_bridge_has_multiple_vxlans(br_dev)) {
6236                 NL_SET_ERR_MSG_MOD(extack, "Multiple VxLAN devices are not supported in a VLAN-unaware bridge");
6237                 return false;
6238         }
6239
6240         if (br_vlan_enabled(br_dev) &&
6241             !mlxsw_sp_bridge_vxlan_vlan_is_valid(br_dev)) {
6242                 NL_SET_ERR_MSG_MOD(extack, "Multiple VxLAN devices cannot have the same VLAN as PVID and egress untagged");
6243                 return false;
6244         }
6245
6246         return true;
6247 }
6248
6249 static int mlxsw_sp_netdevice_port_upper_event(struct net_device *lower_dev,
6250                                                struct net_device *dev,
6251                                                unsigned long event, void *ptr)
6252 {
6253         struct netdev_notifier_changeupper_info *info;
6254         struct mlxsw_sp_port *mlxsw_sp_port;
6255         struct netlink_ext_ack *extack;
6256         struct net_device *upper_dev;
6257         struct mlxsw_sp *mlxsw_sp;
6258         int err = 0;
6259
6260         mlxsw_sp_port = netdev_priv(dev);
6261         mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
6262         info = ptr;
6263         extack = netdev_notifier_info_to_extack(&info->info);
6264
6265         switch (event) {
6266         case NETDEV_PRECHANGEUPPER:
6267                 upper_dev = info->upper_dev;
6268                 if (!is_vlan_dev(upper_dev) &&
6269                     !netif_is_lag_master(upper_dev) &&
6270                     !netif_is_bridge_master(upper_dev) &&
6271                     !netif_is_ovs_master(upper_dev) &&
6272                     !netif_is_macvlan(upper_dev)) {
6273                         NL_SET_ERR_MSG_MOD(extack, "Unknown upper device type");
6274                         return -EINVAL;
6275                 }
6276                 if (!info->linking)
6277                         break;
6278                 if (netif_is_bridge_master(upper_dev) &&
6279                     !mlxsw_sp_bridge_device_is_offloaded(mlxsw_sp, upper_dev) &&
6280                     mlxsw_sp_bridge_has_vxlan(upper_dev) &&
6281                     !mlxsw_sp_bridge_vxlan_is_valid(upper_dev, extack))
6282                         return -EOPNOTSUPP;
6283                 if (netdev_has_any_upper_dev(upper_dev) &&
6284                     (!netif_is_bridge_master(upper_dev) ||
6285                      !mlxsw_sp_bridge_device_is_offloaded(mlxsw_sp,
6286                                                           upper_dev))) {
6287                         NL_SET_ERR_MSG_MOD(extack, "Enslaving a port to a device that already has an upper device is not supported");
6288                         return -EINVAL;
6289                 }
6290                 if (netif_is_lag_master(upper_dev) &&
6291                     !mlxsw_sp_master_lag_check(mlxsw_sp, upper_dev,
6292                                                info->upper_info, extack))
6293                         return -EINVAL;
6294                 if (netif_is_lag_master(upper_dev) && vlan_uses_dev(dev)) {
6295                         NL_SET_ERR_MSG_MOD(extack, "Master device is a LAG master and this device has a VLAN");
6296                         return -EINVAL;
6297                 }
6298                 if (netif_is_lag_port(dev) && is_vlan_dev(upper_dev) &&
6299                     !netif_is_lag_master(vlan_dev_real_dev(upper_dev))) {
6300                         NL_SET_ERR_MSG_MOD(extack, "Can not put a VLAN on a LAG port");
6301                         return -EINVAL;
6302                 }
6303                 if (netif_is_macvlan(upper_dev) &&
6304                     !mlxsw_sp_rif_exists(mlxsw_sp, lower_dev)) {
6305                         NL_SET_ERR_MSG_MOD(extack, "macvlan is only supported on top of router interfaces");
6306                         return -EOPNOTSUPP;
6307                 }
6308                 if (netif_is_ovs_master(upper_dev) && vlan_uses_dev(dev)) {
6309                         NL_SET_ERR_MSG_MOD(extack, "Master device is an OVS master and this device has a VLAN");
6310                         return -EINVAL;
6311                 }
6312                 if (netif_is_ovs_port(dev) && is_vlan_dev(upper_dev)) {
6313                         NL_SET_ERR_MSG_MOD(extack, "Can not put a VLAN on an OVS port");
6314                         return -EINVAL;
6315                 }
6316                 break;
6317         case NETDEV_CHANGEUPPER:
6318                 upper_dev = info->upper_dev;
6319                 if (netif_is_bridge_master(upper_dev)) {
6320                         if (info->linking)
6321                                 err = mlxsw_sp_port_bridge_join(mlxsw_sp_port,
6322                                                                 lower_dev,
6323                                                                 upper_dev,
6324                                                                 extack);
6325                         else
6326                                 mlxsw_sp_port_bridge_leave(mlxsw_sp_port,
6327                                                            lower_dev,
6328                                                            upper_dev);
6329                 } else if (netif_is_lag_master(upper_dev)) {
6330                         if (info->linking) {
6331                                 err = mlxsw_sp_port_lag_join(mlxsw_sp_port,
6332                                                              upper_dev);
6333                         } else {
6334                                 mlxsw_sp_port_lag_col_dist_disable(mlxsw_sp_port);
6335                                 mlxsw_sp_port_lag_leave(mlxsw_sp_port,
6336                                                         upper_dev);
6337                         }
6338                 } else if (netif_is_ovs_master(upper_dev)) {
6339                         if (info->linking)
6340                                 err = mlxsw_sp_port_ovs_join(mlxsw_sp_port);
6341                         else
6342                                 mlxsw_sp_port_ovs_leave(mlxsw_sp_port);
6343                 } else if (netif_is_macvlan(upper_dev)) {
6344                         if (!info->linking)
6345                                 mlxsw_sp_rif_macvlan_del(mlxsw_sp, upper_dev);
6346                 } else if (is_vlan_dev(upper_dev)) {
6347                         struct net_device *br_dev;
6348
6349                         if (!netif_is_bridge_port(upper_dev))
6350                                 break;
6351                         if (info->linking)
6352                                 break;
6353                         br_dev = netdev_master_upper_dev_get(upper_dev);
6354                         mlxsw_sp_port_bridge_leave(mlxsw_sp_port, upper_dev,
6355                                                    br_dev);
6356                 }
6357                 break;
6358         }
6359
6360         return err;
6361 }
6362
6363 static int mlxsw_sp_netdevice_port_lower_event(struct net_device *dev,
6364                                                unsigned long event, void *ptr)
6365 {
6366         struct netdev_notifier_changelowerstate_info *info;
6367         struct mlxsw_sp_port *mlxsw_sp_port;
6368         int err;
6369
6370         mlxsw_sp_port = netdev_priv(dev);
6371         info = ptr;
6372
6373         switch (event) {
6374         case NETDEV_CHANGELOWERSTATE:
6375                 if (netif_is_lag_port(dev) && mlxsw_sp_port->lagged) {
6376                         err = mlxsw_sp_port_lag_changed(mlxsw_sp_port,
6377                                                         info->lower_state_info);
6378                         if (err)
6379                                 netdev_err(dev, "Failed to reflect link aggregation lower state change\n");
6380                 }
6381                 break;
6382         }
6383
6384         return 0;
6385 }
6386
6387 static int mlxsw_sp_netdevice_port_event(struct net_device *lower_dev,
6388                                          struct net_device *port_dev,
6389                                          unsigned long event, void *ptr)
6390 {
6391         switch (event) {
6392         case NETDEV_PRECHANGEUPPER:
6393         case NETDEV_CHANGEUPPER:
6394                 return mlxsw_sp_netdevice_port_upper_event(lower_dev, port_dev,
6395                                                            event, ptr);
6396         case NETDEV_CHANGELOWERSTATE:
6397                 return mlxsw_sp_netdevice_port_lower_event(port_dev, event,
6398                                                            ptr);
6399         }
6400
6401         return 0;
6402 }
6403
6404 static int mlxsw_sp_netdevice_lag_event(struct net_device *lag_dev,
6405                                         unsigned long event, void *ptr)
6406 {
6407         struct net_device *dev;
6408         struct list_head *iter;
6409         int ret;
6410
6411         netdev_for_each_lower_dev(lag_dev, dev, iter) {
6412                 if (mlxsw_sp_port_dev_check(dev)) {
6413                         ret = mlxsw_sp_netdevice_port_event(lag_dev, dev, event,
6414                                                             ptr);
6415                         if (ret)
6416                                 return ret;
6417                 }
6418         }
6419
6420         return 0;
6421 }
6422
6423 static int mlxsw_sp_netdevice_port_vlan_event(struct net_device *vlan_dev,
6424                                               struct net_device *dev,
6425                                               unsigned long event, void *ptr,
6426                                               u16 vid)
6427 {
6428         struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
6429         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
6430         struct netdev_notifier_changeupper_info *info = ptr;
6431         struct netlink_ext_ack *extack;
6432         struct net_device *upper_dev;
6433         int err = 0;
6434
6435         extack = netdev_notifier_info_to_extack(&info->info);
6436
6437         switch (event) {
6438         case NETDEV_PRECHANGEUPPER:
6439                 upper_dev = info->upper_dev;
6440                 if (!netif_is_bridge_master(upper_dev) &&
6441                     !netif_is_macvlan(upper_dev)) {
6442                         NL_SET_ERR_MSG_MOD(extack, "Unknown upper device type");
6443                         return -EINVAL;
6444                 }
6445                 if (!info->linking)
6446                         break;
6447                 if (netif_is_bridge_master(upper_dev) &&
6448                     !mlxsw_sp_bridge_device_is_offloaded(mlxsw_sp, upper_dev) &&
6449                     mlxsw_sp_bridge_has_vxlan(upper_dev) &&
6450                     !mlxsw_sp_bridge_vxlan_is_valid(upper_dev, extack))
6451                         return -EOPNOTSUPP;
6452                 if (netdev_has_any_upper_dev(upper_dev) &&
6453                     (!netif_is_bridge_master(upper_dev) ||
6454                      !mlxsw_sp_bridge_device_is_offloaded(mlxsw_sp,
6455                                                           upper_dev))) {
6456                         NL_SET_ERR_MSG_MOD(extack, "Enslaving a port to a device that already has an upper device is not supported");
6457                         return -EINVAL;
6458                 }
6459                 if (netif_is_macvlan(upper_dev) &&
6460                     !mlxsw_sp_rif_exists(mlxsw_sp, vlan_dev)) {
6461                         NL_SET_ERR_MSG_MOD(extack, "macvlan is only supported on top of router interfaces");
6462                         return -EOPNOTSUPP;
6463                 }
6464                 break;
6465         case NETDEV_CHANGEUPPER:
6466                 upper_dev = info->upper_dev;
6467                 if (netif_is_bridge_master(upper_dev)) {
6468                         if (info->linking)
6469                                 err = mlxsw_sp_port_bridge_join(mlxsw_sp_port,
6470                                                                 vlan_dev,
6471                                                                 upper_dev,
6472                                                                 extack);
6473                         else
6474                                 mlxsw_sp_port_bridge_leave(mlxsw_sp_port,
6475                                                            vlan_dev,
6476                                                            upper_dev);
6477                 } else if (netif_is_macvlan(upper_dev)) {
6478                         if (!info->linking)
6479                                 mlxsw_sp_rif_macvlan_del(mlxsw_sp, upper_dev);
6480                 } else {
6481                         err = -EINVAL;
6482                         WARN_ON(1);
6483                 }
6484                 break;
6485         }
6486
6487         return err;
6488 }
6489
6490 static int mlxsw_sp_netdevice_lag_port_vlan_event(struct net_device *vlan_dev,
6491                                                   struct net_device *lag_dev,
6492                                                   unsigned long event,
6493                                                   void *ptr, u16 vid)
6494 {
6495         struct net_device *dev;
6496         struct list_head *iter;
6497         int ret;
6498
6499         netdev_for_each_lower_dev(lag_dev, dev, iter) {
6500                 if (mlxsw_sp_port_dev_check(dev)) {
6501                         ret = mlxsw_sp_netdevice_port_vlan_event(vlan_dev, dev,
6502                                                                  event, ptr,
6503                                                                  vid);
6504                         if (ret)
6505                                 return ret;
6506                 }
6507         }
6508
6509         return 0;
6510 }
6511
6512 static int mlxsw_sp_netdevice_bridge_vlan_event(struct net_device *vlan_dev,
6513                                                 struct net_device *br_dev,
6514                                                 unsigned long event, void *ptr,
6515                                                 u16 vid)
6516 {
6517         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_lower_get(vlan_dev);
6518         struct netdev_notifier_changeupper_info *info = ptr;
6519         struct netlink_ext_ack *extack;
6520         struct net_device *upper_dev;
6521
6522         if (!mlxsw_sp)
6523                 return 0;
6524
6525         extack = netdev_notifier_info_to_extack(&info->info);
6526
6527         switch (event) {
6528         case NETDEV_PRECHANGEUPPER:
6529                 upper_dev = info->upper_dev;
6530                 if (!netif_is_macvlan(upper_dev)) {
6531                         NL_SET_ERR_MSG_MOD(extack, "Unknown upper device type");
6532                         return -EOPNOTSUPP;
6533                 }
6534                 if (!info->linking)
6535                         break;
6536                 if (netif_is_macvlan(upper_dev) &&
6537                     !mlxsw_sp_rif_exists(mlxsw_sp, vlan_dev)) {
6538                         NL_SET_ERR_MSG_MOD(extack, "macvlan is only supported on top of router interfaces");
6539                         return -EOPNOTSUPP;
6540                 }
6541                 break;
6542         case NETDEV_CHANGEUPPER:
6543                 upper_dev = info->upper_dev;
6544                 if (info->linking)
6545                         break;
6546                 if (netif_is_macvlan(upper_dev))
6547                         mlxsw_sp_rif_macvlan_del(mlxsw_sp, upper_dev);
6548                 break;
6549         }
6550
6551         return 0;
6552 }
6553
6554 static int mlxsw_sp_netdevice_vlan_event(struct net_device *vlan_dev,
6555                                          unsigned long event, void *ptr)
6556 {
6557         struct net_device *real_dev = vlan_dev_real_dev(vlan_dev);
6558         u16 vid = vlan_dev_vlan_id(vlan_dev);
6559
6560         if (mlxsw_sp_port_dev_check(real_dev))
6561                 return mlxsw_sp_netdevice_port_vlan_event(vlan_dev, real_dev,
6562                                                           event, ptr, vid);
6563         else if (netif_is_lag_master(real_dev))
6564                 return mlxsw_sp_netdevice_lag_port_vlan_event(vlan_dev,
6565                                                               real_dev, event,
6566                                                               ptr, vid);
6567         else if (netif_is_bridge_master(real_dev))
6568                 return mlxsw_sp_netdevice_bridge_vlan_event(vlan_dev, real_dev,
6569                                                             event, ptr, vid);
6570
6571         return 0;
6572 }
6573
6574 static int mlxsw_sp_netdevice_bridge_event(struct net_device *br_dev,
6575                                            unsigned long event, void *ptr)
6576 {
6577         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_lower_get(br_dev);
6578         struct netdev_notifier_changeupper_info *info = ptr;
6579         struct netlink_ext_ack *extack;
6580         struct net_device *upper_dev;
6581
6582         if (!mlxsw_sp)
6583                 return 0;
6584
6585         extack = netdev_notifier_info_to_extack(&info->info);
6586
6587         switch (event) {
6588         case NETDEV_PRECHANGEUPPER:
6589                 upper_dev = info->upper_dev;
6590                 if (!is_vlan_dev(upper_dev) && !netif_is_macvlan(upper_dev)) {
6591                         NL_SET_ERR_MSG_MOD(extack, "Unknown upper device type");
6592                         return -EOPNOTSUPP;
6593                 }
6594                 if (!info->linking)
6595                         break;
6596                 if (netif_is_macvlan(upper_dev) &&
6597                     !mlxsw_sp_rif_exists(mlxsw_sp, br_dev)) {
6598                         NL_SET_ERR_MSG_MOD(extack, "macvlan is only supported on top of router interfaces");
6599                         return -EOPNOTSUPP;
6600                 }
6601                 break;
6602         case NETDEV_CHANGEUPPER:
6603                 upper_dev = info->upper_dev;
6604                 if (info->linking)
6605                         break;
6606                 if (is_vlan_dev(upper_dev))
6607                         mlxsw_sp_rif_destroy_by_dev(mlxsw_sp, upper_dev);
6608                 if (netif_is_macvlan(upper_dev))
6609                         mlxsw_sp_rif_macvlan_del(mlxsw_sp, upper_dev);
6610                 break;
6611         }
6612
6613         return 0;
6614 }
6615
6616 static int mlxsw_sp_netdevice_macvlan_event(struct net_device *macvlan_dev,
6617                                             unsigned long event, void *ptr)
6618 {
6619         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_lower_get(macvlan_dev);
6620         struct netdev_notifier_changeupper_info *info = ptr;
6621         struct netlink_ext_ack *extack;
6622
6623         if (!mlxsw_sp || event != NETDEV_PRECHANGEUPPER)
6624                 return 0;
6625
6626         extack = netdev_notifier_info_to_extack(&info->info);
6627
6628         /* VRF enslavement is handled in mlxsw_sp_netdevice_vrf_event() */
6629         NL_SET_ERR_MSG_MOD(extack, "Unknown upper device type");
6630
6631         return -EOPNOTSUPP;
6632 }
6633
6634 static bool mlxsw_sp_is_vrf_event(unsigned long event, void *ptr)
6635 {
6636         struct netdev_notifier_changeupper_info *info = ptr;
6637
6638         if (event != NETDEV_PRECHANGEUPPER && event != NETDEV_CHANGEUPPER)
6639                 return false;
6640         return netif_is_l3_master(info->upper_dev);
6641 }
6642
6643 static int mlxsw_sp_netdevice_vxlan_event(struct mlxsw_sp *mlxsw_sp,
6644                                           struct net_device *dev,
6645                                           unsigned long event, void *ptr)
6646 {
6647         struct netdev_notifier_changeupper_info *cu_info;
6648         struct netdev_notifier_info *info = ptr;
6649         struct netlink_ext_ack *extack;
6650         struct net_device *upper_dev;
6651
6652         extack = netdev_notifier_info_to_extack(info);
6653
6654         switch (event) {
6655         case NETDEV_CHANGEUPPER:
6656                 cu_info = container_of(info,
6657                                        struct netdev_notifier_changeupper_info,
6658                                        info);
6659                 upper_dev = cu_info->upper_dev;
6660                 if (!netif_is_bridge_master(upper_dev))
6661                         return 0;
6662                 if (!mlxsw_sp_lower_get(upper_dev))
6663                         return 0;
6664                 if (!mlxsw_sp_bridge_vxlan_is_valid(upper_dev, extack))
6665                         return -EOPNOTSUPP;
6666                 if (cu_info->linking) {
6667                         if (!netif_running(dev))
6668                                 return 0;
6669                         /* When the bridge is VLAN-aware, the VNI of the VxLAN
6670                          * device needs to be mapped to a VLAN, but at this
6671                          * point no VLANs are configured on the VxLAN device
6672                          */
6673                         if (br_vlan_enabled(upper_dev))
6674                                 return 0;
6675                         return mlxsw_sp_bridge_vxlan_join(mlxsw_sp, upper_dev,
6676                                                           dev, 0, extack);
6677                 } else {
6678                         /* VLANs were already flushed, which triggered the
6679                          * necessary cleanup
6680                          */
6681                         if (br_vlan_enabled(upper_dev))
6682                                 return 0;
6683                         mlxsw_sp_bridge_vxlan_leave(mlxsw_sp, dev);
6684                 }
6685                 break;
6686         case NETDEV_PRE_UP:
6687                 upper_dev = netdev_master_upper_dev_get(dev);
6688                 if (!upper_dev)
6689                         return 0;
6690                 if (!netif_is_bridge_master(upper_dev))
6691                         return 0;
6692                 if (!mlxsw_sp_lower_get(upper_dev))
6693                         return 0;
6694                 return mlxsw_sp_bridge_vxlan_join(mlxsw_sp, upper_dev, dev, 0,
6695                                                   extack);
6696         case NETDEV_DOWN:
6697                 upper_dev = netdev_master_upper_dev_get(dev);
6698                 if (!upper_dev)
6699                         return 0;
6700                 if (!netif_is_bridge_master(upper_dev))
6701                         return 0;
6702                 if (!mlxsw_sp_lower_get(upper_dev))
6703                         return 0;
6704                 mlxsw_sp_bridge_vxlan_leave(mlxsw_sp, dev);
6705                 break;
6706         }
6707
6708         return 0;
6709 }
6710
6711 static int mlxsw_sp_netdevice_event(struct notifier_block *nb,
6712                                     unsigned long event, void *ptr)
6713 {
6714         struct net_device *dev = netdev_notifier_info_to_dev(ptr);
6715         struct mlxsw_sp_span_entry *span_entry;
6716         struct mlxsw_sp *mlxsw_sp;
6717         int err = 0;
6718
6719         mlxsw_sp = container_of(nb, struct mlxsw_sp, netdevice_nb);
6720         if (event == NETDEV_UNREGISTER) {
6721                 span_entry = mlxsw_sp_span_entry_find_by_port(mlxsw_sp, dev);
6722                 if (span_entry)
6723                         mlxsw_sp_span_entry_invalidate(mlxsw_sp, span_entry);
6724         }
6725         mlxsw_sp_span_respin(mlxsw_sp);
6726
6727         if (netif_is_vxlan(dev))
6728                 err = mlxsw_sp_netdevice_vxlan_event(mlxsw_sp, dev, event, ptr);
6729         if (mlxsw_sp_netdev_is_ipip_ol(mlxsw_sp, dev))
6730                 err = mlxsw_sp_netdevice_ipip_ol_event(mlxsw_sp, dev,
6731                                                        event, ptr);
6732         else if (mlxsw_sp_netdev_is_ipip_ul(mlxsw_sp, dev))
6733                 err = mlxsw_sp_netdevice_ipip_ul_event(mlxsw_sp, dev,
6734                                                        event, ptr);
6735         else if (event == NETDEV_PRE_CHANGEADDR ||
6736                  event == NETDEV_CHANGEADDR ||
6737                  event == NETDEV_CHANGEMTU)
6738                 err = mlxsw_sp_netdevice_router_port_event(dev, event, ptr);
6739         else if (mlxsw_sp_is_vrf_event(event, ptr))
6740                 err = mlxsw_sp_netdevice_vrf_event(dev, event, ptr);
6741         else if (mlxsw_sp_port_dev_check(dev))
6742                 err = mlxsw_sp_netdevice_port_event(dev, dev, event, ptr);
6743         else if (netif_is_lag_master(dev))
6744                 err = mlxsw_sp_netdevice_lag_event(dev, event, ptr);
6745         else if (is_vlan_dev(dev))
6746                 err = mlxsw_sp_netdevice_vlan_event(dev, event, ptr);
6747         else if (netif_is_bridge_master(dev))
6748                 err = mlxsw_sp_netdevice_bridge_event(dev, event, ptr);
6749         else if (netif_is_macvlan(dev))
6750                 err = mlxsw_sp_netdevice_macvlan_event(dev, event, ptr);
6751
6752         return notifier_from_errno(err);
6753 }
6754
6755 static struct notifier_block mlxsw_sp_inetaddr_valid_nb __read_mostly = {
6756         .notifier_call = mlxsw_sp_inetaddr_valid_event,
6757 };
6758
6759 static struct notifier_block mlxsw_sp_inet6addr_valid_nb __read_mostly = {
6760         .notifier_call = mlxsw_sp_inet6addr_valid_event,
6761 };
6762
6763 static const struct pci_device_id mlxsw_sp1_pci_id_table[] = {
6764         {PCI_VDEVICE(MELLANOX, PCI_DEVICE_ID_MELLANOX_SPECTRUM), 0},
6765         {0, },
6766 };
6767
6768 static struct pci_driver mlxsw_sp1_pci_driver = {
6769         .name = mlxsw_sp1_driver_name,
6770         .id_table = mlxsw_sp1_pci_id_table,
6771 };
6772
6773 static const struct pci_device_id mlxsw_sp2_pci_id_table[] = {
6774         {PCI_VDEVICE(MELLANOX, PCI_DEVICE_ID_MELLANOX_SPECTRUM2), 0},
6775         {0, },
6776 };
6777
6778 static struct pci_driver mlxsw_sp2_pci_driver = {
6779         .name = mlxsw_sp2_driver_name,
6780         .id_table = mlxsw_sp2_pci_id_table,
6781 };
6782
6783 static const struct pci_device_id mlxsw_sp3_pci_id_table[] = {
6784         {PCI_VDEVICE(MELLANOX, PCI_DEVICE_ID_MELLANOX_SPECTRUM3), 0},
6785         {0, },
6786 };
6787
6788 static struct pci_driver mlxsw_sp3_pci_driver = {
6789         .name = mlxsw_sp3_driver_name,
6790         .id_table = mlxsw_sp3_pci_id_table,
6791 };
6792
6793 static int __init mlxsw_sp_module_init(void)
6794 {
6795         int err;
6796
6797         register_inetaddr_validator_notifier(&mlxsw_sp_inetaddr_valid_nb);
6798         register_inet6addr_validator_notifier(&mlxsw_sp_inet6addr_valid_nb);
6799
6800         err = mlxsw_core_driver_register(&mlxsw_sp1_driver);
6801         if (err)
6802                 goto err_sp1_core_driver_register;
6803
6804         err = mlxsw_core_driver_register(&mlxsw_sp2_driver);
6805         if (err)
6806                 goto err_sp2_core_driver_register;
6807
6808         err = mlxsw_core_driver_register(&mlxsw_sp3_driver);
6809         if (err)
6810                 goto err_sp3_core_driver_register;
6811
6812         err = mlxsw_pci_driver_register(&mlxsw_sp1_pci_driver);
6813         if (err)
6814                 goto err_sp1_pci_driver_register;
6815
6816         err = mlxsw_pci_driver_register(&mlxsw_sp2_pci_driver);
6817         if (err)
6818                 goto err_sp2_pci_driver_register;
6819
6820         err = mlxsw_pci_driver_register(&mlxsw_sp3_pci_driver);
6821         if (err)
6822                 goto err_sp3_pci_driver_register;
6823
6824         return 0;
6825
6826 err_sp3_pci_driver_register:
6827         mlxsw_pci_driver_unregister(&mlxsw_sp2_pci_driver);
6828 err_sp2_pci_driver_register:
6829         mlxsw_pci_driver_unregister(&mlxsw_sp1_pci_driver);
6830 err_sp1_pci_driver_register:
6831         mlxsw_core_driver_unregister(&mlxsw_sp3_driver);
6832 err_sp3_core_driver_register:
6833         mlxsw_core_driver_unregister(&mlxsw_sp2_driver);
6834 err_sp2_core_driver_register:
6835         mlxsw_core_driver_unregister(&mlxsw_sp1_driver);
6836 err_sp1_core_driver_register:
6837         unregister_inet6addr_validator_notifier(&mlxsw_sp_inet6addr_valid_nb);
6838         unregister_inetaddr_validator_notifier(&mlxsw_sp_inetaddr_valid_nb);
6839         return err;
6840 }
6841
6842 static void __exit mlxsw_sp_module_exit(void)
6843 {
6844         mlxsw_pci_driver_unregister(&mlxsw_sp3_pci_driver);
6845         mlxsw_pci_driver_unregister(&mlxsw_sp2_pci_driver);
6846         mlxsw_pci_driver_unregister(&mlxsw_sp1_pci_driver);
6847         mlxsw_core_driver_unregister(&mlxsw_sp3_driver);
6848         mlxsw_core_driver_unregister(&mlxsw_sp2_driver);
6849         mlxsw_core_driver_unregister(&mlxsw_sp1_driver);
6850         unregister_inet6addr_validator_notifier(&mlxsw_sp_inet6addr_valid_nb);
6851         unregister_inetaddr_validator_notifier(&mlxsw_sp_inetaddr_valid_nb);
6852 }
6853
6854 module_init(mlxsw_sp_module_init);
6855 module_exit(mlxsw_sp_module_exit);
6856
6857 MODULE_LICENSE("Dual BSD/GPL");
6858 MODULE_AUTHOR("Jiri Pirko <jiri@mellanox.com>");
6859 MODULE_DESCRIPTION("Mellanox Spectrum driver");
6860 MODULE_DEVICE_TABLE(pci, mlxsw_sp1_pci_id_table);
6861 MODULE_DEVICE_TABLE(pci, mlxsw_sp2_pci_id_table);
6862 MODULE_DEVICE_TABLE(pci, mlxsw_sp3_pci_id_table);
6863 MODULE_FIRMWARE(MLXSW_SP1_FW_FILENAME);
6864 MODULE_FIRMWARE(MLXSW_SP2_FW_FILENAME);